[clang] [ValueTracking] Simplify uaddo pattern (PR #65910)
Yingwei Zheng via cfe-commits
cfe-commits at lists.llvm.org
Sat Sep 16 05:21:53 PDT 2023
https://github.com/dtcxzyw updated https://github.com/llvm/llvm-project/pull/65910
>From 9bb817aa40dd9bc1bbb18b4cf4bc079145c8ecaa Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Mon, 11 Sep 2023 03:58:02 +0800
Subject: [PATCH] [ValueTracking] Simplify uaddo pattern
---
llvm/lib/Analysis/ValueTracking.cpp | 23 ++++
.../InstSimplify/and-or-implied-cond.ll | 104 ++++++++++++++++++
2 files changed, 127 insertions(+)
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index c4153b824c37e0a..5aaff4ee81be969 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -8291,6 +8291,29 @@ static std::optional<bool> isImpliedCondICmps(const ICmpInst *LHS,
if (L0 == R0 && match(L1, m_APInt(LC)) && match(R1, m_APInt(RC)))
return isImpliedCondCommonOperandWithConstants(LPred, *LC, RPred, *RC);
+ // L0 = R0 = L1 + R1, L0 >=u L1 implies R0 >=u R1, L0 <u L1 implies R0 <u R1
+ if (ICmpInst::isUnsigned(LPred) && ICmpInst::isUnsigned(RPred)) {
+ if (L0 == R1) {
+ std::swap(R0, R1);
+ RPred = ICmpInst::getSwappedPredicate(RPred);
+ }
+ if (L1 == R0) {
+ std::swap(L0, L1);
+ LPred = ICmpInst::getSwappedPredicate(LPred);
+ }
+ if (L1 == R1) {
+ std::swap(L0, L1);
+ LPred = ICmpInst::getSwappedPredicate(LPred);
+ std::swap(R0, R1);
+ RPred = ICmpInst::getSwappedPredicate(RPred);
+ }
+ if (L0 == R0 &&
+ (LPred == ICmpInst::ICMP_UGE || LPred == ICmpInst::ICMP_ULT) &&
+ (RPred == ICmpInst::ICMP_ULT || RPred == ICmpInst::ICMP_UGE) &&
+ match(L0, m_c_Add(m_Specific(L1), m_Specific(R1))))
+ return LPred == RPred;
+ }
+
if (LPred == RPred)
return isImpliedCondOperands(LPred, L0, L1, R0, R1, DL, Depth);
diff --git a/llvm/test/Transforms/InstSimplify/and-or-implied-cond.ll b/llvm/test/Transforms/InstSimplify/and-or-implied-cond.ll
index 90b0abd40cb4400..df442dd8f185c81 100644
--- a/llvm/test/Transforms/InstSimplify/and-or-implied-cond.ll
+++ b/llvm/test/Transforms/InstSimplify/and-or-implied-cond.ll
@@ -126,3 +126,107 @@ define i1 @and_not_implied(i8 %x, i1 %c) {
%and = and i1 %or, %cmp2
ret i1 %and
}
+
+define i1 @uaddo_and(i64 %a, i64 %b){
+; CHECK-LABEL: @uaddo_and(
+; CHECK-NEXT: [[S:%.*]] = add i64 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[COND_A:%.*]] = icmp uge i64 [[S]], [[A]]
+; CHECK-NEXT: ret i1 [[COND_A]]
+;
+ %s = add i64 %a, %b
+ %cond_a = icmp uge i64 %s, %a
+ %cond_b = icmp uge i64 %s, %b
+ %cond = and i1 %cond_a, %cond_b
+ ret i1 %cond
+}
+
+define i1 @uaddo_and_commuted1(i64 %a, i64 %b){
+; CHECK-LABEL: @uaddo_and_commuted1(
+; CHECK-NEXT: [[S:%.*]] = add i64 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[COND_A:%.*]] = icmp ule i64 [[A]], [[S]]
+; CHECK-NEXT: ret i1 [[COND_A]]
+;
+ %s = add i64 %a, %b
+ %cond_a = icmp ule i64 %a, %s
+ %cond_b = icmp uge i64 %s, %b
+ %cond = and i1 %cond_a, %cond_b
+ ret i1 %cond
+}
+
+define i1 @uaddo_and_commuted2(i64 %a, i64 %b){
+; CHECK-LABEL: @uaddo_and_commuted2(
+; CHECK-NEXT: [[S:%.*]] = add i64 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[COND_A:%.*]] = icmp uge i64 [[S]], [[A]]
+; CHECK-NEXT: ret i1 [[COND_A]]
+;
+ %s = add i64 %a, %b
+ %cond_a = icmp uge i64 %s, %a
+ %cond_b = icmp ule i64 %b, %s
+ %cond = and i1 %cond_a, %cond_b
+ ret i1 %cond
+}
+
+define i1 @uaddo_and_commuted3(i64 %a, i64 %b){
+; CHECK-LABEL: @uaddo_and_commuted3(
+; CHECK-NEXT: [[S:%.*]] = add i64 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[COND_A:%.*]] = icmp ule i64 [[A]], [[S]]
+; CHECK-NEXT: ret i1 [[COND_A]]
+;
+ %s = add i64 %a, %b
+ %cond_a = icmp ule i64 %a, %s
+ %cond_b = icmp ule i64 %b, %s
+ %cond = and i1 %cond_a, %cond_b
+ ret i1 %cond
+}
+
+define i1 @uaddo_or(i64 %a, i64 %b){
+; CHECK-LABEL: @uaddo_or(
+; CHECK-NEXT: [[S:%.*]] = add i64 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[COND_A:%.*]] = icmp ult i64 [[S]], [[A]]
+; CHECK-NEXT: ret i1 [[COND_A]]
+;
+ %s = add i64 %a, %b
+ %cond_a = icmp ult i64 %s, %a
+ %cond_b = icmp ult i64 %s, %b
+ %cond = or i1 %cond_a, %cond_b
+ ret i1 %cond
+}
+
+define i1 @uaddo_or_commuted1(i64 %a, i64 %b){
+; CHECK-LABEL: @uaddo_or_commuted1(
+; CHECK-NEXT: [[S:%.*]] = add i64 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[COND_A:%.*]] = icmp ugt i64 [[A]], [[S]]
+; CHECK-NEXT: ret i1 [[COND_A]]
+;
+ %s = add i64 %a, %b
+ %cond_a = icmp ugt i64 %a, %s
+ %cond_b = icmp ult i64 %s, %b
+ %cond = or i1 %cond_a, %cond_b
+ ret i1 %cond
+}
+
+define i1 @uaddo_or_commuted2(i64 %a, i64 %b){
+; CHECK-LABEL: @uaddo_or_commuted2(
+; CHECK-NEXT: [[S:%.*]] = add i64 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[COND_A:%.*]] = icmp ult i64 [[S]], [[A]]
+; CHECK-NEXT: ret i1 [[COND_A]]
+;
+ %s = add i64 %a, %b
+ %cond_a = icmp ult i64 %s, %a
+ %cond_b = icmp ugt i64 %b, %s
+ %cond = or i1 %cond_a, %cond_b
+ ret i1 %cond
+}
+
+define i1 @uaddo_or_commuted3(i64 %a, i64 %b){
+; CHECK-LABEL: @uaddo_or_commuted3(
+; CHECK-NEXT: [[S:%.*]] = add i64 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[COND_A:%.*]] = icmp ugt i64 [[A]], [[S]]
+; CHECK-NEXT: ret i1 [[COND_A]]
+;
+ %s = add i64 %a, %b
+ %cond_a = icmp ugt i64 %a, %s
+ %cond_b = icmp ugt i64 %b, %s
+ %cond = or i1 %cond_a, %cond_b
+ ret i1 %cond
+}
More information about the cfe-commits
mailing list