Skip to content

Commit c426594

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

File tree

2 files changed

+477
-0
lines changed

2 files changed

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

0 commit comments

Comments
 (0)