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