11#include "llvm/ADT/SetVector.h"
12#include "llvm/ADT/StringMap.h"
13#include "llvm/Support/TimeProfiler.h"
20#define GEN_PASS_DEF_GOTOSOLVER
21#include "clang/CIR/Dialect/Passes.h.inc"
26struct GotoSolverPass :
public impl::GotoSolverBase<GotoSolverPass> {
27 GotoSolverPass() =
default;
28 void runOnOperation()
override;
31static void process(cir::FuncOp func,
33 mlir::OpBuilder rewriter(func.getContext());
34 llvm::StringMap<Block *> labels;
43 globalBlockAddrLabels);
45 func.getBody().walk([&](mlir::Operation *op) {
46 if (
auto lab = dyn_cast<cir::LabelOp>(op)) {
47 labels.try_emplace(lab.getLabel(), lab->getBlock());
48 }
else if (
auto goTo = dyn_cast<cir::GotoOp>(op)) {
49 gotos.push_back(goTo);
50 }
else if (
auto indirect = dyn_cast<cir::IndirectGotoOp>(op)) {
51 indirectGotos.push_back(indirect);
52 }
else if (
auto blockAddr = dyn_cast<cir::BlockAddressOp>(op)) {
53 addrTakenLabels.insert(blockAddr.getBlockAddrInfo().getLabel());
59 for (
auto &lab : labels) {
60 if (!addrTakenLabels.contains(lab.getKey())) {
61 if (
auto labelOp = dyn_cast<cir::LabelOp>(&lab.getValue()->front()))
67 for (
auto goTo : gotos) {
68 mlir::OpBuilder::InsertionGuard guard(rewriter);
69 rewriter.setInsertionPoint(goTo);
70 Block *dest = labels[goTo.getLabel()];
71 cir::BrOp::create(rewriter, goTo.getLoc(), dest);
78 if (indirectGotos.empty())
88 for (cir::IndirectGotoOp indirect : indirectGotos)
89 gotoLocs.push_back(indirect.getLoc());
90 mlir::Location loc = mlir::FusedLoc::get(func.getContext(), gotoLocs);
91 mlir::Type addrType = indirectGotos.front().getAddr().getType();
92 Block *indirectGotoBlock = rewriter.createBlock(
93 &func.getBody(), func.getBody().end(), {addrType}, {loc});
97 for (StringRef name : addrTakenLabels) {
98 Block *dest = labels[
name];
99 assert(dest &&
"address-taken label has no cir.label in this function");
100 successors.push_back(dest);
101 succOperands.push_back(dest->getArguments());
103 cir::IndirectBrOp::create(rewriter, loc, indirectGotoBlock->getArgument(0),
104 false, succOperands, successors);
106 for (
auto indirect : indirectGotos) {
107 mlir::OpBuilder::InsertionGuard guard(rewriter);
108 rewriter.setInsertionPoint(indirect);
109 cir::BrOp::create(rewriter, indirect.getLoc(), indirectGotoBlock,
115void GotoSolverPass::runOnOperation() {
116 llvm::TimeTraceScope scope(
"Goto Solver");
124 llvm::StringMap<llvm::SmallSetVector<StringRef, 4>> globalBlockAddrLabels;
125 getOperation()->walk([&](mlir::Operation *op) {
126 for (
const mlir::NamedAttribute &namedAttr : op->getAttrs()) {
127 namedAttr.getValue().walk([&](cir::BlockAddrInfoAttr info) {
128 globalBlockAddrLabels[
info.getFunc().getValue()].insert(
133 namedAttr.getValue().walk([&](cir::BlockAddrDiffAttr diff) {
134 llvm::SmallSetVector<StringRef, 4> &labels =
135 globalBlockAddrLabels[diff.getFunc().getValue()];
136 labels.insert(diff.getLhsLabel().getValue());
137 labels.insert(diff.getRhsLabel().getValue());
142 static const llvm::SmallVector<StringRef> empty;
143 getOperation()->walk([&](cir::FuncOp func) {
144 auto it = globalBlockAddrLabels.find(func.getSymName());
145 process(func, it == globalBlockAddrLabels.end()
146 ? llvm::ArrayRef<StringRef>(empty)
147 : it->second.getArrayRef());
154 return std::make_unique<GotoSolverPass>();
void info(bool Verbose, unsigned Level, const char *Fmt, Ts &&...Args)
Prints an indented note to stderr when Verbose is set.
std::unique_ptr< Pass > createGotoSolverPass()