Skip to content

Commit 8acbe83

Browse files
committed
[ValueTracking] Use assume to compute overflowResult.
1 parent 61157d1 commit 8acbe83

File tree

2 files changed

+48
-35
lines changed

2 files changed

+48
-35
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7177,10 +7177,33 @@ llvm::computeConstantRangeIncludingKnownBits(const WithCache<const Value *> &V,
71777177
return CR1.intersectWith(CR2, RangeType);
71787178
}
71797179

7180+
static bool isKnownToNotOverflowFromAssume(const SimplifyQuery &Q) {
7181+
// Use of assumptions is context-sensitive. If we don't have a context, we
7182+
// cannot use them!
7183+
if (!Q.AC || !Q.CxtI)
7184+
return false;
7185+
7186+
for (AssumptionCache::ResultElem &Elem : Q.AC->assumptionsFor(Q.CxtI)) {
7187+
if (!Elem.Assume)
7188+
continue;
7189+
7190+
AssumeInst *I = cast<AssumeInst>(Elem.Assume);
7191+
if (match(I->getArgOperand(0),
7192+
m_Not(m_ExtractValue<1>(m_Specific(Q.CxtI)))) &&
7193+
isValidAssumeForContext(I, Q.CxtI, /*DT=*/nullptr,
7194+
/*AllowEphemerals=*/true))
7195+
return true;
7196+
}
7197+
return false;
7198+
}
7199+
71807200
OverflowResult llvm::computeOverflowForUnsignedMul(const Value *LHS,
71817201
const Value *RHS,
71827202
const SimplifyQuery &SQ,
71837203
bool IsNSW) {
7204+
if (isKnownToNotOverflowFromAssume(SQ))
7205+
return OverflowResult::NeverOverflows;
7206+
71847207
KnownBits LHSKnown = computeKnownBits(LHS, /*Depth=*/0, SQ);
71857208
KnownBits RHSKnown = computeKnownBits(RHS, /*Depth=*/0, SQ);
71867209

@@ -7196,6 +7219,9 @@ OverflowResult llvm::computeOverflowForUnsignedMul(const Value *LHS,
71967219
OverflowResult llvm::computeOverflowForSignedMul(const Value *LHS,
71977220
const Value *RHS,
71987221
const SimplifyQuery &SQ) {
7222+
if (isKnownToNotOverflowFromAssume(SQ))
7223+
return OverflowResult::NeverOverflows;
7224+
71997225
// Multiplying n * m significant bits yields a result of n + m significant
72007226
// bits. If the total number of significant bits does not exceed the
72017227
// result bit width (minus 1), there is no overflow.
@@ -7236,6 +7262,9 @@ OverflowResult
72367262
llvm::computeOverflowForUnsignedAdd(const WithCache<const Value *> &LHS,
72377263
const WithCache<const Value *> &RHS,
72387264
const SimplifyQuery &SQ) {
7265+
if (isKnownToNotOverflowFromAssume(SQ))
7266+
return OverflowResult::NeverOverflows;
7267+
72397268
ConstantRange LHSRange =
72407269
computeConstantRangeIncludingKnownBits(LHS, /*ForSigned=*/false, SQ);
72417270
ConstantRange RHSRange =
@@ -7251,6 +7280,9 @@ computeOverflowForSignedAdd(const WithCache<const Value *> &LHS,
72517280
return OverflowResult::NeverOverflows;
72527281
}
72537282

7283+
if (isKnownToNotOverflowFromAssume(SQ))
7284+
return OverflowResult::NeverOverflows;
7285+
72547286
// If LHS and RHS each have at least two sign bits, the addition will look
72557287
// like
72567288
//
@@ -7305,6 +7337,9 @@ computeOverflowForSignedAdd(const WithCache<const Value *> &LHS,
73057337
OverflowResult llvm::computeOverflowForUnsignedSub(const Value *LHS,
73067338
const Value *RHS,
73077339
const SimplifyQuery &SQ) {
7340+
if (isKnownToNotOverflowFromAssume(SQ))
7341+
return OverflowResult::NeverOverflows;
7342+
73087343
// X - (X % ?)
73097344
// The remainder of a value can't have greater magnitude than itself,
73107345
// so the subtraction can't overflow.
@@ -7338,6 +7373,9 @@ OverflowResult llvm::computeOverflowForUnsignedSub(const Value *LHS,
73387373
OverflowResult llvm::computeOverflowForSignedSub(const Value *LHS,
73397374
const Value *RHS,
73407375
const SimplifyQuery &SQ) {
7376+
if (isKnownToNotOverflowFromAssume(SQ))
7377+
return OverflowResult::NeverOverflows;
7378+
73417379
// X - (X % ?)
73427380
// The remainder of a value can't have greater magnitude than itself,
73437381
// so the subtraction can't overflow.
@@ -10180,6 +10218,9 @@ void llvm::findValuesAffectedByCondition(
1018010218
m_Value()))) {
1018110219
// Handle patterns that computeKnownFPClass() support.
1018210220
AddAffected(A);
10221+
} else if (IsAssume && match(V, m_Not(m_ExtractValue<1>(m_Value(A)))) &&
10222+
isa<WithOverflowInst>(A)) {
10223+
AddAffected(A);
1018310224
}
1018410225
}
1018510226
}

llvm/test/Transforms/InstCombine/with_overflow.ll

Lines changed: 7 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,11 +1067,7 @@ define i8 @smul_7(i8 %x, ptr %p) {
10671067

10681068
define i8 @uadd_assume_no_overflow(i8 noundef %a, i8 noundef %b) {
10691069
; CHECK-LABEL: @uadd_assume_no_overflow(
1070-
; CHECK-NEXT: [[CALL1:%.*]] = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 [[A:%.*]], i8 [[B:%.*]])
1071-
; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[CALL1]], 1
1072-
; CHECK-NEXT: [[CALL:%.*]] = extractvalue { i8, i1 } [[CALL1]], 0
1073-
; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[OVERFLOW]], true
1074-
; CHECK-NEXT: call void @llvm.assume(i1 [[NOT]])
1070+
; CHECK-NEXT: [[CALL:%.*]] = add nuw i8 [[A:%.*]], [[B:%.*]]
10751071
; CHECK-NEXT: ret i8 [[CALL]]
10761072
;
10771073
%call = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 %a, i8 %b)
@@ -1084,11 +1080,7 @@ define i8 @uadd_assume_no_overflow(i8 noundef %a, i8 noundef %b) {
10841080

10851081
define i8 @sadd_assume_no_overflow(i8 noundef %a, i8 noundef %b) {
10861082
; CHECK-LABEL: @sadd_assume_no_overflow(
1087-
; CHECK-NEXT: [[CALL1:%.*]] = call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[A:%.*]], i8 [[B:%.*]])
1088-
; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[CALL1]], 1
1089-
; CHECK-NEXT: [[CALL:%.*]] = extractvalue { i8, i1 } [[CALL1]], 0
1090-
; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[OVERFLOW]], true
1091-
; CHECK-NEXT: call void @llvm.assume(i1 [[NOT]])
1083+
; CHECK-NEXT: [[CALL:%.*]] = add nsw i8 [[A:%.*]], [[B:%.*]]
10921084
; CHECK-NEXT: ret i8 [[CALL]]
10931085
;
10941086
%call = call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %a, i8 %b)
@@ -1101,11 +1093,7 @@ define i8 @sadd_assume_no_overflow(i8 noundef %a, i8 noundef %b) {
11011093

11021094
define i8 @usub_assume_no_overflow(i8 noundef %a, i8 noundef %b) {
11031095
; CHECK-LABEL: @usub_assume_no_overflow(
1104-
; CHECK-NEXT: [[CALL1:%.*]] = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[A:%.*]], i8 [[B:%.*]])
1105-
; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[CALL1]], 1
1106-
; CHECK-NEXT: [[CALL:%.*]] = extractvalue { i8, i1 } [[CALL1]], 0
1107-
; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[OVERFLOW]], true
1108-
; CHECK-NEXT: call void @llvm.assume(i1 [[NOT]])
1096+
; CHECK-NEXT: [[CALL:%.*]] = sub nuw i8 [[A:%.*]], [[B:%.*]]
11091097
; CHECK-NEXT: ret i8 [[CALL]]
11101098
;
11111099
%call = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %a, i8 %b)
@@ -1118,11 +1106,7 @@ define i8 @usub_assume_no_overflow(i8 noundef %a, i8 noundef %b) {
11181106

11191107
define i8 @ssub_assume_no_overflow(i8 noundef %a, i8 noundef %b) {
11201108
; CHECK-LABEL: @ssub_assume_no_overflow(
1121-
; CHECK-NEXT: [[CALL1:%.*]] = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[A:%.*]], i8 [[B:%.*]])
1122-
; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[CALL1]], 1
1123-
; CHECK-NEXT: [[CALL:%.*]] = extractvalue { i8, i1 } [[CALL1]], 0
1124-
; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[OVERFLOW]], true
1125-
; CHECK-NEXT: call void @llvm.assume(i1 [[NOT]])
1109+
; CHECK-NEXT: [[CALL:%.*]] = sub nsw i8 [[A:%.*]], [[B:%.*]]
11261110
; CHECK-NEXT: ret i8 [[CALL]]
11271111
;
11281112
%call = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %a, i8 %b)
@@ -1135,11 +1119,7 @@ define i8 @ssub_assume_no_overflow(i8 noundef %a, i8 noundef %b) {
11351119

11361120
define i8 @umul_assume_no_overflow(i8 noundef %a, i8 noundef %b) {
11371121
; CHECK-LABEL: @umul_assume_no_overflow(
1138-
; CHECK-NEXT: [[CALL1:%.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 [[A:%.*]], i8 [[B:%.*]])
1139-
; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[CALL1]], 1
1140-
; CHECK-NEXT: [[CALL:%.*]] = extractvalue { i8, i1 } [[CALL1]], 0
1141-
; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[OVERFLOW]], true
1142-
; CHECK-NEXT: call void @llvm.assume(i1 [[NOT]])
1122+
; CHECK-NEXT: [[CALL:%.*]] = mul nuw i8 [[A:%.*]], [[B:%.*]]
11431123
; CHECK-NEXT: ret i8 [[CALL]]
11441124
;
11451125
%call = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %a, i8 %b)
@@ -1152,11 +1132,7 @@ define i8 @umul_assume_no_overflow(i8 noundef %a, i8 noundef %b) {
11521132

11531133
define i8 @smul_assume_no_overflow(i8 noundef %a, i8 noundef %b) {
11541134
; CHECK-LABEL: @smul_assume_no_overflow(
1155-
; CHECK-NEXT: [[CALL1:%.*]] = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[A:%.*]], i8 [[B:%.*]])
1156-
; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[CALL1]], 1
1157-
; CHECK-NEXT: [[CALL:%.*]] = extractvalue { i8, i1 } [[CALL1]], 0
1158-
; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[OVERFLOW]], true
1159-
; CHECK-NEXT: call void @llvm.assume(i1 [[NOT]])
1135+
; CHECK-NEXT: [[CALL:%.*]] = mul nsw i8 [[A:%.*]], [[B:%.*]]
11601136
; CHECK-NEXT: ret i8 [[CALL]]
11611137
;
11621138
%call = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %a, i8 %b)
@@ -1169,11 +1145,7 @@ define i8 @smul_assume_no_overflow(i8 noundef %a, i8 noundef %b) {
11691145

11701146
define i1 @ephemeral_call_assume_no_overflow(i8 noundef %a, i8 noundef %b) {
11711147
; CHECK-LABEL: @ephemeral_call_assume_no_overflow(
1172-
; CHECK-NEXT: [[CALL:%.*]] = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[A:%.*]], i8 [[B:%.*]])
1173-
; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[CALL]], 1
1174-
; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[OVERFLOW]], true
1175-
; CHECK-NEXT: call void @llvm.assume(i1 [[NOT]])
1176-
; CHECK-NEXT: ret i1 [[NOT]]
1148+
; CHECK-NEXT: ret i1 true
11771149
;
11781150
%call = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %a, i8 %b)
11791151
%overflow = extractvalue { i8, i1 } %call, 1

0 commit comments

Comments
 (0)