Skip to content

Commit 3b7b235

Browse files
committed
[CodeGenPrepare] Prepare the usubo check with the opposite overflow condition
We check the overflow condition before codegenprepare makes it into the intrinsic, but not the opposite.
1 parent 4089c5d commit 3b7b235

File tree

3 files changed

+148
-54
lines changed

3 files changed

+148
-54
lines changed

llvm/lib/CodeGen/CodeGenPrepare.cpp

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -470,10 +470,11 @@ class CodeGenPrepare {
470470

471471
bool tryToSinkFreeOperands(Instruction *I);
472472
bool replaceMathCmpWithIntrinsic(BinaryOperator *BO, Value *Arg0, Value *Arg1,
473-
CmpInst *Cmp, Intrinsic::ID IID);
473+
CmpInst *Cmp, Intrinsic::ID IID, bool NegateOverflow = false);
474474
bool optimizeCmp(CmpInst *Cmp, ModifyDT &ModifiedDT);
475475
bool optimizeURem(Instruction *Rem);
476476
bool combineToUSubWithOverflow(CmpInst *Cmp, ModifyDT &ModifiedDT);
477+
bool combineToUSubWithNegatedOverflow(CmpInst *Cmp, ModifyDT &ModifiedDT);
477478
bool combineToUAddWithOverflow(CmpInst *Cmp, ModifyDT &ModifiedDT);
478479
bool unfoldPowerOf2Test(CmpInst *Cmp);
479480
void verifyBFIUpdates(Function &F);
@@ -1552,7 +1553,7 @@ static bool isIVIncrement(const Value *V, const LoopInfo *LI) {
15521553
bool CodeGenPrepare::replaceMathCmpWithIntrinsic(BinaryOperator *BO,
15531554
Value *Arg0, Value *Arg1,
15541555
CmpInst *Cmp,
1555-
Intrinsic::ID IID) {
1556+
Intrinsic::ID IID, bool NegateOverflow) {
15561557
auto IsReplacableIVIncrement = [this, &Cmp](BinaryOperator *BO) {
15571558
if (!isIVIncrement(BO, LI))
15581559
return false;
@@ -1624,6 +1625,8 @@ bool CodeGenPrepare::replaceMathCmpWithIntrinsic(BinaryOperator *BO,
16241625
assert(BO->hasOneUse() &&
16251626
"Patterns with XOr should use the BO only in the compare");
16261627
Value *OV = Builder.CreateExtractValue(MathOV, 1, "ov");
1628+
if (NegateOverflow)
1629+
OV = Builder.CreateXor(OV, ConstantInt::getAllOnesValue(OV->getType()));
16271630
replaceAllUsesWith(Cmp, OV, FreshBBs, IsHugeFunc);
16281631
Cmp->eraseFromParent();
16291632
BO->eraseFromParent();
@@ -1759,6 +1762,71 @@ bool CodeGenPrepare::combineToUSubWithOverflow(CmpInst *Cmp,
17591762
return true;
17601763
}
17611764

1765+
bool CodeGenPrepare::combineToUSubWithNegatedOverflow(CmpInst *Cmp,
1766+
ModifyDT &ModifiedDT) {
1767+
// We are not expecting non-canonical/degenerate code. Just bail out.
1768+
Value *A = Cmp->getOperand(0), *B = Cmp->getOperand(1);
1769+
if (isa<Constant>(A) && isa<Constant>(B))
1770+
return false;
1771+
1772+
// Convert (A u<= B) to (A u>= B) to simplify pattern matching.
1773+
ICmpInst::Predicate Pred = Cmp->getPredicate();
1774+
if (Pred == ICmpInst::ICMP_ULE) {
1775+
std::swap(A, B);
1776+
Pred = ICmpInst::ICMP_UGE;
1777+
}
1778+
// Convert special-case: (A != 0) is the same as (A u>= 1).
1779+
if (Pred == ICmpInst::ICMP_NE && match(B, m_ZeroInt())) {
1780+
B = ConstantInt::get(B->getType(), 1);
1781+
Pred = ICmpInst::ICMP_UGE;
1782+
}
1783+
1784+
// Convert special-case: (A == 0) is the same as (0 u>= A).
1785+
if (Pred == ICmpInst::ICMP_EQ && match(B, m_ZeroInt())) {
1786+
std::swap(A, B);
1787+
Pred = ICmpInst::ICMP_UGE;
1788+
}
1789+
1790+
if (Pred != ICmpInst::ICMP_UGE)
1791+
return false;
1792+
1793+
// Walk the users of a variable operand of a compare looking for a subtract or
1794+
// add with that same operand. Also match the 2nd operand of the compare to
1795+
// the add/sub, but that may be a negated constant operand of an add.
1796+
Value *CmpVariableOperand = isa<Constant>(A) ? B : A;
1797+
BinaryOperator *Sub = nullptr;
1798+
for (User *U : CmpVariableOperand->users()) {
1799+
// A - B, A u> B --> usubo(A, B)
1800+
if (match(U, m_Sub(m_Specific(A), m_Specific(B)))) {
1801+
Sub = cast<BinaryOperator>(U);
1802+
break;
1803+
}
1804+
1805+
// A + (-C), A u> C (canonicalized form of (sub A, C))
1806+
const APInt *CmpC, *AddC;
1807+
if (match(U, m_Add(m_Specific(A), m_APInt(AddC))) &&
1808+
match(B, m_APInt(CmpC)) && *AddC == -(*CmpC)) {
1809+
Sub = cast<BinaryOperator>(U);
1810+
break;
1811+
}
1812+
}
1813+
if (!Sub)
1814+
return false;
1815+
1816+
if (!TLI->shouldFormOverflowOp(ISD::USUBO,
1817+
TLI->getValueType(*DL, Sub->getType()),
1818+
Sub->hasNUsesOrMore(1)))
1819+
return false;
1820+
1821+
if (!replaceMathCmpWithIntrinsic(Sub, Sub->getOperand(0), Sub->getOperand(1),
1822+
Cmp, Intrinsic::usub_with_overflow, true))
1823+
return false;
1824+
1825+
// Reset callers - do not crash by iterating over a dead instruction.
1826+
ModifiedDT = ModifyDT::ModifyInstDT;
1827+
return true;
1828+
}
1829+
17621830
// Decanonicalizes icmp+ctpop power-of-two test if ctpop is slow.
17631831
// The same transformation exists in DAG combiner, but we repeat it here because
17641832
// DAG builder can break the pattern by moving icmp into a successor block.
@@ -2224,6 +2292,9 @@ bool CodeGenPrepare::optimizeCmp(CmpInst *Cmp, ModifyDT &ModifiedDT) {
22242292
if (combineToUSubWithOverflow(Cmp, ModifiedDT))
22252293
return true;
22262294

2295+
if (combineToUSubWithNegatedOverflow(Cmp, ModifiedDT))
2296+
return true;
2297+
22272298
if (unfoldPowerOf2Test(Cmp))
22282299
return true;
22292300

llvm/test/CodeGen/X86/sub-with-overflow.ll

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -111,14 +111,19 @@ define i1 @usubo_uge_i64_overflow_used(i64 %x, i64 %y, ptr %p) {
111111
define i1 @usubo_uge_i64_math_overflow_used(i64 %x, i64 %y, ptr %p) {
112112
; CHECK-LABEL: usubo_uge_i64_math_overflow_used:
113113
; CHECK: # %bb.0:
114-
; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax
114+
; CHECK-NEXT: pushl %esi
115+
; CHECK-NEXT: .cfi_def_cfa_offset 8
116+
; CHECK-NEXT: .cfi_offset %esi, -8
115117
; CHECK-NEXT: movl {{[0-9]+}}(%esp), %ecx
116118
; CHECK-NEXT: movl {{[0-9]+}}(%esp), %edx
117-
; CHECK-NEXT: subl {{[0-9]+}}(%esp), %ecx
118-
; CHECK-NEXT: movl %ecx, (%eax)
119-
; CHECK-NEXT: sbbl {{[0-9]+}}(%esp), %edx
120-
; CHECK-NEXT: movl %edx, 4(%eax)
119+
; CHECK-NEXT: movl {{[0-9]+}}(%esp), %esi
120+
; CHECK-NEXT: subl {{[0-9]+}}(%esp), %edx
121+
; CHECK-NEXT: sbbl {{[0-9]+}}(%esp), %esi
121122
; CHECK-NEXT: setae %al
123+
; CHECK-NEXT: movl %edx, (%ecx)
124+
; CHECK-NEXT: movl %esi, 4(%ecx)
125+
; CHECK-NEXT: popl %esi
126+
; CHECK-NEXT: .cfi_def_cfa_offset 4
122127
; CHECK-NEXT: retl
123128
%s = sub i64 %x, %y
124129
store i64 %s, ptr %p
@@ -141,13 +146,11 @@ define i1 @usubo_ule_i32_overflow_used(i32 %x, i32 %y, ptr %p) {
141146
define i1 @usubo_ne_zero_i16_overflow_used(i16 %x, ptr %p) {
142147
; CHECK-LABEL: usubo_ne_zero_i16_overflow_used:
143148
; CHECK: # %bb.0:
144-
; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax
145149
; CHECK-NEXT: movl {{[0-9]+}}(%esp), %ecx
146-
; CHECK-NEXT: movl %eax, %edx
147-
; CHECK-NEXT: decl %edx
150+
; CHECK-NEXT: movzwl {{[0-9]+}}(%esp), %edx
151+
; CHECK-NEXT: subw $1, %dx
152+
; CHECK-NEXT: setae %al
148153
; CHECK-NEXT: movw %dx, (%ecx)
149-
; CHECK-NEXT: testw %ax, %ax
150-
; CHECK-NEXT: setne %al
151154
; CHECK-NEXT: retl
152155
%s = sub i16 %x, 1
153156
store i16 %s, ptr %p
@@ -158,11 +161,11 @@ define i1 @usubo_ne_zero_i16_overflow_used(i16 %x, ptr %p) {
158161
define i1 @usubo_eq_zero_i8_overflow_used(i8 %x, ptr %p) {
159162
; CHECK-LABEL: usubo_eq_zero_i8_overflow_used:
160163
; CHECK: # %bb.0:
161-
; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax
162-
; CHECK-NEXT: movzbl {{[0-9]+}}(%esp), %ecx
163-
; CHECK-NEXT: negb %cl
164-
; CHECK-NEXT: movb %cl, (%eax)
164+
; CHECK-NEXT: movl {{[0-9]+}}(%esp), %ecx
165+
; CHECK-NEXT: xorl %edx, %edx
166+
; CHECK-NEXT: subb {{[0-9]+}}(%esp), %dl
165167
; CHECK-NEXT: setae %al
168+
; CHECK-NEXT: movb %dl, (%ecx)
166169
; CHECK-NEXT: retl
167170
%s = sub i8 0, %x
168171
store i8 %s, ptr %p

llvm/test/Transforms/CodeGenPrepare/X86/overflow-intrinsics.ll

Lines changed: 58 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,16 +1006,20 @@ exit:
10061006

10071007
define i1 @usubo_uge_i64_overflow_used(i64 %x, i64 %y, ptr %p) {
10081008
; CHECK-LABEL: @usubo_uge_i64_overflow_used(
1009-
; CHECK-NEXT: [[S:%.*]] = sub i64 [[X:%.*]], [[Y:%.*]]
1010-
; CHECK-NEXT: [[OV:%.*]] = icmp uge i64 [[X]], [[Y]]
1009+
; CHECK-NEXT: [[TMP1:%.*]] = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 [[X:%.*]], i64 [[Y:%.*]])
1010+
; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
1011+
; CHECK-NEXT: [[OV1:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
1012+
; CHECK-NEXT: [[OV:%.*]] = xor i1 [[OV1]], true
10111013
; CHECK-NEXT: ret i1 [[OV]]
10121014
;
10131015
; DEBUG-LABEL: @usubo_uge_i64_overflow_used(
1014-
; DEBUG-NEXT: [[S:%.*]] = sub i64 [[X:%.*]], [[Y:%.*]], !dbg [[DBG340:![0-9]+]]
1015-
; DEBUG-NEXT: #dbg_value(i64 [[S]], [[META338:![0-9]+]], !DIExpression(), [[DBG340]])
1016-
; DEBUG-NEXT: [[OV:%.*]] = icmp uge i64 [[X]], [[Y]], !dbg [[DBG341:![0-9]+]]
1017-
; DEBUG-NEXT: #dbg_value(i1 [[OV]], [[META339:![0-9]+]], !DIExpression(), [[DBG341]])
1018-
; DEBUG-NEXT: ret i1 [[OV]], !dbg [[DBG342:![0-9]+]]
1016+
; DEBUG-NEXT: [[TMP1:%.*]] = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 [[X:%.*]], i64 [[Y:%.*]]), !dbg [[DBG340:![0-9]+]]
1017+
; DEBUG-NEXT: [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0, !dbg [[DBG340]]
1018+
; DEBUG-NEXT: [[OV1:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1, !dbg [[DBG340]]
1019+
; DEBUG-NEXT: [[TMP2:%.*]] = xor i1 [[OV1]], true, !dbg [[DBG340]]
1020+
; DEBUG-NEXT: #dbg_value(i64 [[MATH]], [[META338:![0-9]+]], !DIExpression(), [[DBG340]])
1021+
; DEBUG-NEXT: #dbg_value(i1 [[TMP2]], [[META339:![0-9]+]], !DIExpression(), [[META341:![0-9]+]])
1022+
; DEBUG-NEXT: ret i1 [[TMP2]], !dbg [[DBG342:![0-9]+]]
10191023
;
10201024
%s = sub i64 %x, %y
10211025
%ov = icmp uge i64 %x, %y
@@ -1024,18 +1028,22 @@ define i1 @usubo_uge_i64_overflow_used(i64 %x, i64 %y, ptr %p) {
10241028

10251029
define i1 @usubo_uge_i64_math_overflow_used(i64 %x, i64 %y, ptr %p) {
10261030
; CHECK-LABEL: @usubo_uge_i64_math_overflow_used(
1027-
; CHECK-NEXT: [[S:%.*]] = sub i64 [[X:%.*]], [[Y:%.*]]
1031+
; CHECK-NEXT: [[TMP1:%.*]] = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 [[X:%.*]], i64 [[Y:%.*]])
1032+
; CHECK-NEXT: [[S:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
1033+
; CHECK-NEXT: [[OV1:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
1034+
; CHECK-NEXT: [[OV:%.*]] = xor i1 [[OV1]], true
10281035
; CHECK-NEXT: store i64 [[S]], ptr [[P:%.*]], align 8
1029-
; CHECK-NEXT: [[OV:%.*]] = icmp uge i64 [[X]], [[Y]]
10301036
; CHECK-NEXT: ret i1 [[OV]]
10311037
;
10321038
; DEBUG-LABEL: @usubo_uge_i64_math_overflow_used(
1033-
; DEBUG-NEXT: [[S:%.*]] = sub i64 [[X:%.*]], [[Y:%.*]], !dbg [[DBG347:![0-9]+]]
1034-
; DEBUG-NEXT: #dbg_value(i64 [[S]], [[META345:![0-9]+]], !DIExpression(), [[DBG347]])
1035-
; DEBUG-NEXT: store i64 [[S]], ptr [[P:%.*]], align 8, !dbg [[DBG348:![0-9]+]]
1036-
; DEBUG-NEXT: [[OV:%.*]] = icmp uge i64 [[X]], [[Y]], !dbg [[DBG349:![0-9]+]]
1037-
; DEBUG-NEXT: #dbg_value(i1 [[OV]], [[META346:![0-9]+]], !DIExpression(), [[DBG349]])
1038-
; DEBUG-NEXT: ret i1 [[OV]], !dbg [[DBG350:![0-9]+]]
1039+
; DEBUG-NEXT: [[TMP1:%.*]] = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 [[X:%.*]], i64 [[Y:%.*]]), !dbg [[DBG347:![0-9]+]]
1040+
; DEBUG-NEXT: [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0, !dbg [[DBG347]]
1041+
; DEBUG-NEXT: [[OV1:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1, !dbg [[DBG347]]
1042+
; DEBUG-NEXT: [[TMP2:%.*]] = xor i1 [[OV1]], true, !dbg [[DBG347]]
1043+
; DEBUG-NEXT: #dbg_value(i64 [[MATH]], [[META345:![0-9]+]], !DIExpression(), [[DBG347]])
1044+
; DEBUG-NEXT: store i64 [[MATH]], ptr [[P:%.*]], align 8, !dbg [[DBG348:![0-9]+]]
1045+
; DEBUG-NEXT: #dbg_value(i1 [[TMP2]], [[META346:![0-9]+]], !DIExpression(), [[META349:![0-9]+]])
1046+
; DEBUG-NEXT: ret i1 [[TMP2]], !dbg [[DBG350:![0-9]+]]
10391047
;
10401048
%s = sub i64 %x, %y
10411049
store i64 %s, ptr %p
@@ -1045,16 +1053,20 @@ define i1 @usubo_uge_i64_math_overflow_used(i64 %x, i64 %y, ptr %p) {
10451053

10461054
define i1 @usubo_ule_i32_overflow_used(i32 %x, i32 %y, ptr %p) {
10471055
; CHECK-LABEL: @usubo_ule_i32_overflow_used(
1048-
; CHECK-NEXT: [[S:%.*]] = sub i32 [[Y:%.*]], [[X:%.*]]
1049-
; CHECK-NEXT: [[OV:%.*]] = icmp uge i32 [[Y]], [[X]]
1056+
; CHECK-NEXT: [[TMP1:%.*]] = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 [[Y:%.*]], i32 [[X:%.*]])
1057+
; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0
1058+
; CHECK-NEXT: [[OV1:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
1059+
; CHECK-NEXT: [[OV:%.*]] = xor i1 [[OV1]], true
10501060
; CHECK-NEXT: ret i1 [[OV]]
10511061
;
10521062
; DEBUG-LABEL: @usubo_ule_i32_overflow_used(
1053-
; DEBUG-NEXT: [[S:%.*]] = sub i32 [[Y:%.*]], [[X:%.*]], !dbg [[DBG355:![0-9]+]]
1054-
; DEBUG-NEXT: #dbg_value(i32 [[S]], [[META353:![0-9]+]], !DIExpression(), [[DBG355]])
1055-
; DEBUG-NEXT: [[OV:%.*]] = icmp uge i32 [[Y]], [[X]], !dbg [[DBG356:![0-9]+]]
1056-
; DEBUG-NEXT: #dbg_value(i1 [[OV]], [[META354:![0-9]+]], !DIExpression(), [[DBG356]])
1057-
; DEBUG-NEXT: ret i1 [[OV]], !dbg [[DBG357:![0-9]+]]
1063+
; DEBUG-NEXT: [[TMP1:%.*]] = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 [[Y:%.*]], i32 [[X:%.*]]), !dbg [[DBG355:![0-9]+]]
1064+
; DEBUG-NEXT: [[MATH:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0, !dbg [[DBG355]]
1065+
; DEBUG-NEXT: [[OV1:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1, !dbg [[DBG355]]
1066+
; DEBUG-NEXT: [[TMP2:%.*]] = xor i1 [[OV1]], true, !dbg [[DBG355]]
1067+
; DEBUG-NEXT: #dbg_value(i32 [[MATH]], [[META353:![0-9]+]], !DIExpression(), [[DBG355]])
1068+
; DEBUG-NEXT: #dbg_value(i1 [[TMP2]], [[META354:![0-9]+]], !DIExpression(), [[META356:![0-9]+]])
1069+
; DEBUG-NEXT: ret i1 [[TMP2]], !dbg [[DBG357:![0-9]+]]
10581070
;
10591071
%s = sub i32 %y, %x
10601072
%ov = icmp ule i32 %x, %y
@@ -1063,18 +1075,22 @@ define i1 @usubo_ule_i32_overflow_used(i32 %x, i32 %y, ptr %p) {
10631075

10641076
define i1 @usubo_ne_zero_i16_overflow_used(i16 %x, ptr %p) {
10651077
; CHECK-LABEL: @usubo_ne_zero_i16_overflow_used(
1066-
; CHECK-NEXT: [[S:%.*]] = sub i16 [[X:%.*]], 1
1078+
; CHECK-NEXT: [[TMP1:%.*]] = call { i16, i1 } @llvm.usub.with.overflow.i16(i16 [[X:%.*]], i16 1)
1079+
; CHECK-NEXT: [[S:%.*]] = extractvalue { i16, i1 } [[TMP1]], 0
1080+
; CHECK-NEXT: [[OV1:%.*]] = extractvalue { i16, i1 } [[TMP1]], 1
1081+
; CHECK-NEXT: [[OV:%.*]] = xor i1 [[OV1]], true
10671082
; CHECK-NEXT: store i16 [[S]], ptr [[P:%.*]], align 2
1068-
; CHECK-NEXT: [[OV:%.*]] = icmp ne i16 [[X]], 0
10691083
; CHECK-NEXT: ret i1 [[OV]]
10701084
;
10711085
; DEBUG-LABEL: @usubo_ne_zero_i16_overflow_used(
1072-
; DEBUG-NEXT: [[S:%.*]] = sub i16 [[X:%.*]], 1, !dbg [[DBG362:![0-9]+]]
1073-
; DEBUG-NEXT: #dbg_value(i16 [[S]], [[META360:![0-9]+]], !DIExpression(), [[DBG362]])
1074-
; DEBUG-NEXT: store i16 [[S]], ptr [[P:%.*]], align 2, !dbg [[DBG363:![0-9]+]]
1075-
; DEBUG-NEXT: [[OV:%.*]] = icmp ne i16 [[X]], 0, !dbg [[DBG364:![0-9]+]]
1076-
; DEBUG-NEXT: #dbg_value(i1 [[OV]], [[META361:![0-9]+]], !DIExpression(), [[DBG364]])
1077-
; DEBUG-NEXT: ret i1 [[OV]], !dbg [[DBG365:![0-9]+]]
1086+
; DEBUG-NEXT: [[TMP1:%.*]] = call { i16, i1 } @llvm.usub.with.overflow.i16(i16 [[X:%.*]], i16 1), !dbg [[DBG362:![0-9]+]]
1087+
; DEBUG-NEXT: [[MATH:%.*]] = extractvalue { i16, i1 } [[TMP1]], 0, !dbg [[DBG362]]
1088+
; DEBUG-NEXT: [[OV1:%.*]] = extractvalue { i16, i1 } [[TMP1]], 1, !dbg [[DBG362]]
1089+
; DEBUG-NEXT: [[TMP2:%.*]] = xor i1 [[OV1]], true, !dbg [[DBG362]]
1090+
; DEBUG-NEXT: #dbg_value(i16 [[MATH]], [[META360:![0-9]+]], !DIExpression(), [[DBG362]])
1091+
; DEBUG-NEXT: store i16 [[MATH]], ptr [[P:%.*]], align 2, !dbg [[DBG363:![0-9]+]]
1092+
; DEBUG-NEXT: #dbg_value(i1 [[TMP2]], [[META361:![0-9]+]], !DIExpression(), [[META364:![0-9]+]])
1093+
; DEBUG-NEXT: ret i1 [[TMP2]], !dbg [[DBG365:![0-9]+]]
10781094
;
10791095
%s = sub i16 %x, 1
10801096
store i16 %s, ptr %p
@@ -1084,18 +1100,22 @@ define i1 @usubo_ne_zero_i16_overflow_used(i16 %x, ptr %p) {
10841100

10851101
define i1 @usubo_eq_zero_i8_overflow_used(i8 %x, ptr %p) {
10861102
; CHECK-LABEL: @usubo_eq_zero_i8_overflow_used(
1087-
; CHECK-NEXT: [[S:%.*]] = sub i8 0, [[X:%.*]]
1103+
; CHECK-NEXT: [[TMP1:%.*]] = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 0, i8 [[X:%.*]])
1104+
; CHECK-NEXT: [[S:%.*]] = extractvalue { i8, i1 } [[TMP1]], 0
1105+
; CHECK-NEXT: [[OV1:%.*]] = extractvalue { i8, i1 } [[TMP1]], 1
1106+
; CHECK-NEXT: [[OV:%.*]] = xor i1 [[OV1]], true
10881107
; CHECK-NEXT: store i8 [[S]], ptr [[P:%.*]], align 1
1089-
; CHECK-NEXT: [[OV:%.*]] = icmp eq i8 [[X]], 0
10901108
; CHECK-NEXT: ret i1 [[OV]]
10911109
;
10921110
; DEBUG-LABEL: @usubo_eq_zero_i8_overflow_used(
1093-
; DEBUG-NEXT: [[S:%.*]] = sub i8 0, [[X:%.*]], !dbg [[DBG370:![0-9]+]]
1094-
; DEBUG-NEXT: #dbg_value(i8 [[S]], [[META368:![0-9]+]], !DIExpression(), [[DBG370]])
1095-
; DEBUG-NEXT: store i8 [[S]], ptr [[P:%.*]], align 1, !dbg [[DBG371:![0-9]+]]
1096-
; DEBUG-NEXT: [[OV:%.*]] = icmp eq i8 [[X]], 0, !dbg [[DBG372:![0-9]+]]
1097-
; DEBUG-NEXT: #dbg_value(i1 [[OV]], [[META369:![0-9]+]], !DIExpression(), [[DBG372]])
1098-
; DEBUG-NEXT: ret i1 [[OV]], !dbg [[DBG373:![0-9]+]]
1111+
; DEBUG-NEXT: [[TMP1:%.*]] = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 0, i8 [[X:%.*]]), !dbg [[DBG370:![0-9]+]]
1112+
; DEBUG-NEXT: [[MATH:%.*]] = extractvalue { i8, i1 } [[TMP1]], 0, !dbg [[DBG370]]
1113+
; DEBUG-NEXT: [[OV1:%.*]] = extractvalue { i8, i1 } [[TMP1]], 1, !dbg [[DBG370]]
1114+
; DEBUG-NEXT: [[TMP2:%.*]] = xor i1 [[OV1]], true, !dbg [[DBG370]]
1115+
; DEBUG-NEXT: #dbg_value(i8 [[MATH]], [[META368:![0-9]+]], !DIExpression(), [[DBG370]])
1116+
; DEBUG-NEXT: store i8 [[MATH]], ptr [[P:%.*]], align 1, !dbg [[DBG371:![0-9]+]]
1117+
; DEBUG-NEXT: #dbg_value(i1 [[TMP2]], [[META369:![0-9]+]], !DIExpression(), [[META372:![0-9]+]])
1118+
; DEBUG-NEXT: ret i1 [[TMP2]], !dbg [[DBG373:![0-9]+]]
10991119
;
11001120
%s = sub i8 0, %x
11011121
store i8 %s, ptr %p

0 commit comments

Comments
 (0)