1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2 ; RUN: opt -S -passes=gvn-hoist < %s | FileCheck %s
4 ; Checking gvn-hoist in case of indirect branches.
6 %class.bar = type { ptr, ptr }
7 %class.base = type { ptr }
9 @bar = local_unnamed_addr global ptr null, align 8
10 @bar1 = local_unnamed_addr global ptr null, align 8
12 ; Check that the bitcast is not hoisted because it is after an indirect call
13 define i32 @foo(ptr nocapture readonly %i) {
14 ; CHECK-LABEL: define i32 @foo
15 ; CHECK-SAME: (ptr nocapture readonly [[I:%.*]]) {
17 ; CHECK-NEXT: [[AGG_TMP:%.*]] = alloca [[CLASS_BAR:%.*]], align 8
18 ; CHECK-NEXT: [[X:%.*]] = getelementptr inbounds [[CLASS_BAR]], ptr [[AGG_TMP]], i64 0, i32 1
19 ; CHECK-NEXT: [[Y:%.*]] = load ptr, ptr [[X]], align 8
20 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I]], align 4
21 ; CHECK-NEXT: [[DOTOFF:%.*]] = add i32 [[TMP0]], -1
22 ; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i32 [[DOTOFF]], 2
23 ; CHECK-NEXT: br i1 [[SWITCH]], label [[L1_PREHEADER:%.*]], label [[SW_DEFAULT:%.*]]
24 ; CHECK: l1.preheader:
25 ; CHECK-NEXT: [[B1:%.*]] = bitcast ptr [[Y]] to ptr
26 ; CHECK-NEXT: br label [[L1:%.*]]
28 ; CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr @bar, align 8
29 ; CHECK-NEXT: [[CALL:%.*]] = tail call i32 [[TMP1]]()
30 ; CHECK-NEXT: [[B2:%.*]] = bitcast ptr [[Y]] to ptr
31 ; CHECK-NEXT: br label [[L1]]
33 ; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr @bar1, align 8
34 ; CHECK-NEXT: [[CALL2:%.*]] = tail call i32 [[TMP2]]()
35 ; CHECK-NEXT: br label [[L1_PREHEADER]]
38 %agg.tmp = alloca %class.bar, align 8
39 %x= getelementptr inbounds %class.bar, ptr %agg.tmp, i64 0, i32 1
40 %y = load ptr, ptr %x, align 8
41 %0 = load i32, ptr %i, align 4
42 %.off = add i32 %0, -1
43 %switch = icmp ult i32 %.off, 2
44 br i1 %switch, label %l1.preheader, label %sw.default
46 l1.preheader: ; preds = %sw.default, %entry
47 %b1 = bitcast ptr %y to ptr
50 l1: ; preds = %l1.preheader, %l1
51 %1 = load ptr, ptr @bar, align 8
52 %call = tail call i32 %1()
53 %b2 = bitcast ptr %y to ptr
56 sw.default: ; preds = %entry
57 %2 = load ptr, ptr @bar1, align 8
58 %call2 = tail call i32 %2()
59 br label %l1.preheader
63 ; Any instruction inside an infinite loop will not be hoisted because
64 ; there is no path to exit of the function.
65 define i32 @foo1(ptr nocapture readonly %i) {
66 ; CHECK-LABEL: define i32 @foo1
67 ; CHECK-SAME: (ptr nocapture readonly [[I:%.*]]) {
69 ; CHECK-NEXT: [[AGG_TMP:%.*]] = alloca [[CLASS_BAR:%.*]], align 8
70 ; CHECK-NEXT: [[X:%.*]] = getelementptr inbounds [[CLASS_BAR]], ptr [[AGG_TMP]], i64 0, i32 1
71 ; CHECK-NEXT: [[Y:%.*]] = load ptr, ptr [[X]], align 8
72 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I]], align 4
73 ; CHECK-NEXT: [[DOTOFF:%.*]] = add i32 [[TMP0]], -1
74 ; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i32 [[DOTOFF]], 2
75 ; CHECK-NEXT: br i1 [[SWITCH]], label [[L1_PREHEADER:%.*]], label [[SW_DEFAULT:%.*]]
76 ; CHECK: l1.preheader:
77 ; CHECK-NEXT: [[B1:%.*]] = bitcast ptr [[Y]] to ptr
78 ; CHECK-NEXT: [[Y1:%.*]] = load ptr, ptr [[X]], align 8
79 ; CHECK-NEXT: br label [[L1:%.*]]
81 ; CHECK-NEXT: [[B2:%.*]] = bitcast ptr [[Y]] to ptr
82 ; CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr @bar, align 8
83 ; CHECK-NEXT: [[Y2:%.*]] = load ptr, ptr [[X]], align 8
84 ; CHECK-NEXT: [[CALL:%.*]] = tail call i32 [[TMP1]]()
85 ; CHECK-NEXT: br label [[L1]]
87 ; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr @bar1, align 8
88 ; CHECK-NEXT: [[CALL2:%.*]] = tail call i32 [[TMP2]]()
89 ; CHECK-NEXT: br label [[L1_PREHEADER]]
92 %agg.tmp = alloca %class.bar, align 8
93 %x= getelementptr inbounds %class.bar, ptr %agg.tmp, i64 0, i32 1
94 %y = load ptr, ptr %x, align 8
95 %0 = load i32, ptr %i, align 4
96 %.off = add i32 %0, -1
97 %switch = icmp ult i32 %.off, 2
98 br i1 %switch, label %l1.preheader, label %sw.default
100 l1.preheader: ; preds = %sw.default, %entry
101 %b1 = bitcast ptr %y to ptr
102 %y1 = load ptr, ptr %x, align 8
105 l1: ; preds = %l1.preheader, %l1
106 %b2 = bitcast ptr %y to ptr
107 %1 = load ptr, ptr @bar, align 8
108 %y2 = load ptr, ptr %x, align 8
109 %call = tail call i32 %1()
112 sw.default: ; preds = %entry
113 %2 = load ptr, ptr @bar1, align 8
114 %call2 = tail call i32 %2()
115 br label %l1.preheader
118 ; Check that bitcast is hoisted even when one of them is partially redundant.
119 define i32 @test13(ptr %P, ptr %Ptr, ptr nocapture readonly %i) {
120 ; CHECK-LABEL: define i32 @test13
121 ; CHECK-SAME: (ptr [[P:%.*]], ptr [[PTR:%.*]], ptr nocapture readonly [[I:%.*]]) {
123 ; CHECK-NEXT: [[AGG_TMP:%.*]] = alloca [[CLASS_BAR:%.*]], align 8
124 ; CHECK-NEXT: [[X:%.*]] = getelementptr inbounds [[CLASS_BAR]], ptr [[AGG_TMP]], i64 0, i32 1
125 ; CHECK-NEXT: [[Y:%.*]] = load ptr, ptr [[X]], align 8
126 ; CHECK-NEXT: [[B2:%.*]] = bitcast ptr [[Y]] to ptr
127 ; CHECK-NEXT: indirectbr ptr [[PTR]], [label [[BRBLOCK:%.*]], label %B2]
129 ; CHECK-NEXT: store i32 4, ptr [[P]], align 4
130 ; CHECK-NEXT: br label [[BRBLOCK]]
132 ; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[P]], align 4
133 ; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[L]], 42
134 ; CHECK-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
136 ; CHECK-NEXT: ret i32 123
138 ; CHECK-NEXT: ret i32 1422
141 %agg.tmp = alloca %class.bar, align 8
142 %x= getelementptr inbounds %class.bar, ptr %agg.tmp, i64 0, i32 1
143 %y = load ptr, ptr %x, align 8
144 indirectbr ptr %Ptr, [label %BrBlock, label %B2]
147 %b1 = bitcast ptr %y to ptr
152 %b2 = bitcast ptr %y to ptr
153 %L = load i32, ptr %P
154 %C = icmp eq i32 %L, 42
155 br i1 %C, label %T, label %F
163 ; Check that the bitcast is not hoisted because anticipability
164 ; cannot be guaranteed here as one of the indirect branch targets
165 ; do not have the bitcast instruction.
166 define i32 @test14(ptr %P, ptr %Ptr, ptr nocapture readonly %i) {
167 ; CHECK-LABEL: define i32 @test14
168 ; CHECK-SAME: (ptr [[P:%.*]], ptr [[PTR:%.*]], ptr nocapture readonly [[I:%.*]]) {
170 ; CHECK-NEXT: [[AGG_TMP:%.*]] = alloca [[CLASS_BAR:%.*]], align 8
171 ; CHECK-NEXT: [[X:%.*]] = getelementptr inbounds [[CLASS_BAR]], ptr [[AGG_TMP]], i64 0, i32 1
172 ; CHECK-NEXT: [[Y:%.*]] = load ptr, ptr [[X]], align 8
173 ; CHECK-NEXT: indirectbr ptr [[PTR]], [label [[BRBLOCK:%.*]], label [[B2:%.*]], label %T]
175 ; CHECK-NEXT: [[B1:%.*]] = bitcast ptr [[Y]] to ptr
176 ; CHECK-NEXT: store i32 4, ptr [[P]], align 4
177 ; CHECK-NEXT: br label [[BRBLOCK]]
179 ; CHECK-NEXT: [[B2:%.*]] = bitcast ptr [[Y]] to ptr
180 ; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[P]], align 4
181 ; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[L]], 42
182 ; CHECK-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
184 ; CHECK-NEXT: [[PI:%.*]] = load i32, ptr [[I]], align 4
185 ; CHECK-NEXT: ret i32 [[PI]]
187 ; CHECK-NEXT: [[PL:%.*]] = load i32, ptr [[P]], align 4
188 ; CHECK-NEXT: ret i32 [[PL]]
191 %agg.tmp = alloca %class.bar, align 8
192 %x= getelementptr inbounds %class.bar, ptr %agg.tmp, i64 0, i32 1
193 %y = load ptr, ptr %x, align 8
194 indirectbr ptr %Ptr, [label %BrBlock, label %B2, label %T]
197 %b1 = bitcast ptr %y to ptr
202 %b2 = bitcast ptr %y to ptr
203 %L = load i32, ptr %P
204 %C = icmp eq i32 %L, 42
205 br i1 %C, label %T, label %F
208 %pi = load i32, ptr %i, align 4
211 %pl = load i32, ptr %P
216 ; Check that the bitcast is not hoisted because of a cycle
217 ; due to indirect branches
218 define i32 @test16(ptr %P, ptr %Ptr, ptr nocapture readonly %i) {
219 ; CHECK-LABEL: define i32 @test16
220 ; CHECK-SAME: (ptr [[P:%.*]], ptr [[PTR:%.*]], ptr nocapture readonly [[I:%.*]]) {
222 ; CHECK-NEXT: [[AGG_TMP:%.*]] = alloca [[CLASS_BAR:%.*]], align 8
223 ; CHECK-NEXT: [[X:%.*]] = getelementptr inbounds [[CLASS_BAR]], ptr [[AGG_TMP]], i64 0, i32 1
224 ; CHECK-NEXT: [[Y:%.*]] = load ptr, ptr [[X]], align 8
225 ; CHECK-NEXT: indirectbr ptr [[PTR]], [label [[BRBLOCK:%.*]], label %B2]
227 ; CHECK-NEXT: [[B1:%.*]] = bitcast ptr [[Y]] to ptr
228 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I]], align 4
229 ; CHECK-NEXT: store i32 [[TMP0]], ptr [[P]], align 4
230 ; CHECK-NEXT: br label [[BRBLOCK]]
232 ; CHECK-NEXT: [[B2:%.*]] = bitcast ptr [[Y]] to ptr
233 ; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[P]], align 4
234 ; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[L]], 42
235 ; CHECK-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
237 ; CHECK-NEXT: indirectbr ptr [[P]], [label [[BRBLOCK]], label %B2]
239 ; CHECK-NEXT: indirectbr ptr [[PTR]], [label [[BRBLOCK]], label %B2]
242 %agg.tmp = alloca %class.bar, align 8
243 %x= getelementptr inbounds %class.bar, ptr %agg.tmp, i64 0, i32 1
244 %y = load ptr, ptr %x, align 8
245 indirectbr ptr %Ptr, [label %BrBlock, label %B2]
248 %b1 = bitcast ptr %y to ptr
249 %0 = load i32, ptr %i, align 4
254 %b2 = bitcast ptr %y to ptr
255 %L = load i32, ptr %P
256 %C = icmp eq i32 %L, 42
257 br i1 %C, label %T, label %F
260 indirectbr ptr %P, [label %BrBlock, label %B2]
263 indirectbr ptr %Ptr, [label %BrBlock, label %B2]
267 @_ZTIi = external constant ptr
269 ; Check that an instruction is not hoisted out of landing pad (%lpad4)
270 ; Also within a landing pad no redundancies are removed by gvn-hoist,
271 ; however an instruction may be hoisted into a landing pad if
272 ; landing pad has direct branches (e.g., %lpad to %catch1, %catch)
273 ; This CFG has a cycle (%lpad -> %catch1 -> %lpad4 -> %lpad)
275 define i32 @foo2(ptr nocapture readonly %i) local_unnamed_addr personality ptr @__gxx_personality_v0 {
276 ; CHECK-LABEL: define i32 @foo2
277 ; CHECK-SAME: (ptr nocapture readonly [[I:%.*]]) local_unnamed_addr personality ptr @__gxx_personality_v0 {
279 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I]], align 4
280 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], 0
281 ; CHECK-NEXT: br i1 [[CMP]], label [[TRY_CONT:%.*]], label [[IF_THEN:%.*]]
283 ; CHECK-NEXT: [[EXCEPTION:%.*]] = tail call ptr @__cxa_allocate_exception(i64 4) #[[ATTR1:[0-9]+]]
284 ; CHECK-NEXT: [[TMP1:%.*]] = bitcast ptr [[EXCEPTION]] to ptr
285 ; CHECK-NEXT: store i32 [[TMP0]], ptr [[TMP1]], align 16
286 ; CHECK-NEXT: invoke void @__cxa_throw(ptr [[EXCEPTION]], ptr @_ZTIi, ptr null) #[[ATTR2:[0-9]+]]
287 ; CHECK-NEXT: to label [[UNREACHABLE:%.*]] unwind label [[LPAD:%.*]]
289 ; CHECK-NEXT: [[TMP2:%.*]] = landingpad { ptr, i32 }
290 ; CHECK-NEXT: catch ptr @_ZTIi
291 ; CHECK-NEXT: catch ptr null
292 ; CHECK-NEXT: [[BC1:%.*]] = add i32 [[TMP0]], 10
293 ; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP2]], 0
294 ; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { ptr, i32 } [[TMP2]], 1
295 ; CHECK-NEXT: [[TMP5:%.*]] = tail call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi) #[[ATTR1]]
296 ; CHECK-NEXT: [[MATCHES:%.*]] = icmp eq i32 [[TMP4]], [[TMP5]]
297 ; CHECK-NEXT: [[BC7:%.*]] = add i32 [[TMP0]], 10
298 ; CHECK-NEXT: [[TMP6:%.*]] = tail call ptr @__cxa_begin_catch(ptr [[TMP3]]) #[[ATTR1]]
299 ; CHECK-NEXT: [[BC4:%.*]] = add i32 [[TMP0]], 10
300 ; CHECK-NEXT: br i1 [[MATCHES]], label [[CATCH1:%.*]], label [[CATCH:%.*]]
302 ; CHECK-NEXT: invoke void @__cxa_rethrow() #[[ATTR2]]
303 ; CHECK-NEXT: to label [[UNREACHABLE]] unwind label [[LPAD4:%.*]]
305 ; CHECK-NEXT: [[TMP7:%.*]] = load i32, ptr [[I]], align 4
306 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP7]], 1
307 ; CHECK-NEXT: tail call void @__cxa_end_catch()
308 ; CHECK-NEXT: br label [[TRY_CONT]]
310 ; CHECK-NEXT: [[TMP8:%.*]] = landingpad { ptr, i32 }
311 ; CHECK-NEXT: cleanup
312 ; CHECK-NEXT: [[BC5:%.*]] = add i32 [[TMP0]], 10
313 ; CHECK-NEXT: tail call void @__cxa_end_catch() #[[ATTR1]]
314 ; CHECK-NEXT: invoke void @__cxa_throw(ptr [[EXCEPTION]], ptr @_ZTIi, ptr null) #[[ATTR2]]
315 ; CHECK-NEXT: to label [[UNREACHABLE]] unwind label [[LPAD]]
317 ; CHECK-NEXT: [[K_0:%.*]] = phi i32 [ [[ADD]], [[CATCH]] ], [ 0, [[ENTRY:%.*]] ]
318 ; CHECK-NEXT: [[BC6:%.*]] = add i32 [[TMP0]], 10
319 ; CHECK-NEXT: ret i32 [[K_0]]
320 ; CHECK: unreachable:
321 ; CHECK-NEXT: [[BC2:%.*]] = add i32 [[TMP0]], 10
322 ; CHECK-NEXT: ret i32 [[BC2]]
325 %0 = load i32, ptr %i, align 4
326 %cmp = icmp eq i32 %0, 0
327 br i1 %cmp, label %try.cont, label %if.then
330 %exception = tail call ptr @__cxa_allocate_exception(i64 4) #2
331 %1 = bitcast ptr %exception to ptr
332 store i32 %0, ptr %1, align 16
333 invoke void @__cxa_throw(ptr %exception, ptr @_ZTIi, ptr null) #3
334 to label %unreachable unwind label %lpad
337 %2 = landingpad { ptr, i32 }
340 %bc1 = add i32 %0, 10
341 %3 = extractvalue { ptr, i32 } %2, 0
342 %4 = extractvalue { ptr, i32 } %2, 1
343 %5 = tail call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi) #2
344 %matches = icmp eq i32 %4, %5
345 %bc7 = add i32 %0, 10
346 %6 = tail call ptr @__cxa_begin_catch(ptr %3) #2
347 br i1 %matches, label %catch1, label %catch
350 %bc3 = add i32 %0, 10
351 invoke void @__cxa_rethrow() #3
352 to label %unreachable unwind label %lpad4
355 %bc4 = add i32 %0, 10
356 %7 = load i32, ptr %i, align 4
357 %add = add nsw i32 %7, 1
358 tail call void @__cxa_end_catch()
362 %8 = landingpad { ptr, i32 }
364 %bc5 = add i32 %0, 10
365 tail call void @__cxa_end_catch() #2
366 invoke void @__cxa_throw(ptr %exception, ptr @_ZTIi, ptr null) #3
367 to label %unreachable unwind label %lpad
370 %k.0 = phi i32 [ %add, %catch ], [ 0, %entry ]
371 %bc6 = add i32 %0, 10
375 %bc2 = add i32 %0, 10
379 declare ptr @__cxa_allocate_exception(i64) local_unnamed_addr
381 declare void @__cxa_throw(ptr, ptr, ptr) local_unnamed_addr
383 declare i32 @__gxx_personality_v0(...)
385 ; Function Attrs: nounwind readnone
386 declare i32 @llvm.eh.typeid.for.p0(ptr) #1
388 declare ptr @__cxa_begin_catch(ptr) local_unnamed_addr
390 declare void @__cxa_end_catch() local_unnamed_addr
392 declare void @__cxa_rethrow() local_unnamed_addr
394 attributes #1 = { nounwind readnone }
395 attributes #2 = { nounwind }
396 attributes #3 = { noreturn }