1 ; RUN: opt -gvn-hoist -S < %s | FileCheck %s
2 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
3 target triple = "x86_64-unknown-linux-gnu"
5 @GlobalVar = internal global float 1.000000e+00
7 ; Check that all scalar expressions are hoisted.
9 ; CHECK-LABEL: @scalarsHoisting
16 define float @scalarsHoisting(float %d, float %min, float %max, float %a) {
18 %div = fdiv float 1.000000e+00, %d
19 %cmp = fcmp oge float %div, 0.000000e+00
20 br i1 %cmp, label %if.then, label %if.else
22 if.then: ; preds = %entry
23 %sub = fsub float %min, %a
24 %mul = fmul float %sub, %div
25 %sub1 = fsub float %max, %a
26 %mul2 = fmul float %sub1, %div
29 if.else: ; preds = %entry
30 %sub3 = fsub float %max, %a
31 %mul4 = fmul float %sub3, %div
32 %sub5 = fsub float %min, %a
33 %mul6 = fmul float %sub5, %div
36 if.end: ; preds = %if.else, %if.then
37 %tmax.0 = phi float [ %mul2, %if.then ], [ %mul6, %if.else ]
38 %tmin.0 = phi float [ %mul, %if.then ], [ %mul4, %if.else ]
39 %add = fadd float %tmax.0, %tmin.0
43 ; Check that all loads and scalars depending on the loads are hoisted.
44 ; Check that getelementptr computation gets hoisted before the load.
46 ; CHECK-LABEL: @readsAndScalarsHoisting
57 define float @readsAndScalarsHoisting(float %d, float* %min, float* %max, float* %a) {
59 %div = fdiv float 1.000000e+00, %d
60 %cmp = fcmp oge float %div, 0.000000e+00
61 br i1 %cmp, label %if.then, label %if.else
63 if.then: ; preds = %entry
64 %A = getelementptr float, float* %min, i32 1
65 %0 = load float, float* %A, align 4
66 %1 = load float, float* %a, align 4
67 %sub = fsub float %0, %1
68 %mul = fmul float %sub, %div
69 %2 = load float, float* %max, align 4
70 %sub1 = fsub float %2, %1
71 %mul2 = fmul float %sub1, %div
74 if.else: ; preds = %entry
75 %3 = load float, float* %max, align 4
76 %4 = load float, float* %a, align 4
77 %sub3 = fsub float %3, %4
78 %mul4 = fmul float %sub3, %div
79 %B = getelementptr float, float* %min, i32 1
80 %5 = load float, float* %B, align 4
81 %sub5 = fsub float %5, %4
82 %mul6 = fmul float %sub5, %div
85 if.end: ; preds = %if.else, %if.then
86 %tmax.0 = phi float [ %mul2, %if.then ], [ %mul6, %if.else ]
87 %tmin.0 = phi float [ %mul, %if.then ], [ %mul4, %if.else ]
88 %add = fadd float %tmax.0, %tmin.0
92 ; Check that we do not hoist loads after a store: the first two loads will be
93 ; hoisted, and then the third load will not be hoisted.
95 ; CHECK-LABEL: @readsAndWrites
110 define float @readsAndWrites(float %d, float* %min, float* %max, float* %a) {
112 %div = fdiv float 1.000000e+00, %d
113 %cmp = fcmp oge float %div, 0.000000e+00
114 br i1 %cmp, label %if.then, label %if.else
116 if.then: ; preds = %entry
117 %0 = load float, float* %min, align 4
118 %1 = load float, float* %a, align 4
119 store float %0, float* @GlobalVar
120 %sub = fsub float %0, %1
121 %mul = fmul float %sub, %div
122 %2 = load float, float* %max, align 4
123 %sub1 = fsub float %2, %1
124 %mul2 = fmul float %sub1, %div
127 if.else: ; preds = %entry
128 %3 = load float, float* %max, align 4
129 %4 = load float, float* %a, align 4
130 %sub3 = fsub float %3, %4
131 %mul4 = fmul float %sub3, %div
132 %5 = load float, float* %min, align 4
133 %sub5 = fsub float %5, %4
134 %mul6 = fmul float %sub5, %div
137 if.end: ; preds = %if.else, %if.then
138 %tmax.0 = phi float [ %mul2, %if.then ], [ %mul6, %if.else ]
139 %tmin.0 = phi float [ %mul, %if.then ], [ %mul4, %if.else ]
140 %add = fadd float %tmax.0, %tmin.0
144 ; Check that we do hoist loads when the store is above the insertion point.
146 ; CHECK-LABEL: @readsAndWriteAboveInsertPt
157 define float @readsAndWriteAboveInsertPt(float %d, float* %min, float* %max, float* %a) {
159 %div = fdiv float 1.000000e+00, %d
160 store float 0.000000e+00, float* @GlobalVar
161 %cmp = fcmp oge float %div, 0.000000e+00
162 br i1 %cmp, label %if.then, label %if.else
164 if.then: ; preds = %entry
165 %0 = load float, float* %min, align 4
166 %1 = load float, float* %a, align 4
167 %sub = fsub float %0, %1
168 %mul = fmul float %sub, %div
169 %2 = load float, float* %max, align 4
170 %sub1 = fsub float %2, %1
171 %mul2 = fmul float %sub1, %div
174 if.else: ; preds = %entry
175 %3 = load float, float* %max, align 4
176 %4 = load float, float* %a, align 4
177 %sub3 = fsub float %3, %4
178 %mul4 = fmul float %sub3, %div
179 %5 = load float, float* %min, align 4
180 %sub5 = fsub float %5, %4
181 %mul6 = fmul float %sub5, %div
184 if.end: ; preds = %if.else, %if.then
185 %tmax.0 = phi float [ %mul2, %if.then ], [ %mul6, %if.else ]
186 %tmin.0 = phi float [ %mul, %if.then ], [ %mul4, %if.else ]
187 %add = fadd float %tmax.0, %tmin.0
191 ; Check that dependent expressions are hoisted.
192 ; CHECK-LABEL: @dependentScalarsHoisting
201 define float @dependentScalarsHoisting(float %a, float %b, i1 %c) {
203 br i1 %c, label %if.then, label %if.else
206 %d = fsub float %b, %a
207 %e = fadd float %d, %a
208 %f = fdiv float %e, %a
209 %g = fmul float %f, %a
213 %h = fsub float %b, %a
214 %i = fadd float %h, %a
215 %j = fdiv float %i, %a
216 %k = fmul float %j, %a
220 %r = phi float [ %g, %if.then ], [ %k, %if.else ]
224 ; Check that all independent expressions are hoisted.
225 ; CHECK-LABEL: @independentScalarsHoisting
233 define float @independentScalarsHoisting(float %a, float %b, i1 %c) {
235 br i1 %c, label %if.then, label %if.else
238 %d = fadd float %b, %a
239 %e = fsub float %b, %a
240 %f = fdiv float %b, %a
241 %g = fmul float %b, %a
245 %i = fadd float %b, %a
246 %h = fsub float %b, %a
247 %j = fdiv float %b, %a
248 %k = fmul float %b, %a
252 %p = phi float [ %d, %if.then ], [ %i, %if.else ]
253 %q = phi float [ %e, %if.then ], [ %h, %if.else ]
254 %r = phi float [ %f, %if.then ], [ %j, %if.else ]
255 %s = phi float [ %g, %if.then ], [ %k, %if.else ]
256 %t = fadd float %p, %q
257 %u = fadd float %r, %s
258 %v = fadd float %t, %u
262 ; Check that we hoist load and scalar expressions in triangles.
263 ; CHECK-LABEL: @triangleHoisting
274 define float @triangleHoisting(float %d, float* %min, float* %max, float* %a) {
276 %div = fdiv float 1.000000e+00, %d
277 %cmp = fcmp oge float %div, 0.000000e+00
278 br i1 %cmp, label %if.then, label %if.end
280 if.then: ; preds = %entry
281 %0 = load float, float* %min, align 4
282 %1 = load float, float* %a, align 4
283 %sub = fsub float %0, %1
284 %mul = fmul float %sub, %div
285 %2 = load float, float* %max, align 4
286 %sub1 = fsub float %2, %1
287 %mul2 = fmul float %sub1, %div
290 if.end: ; preds = %entry
291 %p1 = phi float [ %mul2, %if.then ], [ 0.000000e+00, %entry ]
292 %p2 = phi float [ %mul, %if.then ], [ 0.000000e+00, %entry ]
293 %3 = load float, float* %max, align 4
294 %4 = load float, float* %a, align 4
295 %sub3 = fsub float %3, %4
296 %mul4 = fmul float %sub3, %div
297 %5 = load float, float* %min, align 4
298 %sub5 = fsub float %5, %4
299 %mul6 = fmul float %sub5, %div
301 %x = fadd float %p1, %mul6
302 %y = fadd float %p2, %mul4
303 %z = fadd float %x, %y
307 ; Check that we do not hoist loads past stores within a same basic block.
308 ; CHECK-LABEL: @noHoistInSingleBBWithStore
313 define i32 @noHoistInSingleBBWithStore() {
315 %D = alloca i32, align 4
316 %0 = bitcast i32* %D to i8*
317 %bf = load i8, i8* %0, align 4
318 %bf.clear = and i8 %bf, -3
319 store i8 %bf.clear, i8* %0, align 4
320 %bf1 = load i8, i8* %0, align 4
321 %bf.clear1 = and i8 %bf1, 1
322 store i8 %bf.clear1, i8* %0, align 4
326 ; Check that we do not hoist loads past calls within a same basic block.
327 ; CHECK-LABEL: @noHoistInSingleBBWithCall
332 define i32 @noHoistInSingleBBWithCall() {
334 %D = alloca i32, align 4
335 %0 = bitcast i32* %D to i8*
336 %bf = load i8, i8* %0, align 4
337 %bf.clear = and i8 %bf, -3
339 %bf1 = load i8, i8* %0, align 4
340 %bf.clear1 = and i8 %bf1, 1
344 ; Check that we do not hoist loads past stores in any branch of a diamond.
345 ; CHECK-LABEL: @noHoistInDiamondWithOneStore1
349 define float @noHoistInDiamondWithOneStore1(float %d, float* %min, float* %max, float* %a) {
351 %div = fdiv float 1.000000e+00, %d
352 %cmp = fcmp oge float %div, 0.000000e+00
353 br i1 %cmp, label %if.then, label %if.else
355 if.then: ; preds = %entry
356 store float 0.000000e+00, float* @GlobalVar
357 %0 = load float, float* %min, align 4
358 %1 = load float, float* %a, align 4
359 %sub = fsub float %0, %1
360 %mul = fmul float %sub, %div
361 %2 = load float, float* %max, align 4
362 %sub1 = fsub float %2, %1
363 %mul2 = fmul float %sub1, %div
366 if.else: ; preds = %entry
367 ; There are no side effects on the if.else branch.
368 %3 = load float, float* %max, align 4
369 %4 = load float, float* %a, align 4
370 %sub3 = fsub float %3, %4
371 %mul4 = fmul float %sub3, %div
372 %5 = load float, float* %min, align 4
373 %sub5 = fsub float %5, %4
374 %mul6 = fmul float %sub5, %div
377 if.end: ; preds = %if.else, %if.then
378 %tmax.0 = phi float [ %mul2, %if.then ], [ %mul6, %if.else ]
379 %tmin.0 = phi float [ %mul, %if.then ], [ %mul4, %if.else ]
381 %6 = load float, float* %max, align 4
382 %7 = load float, float* %a, align 4
383 %sub6 = fsub float %6, %7
384 %mul7 = fmul float %sub6, %div
385 %8 = load float, float* %min, align 4
386 %sub8 = fsub float %8, %7
387 %mul9 = fmul float %sub8, %div
389 %add = fadd float %tmax.0, %tmin.0
393 ; Check that we do not hoist loads past stores from half diamond.
394 ; CHECK-LABEL: @noHoistInHalfDiamondPastStore
403 define float @noHoistInHalfDiamondPastStore(float %d, float* %min, float* %max, float* %a) {
405 %div = fdiv float 1.000000e+00, %d
406 %cmp = fcmp oge float %div, 0.000000e+00
407 %0 = load float, float* %min, align 4
408 %1 = load float, float* %a, align 4
410 ; Loads should not be hoisted above this store.
411 store float 0.000000e+00, float* @GlobalVar
413 br i1 %cmp, label %if.then, label %if.end
416 ; There are no side effects on the if.then branch.
417 %2 = load float, float* %max, align 4
418 %3 = load float, float* %a, align 4
419 %sub3 = fsub float %2, %3
420 %mul4 = fmul float %sub3, %div
421 %4 = load float, float* %min, align 4
422 %sub5 = fsub float %4, %3
423 %mul6 = fmul float %sub5, %div
427 %tmax.0 = phi float [ %mul4, %if.then ], [ %0, %entry ]
428 %tmin.0 = phi float [ %mul6, %if.then ], [ %1, %entry ]
430 %add = fadd float %tmax.0, %tmin.0
434 ; Check that we do not hoist loads past a store in any branch of a diamond.
435 ; CHECK-LABEL: @noHoistInDiamondWithOneStore2
439 define float @noHoistInDiamondWithOneStore2(float %d, float* %min, float* %max, float* %a) {
441 %div = fdiv float 1.000000e+00, %d
442 %cmp = fcmp oge float %div, 0.000000e+00
443 br i1 %cmp, label %if.then, label %if.else
445 if.then: ; preds = %entry
446 ; There are no side effects on the if.then branch.
447 %0 = load float, float* %min, align 4
448 %1 = load float, float* %a, align 4
449 %sub = fsub float %0, %1
450 %mul = fmul float %sub, %div
451 %2 = load float, float* %max, align 4
452 %sub1 = fsub float %2, %1
453 %mul2 = fmul float %sub1, %div
456 if.else: ; preds = %entry
457 store float 0.000000e+00, float* @GlobalVar
458 %3 = load float, float* %max, align 4
459 %4 = load float, float* %a, align 4
460 %sub3 = fsub float %3, %4
461 %mul4 = fmul float %sub3, %div
462 %5 = load float, float* %min, align 4
463 %sub5 = fsub float %5, %4
464 %mul6 = fmul float %sub5, %div
467 if.end: ; preds = %if.else, %if.then
468 %tmax.0 = phi float [ %mul2, %if.then ], [ %mul6, %if.else ]
469 %tmin.0 = phi float [ %mul, %if.then ], [ %mul4, %if.else ]
471 %6 = load float, float* %max, align 4
472 %7 = load float, float* %a, align 4
473 %sub6 = fsub float %6, %7
474 %mul7 = fmul float %sub6, %div
475 %8 = load float, float* %min, align 4
476 %sub8 = fsub float %8, %7
477 %mul9 = fmul float %sub8, %div
479 %add = fadd float %tmax.0, %tmin.0
483 ; Check that we do not hoist loads outside a loop containing stores.
484 ; CHECK-LABEL: @noHoistInLoopsWithStores
488 define float @noHoistInLoopsWithStores(float %d, float* %min, float* %max, float* %a) {
490 %div = fdiv float 1.000000e+00, %d
491 %cmp = fcmp oge float %div, 0.000000e+00
492 br i1 %cmp, label %do.body, label %if.else
495 %0 = load float, float* %min, align 4
496 %1 = load float, float* %a, align 4
498 ; It is unsafe to hoist the loads outside the loop because of the store.
499 store float 0.000000e+00, float* @GlobalVar
501 %sub = fsub float %0, %1
502 %mul = fmul float %sub, %div
503 %2 = load float, float* %max, align 4
504 %sub1 = fsub float %2, %1
505 %mul2 = fmul float %sub1, %div
509 %cmp1 = fcmp oge float %mul2, 0.000000e+00
510 br i1 %cmp1, label %if.end, label %do.body
513 %3 = load float, float* %max, align 4
514 %4 = load float, float* %a, align 4
515 %sub3 = fsub float %3, %4
516 %mul4 = fmul float %sub3, %div
517 %5 = load float, float* %min, align 4
518 %sub5 = fsub float %5, %4
519 %mul6 = fmul float %sub5, %div
523 %tmax.0 = phi float [ %mul2, %while.cond ], [ %mul6, %if.else ]
524 %tmin.0 = phi float [ %mul, %while.cond ], [ %mul4, %if.else ]
526 %add = fadd float %tmax.0, %tmin.0
530 ; Check that we hoist stores: all the instructions from the then branch
532 ; CHECK-LABEL: @hoistStores
535 ; CHECK-NEXT: getelementptr
537 ; CHECK-NEXT: getelementptr
538 ; CHECK-NEXT: getelementptr
549 %struct.foo = type { i16* }
551 define void @hoistStores(%struct.foo* %s, i32* %coord, i1 zeroext %delta) {
553 %frombool = zext i1 %delta to i8
554 %tobool = trunc i8 %frombool to i1
555 br i1 %tobool, label %if.then, label %if.else
557 if.then: ; preds = %entry
558 %p = getelementptr inbounds %struct.foo, %struct.foo* %s, i32 0, i32 0
559 %0 = load i16*, i16** %p, align 8
560 %incdec.ptr = getelementptr inbounds i16, i16* %0, i32 1
561 store i16* %incdec.ptr, i16** %p, align 8
562 %1 = load i16, i16* %0, align 2
563 %conv = zext i16 %1 to i32
564 %2 = load i32, i32* %coord, align 4
565 %add = add i32 %2, %conv
566 store i32 %add, i32* %coord, align 4
569 if.else: ; preds = %entry
570 %p1 = getelementptr inbounds %struct.foo, %struct.foo* %s, i32 0, i32 0
571 %3 = load i16*, i16** %p1, align 8
572 %incdec.ptr2 = getelementptr inbounds i16, i16* %3, i32 1
573 store i16* %incdec.ptr2, i16** %p1, align 8
574 %4 = load i16, i16* %3, align 2
575 %conv3 = zext i16 %4 to i32
576 %5 = load i32, i32* %coord, align 4
577 %add4 = add i32 %5, %conv3
578 store i32 %add4, i32* %coord, align 4
579 %6 = load i16*, i16** %p1, align 8
580 %incdec.ptr6 = getelementptr inbounds i16, i16* %6, i32 1
581 store i16* %incdec.ptr6, i16** %p1, align 8
582 %7 = load i16, i16* %6, align 2
583 %conv7 = zext i16 %7 to i32
584 %shl = shl i32 %conv7, 8
585 %8 = load i32, i32* %coord, align 4
586 %add8 = add i32 %8, %shl
587 store i32 %add8, i32* %coord, align 4
590 if.end: ; preds = %if.else, %if.then
594 define i32 @mergeAlignments(i1 %b, i32* %y) {
596 br i1 %b, label %if.then, label %if.end
598 if.then: ; preds = %entry
599 %l1 = load i32, i32* %y, align 4
602 if.end: ; preds = %entry
603 %l2 = load i32, i32* %y, align 1
606 return: ; preds = %if.end, %if.then
607 %retval.0 = phi i32 [ %l1, %if.then ], [ %l2, %if.end ]
610 ; CHECK-LABEL: define i32 @mergeAlignments(
611 ; CHECK: %[[load:.*]] = load i32, i32* %y, align 1
612 ; CHECK: %[[phi:.*]] = phi i32 [ %[[load]], %{{.*}} ], [ %[[load]], %{{.*}} ]
613 ; CHECK: i32 %[[phi]]
616 declare i8 @pr30991_f() nounwind readonly
617 declare void @pr30991_f1(i8)
618 define i8 @pr30991(i8* %sp, i8* %word, i1 %b1, i1 %b2) {
620 br i1 %b1, label %a, label %b
623 %r0 = load i8, i8* %word, align 1
624 %incdec.ptr = getelementptr i8, i8* %sp, i32 1
625 %rr0 = call i8 @pr30991_f() nounwind readonly
626 call void @pr30991_f1(i8 %r0)
630 br i1 %b2, label %c, label %x
633 %r1 = load i8, i8* %word, align 1
634 %incdec.ptr115 = getelementptr i8, i8* %sp, i32 1
635 %rr1 = call i8 @pr30991_f() nounwind readonly
636 call void @pr30991_f1(i8 %r1)
640 %r2 = load i8, i8* %word, align 1
644 ; CHECK-LABEL: define i8 @pr30991
645 ; CHECK: %r0 = load i8, i8* %word, align 1
646 ; CHECK-NEXT: br i1 %b1, label %a, label %b