Index: lib/Transforms/InstCombine/InstructionCombining.cpp =================================================================== --- lib/Transforms/InstCombine/InstructionCombining.cpp +++ lib/Transforms/InstCombine/InstructionCombining.cpp @@ -2238,6 +2238,24 @@ unsigned LeadingKnownZeros = KnownZero.countLeadingOnes(); unsigned LeadingKnownOnes = KnownOne.countLeadingOnes(); + Value *Op0 = nullptr; + ConstantInt *AddRHS = nullptr; + if (match(Cond, m_Add(m_Value(Op0), m_ConstantInt(AddRHS)))) { + // Change 'switch (X+4) case 1:' into 'switch (X) case -3'. + for (SwitchInst::CaseIt i = SI.case_begin(), e = SI.case_end(); i != e; + ++i) { + ConstantInt *CaseVal = i.getCaseValue(); + Constant *LHS = CaseVal; + Constant *NewCaseVal = ConstantExpr::getSub(LHS, AddRHS); + assert(isa(NewCaseVal) && + "Result of expression should be constant"); + i.setValue(cast(NewCaseVal)); + } + SI.setCondition(Op0); + if (auto *CondI = dyn_cast(Cond)) + Worklist.Add(CondI); + } + // Compute the number of leading bits we can ignore. // TODO: A better way to determine this would use ComputeNumSignBits(). for (auto &C : SI.cases()) { @@ -2265,30 +2283,6 @@ SI.getContext(), C.getCaseValue()->getValue().trunc(NewWidth))); } - Value *Op0 = nullptr; - ConstantInt *AddRHS = nullptr; - if (match(Cond, m_Add(m_Value(Op0), m_ConstantInt(AddRHS)))) { - // Change 'switch (X+4) case 1:' into 'switch (X) case -3'. - for (SwitchInst::CaseIt i = SI.case_begin(), e = SI.case_end(); i != e; - ++i) { - ConstantInt *CaseVal = i.getCaseValue(); - Constant *LHS = CaseVal; - if (TruncCond) { - LHS = LeadingKnownZeros - ? ConstantExpr::getZExt(CaseVal, Cond->getType()) - : ConstantExpr::getSExt(CaseVal, Cond->getType()); - } - Constant *NewCaseVal = ConstantExpr::getSub(LHS, AddRHS); - assert(isa(NewCaseVal) && - "Result of expression should be constant"); - i.setValue(cast(NewCaseVal)); - } - SI.setCondition(Op0); - if (auto *CondI = dyn_cast(Cond)) - Worklist.Add(CondI); - return &SI; - } - return TruncCond ? &SI : nullptr; } Index: test/Transforms/InstCombine/narrow-switch.ll =================================================================== --- test/Transforms/InstCombine/narrow-switch.ll +++ test/Transforms/InstCombine/narrow-switch.ll @@ -105,9 +105,9 @@ define void @trunc64to59(i64 %a) { ; ALL-LABEL: @trunc64to59( -; ALL: switch i59 -; ALL-NEXT: i59 0, label %sw.bb1 -; ALL-NEXT: i59 18717182647723699, label %sw.bb2 +; ALL: switch i61 +; ALL-NEXT: i61 0, label %sw.bb1 +; ALL-NEXT: i61 18717182647723699, label %sw.bb2 ; ALL-NEXT: ] ; entry: @@ -129,3 +129,46 @@ sw.default: ret void } + +; Make sure the arithmetic evaluation of the switch +; condition is evaluated on the original type +define i32 @trunc32to16(i32 %a0) #0 { +; ALL-LABEL: @trunc32to16( +; ALL: switch i16 +; ALL-NEXT: i16 63, label %sw.bb +; ALL-NEXT: i16 1, label %sw.bb1 +; ALL-NEXT: i16 100, label %sw.bb2 +; ALL-NEXT: ] +; +entry: + %retval = alloca i32, align 4 + %xor = xor i32 %a0, 1034460917 + %shr = lshr i32 %xor, 16 + %add = add i32 %shr, -917677090 + switch i32 %add, label %sw.epilog [ + i32 -917677027, label %sw.bb + i32 -917677089, label %sw.bb1 + i32 -917676990, label %sw.bb2 + ] + +sw.bb: ; preds = %entry + store i32 90, i32* %retval, align 4 + br label %return + +sw.bb1: ; preds = %entry + store i32 91, i32* %retval, align 4 + br label %return + +sw.bb2: ; preds = %entry + store i32 92, i32* %retval, align 4 + br label %return + +sw.epilog: ; preds = %entry + store i32 113, i32* %retval, align 4 + br label %return + +return: ; preds = %sw.epilog, %sw.bb2, + %rval = load i32, i32* %retval, align 4 + ret i32 %rval +} +