[llvm] 1362dfe - [SimplifyCFG] add nsw on SwitchToLookupTable index calculation on MinCaseVal subtraction
via llvm-commits
llvm-commits at lists.llvm.org
Tue May 23 02:02:40 PDT 2023
Author: khei4
Date: 2023-05-23T18:02:31+09:00
New Revision: 1362dfe16583607e39ac88e2a4de0f356c407cc7
URL: https://github.com/llvm/llvm-project/commit/1362dfe16583607e39ac88e2a4de0f356c407cc7
DIFF: https://github.com/llvm/llvm-project/commit/1362dfe16583607e39ac88e2a4de0f356c407cc7.diff
LOG: [SimplifyCFG] add nsw on SwitchToLookupTable index calculation on MinCaseVal subtraction
Differential Revision: https://reviews.llvm.org/D146903
Reviewed By: nikic
Added:
Modified:
llvm/lib/Transforms/Utils/SimplifyCFG.cpp
llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 6e58dc653bf46..0c481b4367c40 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -6473,6 +6473,21 @@ static bool SwitchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
std::vector<DominatorTree::UpdateType> Updates;
+ // Compute the maximum table size representable by the integer type we are
+ // switching upon.
+ unsigned CaseSize = MinCaseVal->getType()->getPrimitiveSizeInBits();
+ uint64_t MaxTableSize = CaseSize > 63 ? UINT64_MAX : 1ULL << CaseSize;
+ assert(MaxTableSize >= TableSize &&
+ "It is impossible for a switch to have more entries than the max "
+ "representable value of its input integer type's size.");
+
+ // If the default destination is unreachable, or if the lookup table covers
+ // all values of the conditional variable, branch directly to the lookup table
+ // BB. Otherwise, check that the condition is within the case range.
+ const bool DefaultIsReachable =
+ !isa<UnreachableInst>(SI->getDefaultDest()->getFirstNonPHIOrDbg());
+ const bool GeneratingCoveredLookupTable = (MaxTableSize == TableSize);
+
// Create the BB that does the lookups.
Module &Mod = *CommonDest->getParent()->getParent();
BasicBlock *LookupBB = BasicBlock::Create(
@@ -6487,24 +6502,17 @@ static bool SwitchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
TableIndex = SI->getCondition();
} else {
TableIndexOffset = MinCaseVal;
- TableIndex =
- Builder.CreateSub(SI->getCondition(), TableIndexOffset, "switch.tableidx");
- }
+ // If the default is unreachable, all case values are s>= MinCaseVal. Then
+ // we can try to attach nsw.
+ bool MayWrap = true;
+ if (!DefaultIsReachable)
+ MaxCaseVal->getValue().ssub_ov(MinCaseVal->getValue(), MayWrap);
- // Compute the maximum table size representable by the integer type we are
- // switching upon.
- unsigned CaseSize = MinCaseVal->getType()->getPrimitiveSizeInBits();
- uint64_t MaxTableSize = CaseSize > 63 ? UINT64_MAX : 1ULL << CaseSize;
- assert(MaxTableSize >= TableSize &&
- "It is impossible for a switch to have more entries than the max "
- "representable value of its input integer type's size.");
+ TableIndex = Builder.CreateSub(SI->getCondition(), TableIndexOffset,
+ "switch.tableidx", /*HasNUW =*/false,
+ /*HasNSW =*/!MayWrap);
+ }
- // If the default destination is unreachable, or if the lookup table covers
- // all values of the conditional variable, branch directly to the lookup table
- // BB. Otherwise, check that the condition is within the case range.
- const bool DefaultIsReachable =
- !isa<UnreachableInst>(SI->getDefaultDest()->getFirstNonPHIOrDbg());
- const bool GeneratingCoveredLookupTable = (MaxTableSize == TableSize);
BranchInst *RangeCheckBranch = nullptr;
if (!DefaultIsReachable || GeneratingCoveredLookupTable) {
diff --git a/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll b/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll
index 0ae2e00418005..72db2cc4f8db9 100644
--- a/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll
+++ b/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll
@@ -1807,3 +1807,127 @@ bb6: ; preds = %start, %bb3, %bb4,
%.sroa.0.0 = phi i32 [ 2222, %bb5 ], [ 1111, %bb4 ], [ 4444, %bb3 ], [ 3333, %start ]
ret i32 %.sroa.0.0
}
+
+; can attach nsw because of default's unreachability and case value type size
+; is big enough to hold max signed value.
+define i32 @nsw_on_index_sub(i8 %n) {
+; CHECK-LABEL: @nsw_on_index_sub(
+; CHECK-NEXT: start:
+; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[N:%.*]] to i3
+; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub nsw i3 [[TRUNC]], -2
+; CHECK-NEXT: [[SWITCH_IDX_CAST:%.*]] = zext i3 [[SWITCH_TABLEIDX]] to i32
+; CHECK-NEXT: [[SWITCH_IDX_MULT:%.*]] = mul i32 [[SWITCH_IDX_CAST]], 1111
+; CHECK-NEXT: [[SWITCH_OFFSET:%.*]] = add i32 [[SWITCH_IDX_MULT]], 1111
+; CHECK-NEXT: ret i32 [[SWITCH_OFFSET]]
+;
+start:
+ %trunc = trunc i8 %n to i3
+ ; we can hold max(cases) - min(cases) = 0b001 - 0b110 = 0b011
+ switch i3 %trunc, label %bb1 [
+ i3 0, label %bb6 ; 0b000
+ i3 1, label %bb3 ; 0b001
+ i3 -2, label %bb4; 0b110
+ i3 -1, label %bb5; 0b111
+ ]
+
+bb1: ; preds = %start
+ unreachable
+
+bb3: ; preds = %start
+ br label %bb6
+
+bb4: ; preds = %start
+ br label %bb6
+
+bb5: ; preds = %start
+ br label %bb6
+
+bb6: ; preds = %start, %bb3, %bb4, %bb5
+ %.sroa.0.0 = phi i32 [ 2222, %bb5 ], [ 1111, %bb4 ], [ 4444, %bb3 ], [ 3333, %start ]
+ ret i32 %.sroa.0.0
+}
+
+; cannot attach nsw on tableidx subtraction
+; because maximum index is greater than INT3_MAX = 3
+define i32 @wrapped_on_index_sub(i8 %n) {
+; CHECK-LABEL: @wrapped_on_index_sub(
+; CHECK-NEXT: start:
+; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[N:%.*]] to i3
+; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i3 [[TRUNC]], -2
+; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i3 [[SWITCH_TABLEIDX]], -3
+; CHECK-NEXT: [[SWITCH_IDX_CAST:%.*]] = zext i3 [[SWITCH_TABLEIDX]] to i32
+; CHECK-NEXT: [[SWITCH_IDX_MULT:%.*]] = mul i32 [[SWITCH_IDX_CAST]], 1111
+; CHECK-NEXT: [[SWITCH_OFFSET:%.*]] = add i32 [[SWITCH_IDX_MULT]], 1111
+; CHECK-NEXT: [[DOTSROA_0_0:%.*]] = select i1 [[TMP0]], i32 [[SWITCH_OFFSET]], i32 0
+; CHECK-NEXT: ret i32 [[DOTSROA_0_0]]
+;
+start:
+ %trunc = trunc i8 %n to i3
+ switch i3 %trunc, label %bb1 [
+ i3 0, label %bb6
+ i3 1, label %bb3
+ i3 2, label %bb7
+ i3 -2, label %bb4
+ i3 -1, label %bb5
+ ]
+
+bb1: ; preds = %start
+ br label %bb6
+
+bb3: ; preds = %start
+ br label %bb6
+
+bb4: ; preds = %start
+ br label %bb6
+
+bb5: ; preds = %start
+ br label %bb6
+
+bb7: ; preds = %start
+ br label %bb6
+
+bb6: ; preds = %start, %bb3, %bb4, %bb5
+ %.sroa.0.0 = phi i32 [ 0, %bb1 ], [ 2222, %bb5 ], [ 1111, %bb4 ], [ 5555, %bb7 ], [ 4444, %bb3 ], [ 3333, %start ]
+ ret i32 %.sroa.0.0
+}
+
+
+; cannot attach nsw on tableidx subtraction
+; because default reachability shows overflow could happen.
+define i32 @wrapped_on_index_sub_default(i8 %n) {
+; CHECK-LABEL: @wrapped_on_index_sub_default(
+; CHECK-NEXT: start:
+; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[N:%.*]] to i3
+; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i3 [[TRUNC]], -2
+; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i3 [[SWITCH_TABLEIDX]], -4
+; CHECK-NEXT: [[SWITCH_IDX_CAST:%.*]] = zext i3 [[SWITCH_TABLEIDX]] to i32
+; CHECK-NEXT: [[SWITCH_IDX_MULT:%.*]] = mul i32 [[SWITCH_IDX_CAST]], 1111
+; CHECK-NEXT: [[SWITCH_OFFSET:%.*]] = add i32 [[SWITCH_IDX_MULT]], 1111
+; CHECK-NEXT: [[DOTSROA_0_0:%.*]] = select i1 [[TMP0]], i32 [[SWITCH_OFFSET]], i32 0
+; CHECK-NEXT: ret i32 [[DOTSROA_0_0]]
+;
+start:
+ %trunc = trunc i8 %n to i3
+ switch i3 %trunc, label %bb1 [
+ i3 0, label %bb6
+ i3 1, label %bb3
+ i3 -2, label %bb4
+ i3 -1, label %bb5
+ ]
+
+bb1: ; preds = %start
+ br label %bb6
+
+bb3: ; preds = %start
+ br label %bb6
+
+bb4: ; preds = %start
+ br label %bb6
+
+bb5: ; preds = %start
+ br label %bb6
+
+bb6: ; preds = %start, %bb3, %bb4, %bb5
+ %.sroa.0.0 = phi i32 [ 0, %bb1 ], [ 2222, %bb5 ], [ 1111, %bb4 ], [ 4444, %bb3 ], [ 3333, %start ]
+ ret i32 %.sroa.0.0
+}
More information about the llvm-commits
mailing list