Skip to content

Commit b1822ef

Browse files
authored
[SCCP] Refine trunc with nsw/nuw flags (#87926)
Following #85592, add support for nsw/nuw flags of trunc in SCCP.
1 parent 38f8fce commit b1822ef

File tree

6 files changed

+218
-18
lines changed

6 files changed

+218
-18
lines changed

llvm/lib/Transforms/Utils/SCCPSolver.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,9 @@ static bool refineInstruction(SCCPSolver &Solver,
120120
};
121121

122122
if (isa<OverflowingBinaryOperator>(Inst)) {
123+
if (Inst.hasNoSignedWrap() && Inst.hasNoUnsignedWrap())
124+
return false;
125+
123126
auto RangeA = GetRange(Inst.getOperand(0));
124127
auto RangeB = GetRange(Inst.getOperand(1));
125128
if (!Inst.hasNoUnsignedWrap()) {
@@ -146,6 +149,24 @@ static bool refineInstruction(SCCPSolver &Solver,
146149
Inst.setNonNeg();
147150
Changed = true;
148151
}
152+
} else if (TruncInst *TI = dyn_cast<TruncInst>(&Inst)) {
153+
if (TI->hasNoSignedWrap() && TI->hasNoUnsignedWrap())
154+
return false;
155+
156+
auto Range = GetRange(Inst.getOperand(0));
157+
uint64_t DestWidth = TI->getDestTy()->getScalarSizeInBits();
158+
if (!TI->hasNoUnsignedWrap()) {
159+
if (Range.getActiveBits() <= DestWidth) {
160+
TI->setHasNoUnsignedWrap(true);
161+
Changed = true;
162+
}
163+
}
164+
if (!TI->hasNoSignedWrap()) {
165+
if (Range.getMinSignedBits() <= DestWidth) {
166+
TI->setHasNoSignedWrap(true);
167+
Changed = true;
168+
}
169+
}
149170
}
150171

151172
return Changed;

llvm/test/Transforms/PhaseOrdering/ARM/arm_mult_q15.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ define void @arm_mult_q15(ptr %pSrcA, ptr %pSrcB, ptr noalias %pDst, i32 %blockS
6969
; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[CONV2]], [[CONV]]
7070
; CHECK-NEXT: [[SHR:%.*]] = ashr i32 [[MUL]], 15
7171
; CHECK-NEXT: [[SPEC_SELECT_I:%.*]] = tail call i32 @llvm.smin.i32(i32 [[SHR]], i32 32767)
72-
; CHECK-NEXT: [[CONV3:%.*]] = trunc i32 [[SPEC_SELECT_I]] to i16
72+
; CHECK-NEXT: [[CONV3:%.*]] = trunc nsw i32 [[SPEC_SELECT_I]] to i16
7373
; CHECK-NEXT: [[INCDEC_PTR4]] = getelementptr inbounds i8, ptr [[PDST_ADDR_04]], i32 2
7474
; CHECK-NEXT: store i16 [[CONV3]], ptr [[PDST_ADDR_04]], align 2
7575
; CHECK-NEXT: [[DEC]] = add i32 [[BLKCNT_06]], -1

llvm/test/Transforms/SCCP/conditions-ranges.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ define i32 @f5(i64 %sz) {
178178
; CHECK-NEXT: br label [[COND_END]]
179179
; CHECK: cond.end:
180180
; CHECK-NEXT: [[COND:%.*]] = phi i64 [ [[DIV]], [[COND_TRUE]] ], [ 1, [[ENTRY:%.*]] ]
181-
; CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[COND]] to i32
181+
; CHECK-NEXT: [[CONV:%.*]] = trunc nuw nsw i64 [[COND]] to i32
182182
; CHECK-NEXT: ret i32 [[CONV]]
183183
;
184184
entry:
@@ -759,7 +759,7 @@ define i32 @udiv_1(i64 %sz) {
759759
; CHECK-NEXT: br label [[COND_END]]
760760
; CHECK: cond.end:
761761
; CHECK-NEXT: [[COND:%.*]] = phi i64 [ [[DIV]], [[COND_TRUE]] ], [ 1, [[ENTRY:%.*]] ]
762-
; CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[COND]] to i32
762+
; CHECK-NEXT: [[CONV:%.*]] = trunc nuw nsw i64 [[COND]] to i32
763763
; CHECK-NEXT: ret i32 [[CONV]]
764764
;
765765
entry:
@@ -786,7 +786,7 @@ define i32 @udiv_2(i64 %sz) {
786786
; CHECK-NEXT: br label [[COND_END]]
787787
; CHECK: cond.end:
788788
; CHECK-NEXT: [[COND:%.*]] = phi i64 [ 0, [[COND_TRUE]] ], [ 1, [[ENTRY:%.*]] ]
789-
; CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[COND]] to i32
789+
; CHECK-NEXT: [[CONV:%.*]] = trunc nuw nsw i64 [[COND]] to i32
790790
; CHECK-NEXT: ret i32 [[CONV]]
791791
;
792792
entry:

llvm/test/Transforms/SCCP/ip-ranges-casts.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
; x = [100, 301)
55
define internal i1 @f.trunc(i32 %x) {
66
; CHECK-LABEL: @f.trunc(
7-
; CHECK-NEXT: [[T_1:%.*]] = trunc i32 [[X:%.*]] to i16
7+
; CHECK-NEXT: [[T_1:%.*]] = trunc nuw nsw i32 [[X:%.*]] to i16
88
; CHECK-NEXT: [[C_2:%.*]] = icmp sgt i16 [[T_1]], 299
99
; CHECK-NEXT: [[C_4:%.*]] = icmp slt i16 [[T_1]], 101
1010
; CHECK-NEXT: [[RES_1:%.*]] = add nuw nsw i1 false, [[C_2]]
@@ -329,7 +329,7 @@ define i64 @caller.sext_to_zext(i32 %i) {
329329
; CHECK-LABEL: @caller.sext_to_zext(
330330
; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[I:%.*]], 9
331331
; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32
332-
; CHECK-NEXT: [[T:%.*]] = call i64 @f.sext_to_zext(i32 [[CONV]])
332+
; CHECK-NEXT: [[T:%.*]] = call i64 @f.sext_to_zext(i32 [[CONV]]), !range [[RNG0:![0-9]+]]
333333
; CHECK-NEXT: ret i64 [[T]]
334334
;
335335
%cmp = icmp sle i32 %i, 9
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2+
; RUN: opt -passes=ipsccp -S %s | FileCheck %s
3+
4+
define i16 @range_from_and_nuw(i32 %a) {
5+
; CHECK-LABEL: define i16 @range_from_and_nuw(
6+
; CHECK-SAME: i32 [[A:%.*]]) {
7+
; CHECK-NEXT: entry:
8+
; CHECK-NEXT: [[AND1:%.*]] = and i32 [[A]], 65535
9+
; CHECK-NEXT: [[TRUNC1:%.*]] = trunc nuw i32 [[AND1]] to i16
10+
; CHECK-NEXT: ret i16 [[TRUNC1]]
11+
;
12+
entry:
13+
%and1 = and i32 %a, 65535
14+
%trunc1 = trunc i32 %and1 to i16
15+
ret i16 %trunc1
16+
}
17+
18+
define i8 @range_from_or_nsw(i16 %a) {
19+
; CHECK-LABEL: define i8 @range_from_or_nsw(
20+
; CHECK-SAME: i16 [[A:%.*]]) {
21+
; CHECK-NEXT: entry:
22+
; CHECK-NEXT: [[AND1:%.*]] = or i16 [[A]], -128
23+
; CHECK-NEXT: [[TRUNC1:%.*]] = trunc nsw i16 [[AND1]] to i8
24+
; CHECK-NEXT: ret i8 [[TRUNC1]]
25+
;
26+
entry:
27+
%and1 = or i16 %a, 65408
28+
%trunc1 = trunc i16 %and1 to i8
29+
ret i8 %trunc1
30+
}
31+
32+
define i16 @range_from_and_nuw_nsw(i32 %a) {
33+
; CHECK-LABEL: define i16 @range_from_and_nuw_nsw(
34+
; CHECK-SAME: i32 [[A:%.*]]) {
35+
; CHECK-NEXT: entry:
36+
; CHECK-NEXT: [[AND1:%.*]] = and i32 [[A]], 32767
37+
; CHECK-NEXT: [[TRUNC1:%.*]] = trunc nuw nsw i32 [[AND1]] to i16
38+
; CHECK-NEXT: ret i16 [[TRUNC1]]
39+
;
40+
entry:
41+
%and1 = and i32 %a, 32767
42+
%trunc1 = trunc i32 %and1 to i16
43+
ret i16 %trunc1
44+
}
45+
46+
define <4 x i16> @range_from_and_nuw_vec(<4 x i32> %a) {
47+
; CHECK-LABEL: define <4 x i16> @range_from_and_nuw_vec(
48+
; CHECK-SAME: <4 x i32> [[A:%.*]]) {
49+
; CHECK-NEXT: entry:
50+
; CHECK-NEXT: [[AND1:%.*]] = and <4 x i32> [[A]], <i32 65535, i32 65535, i32 65535, i32 65535>
51+
; CHECK-NEXT: [[TRUNC1:%.*]] = trunc <4 x i32> [[AND1]] to <4 x i16>
52+
; CHECK-NEXT: ret <4 x i16> [[TRUNC1]]
53+
;
54+
entry:
55+
%and1 = and <4 x i32> %a, <i32 65535, i32 65535, i32 65535, i32 65535>
56+
%trunc1 = trunc <4 x i32> %and1 to <4 x i16>
57+
ret <4 x i16> %trunc1
58+
}
59+
60+
define i4 @range_from_sge_sle(i8 %a) {
61+
; CHECK-LABEL: define i4 @range_from_sge_sle(
62+
; CHECK-SAME: i8 [[A:%.*]]) {
63+
; CHECK-NEXT: entry:
64+
; CHECK-NEXT: [[SGT:%.*]] = icmp sge i8 [[A]], 0
65+
; CHECK-NEXT: [[SLT:%.*]] = icmp sle i8 [[A]], 15
66+
; CHECK-NEXT: [[AND:%.*]] = and i1 [[SGT]], [[SLT]]
67+
; CHECK-NEXT: br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
68+
; CHECK: then:
69+
; CHECK-NEXT: [[AND1:%.*]] = and i8 [[A]], 7
70+
; CHECK-NEXT: [[TRUNC1:%.*]] = trunc nuw i8 [[A]] to i4
71+
; CHECK-NEXT: [[TRUNC2:%.*]] = trunc nuw nsw i8 [[AND1]] to i4
72+
; CHECK-NEXT: [[XOR1:%.*]] = xor i4 [[TRUNC1]], [[TRUNC2]]
73+
; CHECK-NEXT: ret i4 [[XOR1]]
74+
; CHECK: else:
75+
; CHECK-NEXT: [[TRUNC3:%.*]] = trunc i8 [[A]] to i4
76+
; CHECK-NEXT: ret i4 [[TRUNC3]]
77+
;
78+
entry:
79+
%sgt = icmp sge i8 %a, 0
80+
%slt = icmp sle i8 %a, 15
81+
%and = and i1 %sgt, %slt
82+
br i1 %and, label %then, label %else
83+
84+
then:
85+
%and1 = and i8 %a, 7
86+
87+
%trunc1 = trunc i8 %a to i4
88+
%trunc2 = trunc i8 %and1 to i4
89+
%xor1 = xor i4 %trunc1, %trunc2
90+
ret i4 %xor1
91+
92+
else:
93+
%trunc3 = trunc i8 %a to i4
94+
ret i4 %trunc3
95+
}
96+
97+
define i16 @range_from_sext(i16 %a) {
98+
; CHECK-LABEL: define i16 @range_from_sext(
99+
; CHECK-SAME: i16 [[A:%.*]]) {
100+
; CHECK-NEXT: entry:
101+
; CHECK-NEXT: [[SEXT1:%.*]] = sext i16 [[A]] to i32
102+
; CHECK-NEXT: [[TRUNC1:%.*]] = trunc nsw i32 [[SEXT1]] to i16
103+
; CHECK-NEXT: ret i16 [[TRUNC1]]
104+
;
105+
entry:
106+
%sext1 = sext i16 %a to i32
107+
%trunc1 = trunc i32 %sext1 to i16
108+
ret i16 %trunc1
109+
}
110+
111+
define i16 @range_from_zext(i16 %a) {
112+
; CHECK-LABEL: define i16 @range_from_zext(
113+
; CHECK-SAME: i16 [[A:%.*]]) {
114+
; CHECK-NEXT: entry:
115+
; CHECK-NEXT: [[ZEXT1:%.*]] = zext i16 [[A]] to i32
116+
; CHECK-NEXT: [[TRUNC1:%.*]] = trunc nuw i32 [[ZEXT1]] to i16
117+
; CHECK-NEXT: ret i16 [[TRUNC1]]
118+
;
119+
entry:
120+
%zext1 = zext i16 %a to i32
121+
%trunc1 = trunc i32 %zext1 to i16
122+
ret i16 %trunc1
123+
}
124+
125+
define i1 @range_from_select_i1_nuw(i1 %c) {
126+
; CHECK-LABEL: define i1 @range_from_select_i1_nuw(
127+
; CHECK-SAME: i1 [[C:%.*]]) {
128+
; CHECK-NEXT: entry:
129+
; CHECK-NEXT: [[SELECT1:%.*]] = select i1 [[C]], i16 0, i16 1
130+
; CHECK-NEXT: [[TRUNC1:%.*]] = trunc nuw i16 [[SELECT1]] to i1
131+
; CHECK-NEXT: ret i1 [[TRUNC1]]
132+
;
133+
entry:
134+
%select1 = select i1 %c, i16 0, i16 1
135+
%trunc1 = trunc i16 %select1 to i1
136+
ret i1 %trunc1
137+
}
138+
139+
define i1 @range_from_select_i1_nsw(i1 %c) {
140+
; CHECK-LABEL: define i1 @range_from_select_i1_nsw(
141+
; CHECK-SAME: i1 [[C:%.*]]) {
142+
; CHECK-NEXT: entry:
143+
; CHECK-NEXT: [[SELECT1:%.*]] = select i1 [[C]], i16 0, i16 -1
144+
; CHECK-NEXT: [[TRUNC1:%.*]] = trunc nsw i16 [[SELECT1]] to i1
145+
; CHECK-NEXT: ret i1 [[TRUNC1]]
146+
;
147+
entry:
148+
%select1 = select i1 %c, i16 0, i16 -1
149+
%trunc1 = trunc i16 %select1 to i1
150+
ret i1 %trunc1
151+
}
152+
153+
define i1 @range_from_select_i1_fail(i1 %c) {
154+
; CHECK-LABEL: define i1 @range_from_select_i1_fail(
155+
; CHECK-SAME: i1 [[C:%.*]]) {
156+
; CHECK-NEXT: entry:
157+
; CHECK-NEXT: [[SELECT1:%.*]] = select i1 [[C]], i16 1, i16 -1
158+
; CHECK-NEXT: [[TRUNC1:%.*]] = trunc i16 [[SELECT1]] to i1
159+
; CHECK-NEXT: ret i1 [[TRUNC1]]
160+
;
161+
entry:
162+
%select1 = select i1 %c, i16 1, i16 -1
163+
%trunc1 = trunc i16 %select1 to i1
164+
ret i1 %trunc1
165+
}
166+
167+
define i8 @range_from_trunc_fail(i32 %a) {
168+
; CHECK-LABEL: define i8 @range_from_trunc_fail(
169+
; CHECK-SAME: i32 [[A:%.*]]) {
170+
; CHECK-NEXT: entry:
171+
; CHECK-NEXT: [[TRUNC1:%.*]] = trunc i32 [[A]] to i16
172+
; CHECK-NEXT: [[TRUNC2:%.*]] = trunc i16 [[TRUNC1]] to i8
173+
; CHECK-NEXT: ret i8 [[TRUNC2]]
174+
;
175+
entry:
176+
%trunc1 = trunc i32 %a to i16
177+
%trunc2 = trunc i16 %trunc1 to i8
178+
ret i8 %trunc2
179+
}

llvm/test/Transforms/SCCP/widening.ll

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -438,9 +438,9 @@ define void @foo(ptr %arg) {
438438
; SCCP-NEXT: [[TMP:%.*]] = zext i8 undef to i32
439439
; SCCP-NEXT: [[TMP2:%.*]] = load i64, ptr [[ARG:%.*]], align 8
440440
; SCCP-NEXT: switch i32 [[TMP]], label [[BB20:%.*]] [
441-
; SCCP-NEXT: i32 1, label [[BB3:%.*]]
442-
; SCCP-NEXT: i32 2, label [[BB4:%.*]]
443-
; SCCP-NEXT: i32 4, label [[BB19:%.*]]
441+
; SCCP-NEXT: i32 1, label [[BB3:%.*]]
442+
; SCCP-NEXT: i32 2, label [[BB4:%.*]]
443+
; SCCP-NEXT: i32 4, label [[BB19:%.*]]
444444
; SCCP-NEXT: ]
445445
; SCCP: bb3:
446446
; SCCP-NEXT: unreachable
@@ -449,7 +449,7 @@ define void @foo(ptr %arg) {
449449
; SCCP-NEXT: [[TMP6:%.*]] = and i64 [[TMP5]], 3
450450
; SCCP-NEXT: [[TMP7:%.*]] = sub nuw nsw i64 3, [[TMP6]]
451451
; SCCP-NEXT: [[TMP8:%.*]] = shl nuw nsw i64 [[TMP7]], 1
452-
; SCCP-NEXT: [[TMP9:%.*]] = trunc i64 [[TMP8]] to i32
452+
; SCCP-NEXT: [[TMP9:%.*]] = trunc nuw nsw i64 [[TMP8]] to i32
453453
; SCCP-NEXT: [[TMP10:%.*]] = zext nneg i32 [[TMP9]] to i64
454454
; SCCP-NEXT: br label [[BB11:%.*]]
455455
; SCCP: bb11:
@@ -475,9 +475,9 @@ define void @foo(ptr %arg) {
475475
; IPSCCP-NEXT: [[TMP:%.*]] = zext i8 undef to i32
476476
; IPSCCP-NEXT: [[TMP2:%.*]] = load i64, ptr [[ARG:%.*]], align 8
477477
; IPSCCP-NEXT: switch i32 [[TMP]], label [[BB20:%.*]] [
478-
; IPSCCP-NEXT: i32 1, label [[BB3:%.*]]
479-
; IPSCCP-NEXT: i32 2, label [[BB4:%.*]]
480-
; IPSCCP-NEXT: i32 4, label [[BB19:%.*]]
478+
; IPSCCP-NEXT: i32 1, label [[BB3:%.*]]
479+
; IPSCCP-NEXT: i32 2, label [[BB4:%.*]]
480+
; IPSCCP-NEXT: i32 4, label [[BB19:%.*]]
481481
; IPSCCP-NEXT: ]
482482
; IPSCCP: bb3:
483483
; IPSCCP-NEXT: unreachable
@@ -486,7 +486,7 @@ define void @foo(ptr %arg) {
486486
; IPSCCP-NEXT: [[TMP6:%.*]] = and i64 [[TMP5]], 3
487487
; IPSCCP-NEXT: [[TMP7:%.*]] = sub nuw nsw i64 3, [[TMP6]]
488488
; IPSCCP-NEXT: [[TMP8:%.*]] = shl nuw nsw i64 [[TMP7]], 1
489-
; IPSCCP-NEXT: [[TMP9:%.*]] = trunc i64 [[TMP8]] to i32
489+
; IPSCCP-NEXT: [[TMP9:%.*]] = trunc nuw nsw i64 [[TMP8]] to i32
490490
; IPSCCP-NEXT: [[TMP10:%.*]] = zext nneg i32 [[TMP9]] to i64
491491
; IPSCCP-NEXT: br label [[BB11:%.*]]
492492
; IPSCCP: bb11:
@@ -615,7 +615,7 @@ define ptr @wobble(ptr %arg, i32 %arg1) align 2 {
615615
; SCCP-NEXT: [[TMP22:%.*]] = icmp eq i32 [[TMP21]], 0
616616
; SCCP-NEXT: br i1 [[TMP22]], label [[BB23:%.*]], label [[BB25:%.*]]
617617
; SCCP: bb23:
618-
; SCCP-NEXT: [[TMP24:%.*]] = trunc i32 [[TMP3]] to i16
618+
; SCCP-NEXT: [[TMP24:%.*]] = trunc nuw i32 [[TMP3]] to i16
619619
; SCCP-NEXT: store i16 [[TMP24]], ptr [[TMP17]], align 2
620620
; SCCP-NEXT: br label [[BB31]]
621621
; SCCP: bb25:
@@ -639,7 +639,7 @@ define ptr @wobble(ptr %arg, i32 %arg1) align 2 {
639639
; SCCP-NEXT: br i1 [[C_2]], label [[BB39:%.*]], label [[BB58:%.*]]
640640
; SCCP: bb39:
641641
; SCCP-NEXT: [[TMP40:%.*]] = add nsw i32 [[TMP11]], -1
642-
; SCCP-NEXT: [[TMP41:%.*]] = trunc i32 [[TMP3]] to i16
642+
; SCCP-NEXT: [[TMP41:%.*]] = trunc nuw i32 [[TMP3]] to i16
643643
; SCCP-NEXT: store i16 [[TMP41]], ptr @global.11, align 1
644644
; SCCP-NEXT: [[TMP43:%.*]] = add i32 [[TMP7]], [[TMP40]]
645645
; SCCP-NEXT: [[TMP44:%.*]] = mul i32 [[TMP43]], 4
@@ -697,7 +697,7 @@ define ptr @wobble(ptr %arg, i32 %arg1) align 2 {
697697
; IPSCCP-NEXT: [[TMP22:%.*]] = icmp eq i32 [[TMP21]], 0
698698
; IPSCCP-NEXT: br i1 [[TMP22]], label [[BB23:%.*]], label [[BB25:%.*]]
699699
; IPSCCP: bb23:
700-
; IPSCCP-NEXT: [[TMP24:%.*]] = trunc i32 [[TMP3]] to i16
700+
; IPSCCP-NEXT: [[TMP24:%.*]] = trunc nuw i32 [[TMP3]] to i16
701701
; IPSCCP-NEXT: store i16 [[TMP24]], ptr [[TMP17]], align 2
702702
; IPSCCP-NEXT: br label [[BB31]]
703703
; IPSCCP: bb25:
@@ -720,7 +720,7 @@ define ptr @wobble(ptr %arg, i32 %arg1) align 2 {
720720
; IPSCCP-NEXT: [[C_2:%.*]] = icmp eq i32 [[TMP11]], 8
721721
; IPSCCP-NEXT: br i1 [[C_2]], label [[BB39:%.*]], label [[BB58:%.*]]
722722
; IPSCCP: bb39:
723-
; IPSCCP-NEXT: [[TMP41:%.*]] = trunc i32 [[TMP3]] to i16
723+
; IPSCCP-NEXT: [[TMP41:%.*]] = trunc nuw i32 [[TMP3]] to i16
724724
; IPSCCP-NEXT: store i16 [[TMP41]], ptr @global.11, align 1
725725
; IPSCCP-NEXT: [[TMP43:%.*]] = add i32 [[TMP7]], 7
726726
; IPSCCP-NEXT: [[TMP44:%.*]] = mul i32 [[TMP43]], 4

0 commit comments

Comments
 (0)