Skip to content

Commit 13b4d1b

Browse files
committed
[SimplifyCFG][LICM] Add additional speculation tests
These are related to #108854.
1 parent 4eee0cf commit 13b4d1b

File tree

2 files changed

+275
-4
lines changed

2 files changed

+275
-4
lines changed

llvm/test/Transforms/LICM/hoist-deref-load.ll

Lines changed: 77 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ for.end: ; preds = %for.inc, %entry
420420
define void @test7(ptr noalias %a, ptr %b, ptr %cptr, i32 %n) #0 {
421421
; CHECK-LABEL: @test7(
422422
; CHECK-NEXT: entry:
423-
; CHECK-NEXT: [[C:%.*]] = load ptr, ptr [[CPTR:%.*]], align 8, !dereferenceable !0, !align !0
423+
; CHECK-NEXT: [[C:%.*]] = load ptr, ptr [[CPTR:%.*]], align 8, !dereferenceable [[META0:![0-9]+]], !align [[META0]]
424424
; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0
425425
; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]
426426
; CHECK: for.body.preheader:
@@ -492,7 +492,7 @@ for.end: ; preds = %for.inc, %entry
492492
define void @test8(ptr noalias %a, ptr %b, ptr %cptr, i32 %n) #0 {
493493
; CHECK-LABEL: @test8(
494494
; CHECK-NEXT: entry:
495-
; CHECK-NEXT: [[C:%.*]] = load ptr, ptr [[CPTR:%.*]], align 8, !dereferenceable_or_null !0, !align !0
495+
; CHECK-NEXT: [[C:%.*]] = load ptr, ptr [[CPTR:%.*]], align 8, !dereferenceable_or_null [[META0]], !align [[META0]]
496496
; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne ptr [[C]], null
497497
; CHECK-NEXT: br i1 [[NOT_NULL]], label [[NOT_NULL:%.*]], label [[FOR_END:%.*]]
498498
; CHECK: not.null:
@@ -562,7 +562,7 @@ for.end: ; preds = %for.inc, %entry, %n
562562
define void @test9(ptr noalias %a, ptr %b, ptr %cptr, i32 %n) #0 {
563563
; CHECK-LABEL: @test9(
564564
; CHECK-NEXT: entry:
565-
; CHECK-NEXT: [[C:%.*]] = load ptr, ptr [[CPTR:%.*]], align 8, !dereferenceable_or_null !0
565+
; CHECK-NEXT: [[C:%.*]] = load ptr, ptr [[CPTR:%.*]], align 8, !dereferenceable_or_null [[META0]]
566566
; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0
567567
; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]
568568
; CHECK: for.body.preheader:
@@ -693,7 +693,7 @@ define void @test11(ptr noalias %a, ptr %b, ptr dereferenceable(8) %cptr, i32 %n
693693
; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0
694694
; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]
695695
; CHECK: for.body.preheader:
696-
; CHECK-NEXT: [[C:%.*]] = load ptr, ptr [[CPTR:%.*]], align 8, !dereferenceable !0
696+
; CHECK-NEXT: [[C:%.*]] = load ptr, ptr [[CPTR:%.*]], align 8, !dereferenceable [[META0]]
697697
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
698698
; CHECK: for.body:
699699
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
@@ -1164,5 +1164,78 @@ for.end: ; preds = %for.inc, %entry
11641164
ret void
11651165
}
11661166

