Home | History | Annotate | Download | only in GVN
      1 ; RUN: opt < %s -gvn -S | FileCheck %s
      2 
      3 %struct.A = type { i32 (...)** }
      4 @_ZTV1A = available_externally unnamed_addr constant [3 x i8*] [i8* null, i8* bitcast (i8** @_ZTI1A to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A3fooEv to i8*)], align 8
      5 @_ZTI1A = external constant i8*
      6 
      7 @unknownPtr = external global i8
      8 
      9 ; CHECK-LABEL: define i8 @simple() {
     10 define i8 @simple() {
     11 entry:
     12     %ptr = alloca i8
     13     store i8 42, i8* %ptr, !invariant.group !0
     14     call void @foo(i8* %ptr)
     15 
     16     %a = load i8, i8* %ptr, !invariant.group !0
     17     %b = load i8, i8* %ptr, !invariant.group !0
     18     %c = load i8, i8* %ptr, !invariant.group !0
     19 ; CHECK: ret i8 42
     20     ret i8 %a
     21 }
     22 
     23 ; CHECK-LABEL: define i8 @optimizable1() {
     24 define i8 @optimizable1() {
     25 entry:
     26     %ptr = alloca i8
     27     store i8 42, i8* %ptr, !invariant.group !0
     28     %ptr2 = call i8* @llvm.invariant.group.barrier(i8* %ptr)
     29     %a = load i8, i8* %ptr, !invariant.group !0
     30     
     31     call void @foo(i8* %ptr2); call to use %ptr2
     32 ; CHECK: ret i8 42
     33     ret i8 %a
     34 }
     35 
     36 ; CHECK-LABEL: define i8 @optimizable2() {
     37 define i8 @optimizable2() {
     38 entry:
     39     %ptr = alloca i8
     40     store i8 42, i8* %ptr, !invariant.group !0
     41     call void @foo(i8* %ptr)
     42     
     43     store i8 13, i8* %ptr ; can't use this store with invariant.group
     44     %a = load i8, i8* %ptr 
     45     call void @bar(i8 %a) ; call to use %a
     46     
     47     call void @foo(i8* %ptr)
     48     %b = load i8, i8* %ptr, !invariant.group !0
     49     
     50 ; CHECK: ret i8 42
     51     ret i8 %b
     52 }
     53 
     54 ; CHECK-LABEL: define i8 @unoptimizable1() {
     55 define i8 @unoptimizable1() {
     56 entry:
     57     %ptr = alloca i8
     58     store i8 42, i8* %ptr
     59     call void @foo(i8* %ptr)
     60     %a = load i8, i8* %ptr, !invariant.group !0
     61 ; CHECK: ret i8 %a
     62     ret i8 %a
     63 }
     64 
     65 ; CHECK-LABEL: define void @indirectLoads() {
     66 define void @indirectLoads() {
     67 entry:
     68   %a = alloca %struct.A*, align 8
     69   %0 = bitcast %struct.A** %a to i8*
     70   
     71   %call = call i8* @getPointer(i8* null) 
     72   %1 = bitcast i8* %call to %struct.A*
     73   call void @_ZN1AC1Ev(%struct.A* %1)
     74   %2 = bitcast %struct.A* %1 to i8***
     75   
     76 ; CHECK: %vtable = load {{.*}} !invariant.group
     77   %vtable = load i8**, i8*** %2, align 8, !invariant.group !2
     78   %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i64 0, i64 2)
     79   call void @llvm.assume(i1 %cmp.vtables)
     80   
     81   store %struct.A* %1, %struct.A** %a, align 8
     82   %3 = load %struct.A*, %struct.A** %a, align 8
     83   %4 = bitcast %struct.A* %3 to void (%struct.A*)***
     84 
     85 ; CHECK: call void @_ZN1A3fooEv(
     86   %vtable1 = load void (%struct.A*)**, void (%struct.A*)*** %4, align 8, !invariant.group !2
     87   %vfn = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** %vtable1, i64 0
     88   %5 = load void (%struct.A*)*, void (%struct.A*)** %vfn, align 8
     89   call void %5(%struct.A* %3)
     90   %6 = load %struct.A*, %struct.A** %a, align 8
     91   %7 = bitcast %struct.A* %6 to void (%struct.A*)***
     92 
     93 ; CHECK: call void @_ZN1A3fooEv(
     94   %vtable2 = load void (%struct.A*)**, void (%struct.A*)*** %7, align 8, !invariant.group !2
     95   %vfn3 = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** %vtable2, i64 0
     96   %8 = load void (%struct.A*)*, void (%struct.A*)** %vfn3, align 8
     97   
     98   call void %8(%struct.A* %6)
     99   %9 = load %struct.A*, %struct.A** %a, align 8
    100   %10 = bitcast %struct.A* %9 to void (%struct.A*)***
    101   
    102   %vtable4 = load void (%struct.A*)**, void (%struct.A*)*** %10, align 8, !invariant.group !2
    103   %vfn5 = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** %vtable4, i64 0
    104   %11 = load void (%struct.A*)*, void (%struct.A*)** %vfn5, align 8
    105 ; CHECK: call void @_ZN1A3fooEv(
    106   call void %11(%struct.A* %9)
    107  
    108   %vtable5 = load i8**, i8*** %2, align 8, !invariant.group !2
    109   %vfn6 = getelementptr inbounds i8*, i8** %vtable5, i64 0
    110   %12 = bitcast i8** %vfn6 to void (%struct.A*)**
    111   %13 = load void (%struct.A*)*, void (%struct.A*)** %12, align 8
    112 ; CHECK: call void @_ZN1A3fooEv(
    113   call void %13(%struct.A* %9)
    114   
    115   ret void
    116 }
    117 
    118 ; CHECK-LABEL: define void @combiningBitCastWithLoad() {
    119 define void @combiningBitCastWithLoad() {
    120 entry:
    121   %a = alloca %struct.A*, align 8
    122   %0 = bitcast %struct.A** %a to i8*
    123   
    124   %call = call i8* @getPointer(i8* null) 
    125   %1 = bitcast i8* %call to %struct.A*
    126   call void @_ZN1AC1Ev(%struct.A* %1)
    127   %2 = bitcast %struct.A* %1 to i8***
    128   
    129 ; CHECK: %vtable = load {{.*}} !invariant.group
    130   %vtable = load i8**, i8*** %2, align 8, !invariant.group !2
    131   %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i64 0, i64 2)
    132   
    133   store %struct.A* %1, %struct.A** %a, align 8
    134 ; CHECK-NOT: !invariant.group
    135   %3 = load %struct.A*, %struct.A** %a, align 8
    136   %4 = bitcast %struct.A* %3 to void (%struct.A*)***
    137 
    138   %vtable1 = load void (%struct.A*)**, void (%struct.A*)*** %4, align 8, !invariant.group !2
    139   %vfn = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** %vtable1, i64 0
    140   %5 = load void (%struct.A*)*, void (%struct.A*)** %vfn, align 8
    141   call void %5(%struct.A* %3)
    142 
    143   ret void
    144 }
    145 
    146 ; CHECK-LABEL:define void @loadCombine() {
    147 define void @loadCombine() {
    148 enter:
    149   %ptr = alloca i8
    150   store i8 42, i8* %ptr
    151   call void @foo(i8* %ptr)
    152 ; CHECK: %[[A:.*]] = load i8, i8* %ptr, !invariant.group
    153   %a = load i8, i8* %ptr, !invariant.group !0
    154 ; CHECK-NOT: load
    155   %b = load i8, i8* %ptr, !invariant.group !1
    156 ; CHECK: call void @bar(i8 %[[A]])
    157   call void @bar(i8 %a)
    158 ; CHECK: call void @bar(i8 %[[A]])
    159   call void @bar(i8 %b)
    160   ret void
    161 }
    162 
    163 ; CHECK-LABEL: define void @loadCombine1() {
    164 define void @loadCombine1() {
    165 enter:
    166   %ptr = alloca i8
    167   store i8 42, i8* %ptr
    168   call void @foo(i8* %ptr)
    169 ; CHECK: %[[D:.*]] = load i8, i8* %ptr, !invariant.group
    170   %c = load i8, i8* %ptr
    171 ; CHECK-NOT: load
    172   %d = load i8, i8* %ptr, !invariant.group !1
    173 ; CHECK: call void @bar(i8 %[[D]])
    174   call void @bar(i8 %c)
    175 ; CHECK: call void @bar(i8 %[[D]])
    176   call void @bar(i8 %d)
    177   ret void
    178 }
    179 
    180 ; CHECK-LABEL: define void @loadCombine2() {    
    181 define void @loadCombine2() {
    182 enter:
    183   %ptr = alloca i8
    184   store i8 42, i8* %ptr
    185   call void @foo(i8* %ptr)
    186 ; CHECK: %[[E:.*]] = load i8, i8* %ptr, !invariant.group
    187   %e = load i8, i8* %ptr, !invariant.group !1
    188 ; CHECK-NOT: load
    189   %f = load i8, i8* %ptr
    190 ; CHECK: call void @bar(i8 %[[E]])
    191   call void @bar(i8 %e)
    192 ; CHECK: call void @bar(i8 %[[E]])
    193   call void @bar(i8 %f)
    194   ret void
    195 }
    196 
    197 ; CHECK-LABEL: define void @loadCombine3() {
    198 define void @loadCombine3() {
    199 enter:
    200   %ptr = alloca i8
    201   store i8 42, i8* %ptr
    202   call void @foo(i8* %ptr)
    203 ; CHECK: %[[E:.*]] = load i8, i8* %ptr, !invariant.group ![[OneMD:[0-9]]]
    204   %e = load i8, i8* %ptr, !invariant.group !1
    205 ; CHECK-NOT: load
    206   %f = load i8, i8* %ptr, !invariant.group !1
    207 ; CHECK: call void @bar(i8 %[[E]])
    208   call void @bar(i8 %e)
    209 ; CHECK: call void @bar(i8 %[[E]])
    210   call void @bar(i8 %f)
    211   ret void
    212 }
    213 
    214 ; CHECK-LABEL: define i8 @unoptimizable2() {
    215 define i8 @unoptimizable2() {
    216 entry:
    217     %ptr = alloca i8
    218     store i8 42, i8* %ptr
    219     call void @foo(i8* %ptr)
    220     %a = load i8, i8* %ptr
    221     call void @foo(i8* %ptr)
    222     %b = load i8, i8* %ptr, !invariant.group !0
    223     
    224 ; CHECK: ret i8 %a
    225     ret i8 %a
    226 }
    227 
    228 ; CHECK-LABEL: define i8 @unoptimizable3() {
    229 define i8 @unoptimizable3() {
    230 entry:
    231     %ptr = alloca i8
    232     store i8 42, i8* %ptr, !invariant.group !0
    233     %ptr2 = call i8* @getPointer(i8* %ptr)
    234     %a = load i8, i8* %ptr2, !invariant.group !0
    235     
    236 ; CHECK: ret i8 %a
    237     ret i8 %a
    238 }
    239 
    240 ; CHECK-LABEL: define i8 @unoptimizable4() {
    241 define i8 @unoptimizable4() {
    242 entry:
    243     %ptr = alloca i8
    244     store i8 42, i8* %ptr, !invariant.group !0
    245     %ptr2 = call i8* @llvm.invariant.group.barrier(i8* %ptr)
    246     %a = load i8, i8* %ptr2, !invariant.group !0
    247     
    248 ; CHECK: ret i8 %a
    249     ret i8 %a
    250 }
    251 
    252 ; CHECK-LABEL: define i8 @volatile1() {
    253 define i8 @volatile1() {
    254 entry:
    255     %ptr = alloca i8
    256     store i8 42, i8* %ptr, !invariant.group !0
    257     call void @foo(i8* %ptr)
    258     %a = load i8, i8* %ptr, !invariant.group !0
    259     %b = load volatile i8, i8* %ptr
    260 ; CHECK: call void @bar(i8 %b)
    261     call void @bar(i8 %b)
    262 
    263     %c = load volatile i8, i8* %ptr, !invariant.group !0
    264 ; FIXME: we could change %c to 42, preserving volatile load
    265 ; CHECK: call void @bar(i8 %c)
    266     call void @bar(i8 %c)
    267 ; CHECK: ret i8 42
    268     ret i8 %a
    269 }
    270 
    271 ; CHECK-LABEL: define i8 @volatile2() {
    272 define i8 @volatile2() {
    273 entry:
    274     %ptr = alloca i8
    275     store i8 42, i8* %ptr, !invariant.group !0
    276     call void @foo(i8* %ptr)
    277     %a = load i8, i8* %ptr, !invariant.group !0
    278     %b = load volatile i8, i8* %ptr
    279 ; CHECK: call void @bar(i8 %b)
    280     call void @bar(i8 %b)
    281 
    282     %c = load volatile i8, i8* %ptr, !invariant.group !0
    283 ; FIXME: we could change %c to 42, preserving volatile load
    284 ; CHECK: call void @bar(i8 %c)
    285     call void @bar(i8 %c)
    286 ; CHECK: ret i8 42
    287     ret i8 %a
    288 }
    289 
    290 ; CHECK-LABEL: define i8 @fun() {
    291 define i8 @fun() {
    292 entry:
    293     %ptr = alloca i8
    294     store i8 42, i8* %ptr, !invariant.group !0
    295     call void @foo(i8* %ptr)
    296 
    297     %a = load i8, i8* %ptr, !invariant.group !0 ; Can assume that value under %ptr didn't change
    298 ; CHECK: call void @bar(i8 42)
    299     call void @bar(i8 %a)
    300     
    301     call void @foo(i8* %ptr)
    302     %b = load i8, i8* %ptr, !invariant.group !1 ; Can't assume anything, because group changed
    303 ; CHECK: call void @bar(i8 %b)
    304     call void @bar(i8 %b)
    305     
    306     %newPtr = call i8* @getPointer(i8* %ptr) 
    307     %c = load i8, i8* %newPtr, !invariant.group !0 ; Can't assume anything, because we only have information about %ptr
    308 ; CHECK: call void @bar(i8 %c)
    309     call void @bar(i8 %c)
    310     
    311     %unknownValue = load i8, i8* @unknownPtr
    312 ; FIXME: Can assume that %unknownValue == 42
    313 ; CHECK: store i8 %unknownValue, i8* %ptr, !invariant.group !0
    314     store i8 %unknownValue, i8* %ptr, !invariant.group !0 
    315 
    316     %newPtr2 = call i8* @llvm.invariant.group.barrier(i8* %ptr)
    317     %d = load i8, i8* %newPtr2, !invariant.group !0  ; Can't step through invariant.group.barrier to get value of %ptr
    318 ; CHECK: ret i8 %d
    319     ret i8 %d
    320 }
    321 
    322 declare void @foo(i8*)
    323 declare void @bar(i8)
    324 declare i8* @getPointer(i8*)
    325 declare void @_ZN1A3fooEv(%struct.A*)
    326 declare void @_ZN1AC1Ev(%struct.A*)
    327 declare i8* @llvm.invariant.group.barrier(i8*)
    328 
    329 ; Function Attrs: nounwind
    330 declare void @llvm.assume(i1 %cmp.vtables) #0
    331 
    332 
    333 attributes #0 = { nounwind }
    334 ; CHECK: ![[OneMD]] = !{!"other ptr"}
    335 !0 = !{!"magic ptr"}
    336 !1 = !{!"other ptr"}
    337 !2 = !{!"vtable_of_a"}
    338