aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <npopov@redhat.com>2023-06-19 11:42:21 +0200
committerNikita Popov <npopov@redhat.com>2023-06-19 11:49:38 +0200
commitf6a8775c5d9fa6cd49f404da70982f2e7b91c88c (patch)
tree4e47c1a4f94f1e8190c8334328bb1c1bba2fdf17
parent4511d3c33cba90d5d53a1fd6eed89ef9a3f696e1 (diff)
downloadllvm-f6a8775c5d9fa6cd49f404da70982f2e7b91c88c.zip
llvm-f6a8775c5d9fa6cd49f404da70982f2e7b91c88c.tar.gz
llvm-f6a8775c5d9fa6cd49f404da70982f2e7b91c88c.tar.bz2
[InstSimplify] Fold icmp of uadd.sat/usub.sat (PR63381)
Fold uadd.sat(X, Y) uge X and usub.sat(X, Y) ule X to true. Proof: https://alive2.llvm.org/ce/z/596m9X Fixes https://github.com/llvm/llvm-project/issues/63381.
-rw-r--r--llvm/lib/Analysis/InstructionSimplify.cpp36
-rw-r--r--llvm/test/Transforms/InstSimplify/saturating-add-sub.ll32
2 files changed, 44 insertions, 24 deletions
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 616873f..48ffa83 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -3682,6 +3682,36 @@ static Value *simplifyICmpWithDominatingAssume(CmpInst::Predicate Predicate,
return nullptr;
}
+static Value *simplifyICmpWithIntrinsicOnLHS(CmpInst::Predicate Pred,
+ Value *LHS, Value *RHS) {
+ auto *II = dyn_cast<IntrinsicInst>(LHS);
+ if (!II)
+ return nullptr;
+
+ switch (II->getIntrinsicID()) {
+ case Intrinsic::uadd_sat:
+ // uadd.sat(X, Y) uge X, uadd.sat(X, Y) uge Y
+ if (II->getArgOperand(0) == RHS || II->getArgOperand(1) == RHS) {
+ if (Pred == ICmpInst::ICMP_UGE)
+ return ConstantInt::getTrue(getCompareTy(II));
+ if (Pred == ICmpInst::ICMP_ULT)
+ return ConstantInt::getFalse(getCompareTy(II));
+ }
+ return nullptr;
+ case Intrinsic::usub_sat:
+ // usub.sat(X, Y) ule X
+ if (II->getArgOperand(0) == RHS) {
+ if (Pred == ICmpInst::ICMP_ULE)
+ return ConstantInt::getTrue(getCompareTy(II));
+ if (Pred == ICmpInst::ICMP_UGT)
+ return ConstantInt::getFalse(getCompareTy(II));
+ }
+ return nullptr;
+ default:
+ return nullptr;
+ }
+}
+
/// Given operands for an ICmpInst, see if we can fold the result.
/// If not, this returns null.
static Value *simplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
@@ -3946,6 +3976,12 @@ static Value *simplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
if (Value *V = simplifyICmpWithMinMax(Pred, LHS, RHS, Q, MaxRecurse))
return V;
+ if (Value *V = simplifyICmpWithIntrinsicOnLHS(Pred, LHS, RHS))
+ return V;
+ if (Value *V = simplifyICmpWithIntrinsicOnLHS(
+ ICmpInst::getSwappedPredicate(Pred), RHS, LHS))
+ return V;
+
if (Value *V = simplifyICmpWithDominatingAssume(Pred, LHS, RHS, Q))
return V;
diff --git a/llvm/test/Transforms/InstSimplify/saturating-add-sub.ll b/llvm/test/Transforms/InstSimplify/saturating-add-sub.ll
index 616a206..6fb1261 100644
--- a/llvm/test/Transforms/InstSimplify/saturating-add-sub.ll
+++ b/llvm/test/Transforms/InstSimplify/saturating-add-sub.ll
@@ -797,9 +797,7 @@ define i1 @ssub_icmp_op1_smin(i8 %a) {
define i1 @uadd_uge(i8 %x, i8 %y) {
; CHECK-LABEL: @uadd_uge(
-; CHECK-NEXT: [[SAT:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT: [[CMP:%.*]] = icmp uge i8 [[SAT]], [[X]]
-; CHECK-NEXT: ret i1 [[CMP]]
+; CHECK-NEXT: ret i1 true
;
%sat = call i8 @llvm.uadd.sat.i8(i8 %x, i8 %y)
%cmp = icmp uge i8 %sat, %x
@@ -808,9 +806,7 @@ define i1 @uadd_uge(i8 %x, i8 %y) {
define i1 @uadd_uge_rhs(i8 %x, i8 %y) {
; CHECK-LABEL: @uadd_uge_rhs(
-; CHECK-NEXT: [[SAT:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT: [[CMP:%.*]] = icmp uge i8 [[SAT]], [[Y]]
-; CHECK-NEXT: ret i1 [[CMP]]
+; CHECK-NEXT: ret i1 true
;
%sat = call i8 @llvm.uadd.sat.i8(i8 %x, i8 %y)
%cmp = icmp uge i8 %sat, %y
@@ -819,9 +815,7 @@ define i1 @uadd_uge_rhs(i8 %x, i8 %y) {
define i1 @uadd_uge_commuted(i8 %x, i8 %y) {
; CHECK-LABEL: @uadd_uge_commuted(
-; CHECK-NEXT: [[SAT:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT: [[CMP:%.*]] = icmp ule i8 [[X]], [[SAT]]
-; CHECK-NEXT: ret i1 [[CMP]]
+; CHECK-NEXT: ret i1 true
;
%sat = call i8 @llvm.uadd.sat.i8(i8 %x, i8 %y)
%cmp = icmp ule i8 %x, %sat
@@ -830,9 +824,7 @@ define i1 @uadd_uge_commuted(i8 %x, i8 %y) {
define i1 @uadd_ult(i8 %x, i8 %y) {
; CHECK-LABEL: @uadd_ult(
-; CHECK-NEXT: [[SAT:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[SAT]], [[X]]
-; CHECK-NEXT: ret i1 [[CMP]]
+; CHECK-NEXT: ret i1 false
;
%sat = call i8 @llvm.uadd.sat.i8(i8 %x, i8 %y)
%cmp = icmp ult i8 %sat, %x
@@ -841,9 +833,7 @@ define i1 @uadd_ult(i8 %x, i8 %y) {
define <2 x i1> @uadd_uge_vec(<2 x i8> %x, <2 x i8> %y) {
; CHECK-LABEL: @uadd_uge_vec(
-; CHECK-NEXT: [[SAT:%.*]] = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]])
-; CHECK-NEXT: [[CMP:%.*]] = icmp uge <2 x i8> [[SAT]], [[X]]
-; CHECK-NEXT: ret <2 x i1> [[CMP]]
+; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
;
%sat = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> %x, <2 x i8> %y)
%cmp = icmp uge <2 x i8> %sat, %x
@@ -885,9 +875,7 @@ define i1 @uadd_uge_unrelated_op_fail(i8 %x, i8 %y, i8 %z) {
define i1 @usub_ule(i8 %x, i8 %y) {
; CHECK-LABEL: @usub_ule(
-; CHECK-NEXT: [[SAT:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT: [[CMP:%.*]] = icmp ule i8 [[SAT]], [[X]]
-; CHECK-NEXT: ret i1 [[CMP]]
+; CHECK-NEXT: ret i1 true
;
%sat = call i8 @llvm.usub.sat.i8(i8 %x, i8 %y)
%cmp = icmp ule i8 %sat, %x
@@ -907,9 +895,7 @@ define i1 @usub_ule_rhs_fail(i8 %x, i8 %y) {
define i1 @usub_ule_commuted(i8 %x, i8 %y) {
; CHECK-LABEL: @usub_ule_commuted(
-; CHECK-NEXT: [[SAT:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT: [[CMP:%.*]] = icmp uge i8 [[X]], [[SAT]]
-; CHECK-NEXT: ret i1 [[CMP]]
+; CHECK-NEXT: ret i1 true
;
%sat = call i8 @llvm.usub.sat.i8(i8 %x, i8 %y)
%cmp = icmp uge i8 %x, %sat
@@ -918,9 +904,7 @@ define i1 @usub_ule_commuted(i8 %x, i8 %y) {
define i1 @usub_ugt(i8 %x, i8 %y) {
; CHECK-LABEL: @usub_ugt(
-; CHECK-NEXT: [[SAT:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[SAT]], [[X]]
-; CHECK-NEXT: ret i1 [[CMP]]
+; CHECK-NEXT: ret i1 false
;
%sat = call i8 @llvm.usub.sat.i8(i8 %x, i8 %y)
%cmp = icmp ugt i8 %sat, %x