xref: /llvm-project/clang/test/CodeGenCXX/ignored-bitfield-conditional.cpp (revision cd50f910f4d1a6bb54fd8968f067febbc7320f28)
1 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s
2 
3 struct S {
4   int field1 : 5;
5   int field2 : 6;
6   int field3 : 3;
7 };
8 
use(bool cond,struct S s1,struct S s2,int val1,int val2)9 void use(bool cond, struct S s1, struct S s2, int val1, int val2) {
10   // CHECK-LABEL: define {{.*}}use{{.*}}(
11   // CHECK: %[[S1:.+]] = alloca %struct.S
12   // CHECK: %[[S2:.+]] = alloca %struct.S
13   // CHECK: %[[COND:.+]] = alloca i8
14   // CHECK: %[[VAL1:.+]] = alloca i32
15   // CHECK: %[[VAL2:.+]] = alloca i32
16 
17   cond ? s1.field1 = val1 : s1.field2 = val2;
18   // Condition setup, branch.
19   // CHECK: %[[CONDLD:.+]] = load i8, ptr %[[COND]]
20   // CHECK: %[[TO_BOOL:.+]] = trunc i8 %[[CONDLD]] to i1
21   // CHECK: br i1 %[[TO_BOOL]], label %[[TRUE:.+]], label %[[FALSE:.+]]
22 
23   // 'True', branch set the BF, branch to 'end'.
24   // CHECK: [[TRUE]]:
25   // CHECK: %[[VAL1LD:.+]] = load i32, ptr %[[VAL1]]
26   // CHECK: %[[VAL1TRUNC:.+]] = trunc i32 %[[VAL1LD]] to i16
27   // CHECK: %[[BF_LOAD:.+]] = load i16, ptr %[[S1]]
28   // CHECK: %[[BF_VAL:.+]] = and i16 %[[VAL1TRUNC]], 31
29   // CHECK: %[[BF_CLEAR:.+]] = and i16 %[[BF_LOAD]], -32
30   // CHECK: %[[BF_SET:.+]] = or i16 %[[BF_CLEAR]], %[[BF_VAL]]
31   // CHECK: store i16 %[[BF_SET]], ptr %[[S1]]
32   // CHECK: br label %[[END:.+]]
33 
34   // 'False', branch set the OTHER BF, branch to 'end'.
35   // CHECK: [[FALSE]]:
36   // CHECK: %[[VAL2LD:.+]] = load i32, ptr %[[VAL2]]
37   // CHECK: %[[VAL2TRUNC:.+]] = trunc i32 %[[VAL2LD]] to i16
38   // CHECK: %[[BF_LOAD:.+]] = load i16, ptr %[[S1]]
39   // CHECK: %[[BF_VAL:.+]] = and i16 %[[VAL2TRUNC]], 63
40   // CHECK: %[[BF_SHIFT:.+]] = shl i16 %[[BF_VAL]], 5
41   // CHECK: %[[BF_CLEAR:.+]] = and i16 %[[BF_LOAD]], -2017
42   // CHECK: %[[BF_SET:.+]] = or i16 %[[BF_CLEAR]], %[[BF_SHIFT]]
43   // CHECK: store i16 %[[BF_SET]], ptr %[[S1]]
44   // CHECK: br label %[[END:.+]]
45 
46   // CHECK: [[END]]:
47   // There is nothing in the 'end' block associated with this, but it is the
48   // 'continuation' block for the rest of the function.
49 
50   // Same test, has a no-op cast and parens.
51   (void)(cond ? s2.field1 = val1 : s2.field2 = val2);
52   // Condition setup, branch.
53   // CHECK: %[[CONDLD:.+]] = load i8, ptr %[[COND]]
54   // CHECK: %[[TO_BOOL:.+]] = trunc i8 %[[CONDLD]] to i1
55   // CHECK: br i1 %[[TO_BOOL]], label %[[TRUE:.+]], label %[[FALSE:.+]]
56 
57   // 'True', branch set the BF, branch to 'end'.
58   // CHECK: [[TRUE]]:
59   // CHECK: %[[VAL1LD:.+]] = load i32, ptr %[[VAL1]]
60   // CHECK: %[[VAL1TRUNC:.+]] = trunc i32 %[[VAL1LD]] to i16
61   // CHECK: %[[BF_LOAD:.+]] = load i16, ptr %[[S2]]
62   // CHECK: %[[BF_VAL:.+]] = and i16 %[[VAL1TRUNC]], 31
63   // CHECK: %[[BF_CLEAR:.+]] = and i16 %[[BF_LOAD]], -32
64   // CHECK: %[[BF_SET:.+]] = or i16 %[[BF_CLEAR]], %[[BF_VAL]]
65   // CHECK: store i16 %[[BF_SET]], ptr %[[S2]]
66   // CHECK: br label %[[END:.+]]
67 
68   // 'False', branch set the OTHER BF, branch to 'end'.
69   // CHECK: [[FALSE]]:
70   // CHECK: %[[VAL2LD:.+]] = load i32, ptr %[[VAL2]]
71   // CHECK: %[[VAL2TRUNC:.+]] = trunc i32 %[[VAL2LD]] to i16
72   // CHECK: %[[BF_LOAD:.+]] = load i16, ptr %[[S2]]
73   // CHECK: %[[BF_VAL:.+]] = and i16 %[[VAL2TRUNC]], 63
74   // CHECK: %[[BF_SHIFT:.+]] = shl i16 %[[BF_VAL]], 5
75   // CHECK: %[[BF_CLEAR:.+]] = and i16 %[[BF_LOAD]], -2017
76   // CHECK: %[[BF_SET:.+]] = or i16 %[[BF_CLEAR]], %[[BF_SHIFT]]
77   // CHECK: store i16 %[[BF_SET]], ptr %[[S2]]
78   // CHECK: br label %[[END:.+]]
79 
80   // CHECK: [[END]]:
81   // CHECK-NOT: phi
82   // There is nothing in the 'end' block associated with this, but it is the
83   // 'continuation' block for the rest of the function.
84 
85 }
86 
87 
use2(bool cond1,bool cond2,struct S s1,int val1,int val2,int val3)88 void use2(bool cond1, bool cond2, struct S s1, int val1, int val2, int val3) {
89   // CHECK-LABEL: define {{.*}}use2{{.*}}(
90   // CHECK: %[[S1:.+]] = alloca %struct.S
91   // CHECK: %[[COND1:.+]] = alloca i8
92   // CHECK: %[[COND2:.+]] = alloca i8
93   // CHECK: %[[VAL1:.+]] = alloca i32
94   // CHECK: %[[VAL2:.+]] = alloca i32
95   // CHECK: %[[VAL3:.+]] = alloca i32
96 
97   cond1 ? s1.field1 = val1 : cond2 ? s1.field2 = val2 : s1.field3 = val3;
98   // First Condition setup, branch.
99   // CHECK: %[[CONDLD:.+]] = load i8, ptr %[[COND1]]
100   // CHECK: %[[TO_BOOL:.+]] = trunc i8 %[[CONDLD]] to i1
101   // CHECK: br i1 %[[TO_BOOL]], label %[[TRUE:.+]], label %[[FALSE:.+]]
102 
103   // First 'True' branch, sets field1 to val1.
104   // CHECK: [[TRUE]]:
105   // CHECK: %[[VAL1LD:.+]] = load i32, ptr %[[VAL1]]
106   // CHECK: %[[VAL1TRUNC:.+]] = trunc i32 %[[VAL1LD]] to i16
107   // CHECK: %[[BF_LOAD:.+]] = load i16, ptr %[[S1]]
108   // CHECK: %[[BF_VAL:.+]] = and i16 %[[VAL1TRUNC]], 31
109   // CHECK: %[[BF_CLEAR:.+]] = and i16 %[[BF_LOAD]], -32
110   // CHECK: %[[BF_SET:.+]] = or i16 %[[BF_CLEAR]], %[[BF_VAL]]
111   // CHECK: store i16 %[[BF_SET]], ptr %[[S1]]
112   // CHECK: br label %[[END:.+]]
113 
114   // First 'False' branch, starts second ignored expression.
115   // CHECK: [[FALSE]]:
116   // CHECK: %[[CONDLD:.+]] = load i8, ptr %[[COND2]]
117   // CHECK: %[[TO_BOOL:.+]] = trunc i8 %[[CONDLD]] to i1
118   // CHECK: br i1 %[[TO_BOOL]], label %[[TRUE2:.+]], label %[[FALSE2:.+]]
119 
120   // Second 'True' branch, sets field2 to val2.
121   // CHECK: [[TRUE2]]:
122   // CHECK: %[[VAL2LD:.+]] = load i32, ptr %[[VAL2]]
123   // CHECK: %[[VAL2TRUNC:.+]] = trunc i32 %[[VAL2LD]] to i16
124   // CHECK: %[[BF_LOAD:.+]] = load i16, ptr %[[S1]]
125   // CHECK: %[[BF_VAL:.+]] = and i16 %[[VAL2TRUNC]], 63
126   // CHECK: %[[BF_SHIFT:.+]] = shl i16 %[[BF_VAL]], 5
127   // CHECK: %[[BF_CLEAR:.+]] = and i16 %[[BF_LOAD]], -2017
128   // CHECK: %[[BF_SET:.+]] = or i16 %[[BF_CLEAR]], %[[BF_SHIFT]]
129   // CHECK: store i16 %[[BF_SET]], ptr %[[S1]]
130   // CHECK: br label %[[END:.+]]
131 
132   // Second 'False' branch, sets field3 to val3.
133   // CHECK: [[FALSE2]]:
134   // CHECK: %[[VAL3LD:.+]] = load i32, ptr %[[VAL3]]
135   // CHECK: %[[VAL3TRUNC:.+]] = trunc i32 %[[VAL3LD]] to i16
136   // CHECK: %[[BF_LOAD:.+]] = load i16, ptr %[[S1]]
137   // CHECK: %[[BF_VAL:.+]] = and i16 %[[VAL3TRUNC]], 7
138   // CHECK: %[[BF_SHIFT:.+]] = shl i16 %[[BF_VAL]], 11
139   // CHECK: %[[BF_CLEAR:.+]] = and i16 %[[BF_LOAD]], -14337
140   // CHECK: %[[BF_SET:.+]] = or i16 %[[BF_CLEAR]], %[[BF_SHIFT]]
141   // CHECK: store i16 %[[BF_SET]], ptr %[[S1]]
142   // CHECK: br label %[[END:.+]]
143 
144   // CHECK: [[END]]:
145   // CHECK-NOT: phi
146   // Nothing left to do here.
147 }
148 
149 // Catch the end of the IR. This prevents the CHECK-NOT above from matching a
150 // spurious "phi" in file paths printed in the output.
151 // CHECK-LABEL: attributes
152