aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2022-08-05 10:59:09 -0400
committerSanjay Patel <spatel@rotateright.com>2022-08-05 10:59:09 -0400
commit019d76196f79fcff3c148d0163786f9cce70a023 (patch)
treeee50fce3f5e33d8f9ae73be104081cd6b3ef37fc
parent249a7ed750729b79341fb22003a0f4537883d928 (diff)
[InstSimplify] use isImpliedCondition() instead of semi-duplicated code
We get a couple of improvements from recognizing swapped operand patterns that were not handled by the replicated code. This should also enable simplifying larger patterns as seen in issue #56653 and issue #56654, but that requires enhancements to isImpliedCondition() itself.
-rw-r--r--llvm/lib/Analysis/InstructionSimplify.cpp97
-rw-r--r--llvm/test/Transforms/InstSimplify/and-icmps-same-ops.ll5
-rw-r--r--llvm/test/Transforms/InstSimplify/or-icmps-same-ops.ll5
3 files changed, 38 insertions, 69 deletions
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 3c3d9656cc01..95783607a0b2 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -1582,45 +1582,6 @@ static Value *simplifyUnsignedRangeCheck(ICmpInst *ZeroICmp,
return nullptr;
}
-/// Commuted variants are assumed to be handled by calling this function again
-/// with the parameters swapped.
-static Value *simplifyAndOfICmpsWithSameOperands(ICmpInst *Op0, ICmpInst *Op1) {
- ICmpInst::Predicate Pred0, Pred1;
- Value *A, *B;
- if (!match(Op0, m_ICmp(Pred0, m_Value(A), m_Value(B))) ||
- !match(Op1, m_ICmp(Pred1, m_Specific(A), m_Specific(B))))
- return nullptr;
-
- // Check for any combination of predicates that are guaranteed to be disjoint.
- if ((Pred0 == ICmpInst::getInversePredicate(Pred1)) ||
- (Pred0 == ICmpInst::ICMP_EQ && ICmpInst::isFalseWhenEqual(Pred1)) ||
- (Pred0 == ICmpInst::ICMP_SLT && Pred1 == ICmpInst::ICMP_SGT) ||
- (Pred0 == ICmpInst::ICMP_ULT && Pred1 == ICmpInst::ICMP_UGT))
- return getFalse(Op0->getType());
-
- return nullptr;
-}
-
-/// Commuted variants are assumed to be handled by calling this function again
-/// with the parameters swapped.
-static Value *simplifyOrOfICmpsWithSameOperands(ICmpInst *Op0, ICmpInst *Op1) {
- ICmpInst::Predicate Pred0, Pred1;
- Value *A, *B;
- if (!match(Op0, m_ICmp(Pred0, m_Value(A), m_Value(B))) ||
- !match(Op1, m_ICmp(Pred1, m_Specific(A), m_Specific(B))))
- return nullptr;
-
- // Check for any combination of predicates that cover the entire range of
- // possibilities.
- if ((Pred0 == ICmpInst::getInversePredicate(Pred1)) ||
- (Pred0 == ICmpInst::ICMP_NE && ICmpInst::isTrueWhenEqual(Pred1)) ||
- (Pred0 == ICmpInst::ICMP_SLE && Pred1 == ICmpInst::ICMP_SGE) ||
- (Pred0 == ICmpInst::ICMP_ULE && Pred1 == ICmpInst::ICMP_UGE))
- return getTrue(Op0->getType());
-
- return nullptr;
-}
-
/// Test if a pair of compares with a shared operand and 2 constants has an
/// empty set intersection, full set union, or if one compare is a superset of
/// the other.
@@ -1833,11 +1794,6 @@ static Value *simplifyAndOfICmps(ICmpInst *Op0, ICmpInst *Op1,
if (Value *X = simplifyUnsignedRangeCheck(Op1, Op0, /*IsAnd=*/true, Q))
return X;
- if (Value *X = simplifyAndOfICmpsWithSameOperands(Op0, Op1))
- return X;
- if (Value *X = simplifyAndOfICmpsWithSameOperands(Op1, Op0))
- return X;
-
if (Value *X = simplifyAndOrOfICmpsWithConstants(Op0, Op1, true))
return X;
@@ -1914,11 +1870,6 @@ static Value *simplifyOrOfICmps(ICmpInst *Op0, ICmpInst *Op1,
if (Value *X = simplifyUnsignedRangeCheck(Op1, Op0, /*IsAnd=*/false, Q))
return X;
- if (Value *X = simplifyOrOfICmpsWithSameOperands(Op0, Op1))
- return X;
- if (Value *X = simplifyOrOfICmpsWithSameOperands(Op1, Op0))
- return X;
-
if (Value *X = simplifyAndOrOfICmpsWithConstants(Op0, Op1, false))
return X;
@@ -2220,12 +2171,22 @@ static Value *simplifyAndInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
return Constant::getNullValue(Op0->getType());
if (Op0->getType()->isIntOrIntVectorTy(1)) {
- // Op0&Op1 -> Op0 where Op0 implies Op1
- if (isImpliedCondition(Op0, Op1, Q.DL).value_or(false))
- return Op0;
- // Op0&Op1 -> Op1 where Op1 implies Op0
- if (isImpliedCondition(Op1, Op0, Q.DL).value_or(false))
- return Op1;
+ if (Optional<bool> Implied = isImpliedCondition(Op0, Op1, Q.DL)) {
+ // If Op0 is true implies Op1 is true, then Op0 is a subset of Op1.
+ if (*Implied == true)
+ return Op0;
+ // If Op0 is true implies Op1 is false, then they are not true together.
+ if (*Implied == false)
+ return ConstantInt::getFalse(Op0->getType());
+ }
+ if (Optional<bool> Implied = isImpliedCondition(Op1, Op0, Q.DL)) {
+ // If Op1 is true implies Op0 is true, then Op1 is a subset of Op0.
+ if (Implied.getValue())
+ return Op1;
+ // If Op1 is true implies Op0 is false, then they are not true together.
+ if (!Implied.getValue())
+ return ConstantInt::getFalse(Op1->getType());
+ }
}
return nullptr;
@@ -2460,12 +2421,26 @@ static Value *simplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
return V;
if (Op0->getType()->isIntOrIntVectorTy(1)) {
- // Op0|Op1 -> Op1 where Op0 implies Op1
- if (isImpliedCondition(Op0, Op1, Q.DL).value_or(false))
- return Op1;
- // Op0|Op1 -> Op0 where Op1 implies Op0
- if (isImpliedCondition(Op1, Op0, Q.DL).value_or(false))
- return Op0;
+ // If Op0 is true implies Op1 is true, then Op0 is a subset of Op1.
+ if (Optional<bool> Implied = isImpliedCondition(Op0, Op1, Q.DL)) {
+ if (*Implied == true)
+ return Op1;
+ }
+ // If Op0 is false implies Op1 is true, then at least one is always true.
+ if (Optional<bool> Implied = isImpliedCondition(Op0, Op1, Q.DL, false)) {
+ if (*Implied == true)
+ return ConstantInt::getTrue(Op0->getType());
+ }
+ // If Op1 is true implies Op0 is true, then Op1 is a subset of Op0.
+ if (Optional<bool> Implied = isImpliedCondition(Op1, Op0, Q.DL)) {
+ if (*Implied == true)
+ return Op0;
+ }
+ // If Op1 is false implies Op0 is true, then at least one is always true.
+ if (Optional<bool> Implied = isImpliedCondition(Op1, Op0, Q.DL, false)) {
+ if (*Implied == true)
+ return ConstantInt::getTrue(Op1->getType());
+ }
}
return nullptr;
diff --git a/llvm/test/Transforms/InstSimplify/and-icmps-same-ops.ll b/llvm/test/Transforms/InstSimplify/and-icmps-same-ops.ll
index a92a3bc52105..ee3af49cf9aa 100644
--- a/llvm/test/Transforms/InstSimplify/and-icmps-same-ops.ll
+++ b/llvm/test/Transforms/InstSimplify/and-icmps-same-ops.ll
@@ -1224,10 +1224,7 @@ define i1 @ult_uge_swap(i8 %a, i8 %b) {
define i1 @ult_ult_swap(i8 %a, i8 %b) {
; CHECK-LABEL: @ult_ult_swap(
-; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i8 [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i8 [[B]], [[A]]
-; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]]
-; CHECK-NEXT: ret i1 [[AND]]
+; CHECK-NEXT: ret i1 false
;
%cmp1 = icmp ult i8 %a, %b
%cmp2 = icmp ult i8 %b, %a
diff --git a/llvm/test/Transforms/InstSimplify/or-icmps-same-ops.ll b/llvm/test/Transforms/InstSimplify/or-icmps-same-ops.ll
index d1bcb9d0ece0..fb67ba309876 100644
--- a/llvm/test/Transforms/InstSimplify/or-icmps-same-ops.ll
+++ b/llvm/test/Transforms/InstSimplify/or-icmps-same-ops.ll
@@ -1235,10 +1235,7 @@ define i1 @ult_ule_swap(i8 %a, i8 %b) {
define i1 @ule_ule_swap(i8 %a, i8 %b) {
; CHECK-LABEL: @ule_ule_swap(
-; CHECK-NEXT: [[CMP1:%.*]] = icmp ule i8 [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT: [[CMP2:%.*]] = icmp ule i8 [[B]], [[A]]
-; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
-; CHECK-NEXT: ret i1 [[OR]]
+; CHECK-NEXT: ret i1 true
;
%cmp1 = icmp ule i8 %a, %b
%cmp2 = icmp ule i8 %b, %a