Home | History | Annotate | Download | only in EarlyCSE
      1 ; RUN: opt < %s -S -early-cse | FileCheck %s
      2 
      3 ; CHECK-LABEL: @test12(
      4 define i32 @test12(i1 %B, i32* %P1, i32* %P2) {
      5   %load0 = load i32, i32* %P1
      6   %1 = load atomic i32, i32* %P2 seq_cst, align 4
      7   %load1 = load i32, i32* %P1
      8   %sel = select i1 %B, i32 %load0, i32 %load1
      9   ret i32 %sel
     10   ; CHECK: load i32, i32* %P1
     11   ; CHECK: load i32, i32* %P1
     12 }
     13 
     14 ; CHECK-LABEL: @test13(
     15 ; atomic to non-atomic forwarding is legal
     16 define i32 @test13(i1 %B, i32* %P1) {
     17   %a = load atomic i32, i32* %P1 seq_cst, align 4
     18   %b = load i32, i32* %P1
     19   %res = sub i32 %a, %b
     20   ret i32 %res
     21   ; CHECK: load atomic i32, i32* %P1
     22   ; CHECK: ret i32 0
     23 }
     24 
     25 ; CHECK-LABEL: @test14(
     26 ; atomic to unordered atomic forwarding is legal
     27 define i32 @test14(i1 %B, i32* %P1) {
     28   %a = load atomic i32, i32* %P1 seq_cst, align 4
     29   %b = load atomic i32, i32* %P1 unordered, align 4
     30   %res = sub i32 %a, %b
     31   ret i32 %res
     32   ; CHECK: load atomic i32, i32* %P1 seq_cst
     33   ; CHECK-NEXT: ret i32 0
     34 }
     35 
     36 ; CHECK-LABEL: @test15(
     37 ; implementation restriction: can't forward to stonger
     38 ; than unordered
     39 define i32 @test15(i1 %B, i32* %P1, i32* %P2) {
     40   %a = load atomic i32, i32* %P1 seq_cst, align 4
     41   %b = load atomic i32, i32* %P1 seq_cst, align 4
     42   %res = sub i32 %a, %b
     43   ret i32 %res
     44   ; CHECK: load atomic i32, i32* %P1
     45   ; CHECK: load atomic i32, i32* %P1
     46 }
     47 
     48 ; CHECK-LABEL: @test16(
     49 ; forwarding non-atomic to atomic is wrong! (However,
     50 ; it would be legal to use the later value in place of the
     51 ; former in this particular example.  We just don't
     52 ; do that right now.)
     53 define i32 @test16(i1 %B, i32* %P1, i32* %P2) {
     54   %a = load i32, i32* %P1, align 4
     55   %b = load atomic i32, i32* %P1 unordered, align 4
     56   %res = sub i32 %a, %b
     57   ret i32 %res
     58   ; CHECK: load i32, i32* %P1
     59   ; CHECK: load atomic i32, i32* %P1
     60 }
     61 
     62 ; Can't DSE across a full fence
     63 define void @fence_seq_cst_store(i1 %B, i32* %P1, i32* %P2) {
     64 ; CHECK-LABEL: @fence_seq_cst_store
     65 ; CHECK: store
     66 ; CHECK: store atomic
     67 ; CHECK: store
     68   store i32 0, i32* %P1, align 4
     69   store atomic i32 0, i32* %P2 seq_cst, align 4
     70   store i32 0, i32* %P1, align 4
     71   ret void
     72 }
     73 
     74 ; Can't DSE across a full fence
     75 define void @fence_seq_cst(i1 %B, i32* %P1, i32* %P2) {
     76 ; CHECK-LABEL: @fence_seq_cst
     77 ; CHECK: store
     78 ; CHECK: fence seq_cst
     79 ; CHECK: store
     80   store i32 0, i32* %P1, align 4
     81   fence seq_cst
     82   store i32 0, i32* %P1, align 4
     83   ret void
     84 }
     85 
     86 ; Can't DSE across a full fence
     87 define void @fence_asm_sideeffect(i1 %B, i32* %P1, i32* %P2) {
     88 ; CHECK-LABEL: @fence_asm_sideeffect
     89 ; CHECK: store
     90 ; CHECK: call void asm sideeffect
     91 ; CHECK: store
     92   store i32 0, i32* %P1, align 4
     93   call void asm sideeffect "", ""()
     94   store i32 0, i32* %P1, align 4
     95   ret void
     96 }
     97 
     98 ; Can't DSE across a full fence
     99 define void @fence_asm_memory(i1 %B, i32* %P1, i32* %P2) {
    100 ; CHECK-LABEL: @fence_asm_memory
    101 ; CHECK: store
    102 ; CHECK: call void asm
    103 ; CHECK: store
    104   store i32 0, i32* %P1, align 4
    105   call void asm "", "~{memory}"()
    106   store i32 0, i32* %P1, align 4
    107   ret void
    108 }
    109 
    110 ; Can't remove a volatile load
    111 define i32 @volatile_load(i1 %B, i32* %P1, i32* %P2) {
    112   %a = load i32, i32* %P1, align 4
    113   %b = load volatile i32, i32* %P1, align 4
    114   %res = sub i32 %a, %b
    115   ret i32 %res
    116   ; CHECK-LABEL: @volatile_load
    117   ; CHECK: load i32, i32* %P1
    118   ; CHECK: load volatile i32, i32* %P1
    119 }
    120 
    121 ; Can't remove redundant volatile loads
    122 define i32 @redundant_volatile_load(i1 %B, i32* %P1, i32* %P2) {
    123   %a = load volatile i32, i32* %P1, align 4
    124   %b = load volatile i32, i32* %P1, align 4
    125   %res = sub i32 %a, %b
    126   ret i32 %res
    127   ; CHECK-LABEL: @redundant_volatile_load
    128   ; CHECK: load volatile i32, i32* %P1
    129   ; CHECK: load volatile i32, i32* %P1
    130   ; CHECK: sub
    131 }
    132 
    133 ; Can't DSE a volatile store
    134 define void @volatile_store(i1 %B, i32* %P1, i32* %P2) {
    135 ; CHECK-LABEL: @volatile_store
    136 ; CHECK: store volatile
    137 ; CHECK: store
    138   store volatile i32 0, i32* %P1, align 4
    139   store i32 3, i32* %P1, align 4
    140   ret void
    141 }
    142 
    143 ; Can't DSE a redundant volatile store
    144 define void @redundant_volatile_store(i1 %B, i32* %P1, i32* %P2) {
    145 ; CHECK-LABEL: @redundant_volatile_store
    146 ; CHECK: store volatile
    147 ; CHECK: store volatile
    148   store volatile i32 0, i32* %P1, align 4
    149   store volatile i32 0, i32* %P1, align 4
    150   ret void
    151 }
    152 
    153 ; Can value forward from volatiles
    154 define i32 @test20(i1 %B, i32* %P1, i32* %P2) {
    155   %a = load volatile i32, i32* %P1, align 4
    156   %b = load i32, i32* %P1, align 4
    157   %res = sub i32 %a, %b
    158   ret i32 %res
    159   ; CHECK-LABEL: @test20
    160   ; CHECK: load volatile i32, i32* %P1
    161   ; CHECK: ret i32 0
    162 }
    163 
    164 ; Can DSE a non-volatile store in favor of a volatile one
    165 ; currently a missed optimization
    166 define void @test21(i1 %B, i32* %P1, i32* %P2) {
    167 ; CHECK-LABEL: @test21
    168 ; CHECK: store 
    169 ; CHECK: store volatile
    170   store i32 0, i32* %P1, align 4
    171   store volatile i32 3, i32* %P1, align 4
    172   ret void
    173 }
    174 
    175 ; Can DSE a normal store in favor of a unordered one
    176 define void @test22(i1 %B, i32* %P1, i32* %P2) {
    177 ; CHECK-LABEL: @test22
    178 ; CHECK-NEXT: store atomic
    179   store i32 0, i32* %P1, align 4
    180   store atomic i32 3, i32* %P1 unordered, align 4
    181   ret void
    182 }
    183 
    184 ; Can also DSE a unordered store in favor of a normal one
    185 define void @test23(i1 %B, i32* %P1, i32* %P2) {
    186 ; CHECK-LABEL: @test23
    187 ; CHECK-NEXT: store i32 0
    188   store atomic i32 3, i32* %P1 unordered, align 4
    189   store i32 0, i32* %P1, align 4
    190   ret void
    191 }
    192 
    193 ; As an implementation limitation, can't remove ordered stores
    194 ; Note that we could remove the earlier store if we could
    195 ; represent the required ordering.
    196 define void @test24(i1 %B, i32* %P1, i32* %P2) {
    197 ; CHECK-LABEL: @test24
    198 ; CHECK-NEXT: store atomic
    199 ; CHECK-NEXT: store i32 0
    200   store atomic i32 3, i32* %P1 release, align 4
    201   store i32 0, i32* %P1, align 4
    202   ret void
    203 }
    204 
    205 ; Can't remove volatile stores - each is independently observable and
    206 ; the count of such stores is an observable program side effect.
    207 define void @test25(i1 %B, i32* %P1, i32* %P2) {
    208 ; CHECK-LABEL: @test25
    209 ; CHECK-NEXT: store volatile
    210 ; CHECK-NEXT: store volatile
    211   store volatile i32 3, i32* %P1, align 4
    212   store volatile i32 0, i32* %P1, align 4
    213   ret void
    214 }
    215 
    216 ; Can DSE a unordered store in favor of a unordered one
    217 define void @test26(i1 %B, i32* %P1, i32* %P2) {
    218 ; CHECK-LABEL: @test26
    219 ; CHECK-NEXT: store atomic i32 3, i32* %P1 unordered, align 4
    220 ; CHECK-NEXT: ret
    221   store atomic i32 0, i32* %P1 unordered, align 4
    222   store atomic i32 3, i32* %P1 unordered, align 4
    223   ret void
    224 }
    225 
    226 ; Can DSE a unordered store in favor of a ordered one,
    227 ; but current don't due to implementation limits
    228 define void @test27(i1 %B, i32* %P1, i32* %P2) {
    229 ; CHECK-LABEL: @test27
    230 ; CHECK-NEXT: store atomic i32 0, i32* %P1 unordered, align 4
    231 ; CHECK-NEXT: store atomic i32 3, i32* %P1 release, align 4
    232 ; CHECK-NEXT: ret
    233   store atomic i32 0, i32* %P1 unordered, align 4
    234   store atomic i32 3, i32* %P1 release, align 4
    235   ret void
    236 }
    237 
    238 ; Can DSE an unordered atomic store in favor of an
    239 ; ordered one, but current don't due to implementation limits
    240 define void @test28(i1 %B, i32* %P1, i32* %P2) {
    241 ; CHECK-LABEL: @test28
    242 ; CHECK-NEXT: store atomic i32 0, i32* %P1 unordered, align 4
    243 ; CHECK-NEXT: store atomic i32 3, i32* %P1 release, align 4
    244 ; CHECK-NEXT: ret
    245   store atomic i32 0, i32* %P1 unordered, align 4
    246   store atomic i32 3, i32* %P1 release, align 4
    247   ret void
    248 }
    249 
    250 ; As an implementation limitation, can't remove ordered stores
    251 ; see also: @test24
    252 define void @test29(i1 %B, i32* %P1, i32* %P2) {
    253 ; CHECK-LABEL: @test29
    254 ; CHECK-NEXT: store atomic
    255 ; CHECK-NEXT: store atomic
    256   store atomic i32 3, i32* %P1 release, align 4
    257   store atomic i32 0, i32* %P1 unordered, align 4
    258   ret void
    259 }
    260