[llvm] ebb8ffd - [InstSimplify] Extract commutative and folds into helper (NFCI)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 15 07:34:15 PST 2023
Author: Nikita Popov
Date: 2023-11-15T16:31:55+01:00
New Revision: ebb8ffde94476333cb2e95aacfd2e023d7112efb
URL: https://github.com/llvm/llvm-project/commit/ebb8ffde94476333cb2e95aacfd2e023d7112efb
DIFF: https://github.com/llvm/llvm-project/commit/ebb8ffde94476333cb2e95aacfd2e023d7112efb.diff
LOG: [InstSimplify] Extract commutative and folds into helper (NFCI)
There are a number of and folds that are repeated for both
operand orders. Move these into a helper that is invoked with
both orders.
This is conceptually NFC, but may not be entirely so, as the order
of folds may change.
Added:
Modified:
llvm/lib/Analysis/InstructionSimplify.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 2fff10df55038d9..bb58a446b447b3e 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -1993,6 +1993,48 @@ static Value *simplifyLogicOfAddSub(Value *Op0, Value *Op1,
return nullptr;
}
+// Commutative patterns for and that will be tried with both operand orders.
+static Value *simplifyAndCommutative(Value *Op0, Value *Op1,
+ const SimplifyQuery &Q,
+ unsigned MaxRecurse) {
+ // ~A & A = 0
+ if (match(Op0, m_Not(m_Specific(Op1))))
+ return Constant::getNullValue(Op0->getType());
+
+ // (A | ?) & A = A
+ if (match(Op0, m_c_Or(m_Specific(Op1), m_Value())))
+ return Op1;
+
+ // (X | ~Y) & (X | Y) --> X
+ Value *X, *Y;
+ if (match(Op0, m_c_Or(m_Value(X), m_Not(m_Value(Y)))) &&
+ match(Op1, m_c_Or(m_Deferred(X), m_Deferred(Y))))
+ return X;
+
+ // If we have a multiplication overflow check that is being 'and'ed with a
+ // check that one of the multipliers is not zero, we can omit the 'and', and
+ // only keep the overflow check.
+ if (isCheckForZeroAndMulWithOverflow(Op0, Op1, true))
+ return Op1;
+
+ // -A & A = A if A is a power of two or zero.
+ if (match(Op0, m_Neg(m_Specific(Op1))) &&
+ isKnownToBeAPowerOfTwo(Op1, Q.DL, /*OrZero*/ true, 0, Q.AC, Q.CxtI, Q.DT))
+ return Op1;
+
+ // This is a similar pattern used for checking if a value is a power-of-2:
+ // (A - 1) & A --> 0 (if A is a power-of-2 or 0)
+ if (match(Op0, m_Add(m_Specific(Op1), m_AllOnes())) &&
+ isKnownToBeAPowerOfTwo(Op1, Q.DL, /*OrZero*/ true, 0, Q.AC, Q.CxtI, Q.DT))
+ return Constant::getNullValue(Op1->getType());
+
+ if (Value *V =
+ simplifyAndOrWithICmpEq(Instruction::And, Op0, Op1, Q, MaxRecurse))
+ return V;
+
+ return nullptr;
+}
+
/// Given operands for an And, see if we can fold the result.
/// If not, this returns null.
static Value *simplifyAndInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
@@ -2020,26 +2062,10 @@ static Value *simplifyAndInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
if (match(Op1, m_AllOnes()))
return Op0;
- // A & ~A = ~A & A = 0
- if (match(Op0, m_Not(m_Specific(Op1))) || match(Op1, m_Not(m_Specific(Op0))))
- return Constant::getNullValue(Op0->getType());
-
- // (A | ?) & A = A
- if (match(Op0, m_c_Or(m_Specific(Op1), m_Value())))
- return Op1;
-
- // A & (A | ?) = A
- if (match(Op1, m_c_Or(m_Specific(Op0), m_Value())))
- return Op0;
-
- // (X | Y) & (X | ~Y) --> X (commuted 8 ways)
- Value *X, *Y;
- if (match(Op0, m_c_Or(m_Value(X), m_Not(m_Value(Y)))) &&
- match(Op1, m_c_Or(m_Deferred(X), m_Deferred(Y))))
- return X;
- if (match(Op1, m_c_Or(m_Value(X), m_Not(m_Value(Y)))) &&
- match(Op0, m_c_Or(m_Deferred(X), m_Deferred(Y))))
- return X;
+ if (Value *Res = simplifyAndCommutative(Op0, Op1, Q, MaxRecurse))
+ return Res;
+ if (Value *Res = simplifyAndCommutative(Op1, Op0, Q, MaxRecurse))
+ return Res;
if (Value *V = simplifyLogicOfAddSub(Op0, Op1, Instruction::And))
return V;
@@ -2047,6 +2073,7 @@ static Value *simplifyAndInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
// A mask that only clears known zeros of a shifted value is a no-op.
const APInt *Mask;
const APInt *ShAmt;
+ Value *X, *Y;
if (match(Op1, m_APInt(Mask))) {
// If all bits in the inverted and shifted mask are clear:
// and (shl X, ShAmt), Mask --> shl X, ShAmt
@@ -2074,42 +2101,6 @@ static Value *simplifyAndInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
return ConstantInt::getNullValue(Op1->getType());
}
- // If we have a multiplication overflow check that is being 'and'ed with a
- // check that one of the multipliers is not zero, we can omit the 'and', and
- // only keep the overflow check.
- if (isCheckForZeroAndMulWithOverflow(Op0, Op1, true))
- return Op1;
- if (isCheckForZeroAndMulWithOverflow(Op1, Op0, true))
- return Op0;
-
- // A & (-A) = A if A is a power of two or zero.
- if (match(Op0, m_Neg(m_Specific(Op1))) ||
- match(Op1, m_Neg(m_Specific(Op0)))) {
- if (isKnownToBeAPowerOfTwo(Op0, Q.DL, /*OrZero*/ true, 0, Q.AC, Q.CxtI,
- Q.DT))
- return Op0;
- if (isKnownToBeAPowerOfTwo(Op1, Q.DL, /*OrZero*/ true, 0, Q.AC, Q.CxtI,
- Q.DT))
- return Op1;
- }
-
- // This is a similar pattern used for checking if a value is a power-of-2:
- // (A - 1) & A --> 0 (if A is a power-of-2 or 0)
- // A & (A - 1) --> 0 (if A is a power-of-2 or 0)
- if (match(Op0, m_Add(m_Specific(Op1), m_AllOnes())) &&
- isKnownToBeAPowerOfTwo(Op1, Q.DL, /*OrZero*/ true, 0, Q.AC, Q.CxtI, Q.DT))
- return Constant::getNullValue(Op1->getType());
- if (match(Op1, m_Add(m_Specific(Op0), m_AllOnes())) &&
- isKnownToBeAPowerOfTwo(Op0, Q.DL, /*OrZero*/ true, 0, Q.AC, Q.CxtI, Q.DT))
- return Constant::getNullValue(Op0->getType());
-
- if (Value *V =
- simplifyAndOrWithICmpEq(Instruction::And, Op0, Op1, Q, MaxRecurse))
- return V;
- if (Value *V =
- simplifyAndOrWithICmpEq(Instruction::And, Op1, Op0, Q, MaxRecurse))
- return V;
-
if (Value *V = simplifyAndOrOfCmps(Q, Op0, Op1, true))
return V;
More information about the llvm-commits
mailing list