Home | History | Annotate | Download | only in EarlyCSE
      1 ; RUN: opt -S -early-cse < %s | FileCheck %s
      2 
      3 declare void @clobber_and_use(i32)
      4 
      5 define void @f_0(i32* %ptr) {
      6 ; CHECK-LABEL: @f_0(
      7 ; CHECK:   %val0 = load i32, i32* %ptr, !invariant.load !0
      8 ; CHECK:   call void @clobber_and_use(i32 %val0)
      9 ; CHECK:   call void @clobber_and_use(i32 %val0)
     10 ; CHECK:   call void @clobber_and_use(i32 %val0)
     11 ; CHECK:   ret void
     12 
     13   %val0 = load i32, i32* %ptr, !invariant.load !{}
     14   call void @clobber_and_use(i32 %val0)
     15   %val1 = load i32, i32* %ptr, !invariant.load !{}
     16   call void @clobber_and_use(i32 %val1)
     17   %val2 = load i32, i32* %ptr, !invariant.load !{}
     18   call void @clobber_and_use(i32 %val2)
     19   ret void
     20 }
     21 
     22 define void @f_1(i32* %ptr) {
     23 ; We can forward invariant loads to non-invariant loads, since once an
     24 ; invariant load has executed, the location loaded from is known to be
     25 ; unchanging.
     26 
     27 ; CHECK-LABEL: @f_1(
     28 ; CHECK:   %val0 = load i32, i32* %ptr, !invariant.load !0
     29 ; CHECK:   call void @clobber_and_use(i32 %val0)
     30 ; CHECK:   call void @clobber_and_use(i32 %val0)
     31 
     32   %val0 = load i32, i32* %ptr, !invariant.load !{}
     33   call void @clobber_and_use(i32 %val0)
     34   %val1 = load i32, i32* %ptr
     35   call void @clobber_and_use(i32 %val1)
     36   ret void
     37 }
     38 
     39 define void @f_2(i32* %ptr) {
     40 ; Negative test -- we can't forward a non-invariant load into an
     41 ; invariant load.
     42 
     43 ; CHECK-LABEL: @f_2(
     44 ; CHECK:   %val0 = load i32, i32* %ptr
     45 ; CHECK:   call void @clobber_and_use(i32 %val0)
     46 ; CHECK:   %val1 = load i32, i32* %ptr, !invariant.load !0
     47 ; CHECK:   call void @clobber_and_use(i32 %val1)
     48 
     49   %val0 = load i32, i32* %ptr
     50   call void @clobber_and_use(i32 %val0)
     51   %val1 = load i32, i32* %ptr, !invariant.load !{}
     52   call void @clobber_and_use(i32 %val1)
     53   ret void
     54 }
     55 
     56 define void @f_3(i1 %cond, i32* %ptr) {
     57 ; CHECK-LABEL: @f_3(
     58   %val0 = load i32, i32* %ptr, !invariant.load !{}
     59   call void @clobber_and_use(i32 %val0)
     60   br i1 %cond, label %left, label %right
     61 
     62 ; CHECK:  %val0 = load i32, i32* %ptr, !invariant.load !0
     63 ; CHECK: left:
     64 ; CHECK-NEXT:  call void @clobber_and_use(i32 %val0)
     65 
     66 left:
     67   %val1 = load i32, i32* %ptr
     68   call void @clobber_and_use(i32 %val1)
     69   ret void
     70 
     71 right:
     72   ret void
     73 }
     74 
     75 define void @f_4(i1 %cond, i32* %ptr) {
     76 ; Negative test -- can't forward %val0 to %va1 because that'll break
     77 ; def-dominates-use.
     78 
     79 ; CHECK-LABEL: @f_4(
     80   br i1 %cond, label %left, label %merge
     81 
     82 left:
     83 ; CHECK: left:
     84 ; CHECK-NEXT:  %val0 = load i32, i32* %ptr, !invariant.load !
     85 ; CHECK-NEXT:  call void @clobber_and_use(i32 %val0)
     86 
     87   %val0 = load i32, i32* %ptr, !invariant.load !{}
     88   call void @clobber_and_use(i32 %val0)
     89   br label %merge
     90 
     91 merge:
     92 ; CHECK: merge:
     93 ; CHECK-NEXT:   %val1 = load i32, i32* %ptr
     94 ; CHECK-NEXT:   call void @clobber_and_use(i32 %val1)
     95 
     96   %val1 = load i32, i32* %ptr
     97   call void @clobber_and_use(i32 %val1)
     98   ret void
     99 }
    100