[llvm] [SimplifyCFG] Do not run `simplifySwitchOfPowersOfTwo` in early invocations (PR #145477)

via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 24 01:28:59 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Antonio Frighetto (antoniofrighetto)

<details>
<summary>Changes</summary>

It may be desirable not to carry out `simplifySwitchOfPowersOfTwo` transform during early pipeline invocations, so as to let other optimizations occur first.

---
Full diff: https://github.com/llvm/llvm-project/pull/145477.diff


7 Files Affected:

- (modified) llvm/include/llvm/Transforms/Utils/SimplifyCFGOptions.h (+5) 
- (modified) llvm/lib/Passes/PassBuilder.cpp (+2) 
- (modified) llvm/lib/Passes/PassBuilderPipelines.cpp (+5-2) 
- (modified) llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp (+2-1) 
- (modified) llvm/lib/Transforms/Utils/SimplifyCFG.cpp (+2-1) 
- (modified) llvm/test/Other/new-pm-print-pipeline.ll (+2-2) 
- (modified) llvm/test/Transforms/SimplifyCFG/X86/switch-of-powers-of-two.ll (+59-8) 


``````````diff
diff --git a/llvm/include/llvm/Transforms/Utils/SimplifyCFGOptions.h b/llvm/include/llvm/Transforms/Utils/SimplifyCFGOptions.h
index ee3cc950cdb50..376c5ab934244 100644
--- a/llvm/include/llvm/Transforms/Utils/SimplifyCFGOptions.h
+++ b/llvm/include/llvm/Transforms/Utils/SimplifyCFGOptions.h
@@ -32,6 +32,7 @@ struct SimplifyCFGOptions {
   bool SimplifyCondBranch = true;
   bool SpeculateBlocks = true;
   bool SpeculateUnpredictables = false;
+  bool SwitchToCttzAndReducedTable = true;
 
   AssumptionCache *AC = nullptr;
 
@@ -85,6 +86,10 @@ struct SimplifyCFGOptions {
     SpeculateUnpredictables = B;
     return *this;
   }
+  SimplifyCFGOptions &convertSwitchToCttzAndReducedTable(bool B) {
+    SwitchToCttzAndReducedTable = B;
+    return *this;
+  }
 };
 
 } // namespace llvm
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index 4603eaff8ade9..8e149b73be992 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -1001,6 +1001,8 @@ Expected<SimplifyCFGOptions> parseSimplifyCFGOptions(StringRef Params) {
       Result.sinkCommonInsts(Enable);
     } else if (ParamName == "speculate-unpredictables") {
       Result.speculateUnpredictables(Enable);
+    } else if (ParamName == "switch-to-cttz") {
+      Result.convertSwitchToCttzAndReducedTable(Enable);
     } else if (Enable && ParamName.consume_front("bonus-inst-threshold=")) {
       APInt BonusInstThreshold;
       if (ParamName.getAsInteger(0, BonusInstThreshold))
diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp
index c83d2dc1f1514..087987385314a 100644
--- a/llvm/lib/Passes/PassBuilderPipelines.cpp
+++ b/llvm/lib/Passes/PassBuilderPipelines.cpp
@@ -1121,7 +1121,8 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level,
     // Compare/branch metadata may alter the behavior of passes like
     // SimplifyCFG.
     EarlyFPM.addPass(LowerExpectIntrinsicPass());
-    EarlyFPM.addPass(SimplifyCFGPass());
+    EarlyFPM.addPass(SimplifyCFGPass(
+        SimplifyCFGOptions().convertSwitchToCttzAndReducedTable(false)));
     EarlyFPM.addPass(SROAPass(SROAOptions::ModifyCFG));
     EarlyFPM.addPass(EarlyCSEPass());
     if (Level == OptimizationLevel::O3)
@@ -1190,7 +1191,9 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level,
   GlobalCleanupPM.addPass(InstCombinePass());
   invokePeepholeEPCallbacks(GlobalCleanupPM, Level);
   GlobalCleanupPM.addPass(
-      SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true)));
+      SimplifyCFGPass(SimplifyCFGOptions()
+                          .convertSwitchRangeToICmp(true)
+                          .convertSwitchToCttzAndReducedTable(false)));
   MPM.addPass(createModuleToFunctionPassAdaptor(std::move(GlobalCleanupPM),
                                                 PTO.EagerlyInvalidateAnalyses));
 
