diff --git a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp @@ -1934,6 +1934,11 @@ return {Instruction::Add, BO0, BO1}; break; } + case Instruction::Sub: + // sub 0, X --> mul X, -1 + if (match(BO0, m_ZeroInt())) + return {Instruction::Mul, BO1, ConstantInt::getAllOnesValue(Ty)}; + break; default: break; } @@ -2052,14 +2057,19 @@ !match(Shuf.getOperand(1), m_BinOp(B1))) return nullptr; + // If one operand is "0 - X", allow that to be viewed as "X * -1" + // (ConstantsAreOp1) by getAlternateBinop below. If the neg is not paired + // with a multiply, we will exit because C0/C1 will not be set. Value *X, *Y; - Constant *C0, *C1; + Constant *C0 = nullptr, *C1 = nullptr; bool ConstantsAreOp1; if (match(B0, m_BinOp(m_Constant(C0), m_Value(X))) && match(B1, m_BinOp(m_Constant(C1), m_Value(Y)))) ConstantsAreOp1 = false; - else if (match(B0, m_BinOp(m_Value(X), m_Constant(C0))) && - match(B1, m_BinOp(m_Value(Y), m_Constant(C1)))) + else if (match(B0, m_CombineOr(m_BinOp(m_Value(X), m_Constant(C0)), + m_Neg(m_Value(X)))) && + match(B1, m_CombineOr(m_BinOp(m_Value(Y), m_Constant(C1)), + m_Neg(m_Value(Y))))) ConstantsAreOp1 = true; else return nullptr; @@ -2085,7 +2095,7 @@ } } - if (Opc0 != Opc1) + if (Opc0 != Opc1 || !C0 || !C1) return nullptr; // The opcodes must be the same. Use a new name to make that clear. diff --git a/llvm/test/Transforms/InstCombine/shuffle_select.ll b/llvm/test/Transforms/InstCombine/shuffle_select.ll --- a/llvm/test/Transforms/InstCombine/shuffle_select.ll +++ b/llvm/test/Transforms/InstCombine/shuffle_select.ll @@ -1394,10 +1394,8 @@ define <4 x i32> @mul_neg(<4 x i32> %x) { ; CHECK-LABEL: @mul_neg( -; CHECK-NEXT: [[M:%.*]] = mul <4 x i32> [[X:%.*]], -; CHECK-NEXT: [[N:%.*]] = sub <4 x i32> , [[X]] -; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i32> [[M]], <4 x i32> [[N]], <4 x i32> -; CHECK-NEXT: ret <4 x i32> [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = mul <4 x i32> [[X:%.*]], +; CHECK-NEXT: ret <4 x i32> [[TMP1]] ; %m = mul <4 x i32> %x, %n = sub <4 x i32> , %x @@ -1407,10 +1405,8 @@ define <3 x i79> @neg_mul(<3 x i79> %x) { ; CHECK-LABEL: @neg_mul( -; CHECK-NEXT: [[N:%.*]] = sub nsw <3 x i79> , [[X:%.*]] -; CHECK-NEXT: [[M:%.*]] = mul nsw <3 x i79> [[X]], -; CHECK-NEXT: [[R:%.*]] = shufflevector <3 x i79> [[N]], <3 x i79> [[M]], <3 x i32> -; CHECK-NEXT: ret <3 x i79> [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = mul nsw <3 x i79> [[X:%.*]], +; CHECK-NEXT: ret <3 x i79> [[TMP1]] ; %n = sub nsw <3 x i79> , %x %m = mul nsw <3 x i79> %x, @@ -1420,10 +1416,9 @@ define <4 x i32> @mul_neg_2_vars(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @mul_neg_2_vars( -; CHECK-NEXT: [[M:%.*]] = mul nuw <4 x i32> [[X:%.*]], -; CHECK-NEXT: [[N:%.*]] = sub nsw <4 x i32> , [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i32> [[M]], <4 x i32> [[N]], <4 x i32> -; CHECK-NEXT: ret <4 x i32> [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> [[Y:%.*]], <4 x i32> +; CHECK-NEXT: [[TMP2:%.*]] = mul <4 x i32> [[TMP1]], +; CHECK-NEXT: ret <4 x i32> [[TMP2]] ; %m = mul nuw <4 x i32> %x, %n = sub nsw <4 x i32> , %y @@ -1433,10 +1428,9 @@ define <4 x i32> @neg_mul_2_vars(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @neg_mul_2_vars( -; CHECK-NEXT: [[N:%.*]] = sub nsw <4 x i32> , [[Y:%.*]] -; CHECK-NEXT: [[M:%.*]] = mul nuw nsw <4 x i32> [[X:%.*]], -; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i32> [[N]], <4 x i32> [[M]], <4 x i32> -; CHECK-NEXT: ret <4 x i32> [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[Y:%.*]], <4 x i32> [[X:%.*]], <4 x i32> +; CHECK-NEXT: [[TMP2:%.*]] = mul nsw <4 x i32> [[TMP1]], +; CHECK-NEXT: ret <4 x i32> [[TMP2]] ; %n = sub nsw <4 x i32> , %y %m = mul nuw nsw <4 x i32> %x,