1; Tests various aspects of i1 related lowering.
2
3; RUN: %if --need=target_X8632 --command %p2i --filetype=obj --disassemble \
4; RUN:   --target x8632 -i %s --args -O2 \
5; RUN:   | %if --need=target_X8632 --command FileCheck %s
6
7; RUN: %if --need=target_X8632 --command %p2i --filetype=obj --disassemble \
8; RUN:   --target x8632 -i %s --args -Om1 \
9; RUN:   | %if --need=target_X8632 --command FileCheck %s
10
11; TODO(jpp): Switch to --filetype=obj when possible.
12; RUN: %if --need=target_ARM32 --need=allow_dump \
13; RUN:   --command %p2i --filetype=asm --assemble \
14; RUN:   --disassemble --target arm32 -i %s --args -O2 \
15; RUN:   | %if --need=target_ARM32 --need=allow_dump \
16; RUN:   --command FileCheck --check-prefix ARM32 %s
17
18; RUN: %if --need=target_MIPS32 --need=allow_dump \
19; RUN:   --command %p2i --filetype=asm --assemble --disassemble --target \
20; RUN:   mips32 -i %s --args -O2 -allow-externally-defined-symbols \
21; RUN:   | %if --need=target_MIPS32 --need=allow_dump \
22; RUN:   --command FileCheck --check-prefix MIPS32 %s
23
24; Test that and with true uses immediate 1, not -1.
25define internal i32 @testAndTrue(i32 %arg) {
26entry:
27  %arg_i1 = trunc i32 %arg to i1
28  %result_i1 = and i1 %arg_i1, true
29  %result = zext i1 %result_i1 to i32
30  ret i32 %result
31}
32; CHECK-LABEL: testAndTrue
33; CHECK: and {{.*}},0x1
34; ARM32-LABEL: testAndTrue
35; ARM32: and {{.*}}, #1
36; MIPS32-LABEL: testAndTrue
37; MIPS32: 	andi	{{.*}},0x1
38
39; Test that or with true uses immediate 1, not -1.
40define internal i32 @testOrTrue(i32 %arg) {
41entry:
42  %arg_i1 = trunc i32 %arg to i1
43  %result_i1 = or i1 %arg_i1, true
44  %result = zext i1 %result_i1 to i32
45  ret i32 %result
46}
47; CHECK-LABEL: testOrTrue
48; CHECK: or {{.*}},0x1
49; ARM32-LABEL: testOrTrue
50; ARM32: orr {{.*}}, #1
51; MIPS32-LABEL: testOrTrue
52; MIPS32: 	ori	{{.*}},0x1
53
54; Test that xor with true uses immediate 1, not -1.
55define internal i32 @testXorTrue(i32 %arg) {
56entry:
57  %arg_i1 = trunc i32 %arg to i1
58  %result_i1 = xor i1 %arg_i1, true
59  %result = zext i1 %result_i1 to i32
60  ret i32 %result
61}
62; CHECK-LABEL: testXorTrue
63; CHECK: xor {{.*}},0x1
64; ARM32-LABEL: testXorTrue
65; ARM32: eor {{.*}}, #1
66; MIPS32-LABEL: testXorTrue
67; MIPS32: 	xori	{{.*}},0x1
68
69; Test that trunc to i1 masks correctly.
70define internal i32 @testTrunc(i32 %arg) {
71entry:
72  %arg_i1 = trunc i32 %arg to i1
73  %result = zext i1 %arg_i1 to i32
74  ret i32 %result
75}
76; CHECK-LABEL: testTrunc
77; CHECK: and {{.*}},0x1
78; ARM32-LABEL: testTrunc
79; ARM32: and {{.*}}, #1
80; MIPS32-LABEL: testTrunc
81; MIPS32: 	andi	{{.*}},0x1
82
83; Test zext to i8.
84define internal i32 @testZextI8(i32 %arg) {
85entry:
86  %arg_i1 = trunc i32 %arg to i1
87  %result_i8 = zext i1 %arg_i1 to i8
88  %result = zext i8 %result_i8 to i32
89  ret i32 %result
90}
91; CHECK-LABEL: testZextI8
92; match the trunc instruction
93; CHECK: and {{.*}},0x1
94; match the zext i1 instruction (NOTE: no mov need between i1 and i8).
95; CHECK-NOT: and {{.*}},0x1
96; ARM32-LABEL: testZextI8
97; ARM32: {{.*}}, #1
98; ARM32: uxtb
99; MIPS32-LABEL: testZextI8
100; MIPS32: 	andi	{{.*}},0x1
101; MIPS32: 	andi	{{.*}},0xff
102
103; Test zext to i16.
104define internal i32 @testZextI16(i32 %arg) {
105entry:
106  %arg_i1 = trunc i32 %arg to i1
107  %result_i16 = zext i1 %arg_i1 to i16
108  %result = zext i16 %result_i16 to i32
109  ret i32 %result
110}
111; CHECK-LABEL: testZextI16
112; match the trunc instruction
113; CHECK: and {{.*}},0x1
114; match the zext i1 instruction (note 32-bit reg is used because it's shorter).
115; CHECK: movzx [[REG:e.*]],{{[a-d]l|BYTE PTR}}
116; CHECK-NOT: and [[REG]],0x1
117
118; ARM32-LABEL: testZextI16
119; ARM32: and {{.*}}, #1
120; ARM32: uxth
121
122; MIPS32-LABEL: testZextI16
123; MIPS32: 	andi	{{.*}},0x1
124; MIPS32: 	andi	{{.*}},0xffff
125
126; Test zext to i32.
127define internal i32 @testZextI32(i32 %arg) {
128entry:
129  %arg_i1 = trunc i32 %arg to i1
130  %result_i32 = zext i1 %arg_i1 to i32
131  ret i32 %result_i32
132}
133; CHECK-LABEL: testZextI32
134; match the trunc instruction
135; CHECK: and {{.*}},0x1
136; match the zext i1 instruction
137; CHECK: movzx
138; CHECK-NOT: and {{.*}},0x1
139; ARM32-LABEL: testZextI32
140; ARM32: and {{.*}}, #1
141; MIPS32-LABEL: testZextI32
142; MIPS32: 	andi	{{.*}},0x1
143
144; Test zext to i64.
145define internal i64 @testZextI64(i32 %arg) {
146entry:
147  %arg_i1 = trunc i32 %arg to i1
148  %result_i64 = zext i1 %arg_i1 to i64
149  ret i64 %result_i64
150}
151; CHECK-LABEL: testZextI64
152; match the trunc instruction
153; CHECK: and {{.*}},0x1
154; match the zext i1 instruction
155; CHECK: movzx
156; CHECK: mov {{.*}},0x0
157; ARM32-LABEL: testZextI64
158; ARM32: and {{.*}}, #1
159; ARM32: mov {{.*}}, #0
160; MIPS32-LABEL: testZextI64
161; MIPS32: 	andi	{{.*}},0x1
162; MIPS32: 	li	{{.*}},0
163; MIPS32: 	move
164; MIPS32: 	move
165
166; Test sext to i8.
167define internal i32 @testSextI8(i32 %arg) {
168entry:
169  %arg_i1 = trunc i32 %arg to i1
170  %result_i8 = sext i1 %arg_i1 to i8
171  %result = sext i8 %result_i8 to i32
172  ret i32 %result
173}
174; CHECK-LABEL: testSextI8
175; match the trunc instruction
176; CHECK: and {{.*}},0x1
177; match the sext i1 instruction
178; CHECK: shl [[REG:.*]],0x7
179; CHECK-NEXT: sar [[REG]],0x7
180;
181; ARM32-LABEL: testSextI8
182; ARM32: mov {{.*}}, #0
183; ARM32: tst {{.*}}, #1
184; ARM32: mvn {{.*}}, #0
185; ARM32: movne
186; ARM32: sxtb
187;
188; MIPS32-LABEL: testSextI8
189; MIPS32: 	sll	{{.*}},0x1f
190; MIPS32: 	sra	{{.*}},0x1f
191; MIPS32: 	sll	{{.*}},0x18
192; MIPS32: 	sra	{{.*}},0x18
193
194; Test sext to i16.
195define internal i32 @testSextI16(i32 %arg) {
196entry:
197  %arg_i1 = trunc i32 %arg to i1
198  %result_i16 = sext i1 %arg_i1 to i16
199  %result = sext i16 %result_i16 to i32
200  ret i32 %result
201}
202; CHECK-LABEL: testSextI16
203; match the trunc instruction
204; CHECK: and {{.*}},0x1
205; match the sext i1 instruction
206; CHECK: movzx {{e*}}[[REG:.*]],{{[a-d]l|BYTE PTR}}
207; CHECK-NEXT: shl [[REG]],0xf
208; CHECK-NEXT: sar [[REG]],0xf
209
210; ARM32-LABEL: testSextI16
211; ARM32: mov {{.*}}, #0
212; ARM32: tst {{.*}}, #1
213; ARM32: mvn {{.*}}, #0
214; ARM32: movne
215; ARM32: sxth
216
217; MIPS32-LABEL: testSextI16
218; MIPS32: 	sll	{{.*}},0x1f
219; MIPS32: 	sra	{{.*}},0x1f
220; MIPS32: 	sll	{{.*}},0x10
221; MIPS32: 	sra	{{.*}},0x10
222
223; Test sext to i32.
224define internal i32 @testSextI32(i32 %arg) {
225entry:
226  %arg_i1 = trunc i32 %arg to i1
227  %result_i32 = sext i1 %arg_i1 to i32
228  ret i32 %result_i32
229}
230; CHECK-LABEL: testSextI32
231; match the trunc instruction
232; CHECK: and {{.*}},0x1
233; match the sext i1 instruction
234; CHECK: movzx [[REG:.*]],
235; CHECK-NEXT: shl [[REG]],0x1f
236; CHECK-NEXT: sar [[REG]],0x1f
237
238; ARM32-LABEL: testSextI32
239; ARM32: mov {{.*}}, #0
240; ARM32: tst {{.*}}, #1
241; ARM32: mvn {{.*}}, #0
242; ARM32: movne
243
244; MIPS32-LABEL: testSextI32
245; MIPS32: 	sll	{{.*}},0x1f
246; MIPS32: 	sra	{{.*}},0x1f
247
248; Test sext to i64.
249define internal i64 @testSextI64(i32 %arg) {
250entry:
251  %arg_i1 = trunc i32 %arg to i1
252  %result_i64 = sext i1 %arg_i1 to i64
253  ret i64 %result_i64
254}
255; CHECK-LABEL: testSextI64
256; match the trunc instruction
257; CHECK: and {{.*}},0x1
258; match the sext i1 instruction
259; CHECK: movzx [[REG:.*]],
260; CHECK-NEXT: shl [[REG]],0x1f
261; CHECK-NEXT: sar [[REG]],0x1f
262
263; ARM32-LABEL: testSextI64
264; ARM32: mov {{.*}}, #0
265; ARM32: tst {{.*}}, #1
266; ARM32: mvn {{.*}}, #0
267; ARM32: movne [[REG:r[0-9]+]]
268; ARM32: mov {{.*}}, [[REG]]
269
270; MIPS32-LABEL: testSextI64
271; MIPS32: 	sll	{{.*}},0x1f
272; MIPS32: 	sra	{{.*}},0x1f
273; MIPS32: 	move
274; MIPS32: 	move
275
276; Kind of like sext i1 to i32, but with an immediate source. On ARM,
277; sxtb cannot take an immediate operand, so make sure it's using a reg.
278; If we had optimized constants, this could just be mov dst, 0xffffffff
279; or mvn dst, #0.
280define internal i32 @testSextTrue() {
281  %result = sext i1 true to i32
282  ret i32 %result
283}
284; CHECK-LABEL: testSextTrue
285; CHECK: movzx
286; CHECK-NEXT: shl
287; CHECK-NEXT: sar
288; ARM32-LABEL: testSextTrue
289; ARM32: mov {{.*}}, #0
290; ARM32: tst {{.*}}, #1
291; ARM32: mvn {{.*}}, #0
292; ARM32: movne
293; MIPS32-LABEL: testSextTrue
294; MIPS32: 	li	{{.*}},1
295; MIPS32: 	sll	{{.*}},0x1f
296; MIPS32: 	sra	{{.*}},0x1f
297
298define internal i32 @testZextTrue() {
299  %result = zext i1 true to i32
300  ret i32 %result
301}
302; CHECK-LABEL: testZextTrue
303; CHECK: movzx
304; CHECK-NOT: and {{.*}},0x1
305; ARM32-LABEL: testZextTrue
306; ARM32: mov{{.*}}, #1
307; ARM32: and {{.*}}, #1
308; MIPS32-LABEL: testZextTrue
309; MIPS32: 	li	{{.*}},1
310; MIPS32: 	andi	{{.*}},0x1
311
312; Test fptosi float to i1.
313define internal i32 @testFptosiFloat(float %arg) {
314entry:
315  %arg_i1 = fptosi float %arg to i1
316  %result = sext i1 %arg_i1 to i32
317  ret i32 %result
318}
319; CHECK-LABEL: testFptosiFloat
320; CHECK: cvttss2si
321; CHECK: and {{.*}},0x1
322; CHECK: movzx [[REG:.*]],
323; CHECK-NEXT: shl [[REG]],0x1f
324; CHECK-NEXT: sar [[REG]],0x1f
325; MIPS32-LABEL: testFptosiFloat
326; MIPS32: 	trunc.w.s
327; MIPS32: 	mfc1
328; MIPS32: 	sll	{{.*}},0x1f
329; MIPS32: 	sra	{{.*}},0x1f
330
331; Test fptosi double to i1.
332define internal i32 @testFptosiDouble(double %arg) {
333entry:
334  %arg_i1 = fptosi double %arg to i1
335  %result = sext i1 %arg_i1 to i32
336  ret i32 %result
337}
338; CHECK-LABEL: testFptosiDouble
339; CHECK: cvttsd2si
340; CHECK: and {{.*}},0x1
341; CHECK: movzx [[REG:.*]],
342; CHECK-NEXT: shl [[REG]],0x1f
343; CHECK-NEXT: sar [[REG]],0x1f
344; MIPS32-LABEL: testFptosiDouble
345; MIPS32: 	trunc.w.d
346; MIPS32: 	mfc1
347; MIPS32: 	sll	{{.*}},0x1f
348; MIPS32: 	sra	{{.*}},0x1f
349