1 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s
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
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:.+]]
23 // 'True', branch set the BF, branch to 'end'.
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:.+]]
34 // 'False', branch set the OTHER BF, branch to 'end'.
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:.+]]
47 // There is nothing in the 'end' block associated with this, but it is the
48 // 'continuation' block for the rest of the function.
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:.+]]
57 // 'True', branch set the BF, branch to 'end'.
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:.+]]
68 // 'False', branch set the OTHER BF, branch to 'end'.
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:.+]]
82 // There is nothing in the 'end' block associated with this, but it is the
83 // 'continuation' block for the rest of the function.
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
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:.+]]
103 // First 'True' branch, sets field1 to val1.
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:.+]]
114 // First 'False' branch, starts second ignored expression.
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:.+]]
120 // Second 'True' branch, sets field2 to val2.
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:.+]]
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:.+]]
146 // Nothing left to do here.
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