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