Skip to content

Commit ec5bc53

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

File tree

2 files changed

+454
-0
lines changed

2 files changed

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

0 commit comments

Comments
 (0)