From: Sanjay Patel Date: Thu, 9 Feb 2017 23:13:04 +0000 (+0000) Subject: [InstCombine] allow (X * C2) << C1 --> X * (C2 << C1) for vectors X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=49a435a455e49987ddb916470239f32ffaebf7df;p=llvm [InstCombine] allow (X * C2) << C1 --> X * (C2 << C1) for vectors This fold already existed for vectors but only when 'C1' was a splat constant (but 'C2' could be any constant). There were no tests for any vector constants, so I'm adding a test that shows non-splat constants for both operands. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@294650 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/InstCombine/InstCombineShifts.cpp b/lib/Transforms/InstCombine/InstCombineShifts.cpp index ab8ba9e4be0..9aa679c60e4 100644 --- a/lib/Transforms/InstCombine/InstCombineShifts.cpp +++ b/lib/Transforms/InstCombine/InstCombineShifts.cpp @@ -335,13 +335,6 @@ Instruction *InstCombiner::FoldShiftByConstant(Value *Op0, Constant *Op1, assert(!Op1C->uge(TypeBits) && "Shift over the type width should have been removed already"); - // ((X*C1) << C2) == (X * (C1 << C2)) - if (BinaryOperator *BO = dyn_cast(Op0)) - if (BO->getOpcode() == Instruction::Mul && isLeftShift) - if (Constant *BOOp = dyn_cast(BO->getOperand(1))) - return BinaryOperator::CreateMul(BO->getOperand(0), - ConstantExpr::getShl(BOOp, Op1)); - if (Instruction *FoldedShift = foldOpWithConstantIntoOperand(I)) return FoldedShift; @@ -604,12 +597,18 @@ Instruction *InstCombiner::visitShl(BinaryOperator &I) { } } - // (C1 << A) << C2 -> (C1 << C2) << A - Constant *C1, *C2; - Value *A; - if (match(Op0, m_OneUse(m_Shl(m_Constant(C1), m_Value(A)))) && - match(Op1, m_Constant(C2))) - return BinaryOperator::CreateShl(ConstantExpr::getShl(C1, C2), A); + Constant *C1; + if (match(Op1, m_Constant(C1))) { + Constant *C2; + Value *X; + // (C2 << X) << C1 --> (C2 << C1) << X + if (match(Op0, m_OneUse(m_Shl(m_Constant(C2), m_Value(X))))) + return BinaryOperator::CreateShl(ConstantExpr::getShl(C2, C1), X); + + // (X * C2) << C1 --> X * (C2 << C1) + if (match(Op0, m_Mul(m_Value(X), m_Constant(C2)))) + return BinaryOperator::CreateMul(X, ConstantExpr::getShl(C2, C1)); + } return nullptr; } diff --git a/test/Transforms/InstCombine/apint-shift.ll b/test/Transforms/InstCombine/apint-shift.ll index 7feec91d0c0..f339de35d77 100644 --- a/test/Transforms/InstCombine/apint-shift.ll +++ b/test/Transforms/InstCombine/apint-shift.ll @@ -63,6 +63,8 @@ define i55 @test6(i55 %A) { ret i55 %C } +; (X * C2) << C1 --> X * (C2 << C1) + define i55 @test6a(i55 %A) { ; CHECK-LABEL: @test6a( ; CHECK-NEXT: [[C:%.*]] = mul i55 %A, 6 @@ -73,6 +75,18 @@ define i55 @test6a(i55 %A) { ret i55 %C } +; (X * C2) << C1 --> X * (C2 << C1) + +define <2 x i55> @test6a_vec(<2 x i55> %A) { +; CHECK-LABEL: @test6a_vec( +; CHECK-NEXT: [[C:%.*]] = mul <2 x i55> %A, +; CHECK-NEXT: ret <2 x i55> [[C]] +; + %B = mul <2 x i55> %A, + %C = shl <2 x i55> %B, + ret <2 x i55> %C +} + define i29 @test7(i8 %X) { ; CHECK-LABEL: @test7( ; CHECK-NEXT: ret i29 -1