Home | History | Annotate | Download | only in CodeGenCXX
      1 // RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s \
      2 // RUN:   | FileCheck -check-prefix=CHECK-X86-64 %s
      3 // RUN: %clang_cc1 -triple powerpc64-unknown-unknown -emit-llvm -o - %s \
      4 // RUN:   | FileCheck -check-prefix=CHECK-PPC64 %s
      5 //
      6 // Tests for bitfield access patterns in C++ with special attention to
      7 // conformance to C++11 memory model requirements.
      8 
      9 namespace N0 {
     10   // Test basic bitfield layout access across interesting byte and word
     11   // boundaries on both little endian and big endian platforms.
     12   struct __attribute__((packed)) S {
     13     unsigned b00 : 14;
     14     unsigned b01 : 2;
     15     unsigned b20 : 6;
     16     unsigned b21 : 2;
     17     unsigned b30 : 30;
     18     unsigned b31 : 2;
     19     unsigned b70 : 6;
     20     unsigned b71 : 2;
     21   };
     22   unsigned read00(S* s) {
     23     // CHECK-X86-64-LABEL: define i32 @_ZN2N06read00
     24     // CHECK-X86-64:   %[[ptr:.*]]   = bitcast %{{.*}}* %{{.*}} to i64*
     25     // CHECK-X86-64:   %[[val:.*]]   = load i64, i64* %[[ptr]]
     26     // CHECK-X86-64:   %[[and:.*]]   = and i64 %[[val]], 16383
     27     // CHECK-X86-64:   %[[trunc:.*]] = trunc i64 %[[and]] to i32
     28     // CHECK-X86-64:                   ret i32 %[[trunc]]
     29     // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N06read00
     30     // CHECK-PPC64:   %[[ptr:.*]]   = bitcast %{{.*}}* %{{.*}} to i64*
     31     // CHECK-PPC64:   %[[val:.*]]   = load i64, i64* %[[ptr]]
     32     // CHECK-PPC64:   %[[shr:.*]]   = lshr i64 %[[val]], 50
     33     // CHECK-PPC64:   %[[trunc:.*]] = trunc i64 %[[shr]] to i32
     34     // CHECK-PPC64:                   ret i32 %[[trunc]]
     35     return s->b00;
     36   }
     37   unsigned read01(S* s) {
     38     // CHECK-X86-64-LABEL: define i32 @_ZN2N06read01
     39     // CHECK-X86-64:   %[[ptr:.*]]   = bitcast %{{.*}}* %{{.*}} to i64*
     40     // CHECK-X86-64:   %[[val:.*]]   = load i64, i64* %[[ptr]]
     41     // CHECK-X86-64:   %[[shr:.*]]   = lshr i64 %[[val]], 14
     42     // CHECK-X86-64:   %[[and:.*]]   = and i64 %[[shr]], 3
     43     // CHECK-X86-64:   %[[trunc:.*]] = trunc i64 %[[and]] to i32
     44     // CHECK-X86-64:                   ret i32 %[[trunc]]
     45     // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N06read01
     46     // CHECK-PPC64:   %[[ptr:.*]]   = bitcast %{{.*}}* %{{.*}} to i64*
     47     // CHECK-PPC64:   %[[val:.*]]   = load i64, i64* %[[ptr]]
     48     // CHECK-PPC64:   %[[shr:.*]]   = lshr i64 %[[val]], 48
     49     // CHECK-PPC64:   %[[and:.*]]   = and i64 %[[shr]], 3
     50     // CHECK-PPC64:   %[[trunc:.*]] = trunc i64 %[[and]] to i32
     51     // CHECK-PPC64:                   ret i32 %[[trunc]]
     52     return s->b01;
     53   }
     54   unsigned read20(S* s) {
     55     // CHECK-X86-64-LABEL: define i32 @_ZN2N06read20
     56     // CHECK-X86-64:   %[[ptr:.*]]   = bitcast %{{.*}}* %{{.*}} to i64*
     57     // CHECK-X86-64:   %[[val:.*]]   = load i64, i64* %[[ptr]]
     58     // CHECK-X86-64:   %[[shr:.*]]   = lshr i64 %[[val]], 16
     59     // CHECK-X86-64:   %[[and:.*]]   = and i64 %[[shr]], 63
     60     // CHECK-X86-64:   %[[trunc:.*]] = trunc i64 %[[and]] to i32
     61     // CHECK-X86-64:                   ret i32 %[[trunc]]
     62     // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N06read20
     63     // CHECK-PPC64:   %[[ptr:.*]]   = bitcast %{{.*}}* %{{.*}} to i64*
     64     // CHECK-PPC64:   %[[val:.*]]   = load i64, i64* %[[ptr]]
     65     // CHECK-PPC64:   %[[shr:.*]]   = lshr i64 %[[val]], 42
     66     // CHECK-PPC64:   %[[and:.*]]   = and i64 %[[shr]], 63
     67     // CHECK-PPC64:   %[[trunc:.*]] = trunc i64 %[[and]] to i32
     68     // CHECK-PPC64:                   ret i32 %[[trunc]]
     69     return s->b20;
     70   }
     71   unsigned read21(S* s) {
     72     // CHECK-X86-64-LABEL: define i32 @_ZN2N06read21
     73     // CHECK-X86-64:   %[[ptr:.*]]   = bitcast %{{.*}}* %{{.*}} to i64*
     74     // CHECK-X86-64:   %[[val:.*]]   = load i64, i64* %[[ptr]]
     75     // CHECK-X86-64:   %[[shr:.*]]   = lshr i64 %[[val]], 22
     76     // CHECK-X86-64:   %[[and:.*]]   = and i64 %[[shr]], 3
     77     // CHECK-X86-64:   %[[trunc:.*]] = trunc i64 %[[and]] to i32
     78     // CHECK-X86-64:                   ret i32 %[[trunc]]
     79     // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N06read21
     80     // CHECK-PPC64:   %[[ptr:.*]]   = bitcast %{{.*}}* %{{.*}} to i64*
     81     // CHECK-PPC64:   %[[val:.*]]   = load i64, i64* %[[ptr]]
     82     // CHECK-PPC64:   %[[shr:.*]]   = lshr i64 %[[val]], 40
     83     // CHECK-PPC64:   %[[and:.*]]   = and i64 %[[shr]], 3
     84     // CHECK-PPC64:   %[[trunc:.*]] = trunc i64 %[[and]] to i32
     85     // CHECK-PPC64:                   ret i32 %[[trunc]]
     86     return s->b21;
     87   }
     88   unsigned read30(S* s) {
     89     // CHECK-X86-64-LABEL: define i32 @_ZN2N06read30
     90     // CHECK-X86-64:   %[[ptr:.*]]   = bitcast %{{.*}}* %{{.*}} to i64*
     91     // CHECK-X86-64:   %[[val:.*]]   = load i64, i64* %[[ptr]]
     92     // CHECK-X86-64:   %[[shr:.*]]   = lshr i64 %[[val]], 24
     93     // CHECK-X86-64:   %[[and:.*]]   = and i64 %[[shr]], 1073741823
     94     // CHECK-X86-64:   %[[trunc:.*]] = trunc i64 %[[and]] to i32
     95     // CHECK-X86-64:                   ret i32 %[[trunc]]
     96     // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N06read30
     97     // CHECK-PPC64:   %[[ptr:.*]]   = bitcast %{{.*}}* %{{.*}} to i64*
     98     // CHECK-PPC64:   %[[val:.*]]   = load i64, i64* %[[ptr]]
     99     // CHECK-PPC64:   %[[shr:.*]]   = lshr i64 %[[val]], 10
    100     // CHECK-PPC64:   %[[and:.*]]   = and i64 %[[shr]], 1073741823
    101     // CHECK-PPC64:   %[[trunc:.*]] = trunc i64 %[[and]] to i32
    102     // CHECK-PPC64:                   ret i32 %[[trunc]]
    103     return s->b30;
    104   }
    105   unsigned read31(S* s) {
    106     // CHECK-X86-64-LABEL: define i32 @_ZN2N06read31
    107     // CHECK-X86-64:   %[[ptr:.*]]   = bitcast %{{.*}}* %{{.*}} to i64*
    108     // CHECK-X86-64:   %[[val:.*]]   = load i64, i64* %[[ptr]]
    109     // CHECK-X86-64:   %[[shr:.*]]   = lshr i64 %[[val]], 54
    110     // CHECK-X86-64:   %[[and:.*]]   = and i64 %[[shr]], 3
    111     // CHECK-X86-64:   %[[trunc:.*]] = trunc i64 %[[and]] to i32
    112     // CHECK-X86-64:                   ret i32 %[[trunc]]
    113     // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N06read31
    114     // CHECK-PPC64:   %[[ptr:.*]]   = bitcast %{{.*}}* %{{.*}} to i64*
    115     // CHECK-PPC64:   %[[val:.*]]   = load i64, i64* %[[ptr]]
    116     // CHECK-PPC64:   %[[shr:.*]]   = lshr i64 %[[val]], 8
    117     // CHECK-PPC64:   %[[and:.*]]   = and i64 %[[shr]], 3
    118     // CHECK-PPC64:   %[[trunc:.*]] = trunc i64 %[[and]] to i32
    119     // CHECK-PPC64:                   ret i32 %[[trunc]]
    120     return s->b31;
    121   }
    122   unsigned read70(S* s) {
    123     // CHECK-X86-64-LABEL: define i32 @_ZN2N06read70
    124     // CHECK-X86-64:   %[[ptr:.*]]   = bitcast %{{.*}}* %{{.*}} to i64*
    125     // CHECK-X86-64:   %[[val:.*]]   = load i64, i64* %[[ptr]]
    126     // CHECK-X86-64:   %[[shr:.*]]   = lshr i64 %[[val]], 56
    127     // CHECK-X86-64:   %[[and:.*]]   = and i64 %[[shr]], 63
    128     // CHECK-X86-64:   %[[trunc:.*]] = trunc i64 %[[and]] to i32
    129     // CHECK-X86-64:                   ret i32 %[[trunc]]
    130     // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N06read70
    131     // CHECK-PPC64:   %[[ptr:.*]]   = bitcast %{{.*}}* %{{.*}} to i64*
    132     // CHECK-PPC64:   %[[val:.*]]   = load i64, i64* %[[ptr]]
    133     // CHECK-PPC64:   %[[shr:.*]]   = lshr i64 %[[val]], 2
    134     // CHECK-PPC64:   %[[and:.*]]   = and i64 %[[shr]], 63
    135     // CHECK-PPC64:   %[[trunc:.*]] = trunc i64 %[[and]] to i32
    136     // CHECK-PPC64:                   ret i32 %[[trunc]]
    137     return s->b70;
    138   }
    139   unsigned read71(S* s) {
    140     // CHECK-X86-64-LABEL: define i32 @_ZN2N06read71
    141     // CHECK-X86-64:   %[[ptr:.*]]   = bitcast %{{.*}}* %{{.*}} to i64*
    142     // CHECK-X86-64:   %[[val:.*]]   = load i64, i64* %[[ptr]]
    143     // CHECK-X86-64:   %[[shr:.*]]   = lshr i64 %[[val]], 62
    144     // CHECK-X86-64:   %[[trunc:.*]] = trunc i64 %[[shr]] to i32
    145     // CHECK-X86-64:                   ret i32 %[[trunc]]
    146     // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N06read71
    147     // CHECK-PPC64:   %[[ptr:.*]]   = bitcast %{{.*}}* %{{.*}} to i64*
    148     // CHECK-PPC64:   %[[val:.*]]   = load i64, i64* %[[ptr]]
    149     // CHECK-PPC64:   %[[and:.*]]   = and i64 %[[val]], 3
    150     // CHECK-PPC64:   %[[trunc:.*]] = trunc i64 %[[and]] to i32
    151     // CHECK-PPC64:                   ret i32 %[[trunc]]
    152     return s->b71;
    153   }
    154 }
    155 
    156 namespace N1 {
    157   // Ensure that neither loads nor stores to bitfields are not widened into
    158   // other memory locations. (PR13691)
    159   //
    160   // NOTE: We could potentially widen loads based on their alignment if we are
    161   // comfortable requiring that subsequent memory locations within the
    162   // alignment-widened load are not volatile.
    163   struct S {
    164     char a;
    165     unsigned b : 1;
    166     char c;
    167   };
    168   unsigned read(S* s) {
    169     // CHECK-X86-64-LABEL: define i32 @_ZN2N14read
    170     // CHECK-X86-64:   %[[ptr:.*]] = getelementptr inbounds %{{.*}}, %{{.*}}* %{{.*}}, i32 0, i32 1
    171     // CHECK-X86-64:   %[[val:.*]] = load i8, i8* %[[ptr]]
    172     // CHECK-X86-64:   %[[and:.*]] = and i8 %[[val]], 1
    173     // CHECK-X86-64:   %[[ext:.*]] = zext i8 %[[and]] to i32
    174     // CHECK-X86-64:                 ret i32 %[[ext]]
    175     // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N14read
    176     // CHECK-PPC64:   %[[ptr:.*]] = getelementptr inbounds %{{.*}}, %{{.*}}* %{{.*}}, i32 0, i32 1
    177     // CHECK-PPC64:   %[[val:.*]] = load i8, i8* %[[ptr]]
    178     // CHECK-PPC64:   %[[shr:.*]] = lshr i8 %[[val]], 7
    179     // CHECK-PPC64:   %[[ext:.*]] = zext i8 %[[shr]] to i32
    180     // CHECK-PPC64:                 ret i32 %[[ext]]
    181     return s->b;
    182   }
    183   void write(S* s, unsigned x) {
    184     // CHECK-X86-64-LABEL: define void @_ZN2N15write
    185     // CHECK-X86-64:   %[[ptr:.*]]     = getelementptr inbounds %{{.*}}, %{{.*}}* %{{.*}}, i32 0, i32 1
    186     // CHECK-X86-64:   %[[x_trunc:.*]] = trunc i32 %{{.*}} to i8
    187     // CHECK-X86-64:   %[[old:.*]]     = load i8, i8* %[[ptr]]
    188     // CHECK-X86-64:   %[[x_and:.*]]   = and i8 %[[x_trunc]], 1
    189     // CHECK-X86-64:   %[[old_and:.*]] = and i8 %[[old]], -2
    190     // CHECK-X86-64:   %[[new:.*]]     = or i8 %[[old_and]], %[[x_and]]
    191     // CHECK-X86-64:                     store i8 %[[new]], i8* %[[ptr]]
    192     // CHECK-PPC64-LABEL: define void @_ZN2N15write
    193     // CHECK-PPC64:   %[[ptr:.*]]     = getelementptr inbounds %{{.*}}, %{{.*}}* %{{.*}}, i32 0, i32 1
    194     // CHECK-PPC64:   %[[x_trunc:.*]] = trunc i32 %{{.*}} to i8
    195     // CHECK-PPC64:   %[[old:.*]]     = load i8, i8* %[[ptr]]
    196     // CHECK-PPC64:   %[[x_and:.*]]   = and i8 %[[x_trunc]], 1
    197     // CHECK-PPC64:   %[[x_shl:.*]]   = shl i8 %[[x_and]], 7
    198     // CHECK-PPC64:   %[[old_and:.*]] = and i8 %[[old]], 127
    199     // CHECK-PPC64:   %[[new:.*]]     = or i8 %[[old_and]], %[[x_shl]]
    200     // CHECK-PPC64:                     store i8 %[[new]], i8* %[[ptr]]
    201     s->b = x;
    202   }
    203 }
    204 
    205 namespace N2 {
    206   // Do widen loads and stores to bitfields when those bitfields have padding
    207   // within the struct following them.
    208   struct S {
    209     unsigned b : 24;
    210     void *p;
    211   };
    212   unsigned read(S* s) {
    213     // CHECK-X86-64-LABEL: define i32 @_ZN2N24read
    214     // CHECK-X86-64:   %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i32*
    215     // CHECK-X86-64:   %[[val:.*]] = load i32, i32* %[[ptr]]
    216     // CHECK-X86-64:   %[[and:.*]] = and i32 %[[val]], 16777215
    217     // CHECK-X86-64:                 ret i32 %[[and]]
    218     // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N24read
    219     // CHECK-PPC64:   %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i32*
    220     // CHECK-PPC64:   %[[val:.*]] = load i32, i32* %[[ptr]]
    221     // CHECK-PPC64:   %[[shr:.*]] = lshr i32 %[[val]], 8
    222     // CHECK-PPC64:                 ret i32 %[[shr]]
    223     return s->b;
    224   }
    225   void write(S* s, unsigned x) {
    226     // CHECK-X86-64-LABEL: define void @_ZN2N25write
    227     // CHECK-X86-64:   %[[ptr:.*]]     = bitcast %{{.*}}* %{{.*}} to i32*
    228     // CHECK-X86-64:   %[[old:.*]]     = load i32, i32* %[[ptr]]
    229     // CHECK-X86-64:   %[[x_and:.*]]   = and i32 %{{.*}}, 16777215
    230     // CHECK-X86-64:   %[[old_and:.*]] = and i32 %[[old]], -16777216
    231     // CHECK-X86-64:   %[[new:.*]]     = or i32 %[[old_and]], %[[x_and]]
    232     // CHECK-X86-64:                     store i32 %[[new]], i32* %[[ptr]]
    233     // CHECK-PPC64-LABEL: define void @_ZN2N25write
    234     // CHECK-PPC64:   %[[ptr:.*]]     = bitcast %{{.*}}* %{{.*}} to i32*
    235     // CHECK-PPC64:   %[[old:.*]]     = load i32, i32* %[[ptr]]
    236     // CHECK-PPC64:   %[[x_and:.*]]   = and i32 %{{.*}}, 16777215
    237     // CHECK-PPC64:   %[[x_shl:.*]]   = shl i32 %[[x_and]], 8
    238     // CHECK-PPC64:   %[[old_and:.*]] = and i32 %[[old]], 255
    239     // CHECK-PPC64:   %[[new:.*]]     = or i32 %[[old_and]], %[[x_shl]]
    240     // CHECK-PPC64:                     store i32 %[[new]], i32* %[[ptr]]
    241     s->b = x;
    242   }
    243 }
    244 
    245 namespace N3 {
    246   // Do widen loads and stores to bitfields through the trailing padding at the
    247   // end of a struct.
    248   struct S {
    249     unsigned b : 24;
    250   };
    251   unsigned read(S* s) {
    252     // CHECK-X86-64-LABEL: define i32 @_ZN2N34read
    253     // CHECK-X86-64:   %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i32*
    254     // CHECK-X86-64:   %[[val:.*]] = load i32, i32* %[[ptr]]
    255     // CHECK-X86-64:   %[[and:.*]] = and i32 %[[val]], 16777215
    256     // CHECK-X86-64:                 ret i32 %[[and]]
    257     // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N34read
    258     // CHECK-PPC64:   %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i32*
    259     // CHECK-PPC64:   %[[val:.*]] = load i32, i32* %[[ptr]]
    260     // CHECK-PPC64:   %[[shr:.*]] = lshr i32 %[[val]], 8
    261     // CHECK-PPC64:                 ret i32 %[[shr]]
    262     return s->b;
    263   }
    264   void write(S* s, unsigned x) {
    265     // CHECK-X86-64-LABEL: define void @_ZN2N35write
    266     // CHECK-X86-64:   %[[ptr:.*]]     = bitcast %{{.*}}* %{{.*}} to i32*
    267     // CHECK-X86-64:   %[[old:.*]]     = load i32, i32* %[[ptr]]
    268     // CHECK-X86-64:   %[[x_and:.*]]   = and i32 %{{.*}}, 16777215
    269     // CHECK-X86-64:   %[[old_and:.*]] = and i32 %[[old]], -16777216
    270     // CHECK-X86-64:   %[[new:.*]]     = or i32 %[[old_and]], %[[x_and]]
    271     // CHECK-X86-64:                     store i32 %[[new]], i32* %[[ptr]]
    272     // CHECK-PPC64-LABEL: define void @_ZN2N35write
    273     // CHECK-PPC64:   %[[ptr:.*]]     = bitcast %{{.*}}* %{{.*}} to i32*
    274     // CHECK-PPC64:   %[[old:.*]]     = load i32, i32* %[[ptr]]
    275     // CHECK-PPC64:   %[[x_and:.*]]   = and i32 %{{.*}}, 16777215
    276     // CHECK-PPC64:   %[[x_shl:.*]]   = shl i32 %[[x_and]], 8
    277     // CHECK-PPC64:   %[[old_and:.*]] = and i32 %[[old]], 255
    278     // CHECK-PPC64:   %[[new:.*]]     = or i32 %[[old_and]], %[[x_shl]]
    279     // CHECK-PPC64:                     store i32 %[[new]], i32* %[[ptr]]
    280     s->b = x;
    281   }
    282 }
    283 
    284 namespace N4 {
    285   // Do NOT widen loads and stores to bitfields into padding at the end of
    286   // a class which might end up with members inside of it when inside a derived
    287   // class.
    288   struct Base {
    289     virtual ~Base() {}
    290 
    291     unsigned b : 24;
    292   };
    293   // Imagine some other translation unit introduces:
    294 #if 0
    295   struct Derived : public Base {
    296     char c;
    297   };
    298 #endif
    299   unsigned read(Base* s) {
    300     // FIXME: We should widen this load as long as the function isn't being
    301     // instrumented by ThreadSanitizer.
    302     //
    303     // CHECK-X86-64-LABEL: define i32 @_ZN2N44read
    304     // CHECK-X86-64:   %[[gep:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %{{.*}}, i32 0, i32 1
    305     // CHECK-X86-64:   %[[ptr:.*]] = bitcast [3 x i8]* %[[gep]] to i24*
    306     // CHECK-X86-64:   %[[val:.*]] = load i24, i24* %[[ptr]]
    307     // CHECK-X86-64:   %[[ext:.*]] = zext i24 %[[val]] to i32
    308     // CHECK-X86-64:                 ret i32 %[[ext]]
    309     // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N44read
    310     // CHECK-PPC64:   %[[gep:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %{{.*}}, i32 0, i32 1
    311     // CHECK-PPC64:   %[[ptr:.*]] = bitcast [3 x i8]* %[[gep]] to i24*
    312     // CHECK-PPC64:   %[[val:.*]] = load i24, i24* %[[ptr]]
    313     // CHECK-PPC64:   %[[ext:.*]] = zext i24 %[[val]] to i32
    314     // CHECK-PPC64:                 ret i32 %[[ext]]
    315     return s->b;
    316   }
    317   void write(Base* s, unsigned x) {
    318     // CHECK-X86-64-LABEL: define void @_ZN2N45write
    319     // CHECK-X86-64:   %[[gep:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %{{.*}}, i32 0, i32 1
    320     // CHECK-X86-64:   %[[ptr:.*]] = bitcast [3 x i8]* %[[gep]] to i24*
    321     // CHECK-X86-64:   %[[new:.*]] = trunc i32 %{{.*}} to i24
    322     // CHECK-X86-64:                 store i24 %[[new]], i24* %[[ptr]]
    323     // CHECK-PPC64-LABEL: define void @_ZN2N45write
    324     // CHECK-PPC64:   %[[gep:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %{{.*}}, i32 0, i32 1
    325     // CHECK-PPC64:   %[[ptr:.*]] = bitcast [3 x i8]* %[[gep]] to i24*
    326     // CHECK-PPC64:   %[[new:.*]] = trunc i32 %{{.*}} to i24
    327     // CHECK-PPC64:                 store i24 %[[new]], i24* %[[ptr]]
    328     s->b = x;
    329   }
    330 }
    331 
    332 namespace N5 {
    333   // Widen through padding at the end of a struct even if that struct
    334   // participates in a union with another struct which has a separate field in
    335   // that location. The reasoning is that if the operation is storing to that
    336   // member of the union, it must be the active member, and thus we can write
    337   // through the padding. If it is a load, it might be a load of a common
    338   // prefix through a non-active member, but in such a case the extra bits
    339   // loaded are masked off anyways.
    340   union U {
    341     struct X { unsigned b : 24; char c; } x;
    342     struct Y { unsigned b : 24; } y;
    343   };
    344   unsigned read(U* u) {
    345     // CHECK-X86-64-LABEL: define i32 @_ZN2N54read
    346     // CHECK-X86-64:   %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i32*
    347     // CHECK-X86-64:   %[[val:.*]] = load i32, i32* %[[ptr]]
    348     // CHECK-X86-64:   %[[and:.*]] = and i32 %[[val]], 16777215
    349     // CHECK-X86-64:                 ret i32 %[[and]]
    350     // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N54read
    351     // CHECK-PPC64:   %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i32*
    352     // CHECK-PPC64:   %[[val:.*]] = load i32, i32* %[[ptr]]
    353     // CHECK-PPC64:   %[[shr:.*]] = lshr i32 %[[val]], 8
    354     // CHECK-PPC64:                 ret i32 %[[shr]]
    355     return u->y.b;
    356   }
    357   void write(U* u, unsigned x) {
    358     // CHECK-X86-64-LABEL: define void @_ZN2N55write
    359     // CHECK-X86-64:   %[[ptr:.*]]     = bitcast %{{.*}}* %{{.*}} to i32*
    360     // CHECK-X86-64:   %[[old:.*]]     = load i32, i32* %[[ptr]]
    361     // CHECK-X86-64:   %[[x_and:.*]]   = and i32 %{{.*}}, 16777215
    362     // CHECK-X86-64:   %[[old_and:.*]] = and i32 %[[old]], -16777216
    363     // CHECK-X86-64:   %[[new:.*]]     = or i32 %[[old_and]], %[[x_and]]
    364     // CHECK-X86-64:                     store i32 %[[new]], i32* %[[ptr]]
    365     // CHECK-PPC64-LABEL: define void @_ZN2N55write
    366     // CHECK-PPC64:   %[[ptr:.*]]     = bitcast %{{.*}}* %{{.*}} to i32*
    367     // CHECK-PPC64:   %[[old:.*]]     = load i32, i32* %[[ptr]]
    368     // CHECK-PPC64:   %[[x_and:.*]]   = and i32 %{{.*}}, 16777215
    369     // CHECK-PPC64:   %[[x_shl:.*]]   = shl i32 %[[x_and]], 8
    370     // CHECK-PPC64:   %[[old_and:.*]] = and i32 %[[old]], 255
    371     // CHECK-PPC64:   %[[new:.*]]     = or i32 %[[old_and]], %[[x_shl]]
    372     // CHECK-PPC64:                     store i32 %[[new]], i32* %[[ptr]]
    373     u->y.b = x;
    374   }
    375 }
    376 
    377 namespace N6 {
    378   // Zero-length bitfields partition the memory locations of bitfields for the
    379   // purposes of the memory model. That means stores must not span zero-length
    380   // bitfields and loads may only span them when we are not instrumenting with
    381   // ThreadSanitizer.
    382   // FIXME: We currently don't widen loads even without ThreadSanitizer, even
    383   // though we could.
    384   struct S {
    385     unsigned b1 : 24;
    386     unsigned char : 0;
    387     unsigned char b2 : 8;
    388   };
    389   unsigned read(S* s) {
    390     // CHECK-X86-64-LABEL: define i32 @_ZN2N64read
    391     // CHECK-X86-64:   %[[ptr1:.*]] = bitcast {{.*}}* %{{.*}} to i24*
    392     // CHECK-X86-64:   %[[val1:.*]] = load i24, i24* %[[ptr1]]
    393     // CHECK-X86-64:   %[[ext1:.*]] = zext i24 %[[val1]] to i32
    394     // CHECK-X86-64:   %[[ptr2:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %{{.*}}, i32 0, i32 1
    395     // CHECK-X86-64:   %[[val2:.*]] = load i8, i8* %[[ptr2]]
    396     // CHECK-X86-64:   %[[ext2:.*]] = zext i8 %[[val2]] to i32
    397     // CHECK-X86-64:   %[[add:.*]]  = add nsw i32 %[[ext1]], %[[ext2]]
    398     // CHECK-X86-64:                  ret i32 %[[add]]
    399     // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N64read
    400     // CHECK-PPC64:   %[[ptr1:.*]] = bitcast {{.*}}* %{{.*}} to i24*
    401     // CHECK-PPC64:   %[[val1:.*]] = load i24, i24* %[[ptr1]]
    402     // CHECK-PPC64:   %[[ext1:.*]] = zext i24 %[[val1]] to i32
    403     // CHECK-PPC64:   %[[ptr2:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %{{.*}}, i32 0, i32 1
    404     // CHECK-PPC64:   %[[val2:.*]] = load i8, i8* %[[ptr2]]
    405     // CHECK-PPC64:   %[[ext2:.*]] = zext i8 %[[val2]] to i32
    406     // CHECK-PPC64:   %[[add:.*]]  = add nsw i32 %[[ext1]], %[[ext2]]
    407     // CHECK-PPC64:                  ret i32 %[[add]]
    408     return s->b1 + s->b2;
    409   }
    410   void write(S* s, unsigned x) {
    411     // CHECK-X86-64-LABEL: define void @_ZN2N65write
    412     // CHECK-X86-64:   %[[ptr1:.*]] = bitcast {{.*}}* %{{.*}} to i24*
    413     // CHECK-X86-64:   %[[new1:.*]] = trunc i32 %{{.*}} to i24
    414     // CHECK-X86-64:                  store i24 %[[new1]], i24* %[[ptr1]]
    415     // CHECK-X86-64:   %[[new2:.*]] = trunc i32 %{{.*}} to i8
    416     // CHECK-X86-64:   %[[ptr2:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %{{.*}}, i32 0, i32 1
    417     // CHECK-X86-64:                  store i8 %[[new2]], i8* %[[ptr2]]
    418     // CHECK-PPC64-LABEL: define void @_ZN2N65write
    419     // CHECK-PPC64:   %[[ptr1:.*]] = bitcast {{.*}}* %{{.*}} to i24*
    420     // CHECK-PPC64:   %[[new1:.*]] = trunc i32 %{{.*}} to i24
    421     // CHECK-PPC64:                  store i24 %[[new1]], i24* %[[ptr1]]
    422     // CHECK-PPC64:   %[[new2:.*]] = trunc i32 %{{.*}} to i8
    423     // CHECK-PPC64:   %[[ptr2:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %{{.*}}, i32 0, i32 1
    424     // CHECK-PPC64:                  store i8 %[[new2]], i8* %[[ptr2]]
    425     s->b1 = x;
    426     s->b2 = x;
    427   }
    428 }
    429 
    430 namespace N7 {
    431   // Similar to N4 except that this adds a virtual base to the picture. (PR18430)
    432   // Do NOT widen loads and stores to bitfields into padding at the end of
    433   // a class which might end up with members inside of it when inside a derived
    434   // class.
    435   struct B1 {
    436     virtual void f();
    437     unsigned b1 : 24;
    438   };
    439   struct B2 : virtual B1 {
    440     virtual ~B2();
    441     unsigned b : 24;
    442   };
    443   // Imagine some other translation unit introduces:
    444 #if 0
    445   struct Derived : public B2 {
    446     char c;
    447   };
    448 #endif
    449   unsigned read(B2* s) {
    450     // FIXME: We should widen this load as long as the function isn't being
    451     // instrumented by ThreadSanitizer.
    452     //
    453     // CHECK-X86-64-LABEL: define i32 @_ZN2N74read
    454     // CHECK-X86-64:   %[[gep:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %{{.*}}, i32 0, i32 1
    455     // CHECK-X86-64:   %[[ptr:.*]] = bitcast [3 x i8]* %[[gep]] to i24*
    456     // CHECK-X86-64:   %[[val:.*]] = load i24, i24* %[[ptr]]
    457     // CHECK-X86-64:   %[[ext:.*]] = zext i24 %[[val]] to i32
    458     // CHECK-X86-64:                 ret i32 %[[ext]]
    459     // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N74read
    460     // CHECK-PPC64:   %[[gep:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %{{.*}}, i32 0, i32 1
    461     // CHECK-PPC64:   %[[ptr:.*]] = bitcast [3 x i8]* %[[gep]] to i24*
    462     // CHECK-PPC64:   %[[val:.*]] = load i24, i24* %[[ptr]]
    463     // CHECK-PPC64:   %[[ext:.*]] = zext i24 %[[val]] to i32
    464     // CHECK-PPC64:                 ret i32 %[[ext]]
    465     return s->b;
    466   }
    467   void write(B2* s, unsigned x) {
    468     // CHECK-X86-64-LABEL: define void @_ZN2N75write
    469     // CHECK-X86-64:   %[[gep:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %{{.*}}, i32 0, i32 1
    470     // CHECK-X86-64:   %[[ptr:.*]] = bitcast [3 x i8]* %[[gep]] to i24*
    471     // CHECK-X86-64:   %[[new:.*]] = trunc i32 %{{.*}} to i24
    472     // CHECK-X86-64:                 store i24 %[[new]], i24* %[[ptr]]
    473     // CHECK-PPC64-LABEL: define void @_ZN2N75write
    474     // CHECK-PPC64:   %[[gep:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %{{.*}}, i32 0, i32 1
    475     // CHECK-PPC64:   %[[ptr:.*]] = bitcast [3 x i8]* %[[gep]] to i24*
    476     // CHECK-PPC64:   %[[new:.*]] = trunc i32 %{{.*}} to i24
    477     // CHECK-PPC64:                 store i24 %[[new]], i24* %[[ptr]]
    478     s->b = x;
    479   }
    480 }
    481