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 [4 x i8*] [i8* null, i8* bitcast (i8** @_ZTI1A to i8*), i8* bitcast (i32 (%struct.A*)* @_ZN1A3fooEv to i8*), i8* bitcast (i32 (%struct.A*)* @_ZN1A3barEv to i8*)], align 8
      5 @_ZTI1A = external constant i8*
      6 
      7 ; Checks if indirect calls can be replaced with direct
      8 ; assuming that %vtable == @_ZTV1A (with alignment).
      9 ; Checking const propagation across other BBs
     10 ; CHECK-LABEL: define void @_Z1gb(
     11 
     12 define void @_Z1gb(i1 zeroext %p) {
     13 entry:
     14   %call = tail call noalias i8* @_Znwm(i64 8) #4
     15   %0 = bitcast i8* %call to %struct.A*
     16   tail call void @_ZN1AC1Ev(%struct.A* %0) #1
     17   %1 = bitcast i8* %call to i8***
     18   %vtable = load i8**, i8*** %1, align 8
     19   %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTV1A, i64 0, i64 2)
     20   tail call void @llvm.assume(i1 %cmp.vtables)
     21   br i1 %p, label %if.then, label %if.else
     22 
     23 if.then:                                          ; preds = %entry
     24   %vtable1.cast = bitcast i8** %vtable to i32 (%struct.A*)**
     25   %2 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vtable1.cast, align 8
     26   
     27   ; CHECK: call i32 @_ZN1A3fooEv(
     28   %call2 = tail call i32 %2(%struct.A* %0) #1
     29   
     30   br label %if.end
     31 
     32 if.else:                                          ; preds = %entry
     33   %vfn47 = getelementptr inbounds i8*, i8** %vtable, i64 1
     34   %vfn4 = bitcast i8** %vfn47 to i32 (%struct.A*)**
     35   
     36   ; CHECK: call i32 @_ZN1A3barEv(
     37   %3 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vfn4, align 8
     38   
     39   %call5 = tail call i32 %3(%struct.A* %0) #1
     40   br label %if.end
     41 
     42 if.end:                                           ; preds = %if.else, %if.then
     43   ret void
     44 }
     45 
     46 ; Check integration with invariant.group handling
     47 ; CHECK-LABEL: define void @invariantGroupHandling(i1 zeroext %p) {
     48 define void @invariantGroupHandling(i1 zeroext %p) {
     49 entry:
     50   %call = tail call noalias i8* @_Znwm(i64 8) #4
     51   %0 = bitcast i8* %call to %struct.A*
     52   tail call void @_ZN1AC1Ev(%struct.A* %0) #1
     53   %1 = bitcast i8* %call to i8***
     54   %vtable = load i8**, i8*** %1, align 8, !invariant.group !0
     55   %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTV1A, i64 0, i64 2)
     56   tail call void @llvm.assume(i1 %cmp.vtables)
     57   br i1 %p, label %if.then, label %if.else
     58 
     59 if.then:                                          ; preds = %entry
     60   %vtable1.cast = bitcast i8** %vtable to i32 (%struct.A*)**
     61   %2 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vtable1.cast, align 8
     62   
     63 ; CHECK: call i32 @_ZN1A3fooEv(
     64   %call2 = tail call i32 %2(%struct.A* %0) #1
     65   %vtable1 = load i8**, i8*** %1, align 8, !invariant.group !0
     66   %vtable2.cast = bitcast i8** %vtable1 to i32 (%struct.A*)**
     67   %call1 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vtable2.cast, align 8
     68 ; FIXME: those loads could be also direct, but right now the invariant.group
     69 ; analysis works only on single block
     70 ; CHECK-NOT: call i32 @_ZN1A3fooEv(
     71   %callx = tail call i32 %call1(%struct.A* %0) #1
     72   
     73   %vtable2 = load i8**, i8*** %1, align 8, !invariant.group !0
     74   %vtable3.cast = bitcast i8** %vtable2 to i32 (%struct.A*)**
     75   %call4 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vtable3.cast, align 8
     76 ; CHECK-NOT: call i32 @_ZN1A3fooEv(
     77   %cally = tail call i32 %call4(%struct.A* %0) #1
     78   
     79   %b = bitcast i8* %call to %struct.A**
     80   %vtable3 = load %struct.A*, %struct.A** %b, align 8, !invariant.group !0
     81   %vtable4.cast = bitcast %struct.A* %vtable3 to i32 (%struct.A*)**
     82   %vfun = load i32 (%struct.A*)*, i32 (%struct.A*)** %vtable4.cast, align 8
     83 ; CHECK-NOT: call i32 @_ZN1A3fooEv(
     84   %unknown = tail call i32 %vfun(%struct.A* %0) #1
     85   
     86   br label %if.end
     87 
     88 if.else:                                          ; preds = %entry
     89   %vfn47 = getelementptr inbounds i8*, i8** %vtable, i64 1
     90   %vfn4 = bitcast i8** %vfn47 to i32 (%struct.A*)**
     91   
     92   ; CHECK: call i32 @_ZN1A3barEv(
     93   %3 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vfn4, align 8
     94   
     95   %call5 = tail call i32 %3(%struct.A* %0) #1
     96   br label %if.end
     97 
     98 if.end:                                           ; preds = %if.else, %if.then
     99   ret void
    100 }
    101 
    102 
    103 ; Checking const propagation in the same BB
    104 ; CHECK-LABEL: define i32 @main()
    105 
    106 define i32 @main() {
    107 entry:
    108   %call = tail call noalias i8* @_Znwm(i64 8) 
    109   %0 = bitcast i8* %call to %struct.A*
    110   tail call void @_ZN1AC1Ev(%struct.A* %0) 
    111   %1 = bitcast i8* %call to i8***
    112   %vtable = load i8**, i8*** %1, align 8
    113   %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTV1A, i64 0, i64 2)
    114   tail call void @llvm.assume(i1 %cmp.vtables)
    115   %vtable1.cast = bitcast i8** %vtable to i32 (%struct.A*)**
    116   
    117   ; CHECK: call i32 @_ZN1A3fooEv(
    118   %2 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vtable1.cast, align 8
    119   
    120   %call2 = tail call i32 %2(%struct.A* %0)
    121   ret i32 0
    122 }
    123 
    124 ; This tests checks const propatation with fcmp instruction.
    125 ; CHECK-LABEL: define float @_Z1gf(float %p)
    126 
    127 define float @_Z1gf(float %p) {
    128 entry:
    129   %p.addr = alloca float, align 4
    130   %f = alloca float, align 4
    131   store float %p, float* %p.addr, align 4
    132   
    133   store float 3.000000e+00, float* %f, align 4
    134   %0 = load float, float* %p.addr, align 4
    135   %1 = load float, float* %f, align 4
    136   %cmp = fcmp oeq float %1, %0 ; note const on lhs
    137   call void @llvm.assume(i1 %cmp)
    138   
    139   ; CHECK: ret float 3.000000e+00
    140   ret float %0
    141 }
    142 
    143 ; CHECK-LABEL: define float @_Z1hf(float %p)
    144 
    145 define float @_Z1hf(float %p) {
    146 entry:
    147   %p.addr = alloca float, align 4
    148   store float %p, float* %p.addr, align 4
    149   
    150   %0 = load float, float* %p.addr, align 4
    151   %cmp = fcmp nnan ueq float %0, 3.000000e+00
    152   call void @llvm.assume(i1 %cmp)
    153   
    154   ; CHECK: ret float 3.000000e+00
    155   ret float %0
    156 }
    157 
    158 ; CHECK-LABEL: define float @_Z1if(float %p)
    159 define float @_Z1if(float %p) {
    160 entry:
    161   %p.addr = alloca float, align 4
    162   store float %p, float* %p.addr, align 4
    163   
    164   %0 = load float, float* %p.addr, align 4
    165   %cmp = fcmp ueq float %0, 3.000000e+00 ; no nnan flag - can't propagate
    166   call void @llvm.assume(i1 %cmp)
    167   
    168   ; CHECK-NOT: ret float 3.000000e+00
    169   ret float %0
    170 }
    171 
    172 ; This test checks if constant propagation works for multiple node edges
    173 ; CHECK-LABEL: define i32 @_Z1ii(i32 %p)
    174 define i32 @_Z1ii(i32 %p) {
    175 entry:
    176   %cmp = icmp eq i32 %p, 42
    177   call void @llvm.assume(i1 %cmp)
    178   
    179   ; CHECK: br i1 true, label %bb2, label %bb2
    180   br i1 %cmp, label %bb2, label %bb2
    181 bb2:
    182   call void @llvm.assume(i1 true)
    183   ; CHECK: br i1 true, label %bb2, label %bb2
    184   br i1 %cmp, label %bb2, label %bb2
    185   
    186   ; CHECK: ret i32 42
    187   ret i32 %p
    188 }
    189 
    190 ; CHECK-LABEL: define i32 @_Z1ij(i32 %p)
    191 define i32 @_Z1ij(i32 %p) {
    192 entry:
    193   %cmp = icmp eq i32 %p, 42
    194   call void @llvm.assume(i1 %cmp)
    195   
    196   ; CHECK: br i1 true, label %bb2, label %bb2
    197   br i1 %cmp, label %bb2, label %bb2
    198 bb2:
    199    ; CHECK-NOT: %cmp2 = 
    200   %cmp2 = icmp eq i32 %p, 42
    201   ; CHECK-NOT: call void @llvm.assume(
    202   call void @llvm.assume(i1 %cmp2)
    203   
    204   ; CHECK: br i1 true, label %bb2, label %bb2
    205   br i1 %cmp, label %bb2, label %bb2
    206   
    207   ; CHECK: ret i32 42
    208   ret i32 %p
    209 }
    210 
    211 ; CHECK-LABEL: define i32 @_Z1ik(i32 %p)
    212 define i32 @_Z1ik(i32 %p) {
    213 entry:
    214   %cmp = icmp eq i32 %p, 42
    215   call void @llvm.assume(i1 %cmp)
    216   
    217   ; CHECK: br i1 true, label %bb2, label %bb3
    218   br i1 %cmp, label %bb2, label %bb3
    219 bb2:
    220   ; CHECK-NOT: %cmp3 = 
    221   %cmp3 = icmp eq i32 %p, 43
    222   ; CHECK: store i8 undef, i8* null
    223   call void @llvm.assume(i1 %cmp3)
    224   ret i32 15
    225 bb3:
    226   ret i32 17
    227 }
    228 
    229 declare noalias i8* @_Znwm(i64)
    230 declare void @_ZN1AC1Ev(%struct.A*)
    231 declare void @llvm.assume(i1)
    232 declare i32 @_ZN1A3fooEv(%struct.A*)
    233 declare i32 @_ZN1A3barEv(%struct.A*)
    234 
    235 !0 = !{!"struct A"}
    236