1167+
declare void @use(i64)
1168+
1169+
define void @licm_deref_no_hoist(i1 %c1, i1 %c2, ptr align 8 dereferenceable(8) %p1) {
1170+
; CHECK-LABEL: @licm_deref_no_hoist(
1171+
; CHECK-NEXT: entry:
1172+
; CHECK-NEXT: [[P2:%.*]] = load ptr, ptr [[P1:%.*]], align 8, !align [[META1:![0-9]+]]
1173+
; CHECK-NEXT: br label [[LOOP:%.*]]
1174+
; CHECK: loop:
1175+
; CHECK-NEXT: br i1 [[C1:%.*]], label [[IF:%.*]], label [[LOOP_LATCH:%.*]]
1176+
; CHECK: if:
1177+
; CHECK-NEXT: [[V:%.*]] = load i64, ptr [[P2]], align 8
1178+
; CHECK-NEXT: call void @use(i64 [[V]]) #[[ATTR1:[0-9]+]]
1179+
; CHECK-NEXT: br label [[LOOP_LATCH]]
1180+
; CHECK: loop.latch:
1181+
; CHECK-NEXT: br i1 [[C2:%.*]], label [[LOOP]], label [[EXIT:%.*]]
1182+
; CHECK: exit:
1183+
; CHECK-NEXT: ret void
1184+
;
1185+
entry:
1186+
br label %loop
1187+
1188+
loop:
1189+
br i1 %c1, label %if, label %loop.latch
1190+
1191+
if:
1192+
%p2 = load ptr, ptr %p1, align 8, !dereferenceable !1, !align !1
1193+
%v = load i64, ptr %p2, align 8
1194+
call void @use(i64 %v) memory(none)
1195+
br label %loop.latch
1196+
1197+
loop.latch:
1198+
br i1 %c2, label %loop, label %exit
1199+
1200+
exit:
1201+
ret void
1202+
}
1203+
1204+
define void @licm_deref_hoist(i1 %c1, i1 %c2, ptr align 8 dereferenceable(8) %p1) {
1205+
; CHECK-LABEL: @licm_deref_hoist(
1206+
; CHECK-NEXT: entry:
1207+
; CHECK-NEXT: [[P2:%.*]] = load ptr, ptr [[P1:%.*]], align 8, !dereferenceable [[META1]], !align [[META1]]
1208+
; CHECK-NEXT: [[V:%.*]] = load i64, ptr [[P2]], align 8
1209+
; CHECK-NEXT: br label [[LOOP:%.*]]
1210+
; CHECK: loop:
1211+
; CHECK-NEXT: br i1 [[C1:%.*]], label [[IF:%.*]], label [[LOOP_LATCH:%.*]]
1212+
; CHECK: if:
1213+
; CHECK-NEXT: call void @use(i64 [[V]]) #[[ATTR1]]
1214+
; CHECK-NEXT: br label [[LOOP_LATCH]]
1215+
; CHECK: loop.latch:
1216+
; CHECK-NEXT: br i1 [[C2:%.*]], label [[LOOP]], label [[EXIT:%.*]]
1217+
; CHECK: exit:
1218+
; CHECK-NEXT: ret void
1219+
;
1220+
entry:
1221+
%p2 = load ptr, ptr %p1, align 8, !dereferenceable !1, !align !1
1222+
br label %loop
1223+
1224+
loop:
1225+
br i1 %c1, label %if, label %loop.latch
1226+
1227+
if:
1228+
%v = load i64, ptr %p2, align 8
1229+
call void @use(i64 %v) memory(none)
1230+
br label %loop.latch
1231+
1232+
loop.latch:
1233+
br i1 %c2, label %loop, label %exit
1234+
1235+
exit:
1236+
ret void
1237+
}
1238+
11671239
attributes #0 = { nounwind uwtable nofree nosync }
11681240
!0 = !{i64 4}
1241+
!1 = !{i64 8}
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt -S -passes=simplifycfg < %s | FileCheck %s
3+
4+
define i64 @align_deref_align(i1 %c, ptr %p) {
5+
; CHECK-LABEL: define i64 @align_deref_align(
6+
; CHECK-SAME: i1 [[C:%.*]], ptr [[P:%.*]]) {
7+
; CHECK-NEXT: [[ENTRY:.*]]:
8+
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 8), "align"(ptr [[P]], i64 8) ]
9+
; CHECK-NEXT: br i1 [[C]], label %[[IF:.*]], label %[[EXIT:.*]]
10+
; CHECK: [[IF]]:
11+
; CHECK-NEXT: [[V:%.*]] = load i64, ptr [[P]], align 8
12+
; CHECK-NEXT: br label %[[EXIT]]
13+
; CHECK: [[EXIT]]:
14+
; CHECK-NEXT: [[RES:%.*]] = phi i64 [ [[V]], %[[IF]] ], [ 0, %[[ENTRY]] ]
15+
; CHECK-NEXT: ret i64 [[RES]]
16+
;
17+
entry:
18+
call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %p, i64 8), "align"(ptr %p, i64 8) ]
19+
br i1 %c, label %if, label %exit
20+
21+
if:
22+
%v = load i64, ptr %p, align 8
23+
br label %exit
24+
25+
exit:
26+
%res = phi i64 [ %v, %if ], [ 0, %entry ]
27+
ret i64 %res
28+
}
29+
30+
define i64 @assume_deref_align2(i1 %c1, i32 %x, ptr %p) {
31+
; CHECK-LABEL: define i64 @assume_deref_align2(
32+
; CHECK-SAME: i1 [[C1:%.*]], i32 [[X:%.*]], ptr [[P:%.*]]) {
33+
; CHECK-NEXT: [[ENTRY:.*]]:
34+
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 8), "align"(ptr [[P]], i64 8) ]
35+
; CHECK-NEXT: br i1 [[C1]], label %[[IF1:.*]], label %[[EXIT:.*]]
36+
; CHECK: [[IF1]]:
37+
; CHECK-NEXT: [[C2:%.*]] = icmp ugt i32 [[X]], 10
38+
; CHECK-NEXT: br i1 [[C2]], label %[[IF2:.*]], label %[[EXIT]]
39+
; CHECK: [[IF2]]:
40+
; CHECK-NEXT: [[V:%.*]] = load i64, ptr [[P]], align 8
41+
; CHECK-NEXT: br label %[[EXIT]]
42+
; CHECK: [[EXIT]]:
43+
; CHECK-NEXT: [[RES:%.*]] = phi i64 [ [[V]], %[[IF2]] ], [ 1, %[[IF1]] ], [ 0, %[[ENTRY]] ]
44+
; CHECK-NEXT: ret i64 [[RES]]
45+
;
46+
entry:
47+
call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %p, i64 8), "align"(ptr %p, i64 8) ]
48+
br i1 %c1, label %if1, label %exit
49+
50+
if1:
51+
%c2 = icmp ugt i32 %x, 10
52+
br i1 %c2, label %if2, label %exit
53+
54+
if2:
55+
%v = load i64, ptr %p, align 8
56+
br label %exit
57+
58+
exit:
59+
%res = phi i64 [ %v, %if2 ], [ 1, %if1 ], [ 0, %entry ]
60+
ret i64 %res
61+
}
62+
63+
define i64 @assume_deref_align_not_dominating(i1 %c, ptr %p) {
64+
; CHECK-LABEL: define i64 @assume_deref_align_not_dominating(
65+
; CHECK-SAME: i1 [[C:%.*]], ptr [[P:%.*]]) {
66+
; CHECK-NEXT: [[ENTRY:.*]]:
67+
; CHECK-NEXT: br i1 [[C]], label %[[IF:.*]], label %[[EXIT:.*]]
68+
; CHECK: [[IF]]:
69+
; CHECK-NEXT: [[V:%.*]] = load i64, ptr [[P]], align 8
70+
; CHECK-NEXT: br label %[[EXIT]]
71+
; CHECK: [[EXIT]]:
72+
; CHECK-NEXT: [[RES:%.*]] = phi i64 [ [[V]], %[[IF]] ], [ 0, %[[ENTRY]] ]
73+
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 8), "align"(ptr [[P]], i64 8) ]
74+
; CHECK-NEXT: ret i64 [[RES]]
75+
;
76+
entry:
77+
br i1 %c, label %if, label %exit
78+
79+
if:
80+
%v = load i64, ptr %p, align 8
81+
br label %exit
82+
83+
exit:
84+
%res = phi i64 [ %v, %if ], [ 0, %entry ]
85+
call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %p, i64 8), "align"(ptr %p, i64 8) ]
86+
ret i64 %res
87+
}
88+
89+
; FIXME: This is a miscompile.
90+
define i64 @deref_no_hoist(i1 %c, ptr align 8 dereferenceable(8) %p1) {
91+
; CHECK-LABEL: define i64 @deref_no_hoist(
92+
; CHECK-SAME: i1 [[C:%.*]], ptr align 8 dereferenceable(8) [[P1:%.*]]) {
93+
; CHECK-NEXT: [[ENTRY:.*:]]
94+
; CHECK-NEXT: [[P2:%.*]] = load ptr, ptr [[P1]], align 8, !align [[META0:![0-9]+]]
95+
; CHECK-NEXT: [[V:%.*]] = load i64, ptr [[P2]], align 8
96+
; CHECK-NEXT: [[RES:%.*]] = select i1 [[C]], i64 [[V]], i64 0
97+
; CHECK-NEXT: ret i64 [[RES]]
98+
;
99+
entry:
100+
br i1 %c, label %if, label %exit
101+
102+
if:
103+
%p2 = load ptr, ptr %p1, align 8, !dereferenceable !0, !align !0
104+
%v = load i64, ptr %p2, align 8
105+
br label %exit
106+
107+
exit:
108+
%res = phi i64 [ %v, %if ], [ 0, %entry ]
109+
ret i64 %res
110+
}
111+
112+
define i64 @deref_hoist(i1 %c, ptr align 8 dereferenceable(8) %p1) {
113+
; CHECK-LABEL: define i64 @deref_hoist(
114+
; CHECK-SAME: i1 [[C:%.*]], ptr align 8 dereferenceable(8) [[P1:%.*]]) {
115+
; CHECK-NEXT: [[ENTRY:.*:]]
116+
; CHECK-NEXT: [[P2:%.*]] = load ptr, ptr [[P1]], align 8, !dereferenceable [[META0]], !align [[META0]]
117+
; CHECK-NEXT: [[V:%.*]] = load i64, ptr [[P2]], align 8
118+
; CHECK-NEXT: [[RES:%.*]] = select i1 [[C]], i64 [[V]], i64 0
119+
; CHECK-NEXT: ret i64 [[RES]]
120+
;
121+
entry:
122+
%p2 = load ptr, ptr %p1, align 8, !dereferenceable !0, !align !0
123+
br i1 %c, label %if, label %exit
124+
125+
if:
126+
%v = load i64, ptr %p2, align 8
127+
br label %exit
128+
129+
exit:
130+
%res = phi i64 [ %v, %if ], [ 0, %entry ]
131+
ret i64 %res
132+
}
133+
134+
define i64 @deref_no_hoist2(i1 %c1, i32 %x, ptr align 8 dereferenceable(8) %p1) {
135+
; CHECK-LABEL: define i64 @deref_no_hoist2(
136+
; CHECK-SAME: i1 [[C1:%.*]], i32 [[X:%.*]], ptr align 8 dereferenceable(8) [[P1:%.*]]) {
137+
; CHECK-NEXT: [[ENTRY:.*]]:
138+
; CHECK-NEXT: br i1 [[C1]], label %[[IF1:.*]], label %[[EXIT:.*]]
139+
; CHECK: [[IF1]]:
140+
; CHECK-NEXT: [[C2:%.*]] = icmp ugt i32 [[X]], 10
141+
; CHECK-NEXT: br i1 [[C2]], label %[[IF2:.*]], label %[[EXIT]]
142+
; CHECK: [[IF2]]:
143+
; CHECK-NEXT: [[P2:%.*]] = load ptr, ptr [[P1]], align 8, !dereferenceable [[META0]], !align [[META0]]
144+
; CHECK-NEXT: [[V:%.*]] = load i64, ptr [[P2]], align 8
145+
; CHECK-NEXT: br label %[[EXIT]]
146+
; CHECK: [[EXIT]]:
147+
; CHECK-NEXT: [[RES:%.*]] = phi i64 [ [[V]], %[[IF2]] ], [ 1, %[[IF1]] ], [ 0, %[[ENTRY]] ]
148+
; CHECK-NEXT: ret i64 [[RES]]
149+
;
150+
entry:
151+
br i1 %c1, label %if1, label %exit
152+
153+
if1:
154+
%c2 = icmp ugt i32 %x, 10
155+
br i1 %c2, label %if2, label %exit
156+
157+
if2:
158+
%p2 = load ptr, ptr %p1, align 8, !dereferenceable !0, !align !0
159+
%v = load i64, ptr %p2, align 8
160+
br label %exit
161+
162+
exit:
163+
%res = phi i64 [ %v, %if2 ], [ 1, %if1 ], [ 0, %entry ]
164+
ret i64 %res
165+
}
166+
167+
define i64 @deref_hoist2(i1 %c1, i32 %x, ptr align 8 dereferenceable(8) %p1) {
168+
; CHECK-LABEL: define i64 @deref_hoist2(
169+
; CHECK-SAME: i1 [[C1:%.*]], i32 [[X:%.*]], ptr align 8 dereferenceable(8) [[P1:%.*]]) {
170+
; CHECK-NEXT: [[ENTRY:.*:]]
171+
; CHECK-NEXT: [[P2:%.*]] = load ptr, ptr [[P1]], align 8, !dereferenceable [[META0]], !align [[META0]]
172+
; CHECK-NEXT: [[C2:%.*]] = icmp ugt i32 [[X]], 10
173+
; CHECK-NEXT: [[V:%.*]] = load i64, ptr [[P2]], align 8
174+
; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[C2]], i64 [[V]], i64 1
175+
; CHECK-NEXT: [[RES:%.*]] = select i1 [[C1]], i64 [[SPEC_SELECT]], i64 0
176+
; CHECK-NEXT: ret i64 [[RES]]
177+
;
178+
entry:
179+
%p2 = load ptr, ptr %p1, align 8, !dereferenceable !0, !align !0
180+
br i1 %c1, label %if1, label %exit
181+
182+
if1:
183+
%c2 = icmp ugt i32 %x, 10
184+
br i1 %c2, label %if2, label %exit
185+
186+
if2:
187+
%v = load i64, ptr %p2, align 8
188+
br label %exit
189+
190+
exit:
191+
%res = phi i64 [ %v, %if2 ], [ 1, %if1 ], [ 0, %entry ]
192+
ret i64 %res
193+
}
194+
195+
!0 = !{i64 8}
196+
;.
197+
; CHECK: [[META0]] = !{i64 8}
198+
;.

0 commit comments

Comments
 (0)