llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clangir Author: Bruno Cardoso Lopes (bcardosolopes) <details> <summary>Changes</summary> The pass walked every op in the module checking inherent attributes for BlockAddrInfoAttr/BlockAddrDiffAttr. Block addresses only appear in attributes carried by globals and cir.const values (process() collects cir.block_address ops directly), so scan just those ops and fold the two attribute walks into one. The scan assumes module scope, so the pass is declared on ModuleOp like the other lowering passes. Successor order now follows attribute order: constant labels precede cir.block_address labels, and mixed attribute kinds in one initializer follow initializer order instead of grouping by kind. This matches the order the pass documents, program behavior is unchanged. Saves most of the 0.3-3.0s GotoSolver time on the slowest self-host TUs (e.g. 3.0s -> 0.14s on clang/lib/Sema/SemaExpr.cpp). --- Full diff: https://github.com/llvm/llvm-project/pull/232870.diff 3 Files Affected: - (modified) clang/include/clang/CIR/Dialect/Passes.td (+1-1) - (modified) clang/lib/CIR/Dialect/Transforms/GotoSolver.cpp (+27-21) - (modified) clang/test/CIR/Transforms/goto_solver.cir (+63) ``````````diff diff --git a/clang/include/clang/CIR/Dialect/Passes.td b/clang/include/clang/CIR/Dialect/Passes.td index 6994aa8a4b18a..9b260af789384 100644 --- a/clang/include/clang/CIR/Dialect/Passes.td +++ b/clang/include/clang/CIR/Dialect/Passes.td @@ -72,7 +72,7 @@ def CIRFlattenCFG : Pass<"cir-flatten-cfg"> { let dependentDialects = ["cir::CIRDialect"]; } -def GotoSolver : Pass<"cir-goto-solver"> { +def GotoSolver : Pass<"cir-goto-solver", "mlir::ModuleOp"> { let summary = "Replaces goto operations with branches"; let description = [{ This pass transforms CIR and replaces goto-s with branch diff --git a/clang/lib/CIR/Dialect/Transforms/GotoSolver.cpp b/clang/lib/CIR/Dialect/Transforms/GotoSolver.cpp index ad79927fc40ac..08e4d2eb0a5fe 100644 --- a/clang/lib/CIR/Dialect/Transforms/GotoSolver.cpp +++ b/clang/lib/CIR/Dialect/Transforms/GotoSolver.cpp @@ -115,27 +115,33 @@ static void process(cir::FuncOp func, void GotoSolverPass::runOnOperation() { llvm::TimeTraceScope scope("Goto Solver"); - // Block addresses can also appear in attributes outside of any function body, - // such as global variable initializers. Collect, per target function and in - // initializer order, the labels referenced this way so their LabelOps survive - // and join the indirect branch's successors. A SetVector keeps the first - // occurrence in order: a label named more than once across initializers needs - // to be a successor only once. + // Block addresses also appear in attributes: global initializers and + // cir.const values. Collect, per target function and in walk order, the + // labels referenced this way so their LabelOps survive and join the + // indirect branch's successors. A SetVector keeps the first occurrence + // in order: a label named more than once is a successor only once. + // + // process() collects cir.block_address ops; scan just globals and + // constants for the rest. llvm::StringMap<llvm::SmallSetVector<StringRef, 4>> globalBlockAddrLabels; - getOperation()->walk([&](mlir::Operation *op) { + mlir::ModuleOp module = mlir::cast<mlir::ModuleOp>(getOperation()); + module.walk([&](mlir::Operation *op) { + if (!mlir::isa<cir::GlobalOp, cir::ConstantOp>(op)) + return; auto collectBlockAddresses = [&](mlir::Attribute attr) { - attr.walk([&](cir::BlockAddrInfoAttr info) { - globalBlockAddrLabels[info.getFunc().getValue()].insert( - info.getLabel()); - }); - // A block-address difference attribute references two labels in the same - // function; keep both alive. - attr.walk([&](cir::BlockAddrDiffAttr diff) { - llvm::SmallSetVector<StringRef, 4> &labels = - globalBlockAddrLabels[diff.getFunc().getValue()]; - labels.insert(diff.getLhsLabel().getValue()); - labels.insert(diff.getRhsLabel().getValue()); - }); + attr.walk( + [&](cir::BlockAddrInfoAttr info) { + globalBlockAddrLabels[info.getFunc().getValue()].insert( + info.getLabel()); + }, + [&](cir::BlockAddrDiffAttr diff) { + // A block-address difference attribute references two labels in + // the same function; keep both alive. + llvm::SmallSetVector<StringRef, 4> &labels = + globalBlockAddrLabels[diff.getFunc().getValue()]; + labels.insert(diff.getLhsLabel().getValue()); + labels.insert(diff.getRhsLabel().getValue()); + }); }; op->getName().walkInherentAttrs( op, [&](llvm::StringRef, mlir::Attribute &attr) { @@ -144,12 +150,12 @@ void GotoSolverPass::runOnOperation() { }); static const llvm::SmallVector<StringRef> empty; - getOperation()->walk([&](cir::FuncOp func) { + for (cir::FuncOp func : module.getOps<cir::FuncOp>()) { auto it = globalBlockAddrLabels.find(func.getSymName()); process(func, it == globalBlockAddrLabels.end() ? llvm::ArrayRef<StringRef>(empty) : it->second.getArrayRef()); - }); + } } } // namespace diff --git a/clang/test/CIR/Transforms/goto_solver.cir b/clang/test/CIR/Transforms/goto_solver.cir index 26cd9827ae318..521022f74ef28 100644 --- a/clang/test/CIR/Transforms/goto_solver.cir +++ b/clang/test/CIR/Transforms/goto_solver.cir @@ -1,6 +1,8 @@ // RUN: cir-opt %s -cir-goto-solver --verify-roundtrip -o - | FileCheck %s !void = !cir.void +!s64i = !cir.int<s, 64> +!rec_S = !cir.struct<"S" {data !s64i, data !cir.ptr<!void>}> cir.func @a(){ %0 = cir.alloca "ptr" align(8) init : !cir.ptr<!cir.ptr<!void>> @@ -88,3 +90,64 @@ cir.func @d() { // CHECK: cir.indirect_br %[[DEST]] : !cir.ptr<!void>, [ // CHECK: ^[[L1BB]] // CHECK: ] + +cir.func @e() { + %0 = cir.alloca "ptr" align(8) init : !cir.ptr<!cir.ptr<!void>> + %1 = cir.block_address <@e, "a"> : !cir.ptr<!void> + %2 = cir.const #cir.block_addr_info<@e, "b"> : !cir.ptr<!void> + cir.store align(8) %1, %0 : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>> + %3 = cir.load align(8) %0 : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void> + cir.indirect_goto %3 : !cir.ptr<!void> +^bb1: + cir.label "a" + cir.return +^bb2: + cir.label "b" + cir.return +} + +// Attribute-carried labels precede cir.block_address labels: the constant's +// "b" sorts before the block_address op's "a" in the successor list. +// CHECK: cir.func @e() +// CHECK: ^[[ABB:bb[0-9]+]]: +// CHECK: cir.label "a" +// CHECK: ^[[BBB:bb[0-9]+]]: +// CHECK: cir.label "b" +// CHECK: ^[[EIGB:bb[0-9]+]](%{{.*}}: !cir.ptr<!void>{{.*}}): +// CHECK: cir.indirect_br {{.*}} : !cir.ptr<!void>, [ +// CHECK: ^[[BBB]] +// CHECK: ^[[ABB]] +// CHECK: ] + +cir.global internal @f.s = #cir.const_record<{#cir.block_addr_diff<@f, "b", "c"> : !s64i, #cir.block_addr_info<@f, "a"> : !cir.ptr<!void>}> : !rec_S + +cir.func @f() { + %0 = cir.alloca "ptr" align(8) init : !cir.ptr<!cir.ptr<!void>> + %1 = cir.load align(8) %0 : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void> + cir.indirect_goto %1 : !cir.ptr<!void> +^bb1: + cir.label "a" + cir.return +^bb2: + cir.label "b" + cir.return +^bb3: + cir.label "c" + cir.return +} + +// Mixed attribute kinds in one initializer follow attribute order: the +// diff's "b", "c" precede the info's "a". +// CHECK: cir.func @f() +// CHECK: ^[[FABB:bb[0-9]+]]: +// CHECK: cir.label "a" +// CHECK: ^[[FBBB:bb[0-9]+]]: +// CHECK: cir.label "b" +// CHECK: ^[[FCBB:bb[0-9]+]]: +// CHECK: cir.label "c" +// CHECK: ^[[FIGB:bb[0-9]+]](%{{.*}}: !cir.ptr<!void>{{.*}}): +// CHECK: cir.indirect_br {{.*}} : !cir.ptr<!void>, [ +// CHECK: ^[[FBBB]] +// CHECK: ^[[FCBB]] +// CHECK: ^[[FABB]] +// CHECK: ] `````````` </details> https://github.com/llvm/llvm-project/pull/232870 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