diff --git a/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp b/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp
index a09303bb4469f..4d56993cbd39f 100644
--- a/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp
+++ b/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp
@@ -366,7 +366,8 @@ void SimplifyCFGPass::printPipeline(
   OS << (Options.SpeculateBlocks ? "" : "no-") << "speculate-blocks;";
   OS << (Options.SimplifyCondBranch ? "" : "no-") << "simplify-cond-branch;";
   OS << (Options.SpeculateUnpredictables ? "" : "no-")
-     << "speculate-unpredictables";
+     << "speculate-unpredictables;";
+  OS << (Options.SwitchToCttzAndReducedTable ? "" : "no-") << "switch-to-cttz";
   OS << '>';
 }
 
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index e205551658aa5..decce248063ac 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -7604,7 +7604,8 @@ bool SimplifyCFGOpt::simplifySwitch(SwitchInst *SI, IRBuilder<> &Builder) {
       switchToLookupTable(SI, Builder, DTU, DL, TTI))
     return requestResimplify();
 
-  if (simplifySwitchOfPowersOfTwo(SI, Builder, DL, TTI))
+  if (Options.SwitchToCttzAndReducedTable &&
+      simplifySwitchOfPowersOfTwo(SI, Builder, DL, TTI))
     return requestResimplify();
 
   if (reduceSwitchRange(SI, Builder, DL, TTI))
diff --git a/llvm/test/Other/new-pm-print-pipeline.ll b/llvm/test/Other/new-pm-print-pipeline.ll
index db398d68fd426..8e4efafbc9cb2 100644
--- a/llvm/test/Other/new-pm-print-pipeline.ll
+++ b/llvm/test/Other/new-pm-print-pipeline.ll
@@ -49,8 +49,8 @@
 ; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='function(print<stack-lifetime><may>,print<stack-lifetime><must>)' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-17
 ; CHECK-17: function(print<stack-lifetime><may>,print<stack-lifetime><must>)
 
-; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='function(simplifycfg<bonus-inst-threshold=5;forward-switch-cond;switch-to-lookup;keep-loops;hoist-common-insts;hoist-loads-stores-with-cond-faulting;sink-common-insts;speculate-blocks;simplify-cond-branch;speculate-unpredictables>,simplifycfg<bonus-inst-threshold=7;no-forward-switch-cond;no-switch-to-lookup;no-keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;no-speculate-blocks;no-simplify-cond-branch;no-speculate-unpredictables>)' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-18
-; CHECK-18: function(simplifycfg<bonus-inst-threshold=5;forward-switch-cond;no-switch-range-to-icmp;switch-to-lookup;keep-loops;hoist-common-insts;hoist-loads-stores-with-cond-faulting;sink-common-insts;speculate-blocks;simplify-cond-branch;speculate-unpredictables>,simplifycfg<bonus-inst-threshold=7;no-forward-switch-cond;no-switch-range-to-icmp;no-switch-to-lookup;no-keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;no-speculate-blocks;no-simplify-cond-branch;no-speculate-unpredictables>)
+; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='function(simplifycfg<bonus-inst-threshold=5;forward-switch-cond;switch-to-lookup;keep-loops;hoist-common-insts;hoist-loads-stores-with-cond-faulting;sink-common-insts;speculate-blocks;simplify-cond-branch;speculate-unpredictables;switch-to-cttz>,simplifycfg<bonus-inst-threshold=7;no-forward-switch-cond;no-switch-to-lookup;no-keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;no-speculate-blocks;no-simplify-cond-branch;no-speculate-unpredictables;no-switch-to-cttz>)' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-18
+; CHECK-18: function(simplifycfg<bonus-inst-threshold=5;forward-switch-cond;no-switch-range-to-icmp;switch-to-lookup;keep-loops;hoist-common-insts;hoist-loads-stores-with-cond-faulting;sink-common-insts;speculate-blocks;simplify-cond-branch;speculate-unpredictables;switch-to-cttz>,simplifycfg<bonus-inst-threshold=7;no-forward-switch-cond;no-switch-range-to-icmp;no-switch-to-lookup;no-keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;no-speculate-blocks;no-simplify-cond-branch;no-speculate-unpredictables;no-switch-to-cttz>)
 
 ; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='function(loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only>,loop-vectorize<interleave-forced-only;vectorize-forced-only>)' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-19
 ; CHECK-19: function(loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>,loop-vectorize<interleave-forced-only;vectorize-forced-only;>)
