forked from OSchip/llvm-project
[InstCombine] merge shuffled vector negate and multiply
Add the "(0 - X) --> (X * -1)" reverse identity to the list of alternate form binops. We need a little hack to make the existing logic work because it does not expect to move constants from op0 to op1, but the code comment hopefully makes that clear. I don't think there are any other identities like that. Fixes #54364 Differential Revision: https://reviews.llvm.org/D122390
This commit is contained in:
parent
fea3ca5dc8
commit
5dbb53b1b4
|
@ -1934,6 +1934,11 @@ static BinopElts getAlternateBinop(BinaryOperator *BO, const DataLayout &DL) {
|
|||
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 @@ Instruction *InstCombinerImpl::foldSelectShuffle(ShuffleVectorInst &Shuf) {
|
|||
!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 @@ Instruction *InstCombinerImpl::foldSelectShuffle(ShuffleVectorInst &Shuf) {
|
|||
}
|
||||
}
|
||||
|
||||
if (Opc0 != Opc1)
|
||||
if (Opc0 != Opc1 || !C0 || !C1)
|
||||
return nullptr;
|
||||
|
||||
// The opcodes must be the same. Use a new name to make that clear.
|
||||
|
|
|
@ -1394,10 +1394,8 @@ define <4 x i32> @shl_mul_2_vars(<4 x i32> %v0, <4 x i32> %v1) {
|
|||
|
||||
define <4 x i32> @mul_neg(<4 x i32> %x) {
|
||||
; CHECK-LABEL: @mul_neg(
|
||||
; CHECK-NEXT: [[M:%.*]] = mul <4 x i32> [[X:%.*]], <i32 257, i32 -3, i32 poison, i32 -9>
|
||||
; CHECK-NEXT: [[N:%.*]] = sub <4 x i32> <i32 poison, i32 poison, i32 0, i32 poison>, [[X]]
|
||||
; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i32> [[M]], <4 x i32> [[N]], <4 x i32> <i32 0, i32 1, i32 6, i32 3>
|
||||
; CHECK-NEXT: ret <4 x i32> [[R]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = mul <4 x i32> [[X:%.*]], <i32 257, i32 -3, i32 -1, i32 -9>
|
||||
; CHECK-NEXT: ret <4 x i32> [[TMP1]]
|
||||
;
|
||||
%m = mul <4 x i32> %x, <i32 257, i32 -3, i32 poison, i32 -9>
|
||||
%n = sub <4 x i32> <i32 poison, i32 poison, i32 0, i32 poison>, %x
|
||||
|
@ -1407,10 +1405,8 @@ define <4 x i32> @mul_neg(<4 x i32> %x) {
|
|||
|
||||
define <3 x i79> @neg_mul(<3 x i79> %x) {
|
||||
; CHECK-LABEL: @neg_mul(
|
||||
; CHECK-NEXT: [[N:%.*]] = sub nsw <3 x i79> <i79 0, i79 poison, i79 0>, [[X:%.*]]
|
||||
; CHECK-NEXT: [[M:%.*]] = mul nsw <3 x i79> [[X]], <i79 poison, i79 -3, i79 poison>
|
||||
; CHECK-NEXT: [[R:%.*]] = shufflevector <3 x i79> [[N]], <3 x i79> [[M]], <3 x i32> <i32 0, i32 4, i32 2>
|
||||
; CHECK-NEXT: ret <3 x i79> [[R]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = mul nsw <3 x i79> [[X:%.*]], <i79 -1, i79 -3, i79 -1>
|
||||
; CHECK-NEXT: ret <3 x i79> [[TMP1]]
|
||||
;
|
||||
%n = sub nsw <3 x i79> <i79 0, i79 poison, i79 0>, %x
|
||||
%m = mul nsw <3 x i79> %x, <i79 poison, i79 -3, i79 poison>
|
||||
|
@ -1420,10 +1416,9 @@ define <3 x i79> @neg_mul(<3 x i79> %x) {
|
|||
|
||||
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:%.*]], <i32 42, i32 poison, i32 poison, i32 6>
|
||||
; CHECK-NEXT: [[N:%.*]] = sub nsw <4 x i32> <i32 poison, i32 0, i32 0, i32 poison>, [[Y:%.*]]
|
||||
; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i32> [[M]], <4 x i32> [[N]], <4 x i32> <i32 0, i32 5, i32 6, i32 3>
|
||||
; CHECK-NEXT: ret <4 x i32> [[R]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> [[Y:%.*]], <4 x i32> <i32 0, i32 5, i32 6, i32 3>
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = mul <4 x i32> [[TMP1]], <i32 42, i32 -1, i32 -1, i32 6>
|
||||
; CHECK-NEXT: ret <4 x i32> [[TMP2]]
|
||||
;
|
||||
%m = mul nuw <4 x i32> %x, <i32 42, i32 poison, i32 poison, i32 6>
|
||||
%n = sub nsw <4 x i32> <i32 poison, i32 0, i32 0, i32 poison>, %y
|
||||
|
@ -1433,10 +1428,9 @@ define <4 x i32> @mul_neg_2_vars(<4 x i32> %x, <4 x i32> %y) {
|
|||
|
||||
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> <i32 0, i32 poison, i32 0, i32 poison>, [[Y:%.*]]
|
||||
; CHECK-NEXT: [[M:%.*]] = mul nuw nsw <4 x i32> [[X:%.*]], <i32 poison, i32 42, i32 poison, i32 6>
|
||||
; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i32> [[N]], <4 x i32> [[M]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
|
||||
; CHECK-NEXT: ret <4 x i32> [[R]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[Y:%.*]], <4 x i32> [[X:%.*]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = mul nsw <4 x i32> [[TMP1]], <i32 -1, i32 42, i32 -1, i32 6>
|
||||
; CHECK-NEXT: ret <4 x i32> [[TMP2]]
|
||||
;
|
||||
%n = sub nsw <4 x i32> <i32 0, i32 poison, i32 0, i32 poison>, %y
|
||||
%m = mul nuw nsw <4 x i32> %x, <i32 poison, i32 42, i32 poison, i32 6>
|
||||
|
|
Loading…
Reference in New Issue