Home | History | Annotate | Download | only in TypeBasedAliasAnalysis
      1 ; RUN: opt < %s -tbaa -basicaa -aa-eval -evaluate-aa-metadata -print-no-aliases -print-may-aliases -disable-output 2>&1 | FileCheck %s
      2 ; RUN: opt < %s -tbaa -basicaa -gvn -S | FileCheck %s --check-prefix=OPT
      3 ; Generated from clang/test/CodeGen/tbaa.cpp with "-O1 -struct-path-tbaa -disable-llvm-optzns".
      4 
      5 %struct.StructA = type { i16, i32, i16, i32 }
      6 %struct.StructB = type { i16, %struct.StructA, i32 }
      7 %struct.StructS = type { i16, i32 }
      8 %struct.StructS2 = type { i16, i32 }
      9 %struct.StructC = type { i16, %struct.StructB, i32 }
     10 %struct.StructD = type { i16, %struct.StructB, i32, i8 }
     11 
     12 define i32 @_Z1gPjP7StructAy(i32* %s, %struct.StructA* %A, i64 %count) #0 {
     13 entry:
     14 ; Access to i32* and &(A->f32).
     15 ; CHECK: Function
     16 ; CHECK: MayAlias:   store i32 4, i32* %f32, align 4, !tbaa !8 <->   store i32 1, i32* %0, align 4, !tbaa !6
     17 ; OPT: define
     18 ; OPT: store i32 1
     19 ; OPT: store i32 4
     20 ; OPT: %[[RET:.*]] = load i32, i32*
     21 ; OPT: ret i32 %[[RET]]
     22   %s.addr = alloca i32*, align 8
     23   %A.addr = alloca %struct.StructA*, align 8
     24   %count.addr = alloca i64, align 8
     25   store i32* %s, i32** %s.addr, align 8, !tbaa !0
     26   store %struct.StructA* %A, %struct.StructA** %A.addr, align 8, !tbaa !0
     27   store i64 %count, i64* %count.addr, align 8, !tbaa !4
     28   %0 = load i32*, i32** %s.addr, align 8, !tbaa !0
     29   store i32 1, i32* %0, align 4, !tbaa !6
     30   %1 = load %struct.StructA*, %struct.StructA** %A.addr, align 8, !tbaa !0
     31   %f32 = getelementptr inbounds %struct.StructA, %struct.StructA* %1, i32 0, i32 1
     32   store i32 4, i32* %f32, align 4, !tbaa !8
     33   %2 = load i32*, i32** %s.addr, align 8, !tbaa !0
     34   %3 = load i32, i32* %2, align 4, !tbaa !6
     35   ret i32 %3
     36 }
     37 
     38 define i32 @_Z2g2PjP7StructAy(i32* %s, %struct.StructA* %A, i64 %count) #0 {
     39 entry:
     40 ; Access to i32* and &(A->f16).
     41 ; CHECK: Function
     42 ; CHECK: NoAlias:   store i16 4, i16* %f16, align 2, !tbaa !8 <->   store i32 1, i32* %0, align 4, !tbaa !6
     43 ; OPT: define
     44 ; OPT: store i32 1
     45 ; OPT: store i16 4
     46 ; Remove a load and propagate the value from store.
     47 ; OPT: ret i32 1
     48   %s.addr = alloca i32*, align 8
     49   %A.addr = alloca %struct.StructA*, align 8
     50   %count.addr = alloca i64, align 8
     51   store i32* %s, i32** %s.addr, align 8, !tbaa !0
     52   store %struct.StructA* %A, %struct.StructA** %A.addr, align 8, !tbaa !0
     53   store i64 %count, i64* %count.addr, align 8, !tbaa !4
     54   %0 = load i32*, i32** %s.addr, align 8, !tbaa !0
     55   store i32 1, i32* %0, align 4, !tbaa !6
     56   %1 = load %struct.StructA*, %struct.StructA** %A.addr, align 8, !tbaa !0
     57   %f16 = getelementptr inbounds %struct.StructA, %struct.StructA* %1, i32 0, i32 0
     58   store i16 4, i16* %f16, align 2, !tbaa !11
     59   %2 = load i32*, i32** %s.addr, align 8, !tbaa !0
     60   %3 = load i32, i32* %2, align 4, !tbaa !6
     61   ret i32 %3
     62 }
     63 
     64 define i32 @_Z2g3P7StructAP7StructBy(%struct.StructA* %A, %struct.StructB* %B, i64 %count) #0 {
     65 entry:
     66 ; Access to &(A->f32) and &(B->a.f32).
     67 ; CHECK: Function
     68 ; CHECK: MayAlias:   store i32 4, i32* %f321, align 4, !tbaa !10 <->   store i32 1, i32* %f32, align 4, !tbaa !6
     69 ; OPT: define
     70 ; OPT: store i32 1
     71 ; OPT: store i32 4
     72 ; OPT: %[[RET:.*]] = load i32, i32*
     73 ; OPT: ret i32 %[[RET]]
     74   %A.addr = alloca %struct.StructA*, align 8
     75   %B.addr = alloca %struct.StructB*, align 8
     76   %count.addr = alloca i64, align 8
     77   store %struct.StructA* %A, %struct.StructA** %A.addr, align 8, !tbaa !0
     78   store %struct.StructB* %B, %struct.StructB** %B.addr, align 8, !tbaa !0
     79   store i64 %count, i64* %count.addr, align 8, !tbaa !4
     80   %0 = load %struct.StructA*, %struct.StructA** %A.addr, align 8, !tbaa !0
     81   %f32 = getelementptr inbounds %struct.StructA, %struct.StructA* %0, i32 0, i32 1
     82   store i32 1, i32* %f32, align 4, !tbaa !8
     83   %1 = load %struct.StructB*, %struct.StructB** %B.addr, align 8, !tbaa !0
     84   %a = getelementptr inbounds %struct.StructB, %struct.StructB* %1, i32 0, i32 1
     85   %f321 = getelementptr inbounds %struct.StructA, %struct.StructA* %a, i32 0, i32 1
     86   store i32 4, i32* %f321, align 4, !tbaa !12
     87   %2 = load %struct.StructA*, %struct.StructA** %A.addr, align 8, !tbaa !0
     88   %f322 = getelementptr inbounds %struct.StructA, %struct.StructA* %2, i32 0, i32 1
     89   %3 = load i32, i32* %f322, align 4, !tbaa !8
     90   ret i32 %3
     91 }
     92 
     93 define i32 @_Z2g4P7StructAP7StructBy(%struct.StructA* %A, %struct.StructB* %B, i64 %count) #0 {
     94 entry:
     95 ; Access to &(A->f32) and &(B->a.f16).
     96 ; CHECK: Function
     97 ; CHECK: NoAlias:   store i16 4, i16* %f16, align 2, !tbaa !10 <->   store i32 1, i32* %f32, align 4, !tbaa !6
     98 ; OPT: define
     99 ; OPT: store i32 1
    100 ; OPT: store i16 4
    101 ; Remove a load and propagate the value from store.
    102 ; OPT: ret i32 1
    103   %A.addr = alloca %struct.StructA*, align 8
    104   %B.addr = alloca %struct.StructB*, align 8
    105   %count.addr = alloca i64, align 8
    106   store %struct.StructA* %A, %struct.StructA** %A.addr, align 8, !tbaa !0
    107   store %struct.StructB* %B, %struct.StructB** %B.addr, align 8, !tbaa !0
    108   store i64 %count, i64* %count.addr, align 8, !tbaa !4
    109   %0 = load %struct.StructA*, %struct.StructA** %A.addr, align 8, !tbaa !0
    110   %f32 = getelementptr inbounds %struct.StructA, %struct.StructA* %0, i32 0, i32 1
    111   store i32 1, i32* %f32, align 4, !tbaa !8
    112   %1 = load %struct.StructB*, %struct.StructB** %B.addr, align 8, !tbaa !0
    113   %a = getelementptr inbounds %struct.StructB, %struct.StructB* %1, i32 0, i32 1
    114   %f16 = getelementptr inbounds %struct.StructA, %struct.StructA* %a, i32 0, i32 0
    115   store i16 4, i16* %f16, align 2, !tbaa !14
    116   %2 = load %struct.StructA*, %struct.StructA** %A.addr, align 8, !tbaa !0
    117   %f321 = getelementptr inbounds %struct.StructA, %struct.StructA* %2, i32 0, i32 1
    118   %3 = load i32, i32* %f321, align 4, !tbaa !8
    119   ret i32 %3
    120 }
    121 
    122 define i32 @_Z2g5P7StructAP7StructBy(%struct.StructA* %A, %struct.StructB* %B, i64 %count) #0 {
    123 entry:
    124 ; Access to &(A->f32) and &(B->f32).
    125 ; CHECK: Function
    126 ; CHECK: NoAlias:   store i32 4, i32* %f321, align 4, !tbaa !10 <->   store i32 1, i32* %f32, align 4, !tbaa !6
    127 ; OPT: define
    128 ; OPT: store i32 1
    129 ; OPT: store i32 4
    130 ; Remove a load and propagate the value from store.
    131 ; OPT: ret i32 1
    132   %A.addr = alloca %struct.StructA*, align 8
    133   %B.addr = alloca %struct.StructB*, align 8
    134   %count.addr = alloca i64, align 8
    135   store %struct.StructA* %A, %struct.StructA** %A.addr, align 8, !tbaa !0
    136   store %struct.StructB* %B, %struct.StructB** %B.addr, align 8, !tbaa !0
    137   store i64 %count, i64* %count.addr, align 8, !tbaa !4
    138   %0 = load %struct.StructA*, %struct.StructA** %A.addr, align 8, !tbaa !0
    139   %f32 = getelementptr inbounds %struct.StructA, %struct.StructA* %0, i32 0, i32 1
    140   store i32 1, i32* %f32, align 4, !tbaa !8
    141   %1 = load %struct.StructB*, %struct.StructB** %B.addr, align 8, !tbaa !0
    142   %f321 = getelementptr inbounds %struct.StructB, %struct.StructB* %1, i32 0, i32 2
    143   store i32 4, i32* %f321, align 4, !tbaa !15
    144   %2 = load %struct.StructA*, %struct.StructA** %A.addr, align 8, !tbaa !0
    145   %f322 = getelementptr inbounds %struct.StructA, %struct.StructA* %2, i32 0, i32 1
    146   %3 = load i32, i32* %f322, align 4, !tbaa !8
    147   ret i32 %3
    148 }
    149 
    150 define i32 @_Z2g6P7StructAP7StructBy(%struct.StructA* %A, %struct.StructB* %B, i64 %count) #0 {
    151 entry:
    152 ; Access to &(A->f32) and &(B->a.f32_2).
    153 ; CHECK: Function
    154 ; CHECK: NoAlias:   store i32 4, i32* %f32_2, align 4, !tbaa !10 <->   store i32 1, i32* %f32, align 4, !tbaa !6
    155 ; OPT: define
    156 ; OPT: store i32 1
    157 ; OPT: store i32 4
    158 ; Remove a load and propagate the value from store.
    159 ; OPT: ret i32 1
    160   %A.addr = alloca %struct.StructA*, align 8
    161   %B.addr = alloca %struct.StructB*, align 8
    162   %count.addr = alloca i64, align 8
    163   store %struct.StructA* %A, %struct.StructA** %A.addr, align 8, !tbaa !0
    164   store %struct.StructB* %B, %struct.StructB** %B.addr, align 8, !tbaa !0
    165   store i64 %count, i64* %count.addr, align 8, !tbaa !4
    166   %0 = load %struct.StructA*, %struct.StructA** %A.addr, align 8, !tbaa !0
    167   %f32 = getelementptr inbounds %struct.StructA, %struct.StructA* %0, i32 0, i32 1
    168   store i32 1, i32* %f32, align 4, !tbaa !8
    169   %1 = load %struct.StructB*, %struct.StructB** %B.addr, align 8, !tbaa !0
    170   %a = getelementptr inbounds %struct.StructB, %struct.StructB* %1, i32 0, i32 1
    171   %f32_2 = getelementptr inbounds %struct.StructA, %struct.StructA* %a, i32 0, i32 3
    172   store i32 4, i32* %f32_2, align 4, !tbaa !16
    173   %2 = load %struct.StructA*, %struct.StructA** %A.addr, align 8, !tbaa !0
    174   %f321 = getelementptr inbounds %struct.StructA, %struct.StructA* %2, i32 0, i32 1
    175   %3 = load i32, i32* %f321, align 4, !tbaa !8
    176   ret i32 %3
    177 }
    178 
    179 define i32 @_Z2g7P7StructAP7StructSy(%struct.StructA* %A, %struct.StructS* %S, i64 %count) #0 {
    180 entry:
    181 ; Access to &(A->f32) and &(S->f32).
    182 ; CHECK: Function
    183 ; CHECK: NoAlias:   store i32 4, i32* %f321, align 4, !tbaa !10 <->   store i32 1, i32* %f32, align 4, !tbaa !6
    184 ; OPT: define
    185 ; OPT: store i32 1
    186 ; OPT: store i32 4
    187 ; Remove a load and propagate the value from store.
    188 ; OPT: ret i32 1
    189   %A.addr = alloca %struct.StructA*, align 8
    190   %S.addr = alloca %struct.StructS*, align 8
    191   %count.addr = alloca i64, align 8
    192   store %struct.StructA* %A, %struct.StructA** %A.addr, align 8, !tbaa !0
    193   store %struct.StructS* %S, %struct.StructS** %S.addr, align 8, !tbaa !0
    194   store i64 %count, i64* %count.addr, align 8, !tbaa !4
    195   %0 = load %struct.StructA*, %struct.StructA** %A.addr, align 8, !tbaa !0
    196   %f32 = getelementptr inbounds %struct.StructA, %struct.StructA* %0, i32 0, i32 1
    197   store i32 1, i32* %f32, align 4, !tbaa !8
    198   %1 = load %struct.StructS*, %struct.StructS** %S.addr, align 8, !tbaa !0
    199   %f321 = getelementptr inbounds %struct.StructS, %struct.StructS* %1, i32 0, i32 1
    200   store i32 4, i32* %f321, align 4, !tbaa !17
    201   %2 = load %struct.StructA*, %struct.StructA** %A.addr, align 8, !tbaa !0
    202   %f322 = getelementptr inbounds %struct.StructA, %struct.StructA* %2, i32 0, i32 1
    203   %3 = load i32, i32* %f322, align 4, !tbaa !8
    204   ret i32 %3
    205 }
    206 
    207 define i32 @_Z2g8P7StructAP7StructSy(%struct.StructA* %A, %struct.StructS* %S, i64 %count) #0 {
    208 entry:
    209 ; Access to &(A->f32) and &(S->f16).
    210 ; CHECK: Function
    211 ; CHECK: NoAlias:   store i16 4, i16* %f16, align 2, !tbaa !10 <->   store i32 1, i32* %f32, align 4, !tbaa !6
    212 ; OPT: define
    213 ; OPT: store i32 1
    214 ; OPT: store i16 4
    215 ; Remove a load and propagate the value from store.
    216 ; OPT: ret i32 1
    217   %A.addr = alloca %struct.StructA*, align 8
    218   %S.addr = alloca %struct.StructS*, align 8
    219   %count.addr = alloca i64, align 8
    220   store %struct.StructA* %A, %struct.StructA** %A.addr, align 8, !tbaa !0
    221   store %struct.StructS* %S, %struct.StructS** %S.addr, align 8, !tbaa !0
    222   store i64 %count, i64* %count.addr, align 8, !tbaa !4
    223   %0 = load %struct.StructA*, %struct.StructA** %A.addr, align 8, !tbaa !0
    224   %f32 = getelementptr inbounds %struct.StructA, %struct.StructA* %0, i32 0, i32 1
    225   store i32 1, i32* %f32, align 4, !tbaa !8
    226   %1 = load %struct.StructS*, %struct.StructS** %S.addr, align 8, !tbaa !0
    227   %f16 = getelementptr inbounds %struct.StructS, %struct.StructS* %1, i32 0, i32 0
    228   store i16 4, i16* %f16, align 2, !tbaa !19
    229   %2 = load %struct.StructA*, %struct.StructA** %A.addr, align 8, !tbaa !0
    230   %f321 = getelementptr inbounds %struct.StructA, %struct.StructA* %2, i32 0, i32 1
    231   %3 = load i32, i32* %f321, align 4, !tbaa !8
    232   ret i32 %3
    233 }
    234 
    235 define i32 @_Z2g9P7StructSP8StructS2y(%struct.StructS* %S, %struct.StructS2* %S2, i64 %count) #0 {
    236 entry:
    237 ; Access to &(S->f32) and &(S2->f32).
    238 ; CHECK: Function
    239 ; CHECK: NoAlias:   store i32 4, i32* %f321, align 4, !tbaa !10 <->   store i32 1, i32* %f32, align 4, !tbaa !6
    240 ; OPT: define
    241 ; OPT: store i32 1
    242 ; OPT: store i32 4
    243 ; Remove a load and propagate the value from store.
    244 ; OPT: ret i32 1
    245   %S.addr = alloca %struct.StructS*, align 8
    246   %S2.addr = alloca %struct.StructS2*, align 8
    247   %count.addr = alloca i64, align 8
    248   store %struct.StructS* %S, %struct.StructS** %S.addr, align 8, !tbaa !0
    249   store %struct.StructS2* %S2, %struct.StructS2** %S2.addr, align 8, !tbaa !0
    250   store i64 %count, i64* %count.addr, align 8, !tbaa !4
    251   %0 = load %struct.StructS*, %struct.StructS** %S.addr, align 8, !tbaa !0
    252   %f32 = getelementptr inbounds %struct.StructS, %struct.StructS* %0, i32 0, i32 1
    253   store i32 1, i32* %f32, align 4, !tbaa !17
    254   %1 = load %struct.StructS2*, %struct.StructS2** %S2.addr, align 8, !tbaa !0
    255   %f321 = getelementptr inbounds %struct.StructS2, %struct.StructS2* %1, i32 0, i32 1
    256   store i32 4, i32* %f321, align 4, !tbaa !20
    257   %2 = load %struct.StructS*, %struct.StructS** %S.addr, align 8, !tbaa !0
    258   %f322 = getelementptr inbounds %struct.StructS, %struct.StructS* %2, i32 0, i32 1
    259   %3 = load i32, i32* %f322, align 4, !tbaa !17
    260   ret i32 %3
    261 }
    262 
    263 define i32 @_Z3g10P7StructSP8StructS2y(%struct.StructS* %S, %struct.StructS2* %S2, i64 %count) #0 {
    264 entry:
    265 ; Access to &(S->f32) and &(S2->f16).
    266 ; CHECK: Function
    267 ; CHECK: NoAlias:   store i16 4, i16* %f16, align 2, !tbaa !10 <->   store i32 1, i32* %f32, align 4, !tbaa !6
    268 ; OPT: define
    269 ; OPT: store i32 1
    270 ; OPT: store i16 4
    271 ; Remove a load and propagate the value from store.
    272 ; OPT: ret i32 1
    273   %S.addr = alloca %struct.StructS*, align 8
    274   %S2.addr = alloca %struct.StructS2*, align 8
    275   %count.addr = alloca i64, align 8
    276   store %struct.StructS* %S, %struct.StructS** %S.addr, align 8, !tbaa !0
    277   store %struct.StructS2* %S2, %struct.StructS2** %S2.addr, align 8, !tbaa !0
    278   store i64 %count, i64* %count.addr, align 8, !tbaa !4
    279   %0 = load %struct.StructS*, %struct.StructS** %S.addr, align 8, !tbaa !0
    280   %f32 = getelementptr inbounds %struct.StructS, %struct.StructS* %0, i32 0, i32 1
    281   store i32 1, i32* %f32, align 4, !tbaa !17
    282   %1 = load %struct.StructS2*, %struct.StructS2** %S2.addr, align 8, !tbaa !0
    283   %f16 = getelementptr inbounds %struct.StructS2, %struct.StructS2* %1, i32 0, i32 0
    284   store i16 4, i16* %f16, align 2, !tbaa !22
    285   %2 = load %struct.StructS*, %struct.StructS** %S.addr, align 8, !tbaa !0
    286   %f321 = getelementptr inbounds %struct.StructS, %struct.StructS* %2, i32 0, i32 1
    287   %3 = load i32, i32* %f321, align 4, !tbaa !17
    288   ret i32 %3
    289 }
    290 
    291 define i32 @_Z3g11P7StructCP7StructDy(%struct.StructC* %C, %struct.StructD* %D, i64 %count) #0 {
    292 entry:
    293 ; Access to &(C->b.a.f32) and &(D->b.a.f32).
    294 ; CHECK: Function
    295 ; CHECK: NoAlias:   store i32 4, i32* %f323, align 4, !tbaa !12 <->   store i32 1, i32* %f32, align 4, !tbaa !6
    296 ; OPT: define
    297 ; OPT: store i32 1
    298 ; OPT: store i32 4
    299 ; Remove a load and propagate the value from store.
    300 ; OPT: ret i32 1
    301   %C.addr = alloca %struct.StructC*, align 8
    302   %D.addr = alloca %struct.StructD*, align 8
    303   %count.addr = alloca i64, align 8
    304   store %struct.StructC* %C, %struct.StructC** %C.addr, align 8, !tbaa !0
    305   store %struct.StructD* %D, %struct.StructD** %D.addr, align 8, !tbaa !0
    306   store i64 %count, i64* %count.addr, align 8, !tbaa !4
    307   %0 = load %struct.StructC*, %struct.StructC** %C.addr, align 8, !tbaa !0
    308   %b = getelementptr inbounds %struct.StructC, %struct.StructC* %0, i32 0, i32 1
    309   %a = getelementptr inbounds %struct.StructB, %struct.StructB* %b, i32 0, i32 1
    310   %f32 = getelementptr inbounds %struct.StructA, %struct.StructA* %a, i32 0, i32 1
    311   store i32 1, i32* %f32, align 4, !tbaa !23
    312   %1 = load %struct.StructD*, %struct.StructD** %D.addr, align 8, !tbaa !0
    313   %b1 = getelementptr inbounds %struct.StructD, %struct.StructD* %1, i32 0, i32 1
    314   %a2 = getelementptr inbounds %struct.StructB, %struct.StructB* %b1, i32 0, i32 1
    315   %f323 = getelementptr inbounds %struct.StructA, %struct.StructA* %a2, i32 0, i32 1
    316   store i32 4, i32* %f323, align 4, !tbaa !25
    317   %2 = load %struct.StructC*, %struct.StructC** %C.addr, align 8, !tbaa !0
    318   %b4 = getelementptr inbounds %struct.StructC, %struct.StructC* %2, i32 0, i32 1
    319   %a5 = getelementptr inbounds %struct.StructB, %struct.StructB* %b4, i32 0, i32 1
    320   %f326 = getelementptr inbounds %struct.StructA, %struct.StructA* %a5, i32 0, i32 1
    321   %3 = load i32, i32* %f326, align 4, !tbaa !23
    322   ret i32 %3
    323 }
    324 
    325 define i32 @_Z3g12P7StructCP7StructDy(%struct.StructC* %C, %struct.StructD* %D, i64 %count) #0 {
    326 entry:
    327 ; Access to &(b1->a.f32) and &(b2->a.f32).
    328 ; CHECK: Function
    329 ; CHECK: MayAlias:   store i32 4, i32* %f325, align 4, !tbaa !6 <->   store i32 1, i32* %f32, align 4, !tbaa !6
    330 ; OPT: define
    331 ; OPT: store i32 1
    332 ; OPT: store i32 4
    333 ; OPT: %[[RET:.*]] = load i32, i32*
    334 ; OPT: ret i32 %[[RET]]
    335   %C.addr = alloca %struct.StructC*, align 8
    336   %D.addr = alloca %struct.StructD*, align 8
    337   %count.addr = alloca i64, align 8
    338   %b1 = alloca %struct.StructB*, align 8
    339   %b2 = alloca %struct.StructB*, align 8
    340   store %struct.StructC* %C, %struct.StructC** %C.addr, align 8, !tbaa !0
    341   store %struct.StructD* %D, %struct.StructD** %D.addr, align 8, !tbaa !0
    342   store i64 %count, i64* %count.addr, align 8, !tbaa !4
    343   %0 = load %struct.StructC*, %struct.StructC** %C.addr, align 8, !tbaa !0
    344   %b = getelementptr inbounds %struct.StructC, %struct.StructC* %0, i32 0, i32 1
    345   store %struct.StructB* %b, %struct.StructB** %b1, align 8, !tbaa !0
    346   %1 = load %struct.StructD*, %struct.StructD** %D.addr, align 8, !tbaa !0
    347   %b3 = getelementptr inbounds %struct.StructD, %struct.StructD* %1, i32 0, i32 1
    348   store %struct.StructB* %b3, %struct.StructB** %b2, align 8, !tbaa !0
    349   %2 = load %struct.StructB*, %struct.StructB** %b1, align 8, !tbaa !0
    350   %a = getelementptr inbounds %struct.StructB, %struct.StructB* %2, i32 0, i32 1
    351   %f32 = getelementptr inbounds %struct.StructA, %struct.StructA* %a, i32 0, i32 1
    352   store i32 1, i32* %f32, align 4, !tbaa !12
    353   %3 = load %struct.StructB*, %struct.StructB** %b2, align 8, !tbaa !0
    354   %a4 = getelementptr inbounds %struct.StructB, %struct.StructB* %3, i32 0, i32 1
    355   %f325 = getelementptr inbounds %struct.StructA, %struct.StructA* %a4, i32 0, i32 1
    356   store i32 4, i32* %f325, align 4, !tbaa !12
    357   %4 = load %struct.StructB*, %struct.StructB** %b1, align 8, !tbaa !0
    358   %a6 = getelementptr inbounds %struct.StructB, %struct.StructB* %4, i32 0, i32 1
    359   %f327 = getelementptr inbounds %struct.StructA, %struct.StructA* %a6, i32 0, i32 1
    360   %5 = load i32, i32* %f327, align 4, !tbaa !12
    361   ret i32 %5
    362 }
    363 
    364 attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-frame-pointer-elim-non-leaf"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" }
    365 
    366 !0 = !{!1, !1, i64 0}
    367 !1 = !{!"any pointer", !2}
    368 !2 = !{!"omnipotent char", !3}
    369 !3 = !{!"Simple C/C++ TBAA"}
    370 !4 = !{!5, !5, i64 0}
    371 !5 = !{!"long long", !2}
    372 !6 = !{!7, !7, i64 0}
    373 !7 = !{!"int", !2}
    374 !8 = !{!9, !7, i64 4}
    375 !9 = !{!"_ZTS7StructA", !10, i64 0, !7, i64 4, !10, i64 8, !7, i64 12}
    376 !10 = !{!"short", !2}
    377 !11 = !{!9, !10, i64 0}
    378 !12 = !{!13, !7, i64 8}
    379 !13 = !{!"_ZTS7StructB", !10, i64 0, !9, i64 4, !7, i64 20}
    380 !14 = !{!13, !10, i64 4}
    381 !15 = !{!13, !7, i64 20}
    382 !16 = !{!13, !7, i64 16}
    383 !17 = !{!18, !7, i64 4}
    384 !18 = !{!"_ZTS7StructS", !10, i64 0, !7, i64 4}
    385 !19 = !{!18, !10, i64 0}
    386 !20 = !{!21, !7, i64 4}
    387 !21 = !{!"_ZTS8StructS2", !10, i64 0, !7, i64 4}
    388 !22 = !{!21, !10, i64 0}
    389 !23 = !{!24, !7, i64 12}
    390 !24 = !{!"_ZTS7StructC", !10, i64 0, !13, i64 4, !7, i64 28}
    391 !25 = !{!26, !7, i64 12}
    392 !26 = !{!"_ZTS7StructD", !10, i64 0, !13, i64 4, !7, i64 28, !2, i64 32}
    393