Skip to content

Commit 5ea0260

Browse files
committed
[SimplifyCFG] Add tests for hoisting/sinking callbases with differing attrs; NFC
1 parent afc0557 commit 5ea0260

File tree

2 files changed

+473
-0
lines changed

2 files changed

+473
-0
lines changed
Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
2+
; RUN: opt < %s -passes='simplifycfg<hoist-common-insts>' -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
3+
4+
declare ptr @foo(ptr %p, i64 %x)
5+
declare void @side.effect()
6+
7+
define ptr @test_hoist_int_attrs(i1 %c, ptr %p, i64 %x) {
8+
; CHECK-LABEL: define {{[^@]+}}@test_hoist_int_attrs
9+
; CHECK-SAME: (i1 [[C:%.*]], ptr [[P:%.*]], i64 [[X:%.*]]) {
10+
; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[ELSE:%.*]]
11+
; CHECK: common.ret:
12+
; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi ptr [ [[R:%.*]], [[IF]] ], [ [[R2:%.*]], [[ELSE]] ]
13+
; CHECK-NEXT: ret ptr [[COMMON_RET_OP]]
14+
; CHECK: if:
15+
; CHECK-NEXT: [[R]] = call ptr @foo(ptr align 64 dereferenceable(50) dereferenceable_or_null(100) [[P]], i64 range(i64 10, 1000) [[X]]) #[[ATTR0:[0-9]+]]
16+
; CHECK-NEXT: br label [[COMMON_RET:%.*]]
17+
; CHECK: else:
18+
; CHECK-NEXT: [[R2]] = call ptr @foo(ptr align 32 dereferenceable(100) dereferenceable_or_null(200) [[P]], i64 range(i64 10000, 100000) [[X]]) #[[ATTR1:[0-9]+]]
19+
; CHECK-NEXT: call void @side.effect()
20+
; CHECK-NEXT: br label [[COMMON_RET]]
21+
;
22+
br i1 %c, label %if, label %else
23+
if:
24+
%r = call ptr @foo(ptr dereferenceable(50) align 64 dereferenceable_or_null(100) %p, i64 range(i64 10, 1000) %x) memory(read)
25+
ret ptr %r
26+
27+
else:
28+
%r2 = call ptr @foo(ptr dereferenceable(100) align 32 dereferenceable_or_null(200) %p, i64 range(i64 10000, 100000) %x) memory(write)
29+
call void @side.effect()
30+
ret ptr %r2
31+
}
32+
33+
define ptr @test_hoist_int_attrs2(i1 %c, ptr %p, i64 %x) {
34+
; CHECK-LABEL: define {{[^@]+}}@test_hoist_int_attrs2
35+
; CHECK-SAME: (i1 [[C:%.*]], ptr [[P:%.*]], i64 [[X:%.*]]) {
36+
; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[ELSE:%.*]]
37+
; CHECK: common.ret:
38+
; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi ptr [ [[R:%.*]], [[IF]] ], [ [[R2:%.*]], [[ELSE]] ]
39+
; CHECK-NEXT: ret ptr [[COMMON_RET_OP]]
40+
; CHECK: if:
41+
; CHECK-NEXT: [[R]] = call ptr @foo(ptr dereferenceable(50) [[P]], i64 range(i64 10, 1000) [[X]]) #[[ATTR0]]
42+
; CHECK-NEXT: br label [[COMMON_RET:%.*]]
43+
; CHECK: else:
44+
; CHECK-NEXT: [[R2]] = call ptr @foo(ptr align 32 dereferenceable(100) dereferenceable_or_null(200) [[P]], i64 range(i64 11, 100) [[X]]) #[[ATTR2:[0-9]+]]
45+
; CHECK-NEXT: call void @side.effect()
46+
; CHECK-NEXT: br label [[COMMON_RET]]
47+
;
48+
br i1 %c, label %if, label %else
49+
if:
50+
%r = call ptr @foo(ptr dereferenceable(50) %p, i64 range(i64 10, 1000) %x) memory(read)
51+
ret ptr %r
52+
53+
else:
54+
%r2 = call ptr @foo(ptr dereferenceable(100) align 32 dereferenceable_or_null(200) %p, i64 range(i64 11, 100) %x) memory(none)
55+
call void @side.effect()
56+
ret ptr %r2
57+
}
58+
59+
define ptr @test_hoist_bool_attrs2(i1 %c, ptr %p, i64 %x) {
60+
; CHECK-LABEL: define {{[^@]+}}@test_hoist_bool_attrs2
61+
; CHECK-SAME: (i1 [[C:%.*]], ptr [[P:%.*]], i64 [[X:%.*]]) {
62+
; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[ELSE:%.*]]
63+
; CHECK: common.ret:
64+
; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi ptr [ [[R:%.*]], [[IF]] ], [ [[R2:%.*]], [[ELSE]] ]
65+
; CHECK-NEXT: ret ptr [[COMMON_RET_OP]]
66+
; CHECK: if:
67+
; CHECK-NEXT: [[R]] = call noundef ptr @foo(ptr noundef nonnull readnone [[P]], i64 noundef [[X]]) #[[ATTR3:[0-9]+]]
68+
; CHECK-NEXT: br label [[COMMON_RET:%.*]]
69+
; CHECK: else:
70+
; CHECK-NEXT: [[R2]] = call noundef nonnull ptr @foo(ptr nonnull readonly [[P]], i64 noundef [[X]]) #[[ATTR4:[0-9]+]]
71+
; CHECK-NEXT: call void @side.effect()
72+
; CHECK-NEXT: br label [[COMMON_RET]]
73+
;
74+
br i1 %c, label %if, label %else
75+
if:
76+
%r = call noundef ptr @foo(ptr readnone nonnull noundef %p, i64 noundef %x) cold mustprogress nocallback nofree nosync willreturn
77+
ret ptr %r
78+
79+
else:
80+
%r2 = call noundef nonnull ptr @foo(ptr readonly nonnull %p, i64 noundef %x) mustprogress nocallback nofree willreturn
81+
call void @side.effect()
82+
ret ptr %r2
83+
}
84+
85+
define ptr @test_hoist_bool_attrs3(i1 %c, ptr %p, i64 %x) {
86+
; CHECK-LABEL: define {{[^@]+}}@test_hoist_bool_attrs3
87+
; CHECK-SAME: (i1 [[C:%.*]], ptr [[P:%.*]], i64 [[X:%.*]]) {
88+
; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[ELSE:%.*]]
89+
; CHECK: common.ret:
90+
; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi ptr [ [[R:%.*]], [[IF]] ], [ [[R2:%.*]], [[ELSE]] ]
91+
; CHECK-NEXT: ret ptr [[COMMON_RET_OP]]
92+
; CHECK: if:
93+
; CHECK-NEXT: [[R]] = call nonnull ptr @foo(ptr noundef readonly [[P]], i64 noundef [[X]]) #[[ATTR5:[0-9]+]]
94+
; CHECK-NEXT: br label [[COMMON_RET:%.*]]
95+
; CHECK: else:
96+
; CHECK-NEXT: [[R2]] = call noundef nonnull ptr @foo(ptr nonnull writeonly [[P]], i64 noundef [[X]]) #[[ATTR6:[0-9]+]]
97+
; CHECK-NEXT: call void @side.effect()
98+
; CHECK-NEXT: br label [[COMMON_RET]]
99+
;
100+
br i1 %c, label %if, label %else
101+
if:
102+
%r = call nonnull ptr @foo(ptr readonly noundef %p, i64 noundef %x) cold nocallback nofree nosync willreturn alwaysinline
103+
ret ptr %r
104+
105+
else:
106+
%r2 = call noundef nonnull ptr @foo(ptr writeonly nonnull %p, i64 noundef %x) nosync willreturn alwaysinline
107+
call void @side.effect()
108+
ret ptr %r2
109+
}
110+
111+
define ptr @test_hoist_bool_attrs_fail_non_droppable(i1 %c, ptr %p, i64 %x) {
112+
; CHECK-LABEL: define {{[^@]+}}@test_hoist_bool_attrs_fail_non_droppable
113+
; CHECK-SAME: (i1 [[C:%.*]], ptr [[P:%.*]], i64 [[X:%.*]]) {
114+
; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[ELSE:%.*]]
115+
; CHECK: common.ret:
116+
; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi ptr [ [[R:%.*]], [[IF]] ], [ [[R2:%.*]], [[ELSE]] ]
117+
; CHECK-NEXT: ret ptr [[COMMON_RET_OP]]
118+
; CHECK: if:
119+
; CHECK-NEXT: [[R]] = call nonnull ptr @foo(ptr noundef readonly [[P]], i64 noundef [[X]]) #[[ATTR5]]
120+
; CHECK-NEXT: br label [[COMMON_RET:%.*]]
121+
; CHECK: else:
122+
; CHECK-NEXT: [[R2]] = call noundef nonnull ptr @foo(ptr nonnull writeonly [[P]], i64 noundef [[X]]) #[[ATTR7:[0-9]+]]
123+
; CHECK-NEXT: call void @side.effect()
124+
; CHECK-NEXT: br label [[COMMON_RET]]
125+
;
126+
br i1 %c, label %if, label %else
127+
if:
128+
%r = call nonnull ptr @foo(ptr readonly noundef %p, i64 noundef %x) cold nocallback nofree nosync willreturn alwaysinline
129+
ret ptr %r
130+
131+
else:
132+
%r2 = call noundef nonnull ptr @foo(ptr writeonly nonnull %p, i64 noundef %x) nosync willreturn
133+
call void @side.effect()
134+
ret ptr %r2
135+
}
136+
137+
define ptr @test_hoist_bool_attrs_fail_non_droppable2(i1 %c, ptr %p, i64 %x) {
138+
; CHECK-LABEL: define {{[^@]+}}@test_hoist_bool_attrs_fail_non_droppable2
139+
; CHECK-SAME: (i1 [[C:%.*]], ptr [[P:%.*]], i64 [[X:%.*]]) {
140+
; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[ELSE:%.*]]
141+
; CHECK: common.ret:
142+
; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi ptr [ [[R:%.*]], [[IF]] ], [ [[R2:%.*]], [[ELSE]] ]
143+
; CHECK-NEXT: ret ptr [[COMMON_RET_OP]]
144+
; CHECK: if:
145+
; CHECK-NEXT: [[R]] = call nonnull ptr @foo(ptr noundef readonly [[P]], i64 noundef [[X]]) #[[ATTR8:[0-9]+]]
146+
; CHECK-NEXT: br label [[COMMON_RET:%.*]]
147+
; CHECK: else:
148+
; CHECK-NEXT: [[R2]] = call noundef nonnull ptr @foo(ptr nonnull writeonly byval(i64) [[P]], i64 noundef [[X]]) #[[ATTR7]]
149+
; CHECK-NEXT: call void @side.effect()
150+
; CHECK-NEXT: br label [[COMMON_RET]]
151+
;
152+
br i1 %c, label %if, label %else
153+
if:
154+
%r = call nonnull ptr @foo(ptr readonly noundef %p, i64 noundef %x) cold nocallback nofree nosync willreturn
155+
ret ptr %r
156+
157+
else:
158+
%r2 = call noundef nonnull ptr @foo(ptr byval(i64) writeonly nonnull %p, i64 noundef %x) nosync willreturn
159+
call void @side.effect()
160+
ret ptr %r2
161+
}
162+
163+
define ptr @test_hoist_bool_attrs_fail_non_droppable3(i1 %c, ptr %p, i64 %x) {
164+
; CHECK-LABEL: define {{[^@]+}}@test_hoist_bool_attrs_fail_non_droppable3
165+
; CHECK-SAME: (i1 [[C:%.*]], ptr [[P:%.*]], i64 [[X:%.*]]) {
166+
; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[ELSE:%.*]]
167+
; CHECK: common.ret:
168+
; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi ptr [ [[R:%.*]], [[IF]] ], [ [[R2:%.*]], [[ELSE]] ]
169+
; CHECK-NEXT: ret ptr [[COMMON_RET_OP]]
170+
; CHECK: if:
171+
; CHECK-NEXT: [[R]] = call nonnull ptr @foo(ptr noundef readonly byval(i32) [[P]], i64 noundef [[X]]) #[[ATTR8]]
172+
; CHECK-NEXT: br label [[COMMON_RET:%.*]]
173+
; CHECK: else:
174+
; CHECK-NEXT: [[R2]] = call noundef nonnull ptr @foo(ptr nonnull writeonly byval(i64) [[P]], i64 noundef [[X]]) #[[ATTR7]]
175+
; CHECK-NEXT: call void @side.effect()
176+
; CHECK-NEXT: br label [[COMMON_RET]]
177+
;
178+
br i1 %c, label %if, label %else
179+
if:
180+
%r = call nonnull ptr @foo(ptr byval(i32) readonly noundef %p, i64 noundef %x) cold nocallback nofree nosync willreturn
181+
ret ptr %r
182+
183+
else:
184+
%r2 = call noundef nonnull ptr @foo(ptr byval(i64) writeonly nonnull %p, i64 noundef %x) nosync willreturn
185+
call void @side.effect()
186+
ret ptr %r2
187+
}
188+
189+
define ptr @test_hoist_bool_attrs4(i1 %c, ptr %p, i64 %x) {
190+
; CHECK-LABEL: define {{[^@]+}}@test_hoist_bool_attrs4
191+
; CHECK-SAME: (i1 [[C:%.*]], ptr [[P:%.*]], i64 [[X:%.*]]) {
192+
; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[ELSE:%.*]]
193+
; CHECK: common.ret:
194+
; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi ptr [ [[R:%.*]], [[IF]] ], [ [[R2:%.*]], [[ELSE]] ]
195+
; CHECK-NEXT: ret ptr [[COMMON_RET_OP]]
196+
; CHECK: if:
197+
; CHECK-NEXT: [[R]] = call nonnull ptr @foo(ptr noundef readonly byval(i64) [[P]], i64 noundef [[X]]) #[[ATTR8]]
198+
; CHECK-NEXT: br label [[COMMON_RET:%.*]]
199+
; CHECK: else:
200+
; CHECK-NEXT: [[R2]] = call noundef nonnull ptr @foo(ptr nonnull writeonly byval(i64) [[P]], i64 noundef [[X]]) #[[ATTR7]]
201+
; CHECK-NEXT: call void @side.effect()
202+
; CHECK-NEXT: br label [[COMMON_RET]]
203+
;
204+
br i1 %c, label %if, label %else
205+
if:
206+
%r = call nonnull ptr @foo(ptr byval(i64) readonly noundef %p, i64 noundef %x) cold nocallback nofree nosync willreturn
207+
ret ptr %r
208+
209+
else:
210+
%r2 = call noundef nonnull ptr @foo(ptr byval(i64) writeonly nonnull %p, i64 noundef %x) nosync willreturn
211+
call void @side.effect()
212+
ret ptr %r2
213+
}
214+
;.
215+
; CHECK: attributes #[[ATTR0]] = { memory(read) }
216+
; CHECK: attributes #[[ATTR1]] = { memory(write) }
217+
; CHECK: attributes #[[ATTR2]] = { memory(none) }
218+
; CHECK: attributes #[[ATTR3]] = { cold mustprogress nocallback nofree nosync willreturn }
219+
; CHECK: attributes #[[ATTR4]] = { mustprogress nocallback nofree willreturn }
220+
; CHECK: attributes #[[ATTR5]] = { alwaysinline cold nocallback nofree nosync willreturn }
221+
; CHECK: attributes #[[ATTR6]] = { alwaysinline nosync willreturn }
222+
; CHECK: attributes #[[ATTR7]] = { nosync willreturn }
223+
; CHECK: attributes #[[ATTR8]] = { cold nocallback nofree nosync willreturn }
224+
;.

0 commit comments

Comments
 (0)