[ValueTracking] Simplify uaddo pattern (#65910)

This patch simplifies the overflow check of unsigned addition.

`a + b <u a` implies `a + b <u b`
`a + b >=u a` implies `a + b >=u b`

Alive2: https://alive2.llvm.org/ce/z/H8oK8n
Fixes #65863.
This commit is contained in:
Yingwei Zheng 2023-09-29 01:59:17 +08:00 committed by GitHub
parent 4b4d3832b1
commit 9f2fc88b23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 24 deletions

View File

@ -8292,6 +8292,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_ULT || LPred == ICmpInst::ICMP_UGE) &&
(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);

View File

@ -131,9 +131,7 @@ 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: [[COND_B:%.*]] = icmp uge i64 [[S]], [[B]]
; CHECK-NEXT: [[COND:%.*]] = and i1 [[COND_A]], [[COND_B]]
; CHECK-NEXT: ret i1 [[COND]]
; CHECK-NEXT: ret i1 [[COND_A]]
;
%s = add i64 %a, %b
%cond_a = icmp uge i64 %s, %a
@ -146,9 +144,7 @@ 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: [[COND_B:%.*]] = icmp uge i64 [[S]], [[B]]
; CHECK-NEXT: [[COND:%.*]] = and i1 [[COND_A]], [[COND_B]]
; CHECK-NEXT: ret i1 [[COND]]
; CHECK-NEXT: ret i1 [[COND_A]]
;
%s = add i64 %a, %b
%cond_a = icmp ule i64 %a, %s
@ -161,9 +157,7 @@ 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: [[COND_B:%.*]] = icmp ule i64 [[B]], [[S]]
; CHECK-NEXT: [[COND:%.*]] = and i1 [[COND_A]], [[COND_B]]
; CHECK-NEXT: ret i1 [[COND]]
; CHECK-NEXT: ret i1 [[COND_A]]
;
%s = add i64 %a, %b
%cond_a = icmp uge i64 %s, %a
@ -176,9 +170,7 @@ 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: [[COND_B:%.*]] = icmp ule i64 [[B]], [[S]]
; CHECK-NEXT: [[COND:%.*]] = and i1 [[COND_A]], [[COND_B]]
; CHECK-NEXT: ret i1 [[COND]]
; CHECK-NEXT: ret i1 [[COND_A]]
;
%s = add i64 %a, %b
%cond_a = icmp ule i64 %a, %s
@ -191,9 +183,7 @@ 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: [[COND_B:%.*]] = icmp ult i64 [[S]], [[B]]
; CHECK-NEXT: [[COND:%.*]] = or i1 [[COND_A]], [[COND_B]]
; CHECK-NEXT: ret i1 [[COND]]
; CHECK-NEXT: ret i1 [[COND_A]]
;
%s = add i64 %a, %b
%cond_a = icmp ult i64 %s, %a
@ -206,9 +196,7 @@ 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: [[COND_B:%.*]] = icmp ult i64 [[S]], [[B]]
; CHECK-NEXT: [[COND:%.*]] = or i1 [[COND_A]], [[COND_B]]
; CHECK-NEXT: ret i1 [[COND]]
; CHECK-NEXT: ret i1 [[COND_A]]
;
%s = add i64 %a, %b
%cond_a = icmp ugt i64 %a, %s
@ -221,9 +209,7 @@ 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: [[COND_B:%.*]] = icmp ugt i64 [[B]], [[S]]
; CHECK-NEXT: [[COND:%.*]] = or i1 [[COND_A]], [[COND_B]]
; CHECK-NEXT: ret i1 [[COND]]
; CHECK-NEXT: ret i1 [[COND_A]]
;
%s = add i64 %a, %b
%cond_a = icmp ult i64 %s, %a
@ -236,9 +222,7 @@ 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: [[COND_B:%.*]] = icmp ugt i64 [[B]], [[S]]
; CHECK-NEXT: [[COND:%.*]] = or i1 [[COND_A]], [[COND_B]]
; CHECK-NEXT: ret i1 [[COND]]
; CHECK-NEXT: ret i1 [[COND_A]]
;
%s = add i64 %a, %b
%cond_a = icmp ugt i64 %a, %s