diff --git a/llvm/test/Transforms/SimplifyCFG/X86/switch-of-powers-of-two.ll b/llvm/test/Transforms/SimplifyCFG/X86/switch-of-powers-of-two.ll
index 529826758c138..0e6ef0f5323ad 100644
--- a/llvm/test/Transforms/SimplifyCFG/X86/switch-of-powers-of-two.ll
+++ b/llvm/test/Transforms/SimplifyCFG/X86/switch-of-powers-of-two.ll
@@ -1,16 +1,67 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
-; RUN: opt -passes='simplifycfg<switch-to-lookup>' -simplifycfg-require-and-preserve-domtree=1 -S < %s | FileCheck %s
+; RUN: opt -passes='simplifycfg<no-switch-to-cttz>' -S < %s | FileCheck --check-prefix=NOFOLD %s
+; RUN: opt -passes='simplifycfg' -simplifycfg-require-and-preserve-domtree=1 -S < %s | FileCheck --check-prefix=SWITCH-TO-CTTZ %s
+; RUN: opt -passes='simplifycfg<switch-to-lookup>' -simplifycfg-require-and-preserve-domtree=1 -S < %s | FileCheck --check-prefix=SWITCH-TO-CTTZ-AND-TO-LOOKUP %s
 
 target triple = "x86_64-unknown-linux-gnu"
 
 define i32 @switch_of_powers_two(i32 %arg) {
-; CHECK-LABEL: define i32 @switch_of_powers_two(
-; CHECK-SAME: i32 [[ARG:%.*]]) {
-; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[TMP0:%.*]] = call i32 @llvm.cttz.i32(i32 [[ARG]], i1 true)
-; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [7 x i32], ptr @switch.table.switch_of_powers_two, i32 0, i32 [[TMP0]]
-; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
-; CHECK-NEXT:    ret i32 [[SWITCH_LOAD]]
+; NOFOLD-LABEL: define i32 @switch_of_powers_two(
+; NOFOLD-SAME: i32 [[ARG:%.*]]) {
+; NOFOLD-NEXT:  [[ENTRY:.*]]:
+; NOFOLD-NEXT:    switch i32 [[ARG]], label %[[DEFAULT_CASE:.*]] [
+; NOFOLD-NEXT:      i32 1, label %[[RETURN:.*]]
+; NOFOLD-NEXT:      i32 8, label %[[BB2:.*]]
+; NOFOLD-NEXT:      i32 16, label %[[BB3:.*]]
+; NOFOLD-NEXT:      i32 32, label %[[BB4:.*]]
+; NOFOLD-NEXT:      i32 64, label %[[BB5:.*]]
+; NOFOLD-NEXT:    ]
+; NOFOLD:       [[DEFAULT_CASE]]:
+; NOFOLD-NEXT:    unreachable
+; NOFOLD:       [[BB2]]:
+; NOFOLD-NEXT:    br label %[[RETURN]]
+; NOFOLD:       [[BB3]]:
+; NOFOLD-NEXT:    br label %[[RETURN]]
+; NOFOLD:       [[BB4]]:
+; NOFOLD-NEXT:    br label %[[RETURN]]
+; NOFOLD:       [[BB5]]:
+; NOFOLD-NEXT:    br label %[[RETURN]]
+; NOFOLD:       [[RETURN]]:
+; NOFOLD-NEXT:    [[PHI:%.*]] = phi i32 [ 2, %[[BB2]] ], [ 1, %[[BB3]] ], [ 0, %[[BB4]] ], [ 42, %[[BB5]] ], [ 3, %[[ENTRY]] ]
+; NOFOLD-NEXT:    ret i32 [[PHI]]
+;
+; SWITCH-TO-CTTZ-LABEL: define i32 @switch_of_powers_two(
+; SWITCH-TO-CTTZ-SAME: i32 [[ARG:%.*]]) {
+; SWITCH-TO-CTTZ-NEXT:  [[ENTRY:.*]]:
+; SWITCH-TO-CTTZ-NEXT:    [[TMP0:%.*]] = call i32 @llvm.cttz.i32(i32 [[ARG]], i1 true)
+; SWITCH-TO-CTTZ-NEXT:    switch i32 [[TMP0]], label %[[DEFAULT_CASE:.*]] [
+; SWITCH-TO-CTTZ-NEXT:      i32 0, label %[[RETURN:.*]]
+; SWITCH-TO-CTTZ-NEXT:      i32 3, label %[[BB2:.*]]
+; SWITCH-TO-CTTZ-NEXT:      i32 4, label %[[BB3:.*]]
+; SWITCH-TO-CTTZ-NEXT:      i32 5, label %[[BB4:.*]]
+; SWITCH-TO-CTTZ-NEXT:      i32 6, label %[[BB5:.*]]
+; SWITCH-TO-CTTZ-NEXT:    ]
+; SWITCH-TO-CTTZ:       [[DEFAULT_CASE]]:
+; SWITCH-TO-CTTZ-NEXT:    unreachable
+; SWITCH-TO-CTTZ:       [[BB2]]:
+; SWITCH-TO-CTTZ-NEXT:    br label %[[RETURN]]
+; SWITCH-TO-CTTZ:       [[BB3]]:
+; SWITCH-TO-CTTZ-NEXT:    br label %[[RETURN]]
+; SWITCH-TO-CTTZ:       [[BB4]]:
+; SWITCH-TO-CTTZ-NEXT:    br label %[[RETURN]]
+; SWITCH-TO-CTTZ:       [[BB5]]:
+; SWITCH-TO-CTTZ-NEXT:    br label %[[RETURN]]
+; SWITCH-TO-CTTZ:       [[RETURN]]:
+; SWITCH-TO-CTTZ-NEXT:    [[PHI:%.*]] = phi i32 [ 2, %[[BB2]] ], [ 1, %[[BB3]] ], [ 0, %[[BB4]] ], [ 42, %[[BB5]] ], [ 3, %[[ENTRY]] ]
+; SWITCH-TO-CTTZ-NEXT:    ret i32 [[PHI]]
+;
+; SWITCH-TO-CTTZ-AND-TO-LOOKUP-LABEL: define i32 @switch_of_powers_two(
+; SWITCH-TO-CTTZ-AND-TO-LOOKUP-SAME: i32 [[ARG:%.*]]) {
+; SWITCH-TO-CTTZ-AND-TO-LOOKUP-NEXT:  [[ENTRY:.*:]]
+; SWITCH-TO-CTTZ-AND-TO-LOOKUP-NEXT:    [[TMP0:%.*]] = call i32 @llvm.cttz.i32(i32 [[ARG]], i1 true)
+; SWITCH-TO-CTTZ-AND-TO-LOOKUP-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [7 x i32], ptr @switch.table.switch_of_powers_two, i32 0, i32 [[TMP0]]
+; SWITCH-TO-CTTZ-AND-TO-LOOKUP-NEXT:    [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
+; SWITCH-TO-CTTZ-AND-TO-LOOKUP-NEXT:    ret i32 [[SWITCH_LOAD]]
 ;
 entry:
   switch i32 %arg, label %default_case [

``````````

</details>


https://github.com/llvm/llvm-project/pull/145477


More information about the llvm-commits mailing list