Index: llvm/lib/Transforms/Utils/SimplifyCFG.cpp =================================================================== --- llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -5942,7 +5942,7 @@ /// Build instructions with Builder to retrieve the value at /// the position given by Index in the lookup table. - Value *BuildLookup(Value *Index, IRBuilder<> &Builder); + Value *BuildLookup(Value *Index, IRBuilder<> &Builder, bool DefaultIsReachable); /// Return true if a table with TableSize elements of /// type ElementType would fit in a target-legal register. @@ -6106,7 +6106,8 @@ Kind = ArrayKind; } -Value *SwitchLookupTable::BuildLookup(Value *Index, IRBuilder<> &Builder) { +Value *SwitchLookupTable::BuildLookup(Value *Index, IRBuilder<> &Builder, + bool DefaultIsReachable) { switch (Kind) { case SingleValueKind: return SingleValue; @@ -6115,9 +6116,15 @@ Value *Result = Builder.CreateIntCast(Index, LinearMultiplier->getType(), false, "switch.idx.cast"); if (!LinearMultiplier->isOne()) - Result = Builder.CreateMul(Result, LinearMultiplier, "switch.idx.mult"); + Result = Builder.CreateMul(Result, LinearMultiplier, "switch.idx.mult", + /*HasNUW =*/false, + /*HasNSW =*/!DefaultIsReachable); + if (!LinearOffset->isZero()) - Result = Builder.CreateAdd(Result, LinearOffset, "switch.offset"); + Result = Builder.CreateAdd(Result, LinearOffset, "switch.offset", + /*HasNUW =*/false, + /*HasNSW =*/!DefaultIsReachable); + return Result; } case BitMapKind: { @@ -6132,7 +6139,9 @@ // Multiply the shift amount by the element width. ShiftAmt = Builder.CreateMul( ShiftAmt, ConstantInt::get(MapTy, BitMapElementTy->getBitWidth()), - "switch.shiftamt"); + "switch.shiftamt", + /*HasNUW =*/false, + /*HasNSW =*/!DefaultIsReachable); // Shift down. Value *DownShifted = @@ -6471,6 +6480,21 @@ std::vector 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(SI->getDefaultDest()->getFirstNonPHIOrDbg()); + const bool GeneratingCoveredLookupTable = (MaxTableSize == TableSize); + // Create the BB that does the lookups. Module &Mod = *CommonDest->getParent()->getParent(); BasicBlock *LookupBB = BasicBlock::Create( @@ -6485,24 +6509,11 @@ TableIndex = SI->getCondition(); } else { TableIndexOffset = MinCaseVal; - TableIndex = - Builder.CreateSub(SI->getCondition(), TableIndexOffset, "switch.tableidx"); + TableIndex = Builder.CreateSub(SI->getCondition(), TableIndexOffset, + "switch.tableidx", /*HasNUW =*/false, + /*HasNSW =*/!DefaultIsReachable); } - // 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(SI->getDefaultDest()->getFirstNonPHIOrDbg()); - const bool GeneratingCoveredLookupTable = (MaxTableSize == TableSize); BranchInst *RangeCheckBranch = nullptr; if (!DefaultIsReachable || GeneratingCoveredLookupTable) { @@ -6581,7 +6592,7 @@ SwitchLookupTable Table(Mod, TableSize, TableIndexOffset, ResultList, DV, DL, FuncName); - Value *Result = Table.BuildLookup(TableIndex, Builder); + Value *Result = Table.BuildLookup(TableIndex, Builder, DefaultIsReachable); // Do a small peephole optimization: re-use the switch table compare if // possible. Index: llvm/test/Transforms/SimplifyCFG/X86/switch-table-bug.ll =================================================================== --- llvm/test/Transforms/SimplifyCFG/X86/switch-table-bug.ll +++ llvm/test/Transforms/SimplifyCFG/X86/switch-table-bug.ll @@ -9,7 +9,7 @@ define i64 @_TFO6reduce1E5toRawfS0_FT_Si(i2) { ; CHECK-LABEL: @_TFO6reduce1E5toRawfS0_FT_Si( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i2 [[TMP0:%.*]], -2 +; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub nsw i2 [[TMP0:%.*]], -2 ; CHECK-NEXT: [[SWITCH_TABLEIDX_ZEXT:%.*]] = zext i2 [[SWITCH_TABLEIDX]] to i3 ; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i64], ptr @switch.table._TFO6reduce1E5toRawfS0_FT_Si, i32 0, i3 [[SWITCH_TABLEIDX_ZEXT]] ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i64, ptr [[SWITCH_GEP]], align 8 Index: llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll =================================================================== --- llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll +++ llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll @@ -1696,7 +1696,7 @@ ; CHECK-LABEL: @signed_overflow1( ; CHECK-NEXT: start: ; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[N:%.*]] to i2 -; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i2 [[TRUNC]], -2 +; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub nsw i2 [[TRUNC]], -2 ; CHECK-NEXT: [[SWITCH_TABLEIDX_ZEXT:%.*]] = zext i2 [[SWITCH_TABLEIDX]] to i3 ; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i32], ptr @switch.table.signed_overflow1, i32 0, i3 [[SWITCH_TABLEIDX_ZEXT]] ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4 @@ -1776,10 +1776,10 @@ ; CHECK-LABEL: @signed_overflow_negative( ; CHECK-NEXT: start: ; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[N:%.*]] to i2 -; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i2 [[TRUNC]], -2 +; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub nsw i2 [[TRUNC]], -2 ; CHECK-NEXT: [[SWITCH_IDX_CAST:%.*]] = zext i2 [[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: [[SWITCH_IDX_MULT:%.*]] = mul nsw i32 [[SWITCH_IDX_CAST]], 1111 +; CHECK-NEXT: [[SWITCH_OFFSET:%.*]] = add nsw i32 [[SWITCH_IDX_MULT]], 1111 ; CHECK-NEXT: ret i32 [[SWITCH_OFFSET]] ; start: