Skip to content

Commit a06e72d

Browse files
author
git apple-llvm automerger
committed
Merge commit '8511a8df838f' from llvm.org/release/11.x into apple/stable/20200714
2 parents 9caf3bc + 8511a8d commit a06e72d

File tree

2 files changed

+27
-17
lines changed

2 files changed

+27
-17
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -782,25 +782,24 @@ static Value *canonicalizeSaturatedAdd(ICmpInst *Cmp, Value *TVal, Value *FVal,
782782

783783
// Match unsigned saturated add of 2 variables with an unnecessary 'not'.
784784
// There are 8 commuted variants.
785-
// Canonicalize -1 (saturated result) to true value of the select. Just
786-
// swapping the compare operands is legal, because the selected value is the
787-
// same in case of equality, so we can interchange u< and u<=.
785+
// Canonicalize -1 (saturated result) to true value of the select.
788786
if (match(FVal, m_AllOnes())) {
789787
std::swap(TVal, FVal);
790-
std::swap(Cmp0, Cmp1);
788+
Pred = CmpInst::getInversePredicate(Pred);
791789
}
792790
if (!match(TVal, m_AllOnes()))
793791
return nullptr;
794792

795-
// Canonicalize predicate to 'ULT'.
796-
if (Pred == ICmpInst::ICMP_UGT) {
797-
Pred = ICmpInst::ICMP_ULT;
793+
// Canonicalize predicate to less-than or less-or-equal-than.
794+
if (Pred == ICmpInst::ICMP_UGT || Pred == ICmpInst::ICMP_UGE) {
798795
std::swap(Cmp0, Cmp1);
796+
Pred = CmpInst::getSwappedPredicate(Pred);
799797
}
800-
if (Pred != ICmpInst::ICMP_ULT)
798+
if (Pred != ICmpInst::ICMP_ULT && Pred != ICmpInst::ICMP_ULE)
801799
return nullptr;
802800

803801
// Match unsigned saturated add of 2 variables with an unnecessary 'not'.
802+
// Strictness of the comparison is irrelevant.
804803
Value *Y;
805804
if (match(Cmp0, m_Not(m_Value(X))) &&
806805
match(FVal, m_c_Add(m_Specific(X), m_Value(Y))) && Y == Cmp1) {
@@ -809,6 +808,7 @@ static Value *canonicalizeSaturatedAdd(ICmpInst *Cmp, Value *TVal, Value *FVal,
809808
return Builder.CreateBinaryIntrinsic(Intrinsic::uadd_sat, X, Y);
810809
}
811810
// The 'not' op may be included in the sum but not the compare.
811+
// Strictness of the comparison is irrelevant.
812812
X = Cmp0;
813813
Y = Cmp1;
814814
if (match(FVal, m_c_Add(m_Not(m_Specific(X)), m_Specific(Y)))) {
@@ -819,7 +819,9 @@ static Value *canonicalizeSaturatedAdd(ICmpInst *Cmp, Value *TVal, Value *FVal,
819819
Intrinsic::uadd_sat, BO->getOperand(0), BO->getOperand(1));
820820
}
821821
// The overflow may be detected via the add wrapping round.
822-
if (match(Cmp0, m_c_Add(m_Specific(Cmp1), m_Value(Y))) &&
822+
// This is only valid for strict comparison!
823+
if (Pred == ICmpInst::ICMP_ULT &&
824+
match(Cmp0, m_c_Add(m_Specific(Cmp1), m_Value(Y))) &&
823825
match(FVal, m_c_Add(m_Specific(Cmp1), m_Specific(Y)))) {
824826
// ((X + Y) u< X) ? -1 : (X + Y) --> uadd.sat(X, Y)
825827
// ((X + Y) u< Y) ? -1 : (X + Y) --> uadd.sat(X, Y)

llvm/test/Transforms/InstCombine/saturating-add-sub.ll

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1804,8 +1804,10 @@ define i32 @uadd_sat_via_add(i32 %x, i32 %y) {
18041804

18051805
define i32 @uadd_sat_via_add_nonstrict(i32 %x, i32 %y) {
18061806
; CHECK-LABEL: @uadd_sat_via_add_nonstrict(
1807-
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[Y:%.*]], i32 [[X:%.*]])
1808-
; CHECK-NEXT: ret i32 [[TMP1]]
1807+
; CHECK-NEXT: [[A:%.*]] = add i32 [[X:%.*]], [[Y:%.*]]
1808+
; CHECK-NEXT: [[C_NOT:%.*]] = icmp ugt i32 [[A]], [[Y]]
1809+
; CHECK-NEXT: [[R:%.*]] = select i1 [[C_NOT]], i32 [[A]], i32 -1
1810+
; CHECK-NEXT: ret i32 [[R]]
18091811
;
18101812
%a = add i32 %x, %y
18111813
%c = icmp ule i32 %a, %y
@@ -1826,8 +1828,10 @@ define i32 @uadd_sat_via_add_swapped_select(i32 %x, i32 %y) {
18261828

18271829
define i32 @uadd_sat_via_add_swapped_select_strict(i32 %x, i32 %y) {
18281830
; CHECK-LABEL: @uadd_sat_via_add_swapped_select_strict(
1829-
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[Y:%.*]], i32 [[X:%.*]])
1830-
; CHECK-NEXT: ret i32 [[TMP1]]
1831+
; CHECK-NEXT: [[A:%.*]] = add i32 [[X:%.*]], [[Y:%.*]]
1832+
; CHECK-NEXT: [[C:%.*]] = icmp ugt i32 [[A]], [[Y]]
1833+
; CHECK-NEXT: [[R:%.*]] = select i1 [[C]], i32 [[A]], i32 -1
1834+
; CHECK-NEXT: ret i32 [[R]]
18311835
;
18321836
%a = add i32 %x, %y
18331837
%c = icmp ugt i32 %a, %y
@@ -1848,8 +1852,10 @@ define i32 @uadd_sat_via_add_swapped_cmp(i32 %x, i32 %y) {
18481852

18491853
define i32 @uadd_sat_via_add_swapped_cmp_nonstrict(i32 %x, i32 %y) {
18501854
; CHECK-LABEL: @uadd_sat_via_add_swapped_cmp_nonstrict(
1851-
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[Y:%.*]], i32 [[X:%.*]])
1852-
; CHECK-NEXT: ret i32 [[TMP1]]
1855+
; CHECK-NEXT: [[A:%.*]] = add i32 [[X:%.*]], [[Y:%.*]]
1856+
; CHECK-NEXT: [[C_NOT:%.*]] = icmp ugt i32 [[A]], [[Y]]
1857+
; CHECK-NEXT: [[R:%.*]] = select i1 [[C_NOT]], i32 [[A]], i32 -1
1858+
; CHECK-NEXT: ret i32 [[R]]
18531859
;
18541860
%a = add i32 %x, %y
18551861
%c = icmp uge i32 %y, %a
@@ -1870,8 +1876,10 @@ define i32 @uadd_sat_via_add_swapped_cmp_nonstric(i32 %x, i32 %y) {
18701876

18711877
define i32 @uadd_sat_via_add_swapped_cmp_select_nonstrict(i32 %x, i32 %y) {
18721878
; CHECK-LABEL: @uadd_sat_via_add_swapped_cmp_select_nonstrict(
1873-
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[Y:%.*]], i32 [[X:%.*]])
1874-
; CHECK-NEXT: ret i32 [[TMP1]]
1879+
; CHECK-NEXT: [[A:%.*]] = add i32 [[X:%.*]], [[Y:%.*]]
1880+
; CHECK-NEXT: [[C:%.*]] = icmp ugt i32 [[A]], [[Y]]
1881+
; CHECK-NEXT: [[R:%.*]] = select i1 [[C]], i32 [[A]], i32 -1
1882+
; CHECK-NEXT: ret i32 [[R]]
18751883
;
18761884
%a = add i32 %x, %y
18771885
%c = icmp ult i32 %y, %a

0 commit comments

Comments
 (0)