11#include "llvm/ADT/SmallSet.h"
12#include "llvm/ADT/StringMap.h"
13#include "llvm/ADT/StringSet.h"
14#include "llvm/Support/TimeProfiler.h"
21#define GEN_PASS_DEF_GOTOSOLVER
22#include "clang/CIR/Dialect/Passes.h.inc"
27struct GotoSolverPass :
public impl::GotoSolverBase<GotoSolverPass> {
28 GotoSolverPass() =
default;
29 void runOnOperation()
override;
32static void process(cir::FuncOp func,
33 const llvm::StringSet<> &globalBlockAddrLabel) {
34 mlir::OpBuilder rewriter(func.getContext());
35 llvm::StringMap<Block *> labels;
37 llvm::SmallSet<StringRef, 4> blockAddrLabel;
39 func.getBody().walk([&](mlir::Operation *op) {
40 if (
auto lab = dyn_cast<cir::LabelOp>(op)) {
41 labels.try_emplace(lab.getLabel(), lab->getBlock());
42 }
else if (
auto goTo = dyn_cast<cir::GotoOp>(op)) {
43 gotos.push_back(goTo);
44 }
else if (
auto blockAddr = dyn_cast<cir::BlockAddressOp>(op)) {
45 blockAddrLabel.insert(blockAddr.getBlockAddrInfo().getLabel());
49 for (
auto &lab : labels) {
50 StringRef labelName = lab.getKey();
51 Block *block = lab.getValue();
55 if (!blockAddrLabel.contains(labelName) &&
56 !globalBlockAddrLabel.contains(labelName)) {
58 if (
auto lab = dyn_cast<cir::LabelOp>(&block->front())) {
64 for (
auto goTo : gotos) {
65 mlir::OpBuilder::InsertionGuard guard(rewriter);
66 rewriter.setInsertionPoint(goTo);
67 Block *dest = labels[goTo.getLabel()];
68 cir::BrOp::create(rewriter, goTo.getLoc(), dest);
73void GotoSolverPass::runOnOperation() {
74 llvm::TimeTraceScope scope(
"Goto Solver");
79 llvm::StringMap<llvm::StringSet<>> globalBlockAddrLabels;
80 getOperation()->walk([&](mlir::Operation *op) {
81 for (
const mlir::NamedAttribute &namedAttr : op->getAttrs()) {
82 namedAttr.getValue().walk([&](cir::BlockAddrInfoAttr info) {
83 globalBlockAddrLabels[info.getFunc().getValue()].insert(
89 static const llvm::StringSet<> emptySet;
90 getOperation()->walk([&](cir::FuncOp func) {
91 auto it = globalBlockAddrLabels.find(func.getSymName());
92 process(func, it == globalBlockAddrLabels.end() ? emptySet : it->second);
99 return std::make_unique<GotoSolverPass>();
std::unique_ptr< Pass > createGotoSolverPass()