From: Bruno Cardoso Lopes Date: Fri, 19 Dec 2014 17:12:35 +0000 (+0000) Subject: Reapply: [InstCombine] Fix visitSwitchInst to use right operand types for sub cstexpr X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=06833ca7c15feac86e32d1bc2f88bfbe22410f27 Reapply: [InstCombine] Fix visitSwitchInst to use right operand types for sub cstexpr The visitSwitchInst generates SUB constant expressions to recompute the switch condition. When truncating the condition to a smaller type, SUB expressions should use the previous type (before trunc) for both operands. Also, fix code to also return the modified switch when only the truncation is performed. This fixes an assertion crash. Differential Revision: http://reviews.llvm.org/D6644 rdar://problem/19191835 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@224588 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/InstCombine/InstructionCombining.cpp b/lib/Transforms/InstCombine/InstructionCombining.cpp index 5eee15f6489..898e5708ff1 100644 --- a/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -2095,8 +2095,10 @@ Instruction *InstCombiner::visitSwitchInst(SwitchInst &SI) { // the largest legal integer type. We need to be conservative here since // x86 generates redundant zero-extenstion instructions if the operand is // truncated to i8 or i16. + bool TruncCond = false; if (DL && BitWidth > NewWidth && NewWidth >= DL->getLargestLegalIntTypeSize()) { + TruncCond = true; IntegerType *Ty = IntegerType::get(SI.getContext(), NewWidth); Builder->SetInsertPoint(&SI); Value *NewCond = Builder->CreateTrunc(SI.getCondition(), Ty, "trunc"); @@ -2115,8 +2117,12 @@ Instruction *InstCombiner::visitSwitchInst(SwitchInst &SI) { for (SwitchInst::CaseIt i = SI.case_begin(), e = SI.case_end(); i != e; ++i) { ConstantInt* CaseVal = i.getCaseValue(); - Constant* NewCaseVal = ConstantExpr::getSub(cast(CaseVal), - AddRHS); + 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)); @@ -2126,7 +2132,8 @@ Instruction *InstCombiner::visitSwitchInst(SwitchInst &SI) { return &SI; } } - return nullptr; + + return TruncCond ? &SI : nullptr; } Instruction *InstCombiner::visitExtractValueInst(ExtractValueInst &EV) { diff --git a/test/Transforms/InstCombine/narrow-switch.ll b/test/Transforms/InstCombine/narrow-switch.ll index 7646189b854..f3f19bae03d 100644 --- a/test/Transforms/InstCombine/narrow-switch.ll +++ b/test/Transforms/InstCombine/narrow-switch.ll @@ -91,3 +91,33 @@ return: %retval.0 = phi i32 [ 24, %sw.default ], [ 123, %sw.bb2 ], [ 213, %sw.bb1 ], [ 231, %entry ] ret i32 %retval.0 } + +; Make sure to avoid assertion crashes and use the type before +; truncation to generate the sub constant expressions that leads +; to the recomputed condition. +; +; CHECK-LABEL: @trunc64to59 +; CHECK: switch i59 +; CHECK: i59 0, label +; CHECK: i59 18717182647723699, label + +define void @trunc64to59(i64 %a) { +entry: + %tmp0 = and i64 %a, 15 + %tmp1 = mul i64 %tmp0, -6425668444178048401 + %tmp2 = add i64 %tmp1, 5170979678563097242 + %tmp3 = mul i64 %tmp2, 1627972535142754813 + switch i64 %tmp3, label %sw.default [ + i64 847514119312061490, label %sw.bb1 + i64 866231301959785189, label %sw.bb2 + ] + +sw.bb1: + br label %sw.default + +sw.bb2: + br label %sw.default + +sw.default: + ret void +}