76 lines · cpp
1//====- GotoSolver.cpp -----------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8#include "PassDetail.h"9#include "clang/CIR/Dialect/IR/CIRDialect.h"10#include "clang/CIR/Dialect/Passes.h"11#include "llvm/ADT/SmallSet.h"12#include "llvm/Support/TimeProfiler.h"13#include <memory>14 15using namespace mlir;16using namespace cir;17 18namespace mlir {19#define GEN_PASS_DEF_GOTOSOLVER20#include "clang/CIR/Dialect/Passes.h.inc"21} // namespace mlir22 23namespace {24 25struct GotoSolverPass : public impl::GotoSolverBase<GotoSolverPass> {26 GotoSolverPass() = default;27 void runOnOperation() override;28};29 30static void process(cir::FuncOp func) {31 mlir::OpBuilder rewriter(func.getContext());32 llvm::StringMap<Block *> labels;33 llvm::SmallVector<cir::GotoOp, 4> gotos;34 llvm::SmallSet<StringRef, 4> blockAddrLabel;35 36 func.getBody().walk([&](mlir::Operation *op) {37 if (auto lab = dyn_cast<cir::LabelOp>(op)) {38 labels.try_emplace(lab.getLabel(), lab->getBlock());39 } else if (auto goTo = dyn_cast<cir::GotoOp>(op)) {40 gotos.push_back(goTo);41 } else if (auto blockAddr = dyn_cast<cir::BlockAddressOp>(op)) {42 blockAddrLabel.insert(blockAddr.getBlockAddrInfo().getLabel());43 }44 });45 46 for (auto &lab : labels) {47 StringRef labelName = lab.getKey();48 Block *block = lab.getValue();49 if (!blockAddrLabel.contains(labelName)) {50 // erase the LabelOp inside the block if safe51 if (auto lab = dyn_cast<cir::LabelOp>(&block->front())) {52 lab.erase();53 }54 }55 }56 57 for (auto goTo : gotos) {58 mlir::OpBuilder::InsertionGuard guard(rewriter);59 rewriter.setInsertionPoint(goTo);60 Block *dest = labels[goTo.getLabel()];61 cir::BrOp::create(rewriter, goTo.getLoc(), dest);62 goTo.erase();63 }64}65 66void GotoSolverPass::runOnOperation() {67 llvm::TimeTraceScope scope("Goto Solver");68 getOperation()->walk(&process);69}70 71} // namespace72 73std::unique_ptr<Pass> mlir::createGotoSolverPass() {74 return std::make_unique<GotoSolverPass>();75}76