Skip to content

Commit 73e22ff

Browse files
[Reassociate] Preserve NSW flags after expr tree rewriting (#93105)
We can guarantee NSW on all operands in a reassociated add expression tree when: - All adds in an add operator tree are NSW, AND either - All add operands are guaranteed to be nonnegative, OR - All adds are also NUW - Alive2: - Nonnegative Operands - 3 operands: https://alive2.llvm.org/ce/z/G4XW6Q - 4 operands: https://alive2.llvm.org/ce/z/FWcZ6D - NUW NSW adds: https://alive2.llvm.org/ce/z/vRUxeC --------- Co-authored-by: Nikita Popov <[email protected]>
1 parent f089996 commit 73e22ff

File tree

4 files changed

+132
-34
lines changed

4 files changed

+132
-34
lines changed

llvm/include/llvm/Transforms/Scalar/Reassociate.h

+11-1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,16 @@ struct Factor {
6363
Factor(Value *Base, unsigned Power) : Base(Base), Power(Power) {}
6464
};
6565

66+
struct OverflowTracking {
67+
bool HasNUW;
68+
bool HasNSW;
69+
bool AllKnownNonNegative;
70+
// Note: AllKnownNonNegative can be true in a case where one of the operands
71+
// is negative, but one the operators is not NSW. AllKnownNonNegative should
72+
// not be used independently of HasNSW
73+
OverflowTracking() : HasNUW(true), HasNSW(true), AllKnownNonNegative(true) {}
74+
};
75+
6676
class XorOpnd;
6777

6878
} // end namespace reassociate
@@ -103,7 +113,7 @@ class ReassociatePass : public PassInfoMixin<ReassociatePass> {
103113
void ReassociateExpression(BinaryOperator *I);
104114
void RewriteExprTree(BinaryOperator *I,
105115
SmallVectorImpl<reassociate::ValueEntry> &Ops,
106-
bool HasNUW);
116+
reassociate::OverflowTracking Flags);
107117
Value *OptimizeExpression(BinaryOperator *I,
108118
SmallVectorImpl<reassociate::ValueEntry> &Ops);
109119
Value *OptimizeAdd(Instruction *I,

llvm/lib/Transforms/Scalar/Reassociate.cpp

+22-13
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ using RepeatedValue = std::pair<Value*, APInt>;
471471
static bool LinearizeExprTree(Instruction *I,
472472
SmallVectorImpl<RepeatedValue> &Ops,
473473
ReassociatePass::OrderedSet &ToRedo,
474-
bool &HasNUW) {
474+
reassociate::OverflowTracking &Flags) {
475475
assert((isa<UnaryOperator>(I) || isa<BinaryOperator>(I)) &&
476476
"Expected a UnaryOperator or BinaryOperator!");
477477
LLVM_DEBUG(dbgs() << "LINEARIZE: " << *I << '\n');
@@ -512,6 +512,7 @@ static bool LinearizeExprTree(Instruction *I,
512512
using LeafMap = DenseMap<Value *, APInt>;
513513
LeafMap Leaves; // Leaf -> Total weight so far.
514514
SmallVector<Value *, 8> LeafOrder; // Ensure deterministic leaf output order.
515+
const DataLayout DL = I->getModule()->getDataLayout();
515516

516517
#ifndef NDEBUG
517518
SmallPtrSet<Value *, 8> Visited; // For checking the iteration scheme.
@@ -520,8 +521,10 @@ static bool LinearizeExprTree(Instruction *I,
520521
std::pair<Instruction*, APInt> P = Worklist.pop_back_val();
521522
I = P.first; // We examine the operands of this binary operator.
522523

523-
if (isa<OverflowingBinaryOperator>(I))
524-
HasNUW &= I->hasNoUnsignedWrap();
524+
if (isa<OverflowingBinaryOperator>(I)) {
525+
Flags.HasNUW &= I->hasNoUnsignedWrap();
526+
Flags.HasNSW &= I->hasNoSignedWrap();
527+
}
525528

526529
for (unsigned OpIdx = 0; OpIdx < I->getNumOperands(); ++OpIdx) { // Visit operands.
527530
Value *Op = I->getOperand(OpIdx);
@@ -648,6 +651,8 @@ static bool LinearizeExprTree(Instruction *I,
648651
// Ensure the leaf is only output once.
649652
It->second = 0;
650653
Ops.push_back(std::make_pair(V, Weight));
654+
if (Opcode == Instruction::Add && Flags.AllKnownNonNegative && Flags.HasNSW)
655+
Flags.AllKnownNonNegative &= isKnownNonNegative(V, SimplifyQuery(DL));
651656
}
652657

653658
// For nilpotent operations or addition there may be no operands, for example
@@ -666,7 +671,7 @@ static bool LinearizeExprTree(Instruction *I,
666671
/// linearized and optimized, emit them in-order.
667672
void ReassociatePass::RewriteExprTree(BinaryOperator *I,
668673
SmallVectorImpl<ValueEntry> &Ops,
669-
bool HasNUW) {
674+
OverflowTracking Flags) {
670675
assert(Ops.size() > 1 && "Single values should be used directly!");
671676

672677
// Since our optimizations should never increase the number of operations, the
@@ -834,8 +839,12 @@ void ReassociatePass::RewriteExprTree(BinaryOperator *I,
834839
// Note that it doesn't hold for mul if one of the operands is zero.
835840
// TODO: We can preserve NUW flag if we prove that all mul operands
836841
// are non-zero.
837-
if (HasNUW && ExpressionChangedStart->getOpcode() == Instruction::Add)
838-
ExpressionChangedStart->setHasNoUnsignedWrap();
842+
if (ExpressionChangedStart->getOpcode() == Instruction::Add) {
843+
if (Flags.HasNUW)
844+
ExpressionChangedStart->setHasNoUnsignedWrap();
845+
if (Flags.HasNSW && (Flags.AllKnownNonNegative || Flags.HasNUW))
846+
ExpressionChangedStart->setHasNoSignedWrap();
847+
}
839848
}
840849
}
841850

@@ -1192,8 +1201,8 @@ Value *ReassociatePass::RemoveFactorFromExpression(Value *V, Value *Factor) {
11921201
return nullptr;
11931202

11941203
SmallVector<RepeatedValue, 8> Tree;
1195-
bool HasNUW = true;
1196-
MadeChange |= LinearizeExprTree(BO, Tree, RedoInsts, HasNUW);
1204+
OverflowTracking Flags;
1205+
MadeChange |= LinearizeExprTree(BO, Tree, RedoInsts, Flags);
11971206
SmallVector<ValueEntry, 8> Factors;
11981207
Factors.reserve(Tree.size());
11991208
for (unsigned i = 0, e = Tree.size(); i != e; ++i) {
@@ -1235,7 +1244,7 @@ Value *ReassociatePass::RemoveFactorFromExpression(Value *V, Value *Factor) {
12351244

12361245
if (!FoundFactor) {
12371246
// Make sure to restore the operands to the expression tree.
1238-
RewriteExprTree(BO, Factors, HasNUW);
1247+
RewriteExprTree(BO, Factors, Flags);
12391248
return nullptr;
12401249
}
12411250

@@ -1247,7 +1256,7 @@ Value *ReassociatePass::RemoveFactorFromExpression(Value *V, Value *Factor) {
12471256
RedoInsts.insert(BO);
12481257
V = Factors[0].Op;
12491258
} else {
1250-
RewriteExprTree(BO, Factors, HasNUW);
1259+
RewriteExprTree(BO, Factors, Flags);
12511260
V = BO;
12521261
}
12531262

@@ -2373,8 +2382,8 @@ void ReassociatePass::ReassociateExpression(BinaryOperator *I) {
23732382
// First, walk the expression tree, linearizing the tree, collecting the
23742383
// operand information.
23752384
SmallVector<RepeatedValue, 8> Tree;
2376-
bool HasNUW = true;
2377-
MadeChange |= LinearizeExprTree(I, Tree, RedoInsts, HasNUW);
2385+
OverflowTracking Flags;
2386+
MadeChange |= LinearizeExprTree(I, Tree, RedoInsts, Flags);
23782387
SmallVector<ValueEntry, 8> Ops;
23792388
Ops.reserve(Tree.size());
23802389
for (const RepeatedValue &E : Tree)
@@ -2567,7 +2576,7 @@ void ReassociatePass::ReassociateExpression(BinaryOperator *I) {
25672576
dbgs() << '\n');
25682577
// Now that we ordered and optimized the expressions, splat them back into
25692578
// the expression tree, removing any unneeded nodes.
2570-
RewriteExprTree(I, Ops, HasNUW);
2579+
RewriteExprTree(I, Ops, Flags);
25712580
}
25722581

25732582
void

llvm/test/Transforms/Reassociate/local-cse.ll

+20-20
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,16 @@ define void @chain_spanning_several_blocks(i64 %inv1, i64 %inv2, i64 %inv3, i64
2626
; LOCAL_CSE-LABEL: define void @chain_spanning_several_blocks
2727
; LOCAL_CSE-SAME: (i64 [[INV1:%.*]], i64 [[INV2:%.*]], i64 [[INV3:%.*]], i64 [[INV4:%.*]], i64 [[INV5:%.*]]) {
2828
; LOCAL_CSE-NEXT: bb1:
29-
; LOCAL_CSE-NEXT: [[CHAIN_A0:%.*]] = add nuw i64 [[INV2]], [[INV1]]
29+
; LOCAL_CSE-NEXT: [[CHAIN_A0:%.*]] = add nuw nsw i64 [[INV2]], [[INV1]]
3030
; LOCAL_CSE-NEXT: br label [[BB2:%.*]]
3131
; LOCAL_CSE: bb2:
3232
; LOCAL_CSE-NEXT: [[VAL_BB2:%.*]] = call i64 @get_val()
33-
; LOCAL_CSE-NEXT: [[CHAIN_A1:%.*]] = add nuw i64 [[CHAIN_A0]], [[INV4]]
34-
; LOCAL_CSE-NEXT: [[CHAIN_A2:%.*]] = add nuw i64 [[CHAIN_A1]], [[VAL_BB2]]
35-
; LOCAL_CSE-NEXT: [[CHAIN_B1:%.*]] = add nuw i64 [[CHAIN_A0]], [[INV5]]
36-
; LOCAL_CSE-NEXT: [[CHAIN_B2:%.*]] = add nuw i64 [[CHAIN_B1]], [[VAL_BB2]]
37-
; LOCAL_CSE-NEXT: [[CHAIN_C0:%.*]] = add nuw i64 [[INV3]], [[INV1]]
38-
; LOCAL_CSE-NEXT: [[CHAIN_C1:%.*]] = add nuw i64 [[CHAIN_C0]], [[VAL_BB2]]
33+
; LOCAL_CSE-NEXT: [[CHAIN_A1:%.*]] = add nuw nsw i64 [[CHAIN_A0]], [[INV4]]
34+
; LOCAL_CSE-NEXT: [[CHAIN_A2:%.*]] = add nuw nsw i64 [[CHAIN_A1]], [[VAL_BB2]]
35+
; LOCAL_CSE-NEXT: [[CHAIN_B1:%.*]] = add nuw nsw i64 [[CHAIN_A0]], [[INV5]]
36+
; LOCAL_CSE-NEXT: [[CHAIN_B2:%.*]] = add nuw nsw i64 [[CHAIN_B1]], [[VAL_BB2]]
37+
; LOCAL_CSE-NEXT: [[CHAIN_C0:%.*]] = add nuw nsw i64 [[INV3]], [[INV1]]
38+
; LOCAL_CSE-NEXT: [[CHAIN_C1:%.*]] = add nuw nsw i64 [[CHAIN_C0]], [[VAL_BB2]]
3939
; LOCAL_CSE-NEXT: call void @keep_alive(i64 [[CHAIN_A2]])
4040
; LOCAL_CSE-NEXT: call void @keep_alive(i64 [[CHAIN_B2]])
4141
; LOCAL_CSE-NEXT: call void @keep_alive(i64 [[CHAIN_C1]])
@@ -47,11 +47,11 @@ define void @chain_spanning_several_blocks(i64 %inv1, i64 %inv2, i64 %inv3, i64
4747
; CSE-NEXT: br label [[BB2:%.*]]
4848
; CSE: bb2:
4949
; CSE-NEXT: [[VAL_BB2:%.*]] = call i64 @get_val()
50-
; CSE-NEXT: [[CHAIN_A0:%.*]] = add nuw i64 [[VAL_BB2]], [[INV1]]
51-
; CSE-NEXT: [[CHAIN_A1:%.*]] = add nuw i64 [[CHAIN_A0]], [[INV2]]
50+
; CSE-NEXT: [[CHAIN_A0:%.*]] = add nuw nsw i64 [[VAL_BB2]], [[INV1]]
51+
; CSE-NEXT: [[CHAIN_A1:%.*]] = add nuw nsw i64 [[CHAIN_A0]], [[INV2]]
5252
; CSE-NEXT: [[CHAIN_A2:%.*]] = add nuw nsw i64 [[CHAIN_A1]], [[INV4]]
5353
; CSE-NEXT: [[CHAIN_B2:%.*]] = add nuw nsw i64 [[CHAIN_A1]], [[INV5]]
54-
; CSE-NEXT: [[CHAIN_C1:%.*]] = add nuw i64 [[CHAIN_A0]], [[INV3]]
54+
; CSE-NEXT: [[CHAIN_C1:%.*]] = add nuw nsw i64 [[CHAIN_A0]], [[INV3]]
5555
; CSE-NEXT: call void @keep_alive(i64 [[CHAIN_A2]])
5656
; CSE-NEXT: call void @keep_alive(i64 [[CHAIN_B2]])
5757
; CSE-NEXT: call void @keep_alive(i64 [[CHAIN_C1]])
@@ -90,19 +90,19 @@ define void @chain_spanning_several_blocks_no_entry_anchor() {
9090
; LOCAL_CSE-NEXT: br label [[BB1:%.*]]
9191
; LOCAL_CSE: bb1:
9292
; LOCAL_CSE-NEXT: [[INV1_BB1:%.*]] = call i64 @get_val()
93-
; LOCAL_CSE-NEXT: [[CHAIN_A0:%.*]] = add nuw i64 [[INV1_BB1]], [[INV2_BB0]]
93+
; LOCAL_CSE-NEXT: [[CHAIN_A0:%.*]] = add nuw nsw i64 [[INV1_BB1]], [[INV2_BB0]]
9494
; LOCAL_CSE-NEXT: br label [[BB2:%.*]]
9595
; LOCAL_CSE: bb2:
9696
; LOCAL_CSE-NEXT: [[INV3_BB2:%.*]] = call i64 @get_val()
9797
; LOCAL_CSE-NEXT: [[INV4_BB2:%.*]] = call i64 @get_val()
9898
; LOCAL_CSE-NEXT: [[INV5_BB2:%.*]] = call i64 @get_val()
9999
; LOCAL_CSE-NEXT: [[VAL_BB2:%.*]] = call i64 @get_val()
100-
; LOCAL_CSE-NEXT: [[CHAIN_A1:%.*]] = add nuw i64 [[CHAIN_A0]], [[INV4_BB2]]
101-
; LOCAL_CSE-NEXT: [[CHAIN_A2:%.*]] = add nuw i64 [[CHAIN_A1]], [[VAL_BB2]]
102-
; LOCAL_CSE-NEXT: [[CHAIN_B1:%.*]] = add nuw i64 [[CHAIN_A0]], [[INV5_BB2]]
103-
; LOCAL_CSE-NEXT: [[CHAIN_B2:%.*]] = add nuw i64 [[CHAIN_B1]], [[VAL_BB2]]
104-
; LOCAL_CSE-NEXT: [[CHAIN_C0:%.*]] = add nuw i64 [[VAL_BB2]], [[INV1_BB1]]
105-
; LOCAL_CSE-NEXT: [[CHAIN_C1:%.*]] = add nuw i64 [[CHAIN_C0]], [[INV3_BB2]]
100+
; LOCAL_CSE-NEXT: [[CHAIN_A1:%.*]] = add nuw nsw i64 [[CHAIN_A0]], [[INV4_BB2]]
101+
; LOCAL_CSE-NEXT: [[CHAIN_A2:%.*]] = add nuw nsw i64 [[CHAIN_A1]], [[VAL_BB2]]
102+
; LOCAL_CSE-NEXT: [[CHAIN_B1:%.*]] = add nuw nsw i64 [[CHAIN_A0]], [[INV5_BB2]]
103+
; LOCAL_CSE-NEXT: [[CHAIN_B2:%.*]] = add nuw nsw i64 [[CHAIN_B1]], [[VAL_BB2]]
104+
; LOCAL_CSE-NEXT: [[CHAIN_C0:%.*]] = add nuw nsw i64 [[VAL_BB2]], [[INV1_BB1]]
105+
; LOCAL_CSE-NEXT: [[CHAIN_C1:%.*]] = add nuw nsw i64 [[CHAIN_C0]], [[INV3_BB2]]
106106
; LOCAL_CSE-NEXT: call void @keep_alive(i64 [[CHAIN_A2]])
107107
; LOCAL_CSE-NEXT: call void @keep_alive(i64 [[CHAIN_B2]])
108108
; LOCAL_CSE-NEXT: call void @keep_alive(i64 [[CHAIN_C1]])
@@ -120,11 +120,11 @@ define void @chain_spanning_several_blocks_no_entry_anchor() {
120120
; CSE-NEXT: [[INV4_BB2:%.*]] = call i64 @get_val()
121121
; CSE-NEXT: [[INV5_BB2:%.*]] = call i64 @get_val()
122122
; CSE-NEXT: [[VAL_BB2:%.*]] = call i64 @get_val()
123-
; CSE-NEXT: [[CHAIN_A0:%.*]] = add nuw i64 [[VAL_BB2]], [[INV1_BB1]]
124-
; CSE-NEXT: [[CHAIN_A1:%.*]] = add nuw i64 [[CHAIN_A0]], [[INV2_BB0]]
123+
; CSE-NEXT: [[CHAIN_A0:%.*]] = add nuw nsw i64 [[VAL_BB2]], [[INV1_BB1]]
124+
; CSE-NEXT: [[CHAIN_A1:%.*]] = add nuw nsw i64 [[CHAIN_A0]], [[INV2_BB0]]
125125
; CSE-NEXT: [[CHAIN_A2:%.*]] = add nuw nsw i64 [[CHAIN_A1]], [[INV4_BB2]]
126126
; CSE-NEXT: [[CHAIN_B2:%.*]] = add nuw nsw i64 [[CHAIN_A1]], [[INV5_BB2]]
127-
; CSE-NEXT: [[CHAIN_C1:%.*]] = add nuw i64 [[CHAIN_A0]], [[INV3_BB2]]
127+
; CSE-NEXT: [[CHAIN_C1:%.*]] = add nuw nsw i64 [[CHAIN_A0]], [[INV3_BB2]]
128128
; CSE-NEXT: call void @keep_alive(i64 [[CHAIN_A2]])
129129
; CSE-NEXT: call void @keep_alive(i64 [[CHAIN_B2]])
130130
; CSE-NEXT: call void @keep_alive(i64 [[CHAIN_C1]])
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2+
; RUN: opt < %s -passes=reassociate -S | FileCheck %s
3+
define i32 @nsw_preserve_nonnegative(ptr %ptr0, ptr %ptr1, ptr %ptr2) {
4+
; CHECK-LABEL: define i32 @nsw_preserve_nonnegative(
5+
; CHECK-SAME: ptr [[PTR0:%.*]], ptr [[PTR1:%.*]], ptr [[PTR2:%.*]]) {
6+
; CHECK-NEXT: [[V0:%.*]] = load i32, ptr [[PTR0]], align 4, !range [[RNG0:![0-9]+]]
7+
; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[PTR1]], align 4, !range [[RNG0]]
8+
; CHECK-NEXT: [[V2:%.*]] = load i32, ptr [[PTR2]], align 4, !range [[RNG0]]
9+
; CHECK-NEXT: [[ADD0:%.*]] = add nsw i32 [[V1]], [[V0]]
10+
; CHECK-NEXT: [[ADD1:%.*]] = add nsw i32 [[ADD0]], [[V2]]
11+
; CHECK-NEXT: ret i32 [[ADD1]]
12+
;
13+
%v0 = load i32, ptr %ptr0, !range !1
14+
%v1 = load i32, ptr %ptr1, !range !1
15+
%v2 = load i32, ptr %ptr2, !range !1
16+
%add0 = add nsw i32 %v1, %v2
17+
%add1 = add nsw i32 %add0, %v0
18+
ret i32 %add1
19+
}
20+
21+
define i32 @nsw_preserve_nuw_nsw(ptr %ptr0, ptr %ptr1, ptr %ptr2) {
22+
; CHECK-LABEL: define i32 @nsw_preserve_nuw_nsw(
23+
; CHECK-SAME: ptr [[PTR0:%.*]], ptr [[PTR1:%.*]], ptr [[PTR2:%.*]]) {
24+
; CHECK-NEXT: [[V0:%.*]] = load i32, ptr [[PTR0]], align 4
25+
; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[PTR1]], align 4
26+
; CHECK-NEXT: [[V2:%.*]] = load i32, ptr [[PTR2]], align 4
27+
; CHECK-NEXT: [[ADD0:%.*]] = add nuw nsw i32 [[V1]], [[V0]]
28+
; CHECK-NEXT: [[ADD1:%.*]] = add nuw nsw i32 [[ADD0]], [[V2]]
29+
; CHECK-NEXT: ret i32 [[ADD1]]
30+
;
31+
%v0 = load i32, ptr %ptr0
32+
%v1 = load i32, ptr %ptr1
33+
%v2 = load i32, ptr %ptr2
34+
%add0 = add nuw nsw i32 %v1, %v2
35+
%add1 = add nuw nsw i32 %add0, %v0
36+
ret i32 %add1
37+
}
38+
39+
define i32 @nsw_dont_preserve_negative(ptr %ptr0, ptr %ptr1, ptr %ptr2) {
40+
; CHECK-LABEL: define i32 @nsw_dont_preserve_negative(
41+
; CHECK-SAME: ptr [[PTR0:%.*]], ptr [[PTR1:%.*]], ptr [[PTR2:%.*]]) {
42+
; CHECK-NEXT: [[V0:%.*]] = load i32, ptr [[PTR0]], align 4
43+
; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[PTR1]], align 4, !range [[RNG0]]
44+
; CHECK-NEXT: [[V2:%.*]] = load i32, ptr [[PTR2]], align 4, !range [[RNG0]]
45+
; CHECK-NEXT: [[ADD0:%.*]] = add i32 [[V1]], [[V0]]
46+
; CHECK-NEXT: [[ADD1:%.*]] = add i32 [[ADD0]], [[V2]]
47+
; CHECK-NEXT: ret i32 [[ADD1]]
48+
;
49+
%v0 = load i32, ptr %ptr0
50+
%v1 = load i32, ptr %ptr1, !range !1
51+
%v2 = load i32, ptr %ptr2, !range !1
52+
%add0 = add nsw i32 %v1, %v2
53+
%add1 = add nsw i32 %add0, %v0
54+
ret i32 %add1
55+
}
56+
57+
define i32 @nsw_nopreserve_notallnsw(ptr %ptr0, ptr %ptr1, ptr %ptr2) {
58+
; CHECK-LABEL: define i32 @nsw_nopreserve_notallnsw(
59+
; CHECK-SAME: ptr [[PTR0:%.*]], ptr [[PTR1:%.*]], ptr [[PTR2:%.*]]) {
60+
; CHECK-NEXT: [[V0:%.*]] = load i32, ptr [[PTR0]], align 4, !range [[RNG0:![0-9]+]]
61+
; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[PTR1]], align 4, !range [[RNG0]]
62+
; CHECK-NEXT: [[V2:%.*]] = load i32, ptr [[PTR2]], align 4, !range [[RNG0]]
63+
; CHECK-NEXT: [[ADD0:%.*]] = add i32 [[V1]], [[V0]]
64+
; CHECK-NEXT: [[ADD1:%.*]] = add i32 [[ADD0]], [[V2]]
65+
; CHECK-NEXT: ret i32 [[ADD1]]
66+
;
67+
%v0 = load i32, ptr %ptr0, !range !1
68+
%v1 = load i32, ptr %ptr1, !range !1
69+
%v2 = load i32, ptr %ptr2, !range !1
70+
%add0 = add nsw i32 %v1, %v2
71+
%add1 = add i32 %add0, %v0
72+
ret i32 %add1
73+
}
74+
75+
; Positive 32 bit integers
76+
!1 = !{i32 0, i32 2147483648}
77+
;.
78+
; CHECK: [[RNG0]] = !{i32 0, i32 -2147483648}
79+
;.

0 commit comments

Comments
 (0)