[llvm] f7f7574 - [InstCombine] Canonicalize `switch(C-X)` to `switch(X)` (#77051)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 5 05:03:29 PST 2024
Author: Yingwei Zheng
Date: 2024-01-05T21:03:24+08:00
New Revision: f7f7574afe4cfc11ebe5d8cb811d5cd28dc862f6
URL: https://github.com/llvm/llvm-project/commit/f7f7574afe4cfc11ebe5d8cb811d5cd28dc862f6
DIFF: https://github.com/llvm/llvm-project/commit/f7f7574afe4cfc11ebe5d8cb811d5cd28dc862f6.diff
LOG: [InstCombine] Canonicalize `switch(C-X)` to `switch(X)` (#77051)
This patch canonicalizes `switch(C-X)` to `switch(X)`.
Compile-time impact:
http://llvm-compile-time-tracker.com/compare.php?from=7954c57124b495fbdc73674d71f2e366e4afe522&to=31a9adff1e633f0f3c423fb8487fc15d17e171f2&stat=instructions:u
|stage1-O3|stage1-ReleaseThinLTO|stage1-ReleaseLTO-g|stage1-O0-g|stage2-O3|stage2-O0-g|stage2-clang|
|--|--|--|--|--|--|--|
|-0.01%|+0.02%|+0.02%|+0.05%|-0.07%|-0.02%|-0.02%|
Added:
llvm/test/Transforms/InstCombine/switch-sub.ll
Modified:
llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index f3181dc14792c8..b45c6784b85b6f 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -3208,6 +3208,18 @@ Instruction *InstCombinerImpl::visitSwitchInst(SwitchInst &SI) {
return replaceOperand(SI, 0, Op0);
}
+ ConstantInt *SubLHS;
+ if (match(Cond, m_Sub(m_ConstantInt(SubLHS), m_Value(Op0)))) {
+ // Change 'switch (1-X) case 1:' into 'switch (X) case 0'.
+ for (auto Case : SI.cases()) {
+ Constant *NewCase = ConstantExpr::getSub(SubLHS, Case.getCaseValue());
+ assert(isa<ConstantInt>(NewCase) &&
+ "Result of expression should be constant");
+ Case.setValue(cast<ConstantInt>(NewCase));
+ }
+ return replaceOperand(SI, 0, Op0);
+ }
+
KnownBits Known = computeKnownBits(Cond, 0, &SI);
unsigned LeadingKnownZeros = Known.countMinLeadingZeros();
unsigned LeadingKnownOnes = Known.countMinLeadingOnes();
diff --git a/llvm/test/Transforms/InstCombine/switch-sub.ll b/llvm/test/Transforms/InstCombine/switch-sub.ll
new file mode 100644
index 00000000000000..3fedfddeb7c0fe
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/switch-sub.ll
@@ -0,0 +1,89 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+define i1 @test_switch_with_neg(i32 %a) {
+; CHECK-LABEL: define i1 @test_switch_with_neg(
+; CHECK-SAME: i32 [[A:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: switch i32 [[A]], label [[SW_DEFAULT:%.*]] [
+; CHECK-NEXT: i32 -37, label [[SW_BB:%.*]]
+; CHECK-NEXT: i32 -38, label [[SW_BB]]
+; CHECK-NEXT: i32 -39, label [[SW_BB]]
+; CHECK-NEXT: ]
+; CHECK: sw.bb:
+; CHECK-NEXT: ret i1 true
+; CHECK: sw.default:
+; CHECK-NEXT: ret i1 false
+;
+entry:
+ %a.neg = sub i32 0, %a
+ switch i32 %a.neg, label %sw.default [
+ i32 37, label %sw.bb
+ i32 38, label %sw.bb
+ i32 39, label %sw.bb
+ ]
+
+sw.bb:
+ ret i1 true
+sw.default:
+ ret i1 false
+}
+
+define i1 @test_switch_with_sub(i32 %a) {
+; CHECK-LABEL: define i1 @test_switch_with_sub(
+; CHECK-SAME: i32 [[A:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: switch i32 [[A]], label [[SW_DEFAULT:%.*]] [
+; CHECK-NEXT: i32 0, label [[SW_BB:%.*]]
+; CHECK-NEXT: i32 -1, label [[SW_BB]]
+; CHECK-NEXT: i32 -2, label [[SW_BB]]
+; CHECK-NEXT: ]
+; CHECK: sw.bb:
+; CHECK-NEXT: ret i1 true
+; CHECK: sw.default:
+; CHECK-NEXT: ret i1 false
+;
+entry:
+ %a.neg = sub i32 37, %a
+ switch i32 %a.neg, label %sw.default [
+ i32 37, label %sw.bb
+ i32 38, label %sw.bb
+ i32 39, label %sw.bb
+ ]
+
+sw.bb:
+ ret i1 true
+sw.default:
+ ret i1 false
+}
+
+; Negative tests
+
+define i1 @test_switch_with_sub_nonconst(i32 %a, i32 %b) {
+; CHECK-LABEL: define i1 @test_switch_with_sub_nonconst(
+; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[A_NEG:%.*]] = sub i32 [[B]], [[A]]
+; CHECK-NEXT: switch i32 [[A_NEG]], label [[SW_DEFAULT:%.*]] [
+; CHECK-NEXT: i32 37, label [[SW_BB:%.*]]
+; CHECK-NEXT: i32 38, label [[SW_BB]]
+; CHECK-NEXT: i32 39, label [[SW_BB]]
+; CHECK-NEXT: ]
+; CHECK: sw.bb:
+; CHECK-NEXT: ret i1 true
+; CHECK: sw.default:
+; CHECK-NEXT: ret i1 false
+;
+entry:
+ %a.neg = sub i32 %b, %a
+ switch i32 %a.neg, label %sw.default [
+ i32 37, label %sw.bb
+ i32 38, label %sw.bb
+ i32 39, label %sw.bb
+ ]
+
+sw.bb:
+ ret i1 true
+sw.default:
+ ret i1 false
+}
More information about the llvm-commits
mailing list