Index: llvm/lib/Transforms/Utils/SimplifyCFG.cpp =================================================================== --- llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -6389,14 +6389,71 @@ DefaultResults[PHI] = Result; } - bool UseSwitchConditionAsTableIndex = ShouldUseSwitchConditionAsTableIndex( - *MinCaseVal, *MaxCaseVal, HasDefaultResults, ResultTypes, DL, TTI); - uint64_t TableSize; - if (UseSwitchConditionAsTableIndex) - TableSize = MaxCaseVal->getLimitedValue() + 1; - else - TableSize = - (MaxCaseVal->getValue() - MinCaseVal->getValue()).getLimitedValue() + 1; + auto GetTableSize = [&](ConstantInt *MinCaseConst, ConstantInt *MaxCaseConst, + bool &UseSwitchConditionAsTableIndex) -> unsigned { + UseSwitchConditionAsTableIndex = ShouldUseSwitchConditionAsTableIndex( + *MinCaseConst, *MaxCaseConst, HasDefaultResults, ResultTypes, DL, TTI); + uint64_t TableSize; + if (UseSwitchConditionAsTableIndex) + TableSize = MaxCaseConst->getLimitedValue() + 1; + else + TableSize = (MaxCaseConst->getValue() - MinCaseConst->getValue()) + .getLimitedValue() + + 1; + return TableSize; + }; + + bool UseSwitchConditionAsTableIndex; + uint64_t TableSize = + GetTableSize(MinCaseVal, MaxCaseVal, UseSwitchConditionAsTableIndex); + + // 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()); + bool GeneratingCoveredLookupTable = MaxTableSize == TableSize; + bool NeedntCheckRange = !DefaultIsReachable || GeneratingCoveredLookupTable; + + if (MinCaseVal->isMinValue(true) && MaxCaseVal->isMaxValue(true)) { + // try unsigned if the case value is signed overflow + ConstantInt *UnsignedMinCaseVal = MinCaseVal; + ConstantInt *UnsignedMaxCaseVal = MaxCaseVal; + for (auto Case : SI->cases()) { + ConstantInt *CaseVal = Case.getCaseValue(); + if (CaseVal->getValue().ult(UnsignedMinCaseVal->getValue())) + UnsignedMinCaseVal = CaseVal; + if (CaseVal->getValue().ugt(UnsignedMaxCaseVal->getValue())) + UnsignedMaxCaseVal = CaseVal; + } + + bool UnsignedUseSwitchConditionAsTableIndex; + uint64_t UnsignedTableSize = + GetTableSize(UnsignedMinCaseVal, UnsignedMaxCaseVal, + UnsignedUseSwitchConditionAsTableIndex); + + bool UnsignedGeneratingCoveredLookupTable = + MaxTableSize == UnsignedTableSize; + bool UnsignedNeedntCheckRange = + !DefaultIsReachable || UnsignedGeneratingCoveredLookupTable; + // For the case signed overflow, signed table always needn't check range. + // If the unsigned table need check range it will cause extra overhead. + if (UnsignedNeedntCheckRange) { + TableSize = UnsignedTableSize; + MinCaseVal = UnsignedMinCaseVal; + MaxCaseVal = UnsignedMaxCaseVal; + NeedntCheckRange = UnsignedNeedntCheckRange; + GeneratingCoveredLookupTable = UnsignedGeneratingCoveredLookupTable; + } + } bool TableHasHoles = (NumResults < TableSize); bool NeedMask = (TableHasHoles && !HasDefaultResults); @@ -6431,23 +6488,9 @@ Builder.CreateSub(SI->getCondition(), TableIndexOffset, "switch.tableidx"); } - // 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) { + if (NeedntCheckRange) { Builder.CreateBr(LookupBB); if (DTU) Updates.push_back({DominatorTree::Insert, BB, LookupBB}); @@ -6505,7 +6548,7 @@ AddPredecessorToBlock(SI->getDefaultDest(), MaskBB, BB); } - if (!DefaultIsReachable || GeneratingCoveredLookupTable) { + if (NeedntCheckRange) { // We cached PHINodes in PHIs. To avoid accessing deleted PHINodes later, // do not delete PHINodes here. SI->getDefaultDest()->removePredecessor(BB, 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,11 +9,9 @@ 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_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 -; CHECK-NEXT: ret i64 [[SWITCH_LOAD]] +; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i2 [[TMP0:%.*]], 0 +; CHECK-NEXT: [[SWITCH_IDX_CAST:%.*]] = zext i2 [[SWITCH_TABLEIDX]] to i64 +; CHECK-NEXT: ret i64 [[SWITCH_IDX_CAST]] ; entry: switch i2 %0, label %1 [ 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,11 +1696,11 @@ ; 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_ZEXT:%.*]] = zext i2 [[SWITCH_TABLEIDX]] to i3 -; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i32], [4 x i32]* @switch.table.signed_overflow1, i32 0, i3 [[SWITCH_TABLEIDX_ZEXT]] -; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, i32* [[SWITCH_GEP]], align 4 -; CHECK-NEXT: ret i32 [[SWITCH_LOAD]] +; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i2 [[TRUNC]], 0 +; 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: ret i32 [[SWITCH_OFFSET]] ; start: %trunc = trunc i8 %n to i2 @@ -1732,20 +1732,11 @@ ; CHECK-LABEL: @signed_overflow2( ; CHECK-NEXT: start: ; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[N:%.*]] to i2 -; CHECK-NEXT: switch i2 [[TRUNC]], label [[BB1:%.*]] [ -; CHECK-NEXT: i2 1, label [[BB6:%.*]] -; CHECK-NEXT: i2 -2, label [[BB4:%.*]] -; CHECK-NEXT: i2 -1, label [[BB5:%.*]] -; CHECK-NEXT: ] -; CHECK: bb1: -; CHECK-NEXT: unreachable -; CHECK: bb4: -; CHECK-NEXT: br label [[BB6]] -; CHECK: bb5: -; CHECK-NEXT: br label [[BB6]] -; CHECK: bb6: -; CHECK-NEXT: [[DOTSROA_0_0:%.*]] = phi i32 [ 4444, [[BB5]] ], [ 3333, [[BB4]] ], [ 2222, [[START:%.*]] ] -; CHECK-NEXT: ret i32 [[DOTSROA_0_0]] +; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i2 [[TRUNC]], 1 +; 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]], 2222 +; CHECK-NEXT: ret i32 [[SWITCH_OFFSET]] ; start: %trunc = trunc i8 %n to i2 @@ -1776,11 +1767,11 @@ ; 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_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: ret i32 [[SWITCH_OFFSET]] +; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i2 [[TRUNC]], 0 +; CHECK-NEXT: [[SWITCH_TABLEIDX_ZEXT:%.*]] = zext i2 [[SWITCH_TABLEIDX]] to i3 +; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i32], [4 x i32]* @switch.table.signed_overflow_negative, i32 0, i3 [[SWITCH_TABLEIDX_ZEXT]] +; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, i32* [[SWITCH_GEP]], align 4 +; CHECK-NEXT: ret i32 [[SWITCH_LOAD]] ; start: %trunc = trunc i8 %n to i2