diff --git a/lib/Transforms/InstCombine/InstCombineCasts.cpp b/lib/Transforms/InstCombine/InstCombineCasts.cpp index 88ee1453faf..1ffcc2b1220 100644 --- a/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -462,8 +462,8 @@ Instruction *InstCombiner::visitTrunc(TruncInst &CI) { // Transform trunc(lshr (zext A), Cst) to eliminate one type conversion. Value *A = 0; ConstantInt *Cst = 0; - if (match(Src, m_LShr(m_ZExt(m_Value(A)), m_ConstantInt(Cst))) && - Src->hasOneUse()) { + if (Src->hasOneUse() && + match(Src, m_LShr(m_ZExt(m_Value(A)), m_ConstantInt(Cst)))) { // We have three types to worry about here, the type of A, the source of // the truncate (MidSize), and the destination of the truncate. We know that // ASize < MidSize and MidSize > ResultSize, but don't know the relation @@ -482,6 +482,16 @@ Instruction *InstCombiner::visitTrunc(TruncInst &CI) { Shift->takeName(Src); return CastInst::CreateIntegerCast(Shift, CI.getType(), false); } + + // Transform "trunc (and X, cst)" -> "and (trunc X), cst" so long as the dest + // type isn't non-native. + if (Src->hasOneUse() && isa(Src->getType()) && + ShouldChangeType(Src->getType(), CI.getType()) && + match(Src, m_And(m_Value(A), m_ConstantInt(Cst)))) { + Value *NewTrunc = Builder->CreateTrunc(A, CI.getType(), A->getName()+".tr"); + return BinaryOperator::CreateAnd(NewTrunc, + ConstantExpr::getTrunc(Cst, CI.getType())); + } return 0; } diff --git a/test/Transforms/InstCombine/trunc.ll b/test/Transforms/InstCombine/trunc.ll index f98bfd9236c..4d973418cf6 100644 --- a/test/Transforms/InstCombine/trunc.ll +++ b/test/Transforms/InstCombine/trunc.ll @@ -97,3 +97,23 @@ define i64 @test8(i32 %A, i32 %B) { ; CHECK: ret i64 %ins35 } +define i8 @test9(i32 %X) { + %Y = and i32 %X, 42 + %Z = trunc i32 %Y to i8 + ret i8 %Z +; CHECK: @test9 +; CHECK: trunc +; CHECK: and +; CHECK: ret +} + +; rdar://8808586 +define i8 @test10(i32 %X) { + %Y = trunc i32 %X to i8 + %Z = and i8 %Y, 42 + ret i8 %Z +; CHECK: @test10 +; CHECK: trunc +; CHECK: and +; CHECK: ret +}