diff --git a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp index 8d5dbf83b7ea3..b25c83a2a9626 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp @@ -702,10 +702,18 @@ static bool canShiftBinOpWithConstantRHS(BinaryOperator &Shift, } } -Instruction *InstCombinerImpl::FoldShiftByConstant(Value *Op0, Constant *Op1, +Instruction *InstCombinerImpl::FoldShiftByConstant(Value *Op0, Constant *C1, BinaryOperator &I) { + // (C2 << X) << C1 --> (C2 << C1) << X + // (C2 >> X) >> C1 --> (C2 >> C1) >> X + Constant *C2; + Value *X; + if (match(Op0, m_BinOp(I.getOpcode(), m_Constant(C2), m_Value(X)))) + return BinaryOperator::Create(I.getOpcode(), + ConstantExpr::get(I.getOpcode(), C2, C1), X); + const APInt *Op1C; - if (!match(Op1, m_APInt(Op1C))) + if (!match(C1, m_APInt(Op1C))) return nullptr; // See if we can propagate this shift into the input, this covers the trivial @@ -743,10 +751,10 @@ Instruction *InstCombinerImpl::FoldShiftByConstant(Value *Op0, Constant *Op1, if (match(Op0BO->getOperand(1), m_APInt(Op0C))) { if (canShiftBinOpWithConstantRHS(I, Op0BO)) { Constant *NewRHS = ConstantExpr::get( - I.getOpcode(), cast(Op0BO->getOperand(1)), Op1); + I.getOpcode(), cast(Op0BO->getOperand(1)), C1); Value *NewShift = - Builder.CreateBinOp(I.getOpcode(), Op0BO->getOperand(0), Op1); + Builder.CreateBinOp(I.getOpcode(), Op0BO->getOperand(0), C1); NewShift->takeName(Op0BO); return BinaryOperator::Create(Op0BO->getOpcode(), NewShift, NewRHS); @@ -772,9 +780,9 @@ Instruction *InstCombinerImpl::FoldShiftByConstant(Value *Op0, Constant *Op1, match(TBO->getOperand(1), m_APInt(C)) && canShiftBinOpWithConstantRHS(I, TBO)) { Constant *NewRHS = ConstantExpr::get( - I.getOpcode(), cast(TBO->getOperand(1)), Op1); + I.getOpcode(), cast(TBO->getOperand(1)), C1); - Value *NewShift = Builder.CreateBinOp(I.getOpcode(), FalseVal, Op1); + Value *NewShift = Builder.CreateBinOp(I.getOpcode(), FalseVal, C1); Value *NewOp = Builder.CreateBinOp(TBO->getOpcode(), NewShift, NewRHS); return SelectInst::Create(Cond, NewOp, NewShift); } @@ -789,9 +797,9 @@ Instruction *InstCombinerImpl::FoldShiftByConstant(Value *Op0, Constant *Op1, match(FBO->getOperand(1), m_APInt(C)) && canShiftBinOpWithConstantRHS(I, FBO)) { Constant *NewRHS = ConstantExpr::get( - I.getOpcode(), cast(FBO->getOperand(1)), Op1); + I.getOpcode(), cast(FBO->getOperand(1)), C1); - Value *NewShift = Builder.CreateBinOp(I.getOpcode(), TrueVal, Op1); + Value *NewShift = Builder.CreateBinOp(I.getOpcode(), TrueVal, C1); Value *NewOp = Builder.CreateBinOp(FBO->getOpcode(), NewShift, NewRHS); return SelectInst::Create(Cond, NewShift, NewOp); } @@ -1009,10 +1017,6 @@ Instruction *InstCombinerImpl::visitShl(BinaryOperator &I) { if (match(Op1, m_Constant(C1))) { Constant *C2; Value *X; - // (C2 << X) << C1 --> (C2 << C1) << X - if (match(Op0, 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)); diff --git a/llvm/test/Transforms/InstCombine/and.ll b/llvm/test/Transforms/InstCombine/and.ll index c7a63d7fc5280..2617ac1eb6def 100644 --- a/llvm/test/Transforms/InstCombine/and.ll +++ b/llvm/test/Transforms/InstCombine/and.ll @@ -1699,8 +1699,7 @@ define i16 @shl_lshr_pow2_const_negative_overflow2(i16 %x) { define i16 @lshr_lshr_pow2_const(i16 %x) { ; CHECK-LABEL: @lshr_lshr_pow2_const( -; CHECK-NEXT: [[LSHR1:%.*]] = lshr i16 2048, [[X:%.*]] -; CHECK-NEXT: [[LSHR2:%.*]] = lshr i16 [[LSHR1]], 6 +; CHECK-NEXT: [[LSHR2:%.*]] = lshr i16 32, [[X:%.*]] ; CHECK-NEXT: [[R:%.*]] = and i16 [[LSHR2]], 4 ; CHECK-NEXT: ret i16 [[R]] ; @@ -1712,8 +1711,7 @@ define i16 @lshr_lshr_pow2_const(i16 %x) { define i16 @lshr_lshr_pow2_const_negative_oneuse(i16 %x) { ; CHECK-LABEL: @lshr_lshr_pow2_const_negative_oneuse( -; CHECK-NEXT: [[LSHR1:%.*]] = lshr i16 2048, [[X:%.*]] -; CHECK-NEXT: [[LSHR2:%.*]] = lshr i16 [[LSHR1]], 6 +; CHECK-NEXT: [[LSHR2:%.*]] = lshr i16 32, [[X:%.*]] ; CHECK-NEXT: call void @use16(i16 [[LSHR2]]) ; CHECK-NEXT: [[R:%.*]] = and i16 [[LSHR2]], 4 ; CHECK-NEXT: ret i16 [[R]] @@ -1727,8 +1725,7 @@ define i16 @lshr_lshr_pow2_const_negative_oneuse(i16 %x) { define i16 @lshr_lshr_pow2_const_negative_nopow2_1(i16 %x) { ; CHECK-LABEL: @lshr_lshr_pow2_const_negative_nopow2_1( -; CHECK-NEXT: [[LSHR1:%.*]] = lshr i16 2047, [[X:%.*]] -; CHECK-NEXT: [[LSHR2:%.*]] = lshr i16 [[LSHR1]], 6 +; CHECK-NEXT: [[LSHR2:%.*]] = lshr i16 31, [[X:%.*]] ; CHECK-NEXT: [[R:%.*]] = and i16 [[LSHR2]], 4 ; CHECK-NEXT: ret i16 [[R]] ; @@ -1740,8 +1737,7 @@ define i16 @lshr_lshr_pow2_const_negative_nopow2_1(i16 %x) { define i16 @lshr_lshr_pow2_const_negative_nopow2_2(i16 %x) { ; CHECK-LABEL: @lshr_lshr_pow2_const_negative_nopow2_2( -; CHECK-NEXT: [[LSHR1:%.*]] = lshr i16 8192, [[X:%.*]] -; CHECK-NEXT: [[LSHR2:%.*]] = lshr i16 [[LSHR1]], 6 +; CHECK-NEXT: [[LSHR2:%.*]] = lshr i16 128, [[X:%.*]] ; CHECK-NEXT: [[R:%.*]] = and i16 [[LSHR2]], 3 ; CHECK-NEXT: ret i16 [[R]] ; diff --git a/llvm/test/Transforms/InstCombine/icmp-and-shift.ll b/llvm/test/Transforms/InstCombine/icmp-and-shift.ll index 6193692976a1b..9c9f1a99e82dd 100644 --- a/llvm/test/Transforms/InstCombine/icmp-and-shift.ll +++ b/llvm/test/Transforms/InstCombine/icmp-and-shift.ll @@ -335,8 +335,7 @@ define i32 @icmp_ne_and1_lshr_pow2(i32 %0) { define <2 x i32> @icmp_ne_and1_lshr_pow2_vec(<2 x i32> %0) { ; CHECK-LABEL: @icmp_ne_and1_lshr_pow2_vec( -; CHECK-NEXT: [[LSHR:%.*]] = lshr <2 x i32> , [[TMP0:%.*]] -; CHECK-NEXT: [[AND:%.*]] = lshr <2 x i32> [[LSHR]], +; CHECK-NEXT: [[AND:%.*]] = lshr <2 x i32> , [[TMP0:%.*]] ; CHECK-NEXT: [[AND_LOBIT:%.*]] = and <2 x i32> [[AND]], ; CHECK-NEXT: ret <2 x i32> [[AND_LOBIT]] ; @@ -349,8 +348,7 @@ define <2 x i32> @icmp_ne_and1_lshr_pow2_vec(<2 x i32> %0) { define i32 @icmp_eq_and_pow2_lshr_pow2(i32 %0) { ; CHECK-LABEL: @icmp_eq_and_pow2_lshr_pow2( -; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 8, [[TMP0:%.*]] -; CHECK-NEXT: [[AND:%.*]] = lshr i32 [[LSHR]], 2 +; CHECK-NEXT: [[AND:%.*]] = lshr i32 2, [[TMP0:%.*]] ; CHECK-NEXT: [[AND_LOBIT:%.*]] = and i32 [[AND]], 1 ; CHECK-NEXT: [[TMP2:%.*]] = xor i32 [[AND_LOBIT]], 1 ; CHECK-NEXT: ret i32 [[TMP2]] @@ -375,8 +373,7 @@ define i32 @icmp_eq_and_pow2_lshr_pow2_case2(i32 %0) { define <2 x i32> @icmp_eq_and_pow2_lshr_pow2_vec(<2 x i32> %0) { ; CHECK-LABEL: @icmp_eq_and_pow2_lshr_pow2_vec( -; CHECK-NEXT: [[LSHR:%.*]] = lshr <2 x i32> , [[TMP0:%.*]] -; CHECK-NEXT: [[AND:%.*]] = lshr <2 x i32> [[LSHR]], +; CHECK-NEXT: [[AND:%.*]] = lshr <2 x i32> , [[TMP0:%.*]] ; CHECK-NEXT: [[AND_LOBIT:%.*]] = and <2 x i32> [[AND]], ; CHECK-NEXT: [[TMP2:%.*]] = xor <2 x i32> [[AND_LOBIT]], ; CHECK-NEXT: ret <2 x i32> [[TMP2]] @@ -390,8 +387,7 @@ define <2 x i32> @icmp_eq_and_pow2_lshr_pow2_vec(<2 x i32> %0) { define i32 @icmp_ne_and_pow2_lshr_pow2(i32 %0) { ; CHECK-LABEL: @icmp_ne_and_pow2_lshr_pow2( -; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 8, [[TMP0:%.*]] -; CHECK-NEXT: [[AND:%.*]] = lshr i32 [[LSHR]], 2 +; CHECK-NEXT: [[AND:%.*]] = lshr i32 2, [[TMP0:%.*]] ; CHECK-NEXT: [[AND_LOBIT:%.*]] = and i32 [[AND]], 1 ; CHECK-NEXT: [[TMP2:%.*]] = xor i32 [[AND_LOBIT]], 1 ; CHECK-NEXT: ret i32 [[TMP2]] @@ -416,8 +412,7 @@ define i32 @icmp_ne_and_pow2_lshr_pow2_case2(i32 %0) { define <2 x i32> @icmp_ne_and_pow2_lshr_pow2_vec(<2 x i32> %0) { ; CHECK-LABEL: @icmp_ne_and_pow2_lshr_pow2_vec( -; CHECK-NEXT: [[LSHR:%.*]] = lshr <2 x i32> , [[TMP0:%.*]] -; CHECK-NEXT: [[AND:%.*]] = lshr <2 x i32> [[LSHR]], +; CHECK-NEXT: [[AND:%.*]] = lshr <2 x i32> , [[TMP0:%.*]] ; CHECK-NEXT: [[AND_LOBIT:%.*]] = and <2 x i32> [[AND]], ; CHECK-NEXT: ret <2 x i32> [[AND_LOBIT]] ; diff --git a/llvm/test/Transforms/InstCombine/shift-shift.ll b/llvm/test/Transforms/InstCombine/shift-shift.ll index d76f3c00261a0..aaf10f28b4231 100644 --- a/llvm/test/Transforms/InstCombine/shift-shift.ll +++ b/llvm/test/Transforms/InstCombine/shift-shift.ll @@ -277,7 +277,7 @@ define i32 @ashr_ashr_constants_use(i32 %x) { ; CHECK-LABEL: @ashr_ashr_constants_use( ; CHECK-NEXT: [[S:%.*]] = ashr i32 -33, [[X:%.*]] ; CHECK-NEXT: call void @use32(i32 [[S]]) -; CHECK-NEXT: [[R:%.*]] = ashr i32 [[S]], 3 +; CHECK-NEXT: [[R:%.*]] = ashr i32 -5, [[X]] ; CHECK-NEXT: ret i32 [[R]] ; %s = ashr i32 -33, %x @@ -288,8 +288,7 @@ define i32 @ashr_ashr_constants_use(i32 %x) { define <3 x i8> @ashr_ashr_constants_vec(<3 x i8> %x) { ; CHECK-LABEL: @ashr_ashr_constants_vec( -; CHECK-NEXT: [[S:%.*]] = ashr <3 x i8> , [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = ashr <3 x i8> [[S]], +; CHECK-NEXT: [[R:%.*]] = ashr <3 x i8> , [[X:%.*]] ; CHECK-NEXT: ret <3 x i8> [[R]] ; %s = ashr <3 x i8> , %x @@ -301,7 +300,7 @@ define i32 @lshr_lshr_constants_use(i32 %x) { ; CHECK-LABEL: @lshr_lshr_constants_use( ; CHECK-NEXT: [[S:%.*]] = lshr i32 -33, [[X:%.*]] ; CHECK-NEXT: call void @use32(i32 [[S]]) -; CHECK-NEXT: [[R:%.*]] = lshr i32 [[S]], 3 +; CHECK-NEXT: [[R:%.*]] = lshr i32 536870907, [[X]] ; CHECK-NEXT: ret i32 [[R]] ; %s = lshr i32 -33, %x @@ -312,8 +311,7 @@ define i32 @lshr_lshr_constants_use(i32 %x) { define <3 x i8> @lshr_lshr_constants_vec(<3 x i8> %x) { ; CHECK-LABEL: @lshr_lshr_constants_vec( -; CHECK-NEXT: [[S:%.*]] = lshr <3 x i8> , [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = lshr <3 x i8> [[S]], +; CHECK-NEXT: [[R:%.*]] = lshr <3 x i8> , [[X:%.*]] ; CHECK-NEXT: ret <3 x i8> [[R]] ; %s = lshr <3 x i8> , %x