Home | History | Annotate | Download | only in GVN
      1 ; Tests that check our handling of volatile instructions encountered
      2 ; when scanning for dependencies
      3 ; RUN: opt -basicaa -gvn -S < %s | FileCheck %s
      4 
      5 ; Check that we can bypass a volatile load when searching
      6 ; for dependencies of a non-volatile load
      7 define i32 @test1(i32* nocapture %p, i32* nocapture %q) {
      8 ; CHECK-LABEL: test1
      9 ; CHECK:      %0 = load volatile i32, i32* %q
     10 ; CHECK-NEXT: ret i32 0
     11 entry:
     12   %x = load i32, i32* %p
     13   load volatile i32, i32* %q
     14   %y = load i32, i32* %p
     15   %add = sub i32 %y, %x
     16   ret i32 %add
     17 }
     18 
     19 ; We can not value forward if the query instruction is 
     20 ; volatile, this would be (in effect) removing the volatile load
     21 define i32 @test2(i32* nocapture %p, i32* nocapture %q) {
     22 ; CHECK-LABEL: test2
     23 ; CHECK:      %x = load i32, i32* %p
     24 ; CHECK-NEXT: %y = load volatile i32, i32* %p
     25 ; CHECK-NEXT: %add = sub i32 %y, %x
     26 entry:
     27   %x = load i32, i32* %p
     28   %y = load volatile i32, i32* %p
     29   %add = sub i32 %y, %x
     30   ret i32 %add
     31 }
     32 
     33 ; If the query instruction is itself volatile, we *cannot*
     34 ; reorder it even if p and q are noalias
     35 define i32 @test3(i32* noalias nocapture %p, i32* noalias nocapture %q) {
     36 ; CHECK-LABEL: test3
     37 ; CHECK:      %x = load i32, i32* %p
     38 ; CHECK-NEXT: %0 = load volatile i32, i32* %q
     39 ; CHECK-NEXT: %y = load volatile i32, i32* %p
     40 entry:
     41   %x = load i32, i32* %p
     42   load volatile i32, i32* %q
     43   %y = load volatile i32, i32* %p
     44   %add = sub i32 %y, %x
     45   ret i32 %add
     46 }
     47 
     48 ; If an encountered instruction is both volatile and ordered, 
     49 ; we need to use the strictest ordering of either.  In this 
     50 ; case, the ordering prevents forwarding.
     51 define i32 @test4(i32* noalias nocapture %p, i32* noalias nocapture %q) {
     52 ; CHECK-LABEL: test4
     53 ; CHECK:      %x = load i32, i32* %p
     54 ; CHECK-NEXT: %0 = load atomic volatile i32, i32* %q seq_cst 
     55 ; CHECK-NEXT: %y = load atomic i32, i32* %p seq_cst
     56 entry:
     57   %x = load i32, i32* %p
     58   load atomic volatile i32, i32* %q seq_cst, align 4
     59   %y = load atomic i32, i32* %p seq_cst, align 4
     60   %add = sub i32 %y, %x
     61   ret i32 %add
     62 }
     63 
     64 ; Value forwarding from a volatile load is perfectly legal
     65 define i32 @test5(i32* nocapture %p, i32* nocapture %q) {
     66 ; CHECK-LABEL: test5
     67 ; CHECK:      %x = load volatile i32, i32* %p
     68 ; CHECK-NEXT: ret i32 0
     69 entry:
     70   %x = load volatile i32, i32* %p
     71   %y = load i32, i32* %p
     72   %add = sub i32 %y, %x
     73   ret i32 %add
     74 }
     75 
     76 ; Does cross block redundancy elimination work with volatiles?
     77 define i32 @test6(i32* noalias nocapture %p, i32* noalias nocapture %q) {
     78 ; CHECK-LABEL: test6
     79 ; CHECK:      %y1 = load i32, i32* %p
     80 ; CHECK-LABEL: header
     81 ; CHECK:      %x = load volatile i32, i32* %q
     82 ; CHECK-NEXT: %add = sub i32 %y1, %x
     83 entry:
     84   %y1 = load i32, i32* %p
     85   call void @use(i32 %y1)
     86   br label %header
     87 header:
     88   %x = load volatile i32, i32* %q
     89   %y = load i32, i32* %p
     90   %add = sub i32 %y, %x
     91   %cnd = icmp eq i32 %add, 0
     92   br i1 %cnd, label %exit, label %header
     93 exit:
     94   ret i32 %add
     95 }
     96 
     97 ; Does cross block PRE work with volatiles?
     98 define i32 @test7(i1 %c, i32* noalias nocapture %p, i32* noalias nocapture %q) {
     99 ; CHECK-LABEL: test7
    100 ; CHECK-LABEL: entry.header_crit_edge:
    101 ; CHECK:       %y.pre = load i32, i32* %p
    102 ; CHECK-LABEL: skip:
    103 ; CHECK:       %y1 = load i32, i32* %p
    104 ; CHECK-LABEL: header:
    105 ; CHECK:      %y = phi i32
    106 ; CHECK-NEXT: %x = load volatile i32, i32* %q
    107 ; CHECK-NEXT: %add = sub i32 %y, %x
    108 entry:
    109   br i1 %c, label %header, label %skip
    110 skip:
    111   %y1 = load i32, i32* %p
    112   call void @use(i32 %y1)
    113   br label %header
    114 header:
    115   %x = load volatile i32, i32* %q
    116   %y = load i32, i32* %p
    117   %add = sub i32 %y, %x
    118   %cnd = icmp eq i32 %add, 0
    119   br i1 %cnd, label %exit, label %header
    120 exit:
    121   ret i32 %add
    122 }
    123 
    124 ; Another volatile PRE case - two paths through a loop
    125 ; load in preheader, one path read only, one not
    126 define i32 @test8(i1 %b, i1 %c, i32* noalias %p, i32* noalias %q) {
    127 ; CHECK-LABEL: test8
    128 ; CHECK-LABEL: entry
    129 ; CHECK:       %y1 = load i32, i32* %p
    130 ; CHECK-LABEL: header:
    131 ; CHECK:      %y = phi i32
    132 ; CHECK-NEXT: %x = load volatile i32, i32* %q
    133 ; CHECK-NOT:  load
    134 ; CHECK-LABEL: skip.header_crit_edge:
    135 ; CHECK:       %y.pre = load i32, i32* %p
    136 entry:
    137   %y1 = load i32, i32* %p
    138   call void @use(i32 %y1)
    139   br label %header
    140 header:
    141   %x = load volatile i32, i32* %q
    142   %y = load i32, i32* %p
    143   call void @use(i32 %y)
    144   br i1 %b, label %skip, label %header
    145 skip:
    146   ; escaping the arguments is explicitly required since we marked 
    147   ; them noalias
    148   call void @clobber(i32* %p, i32* %q)
    149   br i1 %c, label %header, label %exit
    150 exit:
    151   %add = sub i32 %y, %x
    152   ret i32 %add
    153 }
    154 
    155 declare void @use(i32) readonly
    156 declare void @clobber(i32* %p, i32* %q)
    157 
    158