Index: llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -233,27 +233,21 @@ } } - if (ConstantInt *CI = dyn_cast(Op1)) { + if (match(Op1, m_NegatedPower2())) { // (Y - X) * (-(2**n)) -> (X - Y) * (2**n), for positive nonzero n - // (Y + const) * (-(2**n)) -> (-constY) * (2**n), for positive nonzero n + // (Y + const) * (-(2**n)) -> (-const - Y) * (2**n), for positive nonzero n // The "* (2**n)" thus becomes a potential shifting opportunity. - { - const APInt & Val = CI->getValue(); - const APInt &PosVal = Val.abs(); - if (Val.isNegative() && PosVal.isPowerOf2()) { - Value *X = nullptr, *Y = nullptr; - if (Op0->hasOneUse()) { - ConstantInt *C1; - Value *Sub = nullptr; - if (match(Op0, m_Sub(m_Value(Y), m_Value(X)))) - Sub = Builder.CreateSub(X, Y, "suba"); - else if (match(Op0, m_Add(m_Value(Y), m_ConstantInt(C1)))) - Sub = Builder.CreateSub(Builder.CreateNeg(C1), Y, "subc"); - if (Sub) - return - BinaryOperator::CreateMul(Sub, - ConstantInt::get(Y->getType(), PosVal)); - } + Value *X = nullptr, *Y = nullptr; + if (Op0->hasOneUse()) { + Constant *C1; + Value *Sub = nullptr; + if (match(Op0, m_Sub(m_Value(Y), m_Value(X)))) + Sub = Builder.CreateSub(X, Y, "suba"); + else if (match(Op0, m_Add(m_Value(Y), m_Constant(C1)))) + Sub = Builder.CreateSub(Builder.CreateNeg(C1), Y, "subc"); + if (Sub) { + Constant *PosVal = ConstantExpr::getNeg(cast(Op1)); + return BinaryOperator::CreateMul(Sub, PosVal); } } } Index: llvm/test/Transforms/InstCombine/mul.ll =================================================================== --- llvm/test/Transforms/InstCombine/mul.ll +++ llvm/test/Transforms/InstCombine/mul.ll @@ -885,8 +885,8 @@ define <2 x i32> @mulsub1_vec(<2 x i32> %a0, <2 x i32> %a1) { ; CHECK-LABEL: @mulsub1_vec( -; CHECK-NEXT: [[SUB:%.*]] = sub <2 x i32> [[A1:%.*]], [[A0:%.*]] -; CHECK-NEXT: [[MUL:%.*]] = mul <2 x i32> [[SUB]], +; CHECK-NEXT: [[SUBA:%.*]] = sub <2 x i32> [[A0:%.*]], [[A1:%.*]] +; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[SUBA]], ; CHECK-NEXT: ret <2 x i32> [[MUL]] ; %sub = sub <2 x i32> %a1, %a0 @@ -896,8 +896,8 @@ define <2 x i32> @mulsub1_vec_nonuniform(<2 x i32> %a0, <2 x i32> %a1) { ; CHECK-LABEL: @mulsub1_vec_nonuniform( -; CHECK-NEXT: [[SUB:%.*]] = sub <2 x i32> [[A1:%.*]], [[A0:%.*]] -; CHECK-NEXT: [[MUL:%.*]] = mul <2 x i32> [[SUB]], +; CHECK-NEXT: [[SUBA:%.*]] = sub <2 x i32> [[A0:%.*]], [[A1:%.*]] +; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[SUBA]], ; CHECK-NEXT: ret <2 x i32> [[MUL]] ; %sub = sub <2 x i32> %a1, %a0 @@ -907,8 +907,8 @@ define <2 x i32> @mulsub1_vec_nonuniform_undef(<2 x i32> %a0, <2 x i32> %a1) { ; CHECK-LABEL: @mulsub1_vec_nonuniform_undef( -; CHECK-NEXT: [[SUB:%.*]] = sub <2 x i32> [[A1:%.*]], [[A0:%.*]] -; CHECK-NEXT: [[MUL:%.*]] = mul <2 x i32> [[SUB]], +; CHECK-NEXT: [[SUBA:%.*]] = sub <2 x i32> [[A0:%.*]], [[A1:%.*]] +; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[SUBA]], ; CHECK-NEXT: ret <2 x i32> [[MUL]] ; %sub = sub <2 x i32> %a1, %a0 @@ -929,8 +929,8 @@ define <2 x i32> @mulsub2_vec(<2 x i32> %a0) { ; CHECK-LABEL: @mulsub2_vec( -; CHECK-NEXT: [[SUB:%.*]] = sub <2 x i32> , [[A0:%.*]] -; CHECK-NEXT: [[MUL:%.*]] = mul <2 x i32> [[SUB]], +; CHECK-NEXT: [[SUBA:%.*]] = shl <2 x i32> [[A0:%.*]], +; CHECK-NEXT: [[MUL:%.*]] = add <2 x i32> [[SUBA]], ; CHECK-NEXT: ret <2 x i32> [[MUL]] ; %sub = sub <2 x i32> , %a0 @@ -940,8 +940,8 @@ define <2 x i32> @mulsub2_vec_nonuniform(<2 x i32> %a0) { ; CHECK-LABEL: @mulsub2_vec_nonuniform( -; CHECK-NEXT: [[SUB:%.*]] = sub <2 x i32> , [[A0:%.*]] -; CHECK-NEXT: [[MUL:%.*]] = mul <2 x i32> [[SUB]], +; CHECK-NEXT: [[SUBA:%.*]] = add <2 x i32> [[A0:%.*]], +; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[SUBA]], ; CHECK-NEXT: ret <2 x i32> [[MUL]] ; %sub = sub <2 x i32> , %a0 @@ -951,8 +951,8 @@ define <2 x i32> @mulsub2_vec_nonuniform_undef(<2 x i32> %a0) { ; CHECK-LABEL: @mulsub2_vec_nonuniform_undef( -; CHECK-NEXT: [[SUB:%.*]] = sub <2 x i32> , [[A0:%.*]] -; CHECK-NEXT: [[MUL:%.*]] = mul <2 x i32> [[SUB]], +; CHECK-NEXT: [[SUBA:%.*]] = add <2 x i32> [[A0:%.*]], +; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[SUBA]], ; CHECK-NEXT: ret <2 x i32> [[MUL]] ; %sub = sub <2 x i32> , %a0 @@ -973,8 +973,8 @@ define <2 x i32> @muladd2_vec(<2 x i32> %a0) { ; CHECK-LABEL: @muladd2_vec( -; CHECK-NEXT: [[TMP1:%.*]] = mul <2 x i32> [[A0:%.*]], -; CHECK-NEXT: [[MUL:%.*]] = add <2 x i32> [[TMP1]], +; CHECK-NEXT: [[SUBC_NEG:%.*]] = mul <2 x i32> [[A0:%.*]], +; CHECK-NEXT: [[MUL:%.*]] = add <2 x i32> [[SUBC_NEG]], ; CHECK-NEXT: ret <2 x i32> [[MUL]] ; %add = add <2 x i32> %a0, @@ -984,8 +984,8 @@ define <2 x i32> @muladd2_vec_nonuniform(<2 x i32> %a0) { ; CHECK-LABEL: @muladd2_vec_nonuniform( -; CHECK-NEXT: [[TMP1:%.*]] = mul <2 x i32> [[A0:%.*]], -; CHECK-NEXT: [[MUL:%.*]] = add <2 x i32> [[TMP1]], +; CHECK-NEXT: [[SUBC:%.*]] = sub <2 x i32> , [[A0:%.*]] +; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[SUBC]], ; CHECK-NEXT: ret <2 x i32> [[MUL]] ; %add = add <2 x i32> %a0, @@ -995,8 +995,8 @@ define <2 x i32> @muladd2_vec_nonuniform_undef(<2 x i32> %a0) { ; CHECK-LABEL: @muladd2_vec_nonuniform_undef( -; CHECK-NEXT: [[TMP1:%.*]] = mul <2 x i32> [[A0:%.*]], -; CHECK-NEXT: [[MUL:%.*]] = add <2 x i32> [[TMP1]], +; CHECK-NEXT: [[SUBC:%.*]] = sub <2 x i32> , [[A0:%.*]] +; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[SUBC]], ; CHECK-NEXT: ret <2 x i32> [[MUL]] ; %add = add <2 x i32> %a0,