Home | History | Annotate | Download | only in InstCombine
      1 ; RUN: opt -S < %s -instcombine | FileCheck %s
      2 
      3 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
      4 target triple = "x86_64-apple-macosx10.7.0"
      5 
      6 ; Check transforms involving atomic operations
      7 
      8 define i32 @test1(i32* %p) {
      9 ; CHECK-LABEL: define i32 @test1(
     10 ; CHECK: %x = load atomic i32, i32* %p seq_cst, align 4
     11 ; CHECK: shl i32 %x, 1
     12   %x = load atomic i32, i32* %p seq_cst, align 4
     13   %y = load i32, i32* %p, align 4
     14   %z = add i32 %x, %y
     15   ret i32 %z
     16 }
     17 
     18 define i32 @test2(i32* %p) {
     19 ; CHECK-LABEL: define i32 @test2(
     20 ; CHECK: %x = load volatile i32, i32* %p, align 4
     21 ; CHECK: %y = load volatile i32, i32* %p, align 4
     22   %x = load volatile i32, i32* %p, align 4
     23   %y = load volatile i32, i32* %p, align 4
     24   %z = add i32 %x, %y
     25   ret i32 %z
     26 }
     27 
     28 ; The exact semantics of mixing volatile and non-volatile on the same
     29 ; memory location are a bit unclear, but conservatively, we know we don't
     30 ; want to remove the volatile.
     31 define i32 @test3(i32* %p) {
     32 ; CHECK-LABEL: define i32 @test3(
     33 ; CHECK: %x = load volatile i32, i32* %p, align 4
     34   %x = load volatile i32, i32* %p, align 4
     35   %y = load i32, i32* %p, align 4
     36   %z = add i32 %x, %y
     37   ret i32 %z
     38 }
     39 
     40 ; Forwarding from a stronger ordered atomic is fine
     41 define i32 @test4(i32* %p) {
     42 ; CHECK-LABEL: define i32 @test4(
     43 ; CHECK: %x = load atomic i32, i32* %p seq_cst, align 4
     44 ; CHECK: shl i32 %x, 1
     45   %x = load atomic i32, i32* %p seq_cst, align 4
     46   %y = load atomic i32, i32* %p unordered, align 4
     47   %z = add i32 %x, %y
     48   ret i32 %z
     49 }
     50 
     51 ; Forwarding from a non-atomic is not.  (The earlier load 
     52 ; could in priciple be promoted to atomic and then forwarded, 
     53 ; but we can't just  drop the atomic from the load.)
     54 define i32 @test5(i32* %p) {
     55 ; CHECK-LABEL: define i32 @test5(
     56 ; CHECK: %x = load atomic i32, i32* %p unordered, align 4
     57   %x = load atomic i32, i32* %p unordered, align 4
     58   %y = load i32, i32* %p, align 4
     59   %z = add i32 %x, %y
     60   ret i32 %z
     61 }
     62 
     63 ; Forwarding atomic to atomic is fine
     64 define i32 @test6(i32* %p) {
     65 ; CHECK-LABEL: define i32 @test6(
     66 ; CHECK: %x = load atomic i32, i32* %p unordered, align 4
     67 ; CHECK: shl i32 %x, 1
     68   %x = load atomic i32, i32* %p unordered, align 4
     69   %y = load atomic i32, i32* %p unordered, align 4
     70   %z = add i32 %x, %y
     71   ret i32 %z
     72 }
     73 
     74 ; FIXME: we currently don't do anything for monotonic
     75 define i32 @test7(i32* %p) {
     76 ; CHECK-LABEL: define i32 @test7(
     77 ; CHECK: %x = load atomic i32, i32* %p seq_cst, align 4
     78 ; CHECK: %y = load atomic i32, i32* %p monotonic, align 4
     79   %x = load atomic i32, i32* %p seq_cst, align 4
     80   %y = load atomic i32, i32* %p monotonic, align 4
     81   %z = add i32 %x, %y
     82   ret i32 %z
     83 }
     84 
     85 ; FIXME: We could forward in racy code
     86 define i32 @test8(i32* %p) {
     87 ; CHECK-LABEL: define i32 @test8(
     88 ; CHECK: %x = load atomic i32, i32* %p seq_cst, align 4
     89 ; CHECK: %y = load atomic i32, i32* %p acquire, align 4
     90   %x = load atomic i32, i32* %p seq_cst, align 4
     91   %y = load atomic i32, i32* %p acquire, align 4
     92   %z = add i32 %x, %y
     93   ret i32 %z
     94 }
     95 
     96 ; An unordered access to null is still unreachable.  There's no
     97 ; ordering imposed.
     98 define i32 @test9() {
     99 ; CHECK-LABEL: define i32 @test9(
    100 ; CHECK: store i32 undef, i32* null
    101   %x = load atomic i32, i32* null unordered, align 4
    102   ret i32 %x
    103 }
    104 
    105 ; FIXME: Could also fold
    106 define i32 @test10() {
    107 ; CHECK-LABEL: define i32 @test10(
    108 ; CHECK: load atomic i32, i32* null monotonic
    109   %x = load atomic i32, i32* null monotonic, align 4
    110   ret i32 %x
    111 }
    112 
    113 ; Would this be legal to fold?  Probably?
    114 define i32 @test11() {
    115 ; CHECK-LABEL: define i32 @test11(
    116 ; CHECK: load atomic i32, i32* null seq_cst
    117   %x = load atomic i32, i32* null seq_cst, align 4
    118   ret i32 %x
    119 }
    120 
    121 ; An unordered access to null is still unreachable.  There's no
    122 ; ordering imposed.
    123 define i32 @test12() {
    124 ; CHECK-LABEL: define i32 @test12(
    125 ; CHECK: store atomic i32 undef, i32* null
    126   store atomic i32 0, i32* null unordered, align 4
    127   ret i32 0
    128 }
    129 
    130 ; FIXME: Could also fold
    131 define i32 @test13() {
    132 ; CHECK-LABEL: define i32 @test13(
    133 ; CHECK: store atomic i32 0, i32* null monotonic
    134   store atomic i32 0, i32* null monotonic, align 4
    135   ret i32 0
    136 }
    137 
    138 ; Would this be legal to fold?  Probably?
    139 define i32 @test14() {
    140 ; CHECK-LABEL: define i32 @test14(
    141 ; CHECK: store atomic i32 0, i32* null seq_cst
    142   store atomic i32 0, i32* null seq_cst, align 4
    143   ret i32 0
    144 }
    145 
    146 @a = external global i32
    147 @b = external global i32
    148 
    149 define i32 @test15(i1 %cnd) {
    150 ; CHECK-LABEL: define i32 @test15(
    151 ; CHECK: load atomic i32, i32* @a unordered, align 4
    152 ; CHECK: load atomic i32, i32* @b unordered, align 4
    153   %addr = select i1 %cnd, i32* @a, i32* @b
    154   %x = load atomic i32, i32* %addr unordered, align 4
    155   ret i32 %x
    156 }
    157 
    158 ; FIXME: This would be legal to transform
    159 define i32 @test16(i1 %cnd) {
    160 ; CHECK-LABEL: define i32 @test16(
    161 ; CHECK: load atomic i32, i32* %addr monotonic, align 4
    162   %addr = select i1 %cnd, i32* @a, i32* @b
    163   %x = load atomic i32, i32* %addr monotonic, align 4
    164   ret i32 %x
    165 }
    166 
    167 ; FIXME: This would be legal to transform
    168 define i32 @test17(i1 %cnd) {
    169 ; CHECK-LABEL: define i32 @test17(
    170 ; CHECK: load atomic i32, i32* %addr seq_cst, align 4
    171   %addr = select i1 %cnd, i32* @a, i32* @b
    172   %x = load atomic i32, i32* %addr seq_cst, align 4
    173   ret i32 %x
    174 }
    175 
    176 define i32 @test22(i1 %cnd) {
    177 ; CHECK-LABEL: define i32 @test22(
    178 ; CHECK: [[PHI:%.*]] = phi i32
    179 ; CHECK: store atomic i32 [[PHI]], i32* @a unordered, align 4
    180   br i1 %cnd, label %block1, label %block2
    181 
    182 block1:
    183   store atomic i32 1, i32* @a unordered, align 4
    184   br label %merge
    185 block2:
    186   store atomic i32 2, i32* @a unordered, align 4
    187   br label %merge
    188 
    189 merge:
    190   ret i32 0
    191 }
    192 
    193 ; TODO: probably also legal here
    194 define i32 @test23(i1 %cnd) {
    195 ; CHECK-LABEL: define i32 @test23(
    196 ; CHECK: br i1 %cnd, label %block1, label %block2
    197   br i1 %cnd, label %block1, label %block2
    198 
    199 block1:
    200   store atomic i32 1, i32* @a monotonic, align 4
    201   br label %merge
    202 block2:
    203   store atomic i32 2, i32* @a monotonic, align 4
    204   br label %merge
    205 
    206 merge:
    207   ret i32 0
    208 }
    209 
    210 declare void @clobber()
    211 
    212 define i32 @test18(float* %p) {
    213 ; CHECK-LABEL: define i32 @test18(
    214 ; CHECK: load atomic i32, i32* [[A:%.*]] unordered, align 4
    215 ; CHECK: store atomic i32 [[B:%.*]], i32* [[C:%.*]] unordered, align 4
    216   %x = load atomic float, float* %p unordered, align 4
    217   call void @clobber() ;; keep the load around
    218   store atomic float %x, float* %p unordered, align 4
    219   ret i32 0
    220 }
    221 
    222 ; TODO: probably also legal in this case
    223 define i32 @test19(float* %p) {
    224 ; CHECK-LABEL: define i32 @test19(
    225 ; CHECK: load atomic float, float* %p seq_cst, align 4
    226 ; CHECK: store atomic float %x, float* %p seq_cst, align 4
    227   %x = load atomic float, float* %p seq_cst, align 4
    228   call void @clobber() ;; keep the load around
    229   store atomic float %x, float* %p seq_cst, align 4
    230   ret i32 0
    231 }
    232 
    233 define i32 @test20(i32** %p, i8* %v) {
    234 ; CHECK-LABEL: define i32 @test20(
    235 ; CHECK: store atomic i8* %v, i8** [[D:%.*]] unordered, align 4
    236   %cast = bitcast i8* %v to i32*
    237   store atomic i32* %cast, i32** %p unordered, align 4
    238   ret i32 0
    239 }
    240 
    241 define i32 @test21(i32** %p, i8* %v) {
    242 ; CHECK-LABEL: define i32 @test21(
    243 ; CHECK: store atomic i32* %cast, i32** %p monotonic, align 4
    244   %cast = bitcast i8* %v to i32*
    245   store atomic i32* %cast, i32** %p monotonic, align 4
    246   ret i32 0
    247 }
    248 
    249 define void @pr27490a(i8** %p1, i8** %p2) {
    250 ; CHECK-LABEL: define void @pr27490
    251 ; CHECK: %1 = bitcast i8** %p1 to i64*
    252 ; CHECK: %l1 = load i64, i64* %1, align 8
    253 ; CHECK: %2 = bitcast i8** %p2 to i64*
    254 ; CHECK: store volatile i64 %l1, i64* %2, align 8
    255   %l = load i8*, i8** %p1
    256   store volatile i8* %l, i8** %p2
    257   ret void
    258 }
    259 
    260 define void @pr27490b(i8** %p1, i8** %p2) {
    261 ; CHECK-LABEL: define void @pr27490
    262 ; CHECK: %1 = bitcast i8** %p1 to i64*
    263 ; CHECK: %l1 = load i64, i64* %1, align 8
    264 ; CHECK: %2 = bitcast i8** %p2 to i64*
    265 ; CHECK: store atomic i64 %l1, i64* %2 seq_cst, align 8
    266   %l = load i8*, i8** %p1
    267   store atomic i8* %l, i8** %p2 seq_cst, align 8
    268   ret void
    269 }
    270