1; RUN: llc -O0 -aarch64-enable-atomic-cfg-tidy=0 -stop-after=irtranslator -global-isel -verify-machineinstrs %s -o - 2>&1 | FileCheck %s
2; RUN: llc -O3 -aarch64-enable-atomic-cfg-tidy=0 -stop-after=irtranslator -global-isel -verify-machineinstrs %s -o - 2>&1 | FileCheck %s --check-prefix=O3
3
4; This file checks that the translation from llvm IR to generic MachineInstr
5; is correct.
6target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
7target triple = "aarch64--"
8
9; Tests for add.
10; CHECK-LABEL: name: addi64
11; CHECK:      [[ARG1:%[0-9]+]]:_(s64) = COPY $x0
12; CHECK-NEXT: [[ARG2:%[0-9]+]]:_(s64) = COPY $x1
13; CHECK-NEXT: [[RES:%[0-9]+]]:_(s64) = G_ADD [[ARG1]], [[ARG2]]
14; CHECK-NEXT: $x0 = COPY [[RES]]
15; CHECK-NEXT: RET_ReallyLR implicit $x0
16define i64 @addi64(i64 %arg1, i64 %arg2) {
17  %res = add i64 %arg1, %arg2
18  ret i64 %res
19}
20
21; CHECK-LABEL: name: muli64
22; CHECK: [[ARG1:%[0-9]+]]:_(s64) = COPY $x0
23; CHECK-NEXT: [[ARG2:%[0-9]+]]:_(s64) = COPY $x1
24; CHECK-NEXT: [[RES:%[0-9]+]]:_(s64) = G_MUL [[ARG1]], [[ARG2]]
25; CHECK-NEXT: $x0 = COPY [[RES]]
26; CHECK-NEXT: RET_ReallyLR implicit $x0
27define i64 @muli64(i64 %arg1, i64 %arg2) {
28  %res = mul i64 %arg1, %arg2
29  ret i64 %res
30}
31
32; Tests for alloca
33; CHECK-LABEL: name: allocai64
34; CHECK: stack:
35; CHECK-NEXT:   - { id: 0, name: ptr1, type: default, offset: 0, size: 8, alignment: 8,
36; CHECK-NEXT:       stack-id: default, callee-saved-register: '', callee-saved-restored: true,
37; CHECK-NEXT: debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
38; CHECK-NEXT:   - { id: 1, name: ptr2, type: default, offset: 0, size: 8, alignment: 1,
39; CHECK-NEXT:       stack-id: default, callee-saved-register: '', callee-saved-restored: true,
40; CHECK-NEXT:       debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
41; CHECK-NEXT:   - { id: 2, name: ptr3, type: default, offset: 0, size: 128, alignment: 8,
42; CHECK-NEXT:       stack-id: default, callee-saved-register: '', callee-saved-restored: true,
43; CHECK-NEXT:       debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
44; CHECK-NEXT:   - { id: 3, name: ptr4, type: default, offset: 0, size: 1, alignment: 8,
45; CHECK: %{{[0-9]+}}:_(p0) = G_FRAME_INDEX %stack.0.ptr1
46; CHECK: %{{[0-9]+}}:_(p0) = G_FRAME_INDEX %stack.1.ptr2
47; CHECK: %{{[0-9]+}}:_(p0) = G_FRAME_INDEX %stack.2.ptr3
48; CHECK: %{{[0-9]+}}:_(p0) = G_FRAME_INDEX %stack.3.ptr4
49define void @allocai64() {
50  %ptr1 = alloca i64
51  %ptr2 = alloca i64, align 1
52  %ptr3 = alloca i64, i32 16
53  %ptr4 = alloca [0 x i64]
54  ret void
55}
56
57; Tests for br.
58; CHECK-LABEL: name: uncondbr
59; CHECK: body:
60;
61; ABI/constant lowering and IR-level entry basic block.
62; CHECK: bb.{{[0-9]+}}.{{[a-zA-Z0-9.]+}}:
63;
64; Make sure we have one successor and only one.
65; CHECK-NEXT: successors: %[[BB2:bb.[0-9]+]](0x80000000)
66;
67; Check that we emit the correct branch.
68; CHECK: G_BR %[[BB2]]
69;
70; Check that end contains the return instruction.
71; CHECK: [[END:bb.[0-9]+]].{{[a-zA-Z0-9.]+}}:
72; CHECK-NEXT: RET_ReallyLR
73;
74; CHECK: bb.{{[0-9]+}}.{{[a-zA-Z0-9.]+}}:
75; CHECK-NEXT: successors: %[[END]](0x80000000)
76; CHECK: G_BR %[[END]]
77define void @uncondbr() {
78entry:
79  br label %bb2
80end:
81  ret void
82bb2:
83  br label %end
84}
85
86; CHECK-LABEL: name: uncondbr_fallthrough
87; CHECK: body:
88; CHECK: bb.{{[0-9]+}}.{{[a-zA-Z0-9.]+}}:
89; CHECK-NEXT: successors: %[[END:bb.[0-9]+]](0x80000000)
90; We don't emit a branch here, as we can fallthrough to the successor.
91; CHECK-NOT: G_BR
92; CHECK: [[END]].{{[a-zA-Z0-9.]+}}:
93; CHECK-NEXT: RET_ReallyLR
94define void @uncondbr_fallthrough() {
95entry:
96  br label %end
97end:
98  ret void
99}
100
101; Tests for conditional br.
102; CHECK-LABEL: name: condbr
103; CHECK: body:
104;
105; ABI/constant lowering and IR-level entry basic block.
106; CHECK: bb.{{[0-9]+}} (%ir-block.{{[0-9]+}}):
107; Make sure we have two successors
108; CHECK-NEXT: successors: %[[TRUE:bb.[0-9]+]](0x40000000),
109; CHECK:                  %[[FALSE:bb.[0-9]+]](0x40000000)
110;
111; CHECK: [[ADDR:%.*]]:_(p0) = COPY $x0
112;
113; Check that we emit the correct branch.
114; CHECK: [[TST:%.*]]:_(s1) = G_LOAD [[ADDR]](p0)
115; CHECK: G_BRCOND [[TST]](s1), %[[TRUE]]
116; CHECK: G_BR %[[FALSE]]
117;
118; Check that each successor contains the return instruction.
119; CHECK: [[TRUE]].{{[a-zA-Z0-9.]+}}:
120; CHECK-NEXT: RET_ReallyLR
121; CHECK: [[FALSE]].{{[a-zA-Z0-9.]+}}:
122; CHECK-NEXT: RET_ReallyLR
123define void @condbr(i1* %tstaddr) {
124  %tst = load i1, i1* %tstaddr
125  br i1 %tst, label %true, label %false
126true:
127  ret void
128false:
129  ret void
130}
131
132; Tests for indirect br.
133; CHECK-LABEL: name: indirectbr
134; CHECK: body:
135;
136; ABI/constant lowering and IR-level entry basic block.
137; CHECK: bb.{{[0-9]+.[a-zA-Z0-9.]+}}:
138; Make sure we have one successor
139; CHECK-NEXT: successors: %[[BB_L1:bb.[0-9]+]](0x80000000)
140; CHECK-NOT: G_BR
141;
142; Check basic block L1 has 2 successors: BBL1 and BBL2
143; CHECK: [[BB_L1]].{{[a-zA-Z0-9.]+}} (address-taken):
144; CHECK-NEXT: successors: %[[BB_L1]](0x40000000),
145; CHECK:                  %[[BB_L2:bb.[0-9]+]](0x40000000)
146; CHECK: G_BRINDIRECT %{{[0-9]+}}(p0)
147;
148; Check basic block L2 is the return basic block
149; CHECK: [[BB_L2]].{{[a-zA-Z0-9.]+}} (address-taken):
150; CHECK-NEXT: RET_ReallyLR
151
152@indirectbr.L = internal unnamed_addr constant [3 x i8*] [i8* blockaddress(@indirectbr, %L1), i8* blockaddress(@indirectbr, %L2), i8* null], align 8
153
154define void @indirectbr() {
155entry:
156  br label %L1
157L1:                                               ; preds = %entry, %L1
158  %i = phi i32 [ 0, %entry ], [ %inc, %L1 ]
159  %inc = add i32 %i, 1
160  %idxprom = zext i32 %i to i64
161  %arrayidx = getelementptr inbounds [3 x i8*], [3 x i8*]* @indirectbr.L, i64 0, i64 %idxprom
162  %brtarget = load i8*, i8** %arrayidx, align 8
163  indirectbr i8* %brtarget, [label %L1, label %L2]
164L2:                                               ; preds = %L1
165  ret void
166}
167
168; Tests for or.
169; CHECK-LABEL: name: ori64
170; CHECK: [[ARG1:%[0-9]+]]:_(s64) = COPY $x0
171; CHECK-NEXT: [[ARG2:%[0-9]+]]:_(s64) = COPY $x1
172; CHECK-NEXT: [[RES:%[0-9]+]]:_(s64) = G_OR [[ARG1]], [[ARG2]]
173; CHECK-NEXT: $x0 = COPY [[RES]]
174; CHECK-NEXT: RET_ReallyLR implicit $x0
175define i64 @ori64(i64 %arg1, i64 %arg2) {
176  %res = or i64 %arg1, %arg2
177  ret i64 %res
178}
179
180; CHECK-LABEL: name: ori32
181; CHECK: [[ARG1:%[0-9]+]]:_(s32) = COPY $w0
182; CHECK-NEXT: [[ARG2:%[0-9]+]]:_(s32) = COPY $w1
183; CHECK-NEXT: [[RES:%[0-9]+]]:_(s32) = G_OR [[ARG1]], [[ARG2]]
184; CHECK-NEXT: $w0 = COPY [[RES]]
185; CHECK-NEXT: RET_ReallyLR implicit $w0
186define i32 @ori32(i32 %arg1, i32 %arg2) {
187  %res = or i32 %arg1, %arg2
188  ret i32 %res
189}
190
191; Tests for xor.
192; CHECK-LABEL: name: xori64
193; CHECK: [[ARG1:%[0-9]+]]:_(s64) = COPY $x0
194; CHECK-NEXT: [[ARG2:%[0-9]+]]:_(s64) = COPY $x1
195; CHECK-NEXT: [[RES:%[0-9]+]]:_(s64) = G_XOR [[ARG1]], [[ARG2]]
196; CHECK-NEXT: $x0 = COPY [[RES]]
197; CHECK-NEXT: RET_ReallyLR implicit $x0
198define i64 @xori64(i64 %arg1, i64 %arg2) {
199  %res = xor i64 %arg1, %arg2
200  ret i64 %res
201}
202
203; CHECK-LABEL: name: xori32
204; CHECK: [[ARG1:%[0-9]+]]:_(s32) = COPY $w0
205; CHECK-NEXT: [[ARG2:%[0-9]+]]:_(s32) = COPY $w1
206; CHECK-NEXT: [[RES:%[0-9]+]]:_(s32) = G_XOR [[ARG1]], [[ARG2]]
207; CHECK-NEXT: $w0 = COPY [[RES]]
208; CHECK-NEXT: RET_ReallyLR implicit $w0
209define i32 @xori32(i32 %arg1, i32 %arg2) {
210  %res = xor i32 %arg1, %arg2
211  ret i32 %res
212}
213
214; Tests for and.
215; CHECK-LABEL: name: andi64
216; CHECK: [[ARG1:%[0-9]+]]:_(s64) = COPY $x0
217; CHECK-NEXT: [[ARG2:%[0-9]+]]:_(s64) = COPY $x1
218; CHECK-NEXT: [[RES:%[0-9]+]]:_(s64) = G_AND [[ARG1]], [[ARG2]]
219; CHECK-NEXT: $x0 = COPY [[RES]]
220; CHECK-NEXT: RET_ReallyLR implicit $x0
221define i64 @andi64(i64 %arg1, i64 %arg2) {
222  %res = and i64 %arg1, %arg2
223  ret i64 %res
224}
225
226; CHECK-LABEL: name: andi32
227; CHECK: [[ARG1:%[0-9]+]]:_(s32) = COPY $w0
228; CHECK-NEXT: [[ARG2:%[0-9]+]]:_(s32) = COPY $w1
229; CHECK-NEXT: [[RES:%[0-9]+]]:_(s32) = G_AND [[ARG1]], [[ARG2]]
230; CHECK-NEXT: $w0 = COPY [[RES]]
231; CHECK-NEXT: RET_ReallyLR implicit $w0
232define i32 @andi32(i32 %arg1, i32 %arg2) {
233  %res = and i32 %arg1, %arg2
234  ret i32 %res
235}
236
237; Tests for sub.
238; CHECK-LABEL: name: subi64
239; CHECK: [[ARG1:%[0-9]+]]:_(s64) = COPY $x0
240; CHECK-NEXT: [[ARG2:%[0-9]+]]:_(s64) = COPY $x1
241; CHECK-NEXT: [[RES:%[0-9]+]]:_(s64) = G_SUB [[ARG1]], [[ARG2]]
242; CHECK-NEXT: $x0 = COPY [[RES]]
243; CHECK-NEXT: RET_ReallyLR implicit $x0
244define i64 @subi64(i64 %arg1, i64 %arg2) {
245  %res = sub i64 %arg1, %arg2
246  ret i64 %res
247}
248
249; CHECK-LABEL: name: subi32
250; CHECK: [[ARG1:%[0-9]+]]:_(s32) = COPY $w0
251; CHECK-NEXT: [[ARG2:%[0-9]+]]:_(s32) = COPY $w1
252; CHECK-NEXT: [[RES:%[0-9]+]]:_(s32) = G_SUB [[ARG1]], [[ARG2]]
253; CHECK-NEXT: $w0 = COPY [[RES]]
254; CHECK-NEXT: RET_ReallyLR implicit $w0
255define i32 @subi32(i32 %arg1, i32 %arg2) {
256  %res = sub i32 %arg1, %arg2
257  ret i32 %res
258}
259
260; CHECK-LABEL: name: ptrtoint
261; CHECK: [[ARG1:%[0-9]+]]:_(p0) = COPY $x0
262; CHECK: [[RES:%[0-9]+]]:_(s64) = G_PTRTOINT [[ARG1]]
263; CHECK: $x0 = COPY [[RES]]
264; CHECK: RET_ReallyLR implicit $x0
265define i64 @ptrtoint(i64* %a) {
266  %val = ptrtoint i64* %a to i64
267  ret i64 %val
268}
269
270; CHECK-LABEL: name: inttoptr
271; CHECK: [[ARG1:%[0-9]+]]:_(s64) = COPY $x0
272; CHECK: [[RES:%[0-9]+]]:_(p0) = G_INTTOPTR [[ARG1]]
273; CHECK: $x0 = COPY [[RES]]
274; CHECK: RET_ReallyLR implicit $x0
275define i64* @inttoptr(i64 %a) {
276  %val = inttoptr i64 %a to i64*
277  ret i64* %val
278}
279
280; CHECK-LABEL: name: trivial_bitcast
281; CHECK: [[ARG1:%[0-9]+]]:_(p0) = COPY $x0
282; CHECK: $x0 = COPY [[ARG1]]
283; CHECK: RET_ReallyLR implicit $x0
284define i64* @trivial_bitcast(i8* %a) {
285  %val = bitcast i8* %a to i64*
286  ret i64* %val
287}
288
289; CHECK-LABEL: name: trivial_bitcast_with_copy
290; CHECK:     [[A:%[0-9]+]]:_(p0) = COPY $x0
291; CHECK:     G_BR %[[CAST:bb\.[0-9]+]]
292
293; CHECK: [[END:bb\.[0-9]+]].{{[a-zA-Z0-9.]+}}:
294; CHECK:     $x0 = COPY [[A]]
295
296; CHECK: [[CAST]].{{[a-zA-Z0-9.]+}}:
297; CHECK:     G_BR %[[END]]
298define i64* @trivial_bitcast_with_copy(i8* %a) {
299  br label %cast
300
301end:
302  ret i64* %val
303
304cast:
305  %val = bitcast i8* %a to i64*
306  br label %end
307}
308
309; CHECK-LABEL: name: bitcast
310; CHECK: [[ARG1:%[0-9]+]]:_(s64) = COPY $x0
311; CHECK: [[RES1:%[0-9]+]]:_(<2 x s32>) = G_BITCAST [[ARG1]]
312; CHECK: [[RES2:%[0-9]+]]:_(s64) = G_BITCAST [[RES1]]
313; CHECK: $x0 = COPY [[RES2]]
314; CHECK: RET_ReallyLR implicit $x0
315define i64 @bitcast(i64 %a) {
316  %res1 = bitcast i64 %a to <2 x i32>
317  %res2 = bitcast <2 x i32> %res1 to i64
318  ret i64 %res2
319}
320
321; CHECK-LABEL: name: addrspacecast
322; CHECK: [[ARG1:%[0-9]+]]:_(p1) = COPY $x0
323; CHECK: [[RES1:%[0-9]+]]:_(p2) = G_ADDRSPACE_CAST [[ARG1]]
324; CHECK: [[RES2:%[0-9]+]]:_(p0) = G_ADDRSPACE_CAST [[RES1]]
325; CHECK: $x0 = COPY [[RES2]]
326; CHECK: RET_ReallyLR implicit $x0
327define i64* @addrspacecast(i32 addrspace(1)* %a) {
328  %res1 = addrspacecast i32 addrspace(1)* %a to i64 addrspace(2)*
329  %res2 = addrspacecast i64 addrspace(2)* %res1 to i64*
330  ret i64* %res2
331}
332
333; CHECK-LABEL: name: trunc
334; CHECK: [[ARG1:%[0-9]+]]:_(s64) = COPY $x0
335; CHECK: [[VEC:%[0-9]+]]:_(<4 x s32>) = G_LOAD
336; CHECK: [[RES1:%[0-9]+]]:_(s8) = G_TRUNC [[ARG1]]
337; CHECK: [[RES2:%[0-9]+]]:_(<4 x s16>) = G_TRUNC [[VEC]]
338define void @trunc(i64 %a) {
339  %vecptr = alloca <4 x i32>
340  %vec = load <4 x i32>, <4 x i32>* %vecptr
341  %res1 = trunc i64 %a to i8
342  %res2 = trunc <4 x i32> %vec to <4 x i16>
343  ret void
344}
345
346; CHECK-LABEL: name: load
347; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
348; CHECK: [[ADDR42:%[0-9]+]]:_(p42) = COPY $x1
349; CHECK: [[VAL1:%[0-9]+]]:_(s64) = G_LOAD [[ADDR]](p0) :: (load 8 from %ir.addr, align 16)
350; CHECK: [[VAL2:%[0-9]+]]:_(s64) = G_LOAD [[ADDR42]](p42) :: (load 8 from %ir.addr42, addrspace 42)
351; CHECK: [[SUM2:%.*]]:_(s64) = G_ADD [[VAL1]], [[VAL2]]
352; CHECK: [[VAL3:%[0-9]+]]:_(s64) = G_LOAD [[ADDR]](p0) :: (volatile load 8 from %ir.addr)
353; CHECK: [[SUM3:%[0-9]+]]:_(s64) = G_ADD [[SUM2]], [[VAL3]]
354; CHECK: [[VAL4:%[0-9]+]]:_(s64) = G_LOAD [[ADDR]](p0) :: (load 8 from %ir.addr, !range !0)
355; CHECK: [[SUM4:%[0-9]+]]:_(s64) = G_ADD [[SUM3]], [[VAL4]]
356; CHECK: $x0 = COPY [[SUM4]]
357; CHECK: RET_ReallyLR implicit $x0
358define i64 @load(i64* %addr, i64 addrspace(42)* %addr42) {
359  %val1 = load i64, i64* %addr, align 16
360
361  %val2 = load i64, i64 addrspace(42)* %addr42
362  %sum2 = add i64 %val1, %val2
363
364  %val3 = load volatile i64, i64* %addr
365  %sum3 = add i64 %sum2, %val3
366
367  %val4 = load i64, i64* %addr, !range !0
368  %sum4 = add i64 %sum3, %val4
369  ret i64 %sum4
370}
371
372; CHECK-LABEL: name: store
373; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
374; CHECK: [[ADDR42:%[0-9]+]]:_(p42) = COPY $x1
375; CHECK: [[VAL1:%[0-9]+]]:_(s64) = COPY $x2
376; CHECK: [[VAL2:%[0-9]+]]:_(s64) = COPY $x3
377; CHECK: G_STORE [[VAL1]](s64), [[ADDR]](p0) :: (store 8 into %ir.addr, align 16)
378; CHECK: G_STORE [[VAL2]](s64), [[ADDR42]](p42) :: (store 8 into %ir.addr42, addrspace 42)
379; CHECK: G_STORE [[VAL1]](s64), [[ADDR]](p0) :: (volatile store 8 into %ir.addr)
380; CHECK: RET_ReallyLR
381define void @store(i64* %addr, i64 addrspace(42)* %addr42, i64 %val1, i64 %val2) {
382  store i64 %val1, i64* %addr, align 16
383  store i64 %val2, i64 addrspace(42)* %addr42
384  store volatile i64 %val1, i64* %addr
385  %sum = add i64 %val1, %val2
386  ret void
387}
388
389; CHECK-LABEL: name: intrinsics
390; CHECK: [[CUR:%[0-9]+]]:_(s32) = COPY $w0
391; CHECK: [[BITS:%[0-9]+]]:_(s32) = COPY $w1
392; CHECK: [[PTR:%[0-9]+]]:_(p0) = G_INTRINSIC intrinsic(@llvm.returnaddress), 0
393; CHECK: [[PTR_VEC:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0.ptr.vec
394; CHECK: [[VEC:%[0-9]+]]:_(<8 x s8>) = G_LOAD [[PTR_VEC]]
395; CHECK: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aarch64.neon.st2), [[VEC]](<8 x s8>), [[VEC]](<8 x s8>), [[PTR]](p0)
396; CHECK: RET_ReallyLR
397declare i8* @llvm.returnaddress(i32)
398declare void @llvm.aarch64.neon.st2.v8i8.p0i8(<8 x i8>, <8 x i8>, i8*)
399declare { <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld2.v8i8.p0v8i8(<8 x i8>*)
400define void @intrinsics(i32 %cur, i32 %bits) {
401  %ptr = call i8* @llvm.returnaddress(i32 0)
402  %ptr.vec = alloca <8 x i8>
403  %vec = load <8 x i8>, <8 x i8>* %ptr.vec
404  call void @llvm.aarch64.neon.st2.v8i8.p0i8(<8 x i8> %vec, <8 x i8> %vec, i8* %ptr)
405  ret void
406}
407
408; CHECK-LABEL: name: test_phi
409; CHECK:     G_BRCOND {{%.*}}, %[[TRUE:bb\.[0-9]+]]
410; CHECK:     G_BR %[[FALSE:bb\.[0-9]+]]
411
412; CHECK: [[TRUE]].{{[a-zA-Z0-9.]+}}:
413; CHECK:     [[RES1:%[0-9]+]]:_(s32) = G_LOAD
414
415; CHECK: [[FALSE]].{{[a-zA-Z0-9.]+}}:
416; CHECK:     [[RES2:%[0-9]+]]:_(s32) = G_LOAD
417
418; CHECK:     [[RES:%[0-9]+]]:_(s32) = G_PHI [[RES1]](s32), %[[TRUE]], [[RES2]](s32), %[[FALSE]]
419; CHECK:     $w0 = COPY [[RES]]
420define i32 @test_phi(i32* %addr1, i32* %addr2, i1 %tst) {
421  br i1 %tst, label %true, label %false
422
423true:
424  %res1 = load i32, i32* %addr1
425  br label %end
426
427false:
428  %res2 = load i32, i32* %addr2
429  br label %end
430
431end:
432  %res = phi i32 [%res1, %true], [%res2, %false]
433  ret i32 %res
434}
435
436; CHECK-LABEL: name: unreachable
437; CHECK: G_ADD
438; CHECK-NEXT: {{^$}}
439; CHECK-NEXT: ...
440define void @unreachable(i32 %a) {
441  %sum = add i32 %a, %a
442  unreachable
443}
444
445  ; It's important that constants are after argument passing, but before the
446  ; rest of the entry block.
447; CHECK-LABEL: name: constant_int
448; CHECK: [[IN:%[0-9]+]]:_(s32) = COPY $w0
449; CHECK: [[ONE:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
450
451; CHECK: bb.{{[0-9]+}}.{{[a-zA-Z0-9.]+}}:
452; CHECK: [[SUM1:%[0-9]+]]:_(s32) = G_ADD [[IN]], [[ONE]]
453; CHECK: [[SUM2:%[0-9]+]]:_(s32) = G_ADD [[IN]], [[ONE]]
454; CHECK: [[RES:%[0-9]+]]:_(s32) = G_ADD [[SUM1]], [[SUM2]]
455; CHECK: $w0 = COPY [[RES]]
456
457define i32 @constant_int(i32 %in) {
458  br label %next
459
460next:
461  %sum1 = add i32 %in, 1
462  %sum2 = add i32 %in, 1
463  %res = add i32 %sum1, %sum2
464  ret i32 %res
465}
466
467; CHECK-LABEL: name: constant_int_start
468; CHECK: [[TWO:%[0-9]+]]:_(s32) = G_CONSTANT i32 2
469; CHECK: [[ANSWER:%[0-9]+]]:_(s32) = G_CONSTANT i32 42
470; CHECK: [[RES:%[0-9]+]]:_(s32) = G_CONSTANT i32 44
471define i32 @constant_int_start() {
472  %res = add i32 2, 42
473  ret i32 %res
474}
475
476; CHECK-LABEL: name: test_undef
477; CHECK: [[UNDEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
478; CHECK: $w0 = COPY [[UNDEF]]
479define i32 @test_undef() {
480  ret i32 undef
481}
482
483; CHECK-LABEL: name: test_constant_inttoptr
484; CHECK: [[ONE:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
485; CHECK: [[PTR:%[0-9]+]]:_(p0) = G_INTTOPTR [[ONE]]
486; CHECK: $x0 = COPY [[PTR]]
487define i8* @test_constant_inttoptr() {
488  ret i8* inttoptr(i64 1 to i8*)
489}
490
491  ; This failed purely because the Constant -> VReg map was kept across
492  ; functions, so reuse the "i64 1" from above.
493; CHECK-LABEL: name: test_reused_constant
494; CHECK: [[ONE:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
495; CHECK: $x0 = COPY [[ONE]]
496define i64 @test_reused_constant() {
497  ret i64 1
498}
499
500; CHECK-LABEL: name: test_sext
501; CHECK: [[IN:%[0-9]+]]:_(s32) = COPY $w0
502; CHECK: [[RES:%[0-9]+]]:_(s64) = G_SEXT [[IN]]
503; CHECK: $x0 = COPY [[RES]]
504define i64 @test_sext(i32 %in) {
505  %res = sext i32 %in to i64
506  ret i64 %res
507}
508
509; CHECK-LABEL: name: test_zext
510; CHECK: [[IN:%[0-9]+]]:_(s32) = COPY $w0
511; CHECK: [[RES:%[0-9]+]]:_(s64) = G_ZEXT [[IN]]
512; CHECK: $x0 = COPY [[RES]]
513define i64 @test_zext(i32 %in) {
514  %res = zext i32 %in to i64
515  ret i64 %res
516}
517
518; CHECK-LABEL: name: test_shl
519; CHECK: [[ARG1:%[0-9]+]]:_(s32) = COPY $w0
520; CHECK-NEXT: [[ARG2:%[0-9]+]]:_(s32) = COPY $w1
521; CHECK-NEXT: [[RES:%[0-9]+]]:_(s32) = G_SHL [[ARG1]], [[ARG2]]
522; CHECK-NEXT: $w0 = COPY [[RES]]
523; CHECK-NEXT: RET_ReallyLR implicit $w0
524define i32 @test_shl(i32 %arg1, i32 %arg2) {
525  %res = shl i32 %arg1, %arg2
526  ret i32 %res
527}
528
529
530; CHECK-LABEL: name: test_lshr
531; CHECK: [[ARG1:%[0-9]+]]:_(s32) = COPY $w0
532; CHECK-NEXT: [[ARG2:%[0-9]+]]:_(s32) = COPY $w1
533; CHECK-NEXT: [[RES:%[0-9]+]]:_(s32) = G_LSHR [[ARG1]], [[ARG2]]
534; CHECK-NEXT: $w0 = COPY [[RES]]
535; CHECK-NEXT: RET_ReallyLR implicit $w0
536define i32 @test_lshr(i32 %arg1, i32 %arg2) {
537  %res = lshr i32 %arg1, %arg2
538  ret i32 %res
539}
540
541; CHECK-LABEL: name: test_ashr
542; CHECK: [[ARG1:%[0-9]+]]:_(s32) = COPY $w0
543; CHECK-NEXT: [[ARG2:%[0-9]+]]:_(s32) = COPY $w1
544; CHECK-NEXT: [[RES:%[0-9]+]]:_(s32) = G_ASHR [[ARG1]], [[ARG2]]
545; CHECK-NEXT: $w0 = COPY [[RES]]
546; CHECK-NEXT: RET_ReallyLR implicit $w0
547define i32 @test_ashr(i32 %arg1, i32 %arg2) {
548  %res = ashr i32 %arg1, %arg2
549  ret i32 %res
550}
551
552; CHECK-LABEL: name: test_sdiv
553; CHECK: [[ARG1:%[0-9]+]]:_(s32) = COPY $w0
554; CHECK-NEXT: [[ARG2:%[0-9]+]]:_(s32) = COPY $w1
555; CHECK-NEXT: [[RES:%[0-9]+]]:_(s32) = G_SDIV [[ARG1]], [[ARG2]]
556; CHECK-NEXT: $w0 = COPY [[RES]]
557; CHECK-NEXT: RET_ReallyLR implicit $w0
558define i32 @test_sdiv(i32 %arg1, i32 %arg2) {
559  %res = sdiv i32 %arg1, %arg2
560  ret i32 %res
561}
562
563; CHECK-LABEL: name: test_udiv
564; CHECK: [[ARG1:%[0-9]+]]:_(s32) = COPY $w0
565; CHECK-NEXT: [[ARG2:%[0-9]+]]:_(s32) = COPY $w1
566; CHECK-NEXT: [[RES:%[0-9]+]]:_(s32) = G_UDIV [[ARG1]], [[ARG2]]
567; CHECK-NEXT: $w0 = COPY [[RES]]
568; CHECK-NEXT: RET_ReallyLR implicit $w0
569define i32 @test_udiv(i32 %arg1, i32 %arg2) {
570  %res = udiv i32 %arg1, %arg2
571  ret i32 %res
572}
573
574; CHECK-LABEL: name: test_srem
575; CHECK: [[ARG1:%[0-9]+]]:_(s32) = COPY $w0
576; CHECK-NEXT: [[ARG2:%[0-9]+]]:_(s32) = COPY $w1
577; CHECK-NEXT: [[RES:%[0-9]+]]:_(s32) = G_SREM [[ARG1]], [[ARG2]]
578; CHECK-NEXT: $w0 = COPY [[RES]]
579; CHECK-NEXT: RET_ReallyLR implicit $w0
580define i32 @test_srem(i32 %arg1, i32 %arg2) {
581  %res = srem i32 %arg1, %arg2
582  ret i32 %res
583}
584
585; CHECK-LABEL: name: test_urem
586; CHECK: [[ARG1:%[0-9]+]]:_(s32) = COPY $w0
587; CHECK-NEXT: [[ARG2:%[0-9]+]]:_(s32) = COPY $w1
588; CHECK-NEXT: [[RES:%[0-9]+]]:_(s32) = G_UREM [[ARG1]], [[ARG2]]
589; CHECK-NEXT: $w0 = COPY [[RES]]
590; CHECK-NEXT: RET_ReallyLR implicit $w0
591define i32 @test_urem(i32 %arg1, i32 %arg2) {
592  %res = urem i32 %arg1, %arg2
593  ret i32 %res
594}
595
596; CHECK-LABEL: name: test_constant_null
597; CHECK: [[NULL:%[0-9]+]]:_(p0) = G_CONSTANT i64 0
598; CHECK: $x0 = COPY [[NULL]]
599define i8* @test_constant_null() {
600  ret i8* null
601}
602
603; CHECK-LABEL: name: test_struct_memops
604; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
605; CHECK: [[VAL1:%[0-9]+]]:_(s8) = G_LOAD %0(p0) :: (load 1 from %ir.addr, align 4)
606; CHECK: [[CST1:%[0-9]+]]:_(s64) = G_CONSTANT i64 4
607; CHECK: [[GEP1:%[0-9]+]]:_(p0) = G_PTR_ADD [[ADDR]], [[CST1]](s64)
608; CHECK: [[VAL2:%[0-9]+]]:_(s32) = G_LOAD [[GEP1]](p0) :: (load 4 from %ir.addr + 4)
609; CHECK: G_STORE [[VAL1]](s8), [[ADDR]](p0) :: (store 1 into %ir.addr, align 4)
610; CHECK: [[GEP2:%[0-9]+]]:_(p0) = G_PTR_ADD [[ADDR]], [[CST1]](s64)
611; CHECK: G_STORE [[VAL2]](s32), [[GEP2]](p0) :: (store 4 into %ir.addr + 4)
612define void @test_struct_memops({ i8, i32 }* %addr) {
613  %val = load { i8, i32 }, { i8, i32 }* %addr
614  store { i8, i32 } %val, { i8, i32 }* %addr
615  ret void
616}
617
618; CHECK-LABEL: name: test_i1_memops
619; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
620; CHECK: [[VAL:%[0-9]+]]:_(s1) = G_LOAD [[ADDR]](p0) :: (load 1 from  %ir.addr)
621; CHECK: G_STORE [[VAL]](s1), [[ADDR]](p0) :: (store 1 into  %ir.addr)
622define void @test_i1_memops(i1* %addr) {
623  %val = load i1, i1* %addr
624  store i1 %val, i1* %addr
625  ret void
626}
627
628; CHECK-LABEL: name: int_comparison
629; CHECK: [[LHS:%[0-9]+]]:_(s32) = COPY $w0
630; CHECK: [[RHS:%[0-9]+]]:_(s32) = COPY $w1
631; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x2
632; CHECK: [[TST:%[0-9]+]]:_(s1) = G_ICMP intpred(ne), [[LHS]](s32), [[RHS]]
633; CHECK: G_STORE [[TST]](s1), [[ADDR]](p0)
634define void @int_comparison(i32 %a, i32 %b, i1* %addr) {
635  %res = icmp ne i32 %a, %b
636  store i1 %res, i1* %addr
637  ret void
638}
639
640; CHECK-LABEL: name: ptr_comparison
641; CHECK: [[LHS:%[0-9]+]]:_(p0) = COPY $x0
642; CHECK: [[RHS:%[0-9]+]]:_(p0) = COPY $x1
643; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x2
644; CHECK: [[TST:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[LHS]](p0), [[RHS]]
645; CHECK: G_STORE [[TST]](s1), [[ADDR]](p0)
646define void @ptr_comparison(i8* %a, i8* %b, i1* %addr) {
647  %res = icmp eq i8* %a, %b
648  store i1 %res, i1* %addr
649  ret void
650}
651
652; CHECK-LABEL: name: test_fadd
653; CHECK: [[ARG1:%[0-9]+]]:_(s32) = COPY $s0
654; CHECK-NEXT: [[ARG2:%[0-9]+]]:_(s32) = COPY $s1
655; CHECK-NEXT: [[RES:%[0-9]+]]:_(s32) = G_FADD [[ARG1]], [[ARG2]]
656; CHECK-NEXT: $s0 = COPY [[RES]]
657; CHECK-NEXT: RET_ReallyLR implicit $s0
658define float @test_fadd(float %arg1, float %arg2) {
659  %res = fadd float %arg1, %arg2
660  ret float %res
661}
662
663; CHECK-LABEL: name: test_fsub
664; CHECK: [[ARG1:%[0-9]+]]:_(s32) = COPY $s0
665; CHECK-NEXT: [[ARG2:%[0-9]+]]:_(s32) = COPY $s1
666; CHECK-NEXT: [[RES:%[0-9]+]]:_(s32) = G_FSUB [[ARG1]], [[ARG2]]
667; CHECK-NEXT: $s0 = COPY [[RES]]
668; CHECK-NEXT: RET_ReallyLR implicit $s0
669define float @test_fsub(float %arg1, float %arg2) {
670  %res = fsub float %arg1, %arg2
671  ret float %res
672}
673
674; CHECK-LABEL: name: test_fmul
675; CHECK: [[ARG1:%[0-9]+]]:_(s32) = COPY $s0
676; CHECK-NEXT: [[ARG2:%[0-9]+]]:_(s32) = COPY $s1
677; CHECK-NEXT: [[RES:%[0-9]+]]:_(s32) = G_FMUL [[ARG1]], [[ARG2]]
678; CHECK-NEXT: $s0 = COPY [[RES]]
679; CHECK-NEXT: RET_ReallyLR implicit $s0
680define float @test_fmul(float %arg1, float %arg2) {
681  %res = fmul float %arg1, %arg2
682  ret float %res
683}
684
685; CHECK-LABEL: name: test_fdiv
686; CHECK: [[ARG1:%[0-9]+]]:_(s32) = COPY $s0
687; CHECK-NEXT: [[ARG2:%[0-9]+]]:_(s32) = COPY $s1
688; CHECK-NEXT: [[RES:%[0-9]+]]:_(s32) = G_FDIV [[ARG1]], [[ARG2]]
689; CHECK-NEXT: $s0 = COPY [[RES]]
690; CHECK-NEXT: RET_ReallyLR implicit $s0
691define float @test_fdiv(float %arg1, float %arg2) {
692  %res = fdiv float %arg1, %arg2
693  ret float %res
694}
695
696; CHECK-LABEL: name: test_frem
697; CHECK: [[ARG1:%[0-9]+]]:_(s32) = COPY $s0
698; CHECK-NEXT: [[ARG2:%[0-9]+]]:_(s32) = COPY $s1
699; CHECK-NEXT: [[RES:%[0-9]+]]:_(s32) = G_FREM [[ARG1]], [[ARG2]]
700; CHECK-NEXT: $s0 = COPY [[RES]]
701; CHECK-NEXT: RET_ReallyLR implicit $s0
702define float @test_frem(float %arg1, float %arg2) {
703  %res = frem float %arg1, %arg2
704  ret float %res
705}
706
707; CHECK-LABEL: name: test_sadd_overflow
708; CHECK: [[LHS:%[0-9]+]]:_(s32) = COPY $w0
709; CHECK: [[RHS:%[0-9]+]]:_(s32) = COPY $w1
710; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x2
711; CHECK: [[VAL:%[0-9]+]]:_(s32), [[OVERFLOW:%[0-9]+]]:_(s1) = G_SADDO [[LHS]], [[RHS]]
712; CHECK: G_STORE [[VAL]](s32), [[ADDR]](p0) :: (store 4 into %ir.addr)
713; CHECK: [[CST:%[0-9]+]]:_(s64) = G_CONSTANT i64 4
714; CHECK: [[GEP:%[0-9]+]]:_(p0) = G_PTR_ADD [[ADDR]], [[CST]](s64)
715; CHECK: G_STORE [[OVERFLOW]](s1), [[GEP]](p0) :: (store 1 into %ir.addr + 4, align 4)
716declare { i32, i1 } @llvm.sadd.with.overflow.i32(i32, i32)
717define void @test_sadd_overflow(i32 %lhs, i32 %rhs, { i32, i1 }* %addr) {
718  %res = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %lhs, i32 %rhs)
719  store { i32, i1 } %res, { i32, i1 }* %addr
720  ret void
721}
722
723; CHECK-LABEL: name: test_uadd_overflow
724; CHECK: [[LHS:%[0-9]+]]:_(s32) = COPY $w0
725; CHECK: [[RHS:%[0-9]+]]:_(s32) = COPY $w1
726; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x2
727; CHECK: [[VAL:%[0-9]+]]:_(s32), [[OVERFLOW:%[0-9]+]]:_(s1) = G_UADDO [[LHS]], [[RHS]]
728; CHECK: G_STORE [[VAL]](s32), [[ADDR]](p0) :: (store 4 into %ir.addr)
729; CHECK: [[CST:%[0-9]+]]:_(s64) = G_CONSTANT i64 4
730; CHECK: [[GEP:%[0-9]+]]:_(p0) = G_PTR_ADD [[ADDR]], [[CST]](s64)
731; CHECK: G_STORE [[OVERFLOW]](s1), [[GEP]](p0) :: (store 1 into %ir.addr + 4, align 4)
732declare { i32, i1 } @llvm.uadd.with.overflow.i32(i32, i32)
733define void @test_uadd_overflow(i32 %lhs, i32 %rhs, { i32, i1 }* %addr) {
734  %res = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %lhs, i32 %rhs)
735  store { i32, i1 } %res, { i32, i1 }* %addr
736  ret void
737}
738
739; CHECK-LABEL: name: test_ssub_overflow
740; CHECK: [[LHS:%[0-9]+]]:_(s32) = COPY $w0
741; CHECK: [[RHS:%[0-9]+]]:_(s32) = COPY $w1
742; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x2
743; CHECK: [[VAL:%[0-9]+]]:_(s32), [[OVERFLOW:%[0-9]+]]:_(s1) = G_SSUBO [[LHS]], [[RHS]]
744; CHECK: G_STORE [[VAL]](s32), [[ADDR]](p0) :: (store 4 into %ir.subr)
745; CHECK: [[CST:%[0-9]+]]:_(s64) = G_CONSTANT i64 4
746; CHECK: [[GEP:%[0-9]+]]:_(p0) = G_PTR_ADD [[ADDR]], [[CST]](s64)
747; CHECK: G_STORE [[OVERFLOW]](s1), [[GEP]](p0) :: (store 1 into %ir.subr + 4, align 4)
748declare { i32, i1 } @llvm.ssub.with.overflow.i32(i32, i32)
749define void @test_ssub_overflow(i32 %lhs, i32 %rhs, { i32, i1 }* %subr) {
750  %res = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %lhs, i32 %rhs)
751  store { i32, i1 } %res, { i32, i1 }* %subr
752  ret void
753}
754
755; CHECK-LABEL: name: test_usub_overflow
756; CHECK: [[LHS:%[0-9]+]]:_(s32) = COPY $w0
757; CHECK: [[RHS:%[0-9]+]]:_(s32) = COPY $w1
758; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x2
759; CHECK: [[VAL:%[0-9]+]]:_(s32), [[OVERFLOW:%[0-9]+]]:_(s1) = G_USUBO [[LHS]], [[RHS]]
760; CHECK: G_STORE [[VAL]](s32), [[ADDR]](p0) :: (store 4 into %ir.subr)
761; CHECK: [[CST:%[0-9]+]]:_(s64) = G_CONSTANT i64 4
762; CHECK: [[GEP:%[0-9]+]]:_(p0) = G_PTR_ADD [[ADDR]], [[CST]](s64)
763; CHECK: G_STORE [[OVERFLOW]](s1), [[GEP]](p0) :: (store 1 into %ir.subr + 4, align 4)
764declare { i32, i1 } @llvm.usub.with.overflow.i32(i32, i32)
765define void @test_usub_overflow(i32 %lhs, i32 %rhs, { i32, i1 }* %subr) {
766  %res = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %lhs, i32 %rhs)
767  store { i32, i1 } %res, { i32, i1 }* %subr
768  ret void
769}
770
771; CHECK-LABEL: name: test_smul_overflow
772; CHECK: [[LHS:%[0-9]+]]:_(s32) = COPY $w0
773; CHECK: [[RHS:%[0-9]+]]:_(s32) = COPY $w1
774; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x2
775; CHECK: [[VAL:%[0-9]+]]:_(s32), [[OVERFLOW:%[0-9]+]]:_(s1) = G_SMULO [[LHS]], [[RHS]]
776; CHECK: G_STORE [[VAL]](s32), [[ADDR]](p0) :: (store 4 into %ir.addr)
777; CHECK: [[CST:%[0-9]+]]:_(s64) = G_CONSTANT i64 4
778; CHECK: [[GEP:%[0-9]+]]:_(p0) = G_PTR_ADD [[ADDR]], [[CST]](s64)
779; CHECK: G_STORE [[OVERFLOW]](s1), [[GEP]](p0) :: (store 1 into %ir.addr + 4, align 4)
780declare { i32, i1 } @llvm.smul.with.overflow.i32(i32, i32)
781define void @test_smul_overflow(i32 %lhs, i32 %rhs, { i32, i1 }* %addr) {
782  %res = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %lhs, i32 %rhs)
783  store { i32, i1 } %res, { i32, i1 }* %addr
784  ret void
785}
786
787; CHECK-LABEL: name: test_umul_overflow
788; CHECK: [[LHS:%[0-9]+]]:_(s32) = COPY $w0
789; CHECK: [[RHS:%[0-9]+]]:_(s32) = COPY $w1
790; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x2
791; CHECK: [[VAL:%[0-9]+]]:_(s32), [[OVERFLOW:%[0-9]+]]:_(s1) = G_UMULO [[LHS]], [[RHS]]
792; CHECK: G_STORE [[VAL]](s32), [[ADDR]](p0) :: (store 4 into %ir.addr)
793; CHECK: [[CST:%[0-9]+]]:_(s64) = G_CONSTANT i64 4
794; CHECK: [[GEP:%[0-9]+]]:_(p0) = G_PTR_ADD [[ADDR]], [[CST]](s64)
795; CHECK: G_STORE [[OVERFLOW]](s1), [[GEP]](p0) :: (store 1 into %ir.addr + 4, align 4)
796declare { i32, i1 } @llvm.umul.with.overflow.i32(i32, i32)
797define void @test_umul_overflow(i32 %lhs, i32 %rhs, { i32, i1 }* %addr) {
798  %res = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %lhs, i32 %rhs)
799  store { i32, i1 } %res, { i32, i1 }* %addr
800  ret void
801}
802
803; CHECK-LABEL: name: test_extractvalue
804; CHECK: %0:_(p0) = COPY $x0
805; CHECK: [[LD1:%[0-9]+]]:_(s8) = G_LOAD %0(p0) :: (load 1 from %ir.addr, align 4)
806; CHECK: [[CST1:%[0-9]+]]:_(s64) = G_CONSTANT i64 4
807; CHECK: [[GEP1:%[0-9]+]]:_(p0) = G_PTR_ADD %0, [[CST1]](s64)
808; CHECK: [[LD2:%[0-9]+]]:_(s8) = G_LOAD [[GEP1]](p0) :: (load 1 from %ir.addr + 4, align 4)
809; CHECK: [[CST2:%[0-9]+]]:_(s64) = G_CONSTANT i64 8
810; CHECK: [[GEP2:%[0-9]+]]:_(p0) = G_PTR_ADD %0, [[CST2]](s64)
811; CHECK: [[LD3:%[0-9]+]]:_(s32) = G_LOAD [[GEP2]](p0) :: (load 4 from %ir.addr + 8)
812; CHECK: [[CST3:%[0-9]+]]:_(s64) = G_CONSTANT i64 12
813; CHECK: [[GEP3:%[0-9]+]]:_(p0) = G_PTR_ADD %0, [[CST3]](s64)
814; CHECK: [[LD4:%[0-9]+]]:_(s32) = G_LOAD [[GEP3]](p0) :: (load 4 from %ir.addr + 12)
815; CHECK: $w0 = COPY [[LD3]](s32)
816%struct.nested = type {i8, { i8, i32 }, i32}
817define i32 @test_extractvalue(%struct.nested* %addr) {
818  %struct = load %struct.nested, %struct.nested* %addr
819  %res = extractvalue %struct.nested %struct, 1, 1
820  ret i32 %res
821}
822
823; CHECK-LABEL: name: test_extractvalue_agg
824; CHECK: %0:_(p0) = COPY $x0
825; CHECK: %1:_(p0) = COPY $x1
826; CHECK: [[LD1:%[0-9]+]]:_(s8) = G_LOAD %0(p0) :: (load 1 from %ir.addr, align 4)
827; CHECK: [[CST1:%[0-9]+]]:_(s64) = G_CONSTANT i64 4
828; CHECK: [[GEP1:%[0-9]+]]:_(p0) = G_PTR_ADD %0, [[CST1]](s64)
829; CHECK: [[LD2:%[0-9]+]]:_(s8) = G_LOAD [[GEP1]](p0) :: (load 1 from %ir.addr + 4, align 4)
830; CHECK: [[CST2:%[0-9]+]]:_(s64) = G_CONSTANT i64 8
831; CHECK: [[GEP2:%[0-9]+]]:_(p0) = G_PTR_ADD %0, [[CST2]](s64)
832; CHECK: [[LD3:%[0-9]+]]:_(s32) = G_LOAD [[GEP2]](p0) :: (load 4 from %ir.addr + 8)
833; CHECK: [[CST3:%[0-9]+]]:_(s64) = G_CONSTANT i64 12
834; CHECK: [[GEP3:%[0-9]+]]:_(p0) = G_PTR_ADD %0, [[CST3]](s64)
835; CHECK: [[LD4:%[0-9]+]]:_(s32) = G_LOAD [[GEP3]](p0) :: (load 4 from %ir.addr + 12)
836; CHECK: G_STORE [[LD2]](s8), %1(p0) :: (store 1 into %ir.addr2, align 4)
837; CHECK: [[GEP4:%[0-9]+]]:_(p0) = G_PTR_ADD %1, [[CST1]](s64)
838; CHECK: G_STORE [[LD3]](s32), [[GEP4]](p0) :: (store 4 into %ir.addr2 + 4)
839define void @test_extractvalue_agg(%struct.nested* %addr, {i8, i32}* %addr2) {
840  %struct = load %struct.nested, %struct.nested* %addr
841  %res = extractvalue %struct.nested %struct, 1
842  store {i8, i32} %res, {i8, i32}* %addr2
843  ret void
844}
845
846; CHECK-LABEL: name: test_trivial_extract_ptr
847; CHECK: [[STRUCT:%[0-9]+]]:_(p0) = COPY $x0
848; CHECK: [[VAL32:%[0-9]+]]:_(s32) = COPY $w1
849; CHECK: [[VAL:%[0-9]+]]:_(s8) = G_TRUNC [[VAL32]]
850; CHECK: G_STORE [[VAL]](s8), [[STRUCT]](p0)
851define void @test_trivial_extract_ptr([1 x i8*] %s, i8 %val) {
852  %addr = extractvalue [1 x i8*] %s, 0
853  store i8 %val, i8* %addr
854  ret void
855}
856
857; CHECK-LABEL: name: test_insertvalue
858; CHECK: %0:_(p0) = COPY $x0
859; CHECK: %1:_(s32) = COPY $w1
860; CHECK: [[LD1:%[0-9]+]]:_(s8) = G_LOAD %0(p0) :: (load 1 from %ir.addr, align 4)
861; CHECK: [[CST1:%[0-9]+]]:_(s64) = G_CONSTANT i64 4
862; CHECK: [[GEP1:%[0-9]+]]:_(p0) = G_PTR_ADD %0, [[CST1]](s64)
863; CHECK: [[LD2:%[0-9]+]]:_(s8) = G_LOAD [[GEP1]](p0) :: (load 1 from %ir.addr + 4, align 4)
864; CHECK: [[CST2:%[0-9]+]]:_(s64) = G_CONSTANT i64 8
865; CHECK: [[GEP2:%[0-9]+]]:_(p0) = G_PTR_ADD %0, [[CST2]](s64)
866; CHECK: [[LD3:%[0-9]+]]:_(s32) = G_LOAD [[GEP2]](p0) :: (load 4 from %ir.addr + 8)
867; CHECK: [[CST3:%[0-9]+]]:_(s64) = G_CONSTANT i64 12
868; CHECK: [[GEP3:%[0-9]+]]:_(p0) = G_PTR_ADD %0, [[CST3]](s64)
869; CHECK: [[LD4:%[0-9]+]]:_(s32) = G_LOAD [[GEP3]](p0) :: (load 4 from %ir.addr + 12)
870; CHECK: G_STORE [[LD1]](s8), %0(p0) :: (store 1 into %ir.addr, align 4)
871; CHECK: [[GEP4:%[0-9]+]]:_(p0) = G_PTR_ADD %0, [[CST1]](s64)
872; CHECK: G_STORE [[LD2]](s8), [[GEP4]](p0) :: (store 1 into %ir.addr + 4, align 4)
873; CHECK: [[GEP5:%[0-9]+]]:_(p0) = G_PTR_ADD %0, [[CST2]](s64)
874; CHECK: G_STORE %1(s32), [[GEP5]](p0) :: (store 4 into %ir.addr + 8)
875; CHECK: [[GEP6:%[0-9]+]]:_(p0) = G_PTR_ADD %0, [[CST3]](s64)
876; CHECK: G_STORE [[LD4]](s32), [[GEP6]](p0) :: (store 4 into %ir.addr + 12)
877define void @test_insertvalue(%struct.nested* %addr, i32 %val) {
878  %struct = load %struct.nested, %struct.nested* %addr
879  %newstruct = insertvalue %struct.nested %struct, i32 %val, 1, 1
880  store %struct.nested %newstruct, %struct.nested* %addr
881  ret void
882}
883
884define [1 x i64] @test_trivial_insert([1 x i64] %s, i64 %val) {
885; CHECK-LABEL: name: test_trivial_insert
886; CHECK: [[STRUCT:%[0-9]+]]:_(s64) = COPY $x0
887; CHECK: [[VAL:%[0-9]+]]:_(s64) = COPY $x1
888; CHECK: $x0 = COPY [[VAL]]
889  %res = insertvalue [1 x i64] %s, i64 %val, 0
890  ret [1 x i64] %res
891}
892
893define [1 x i8*] @test_trivial_insert_ptr([1 x i8*] %s, i8* %val) {
894; CHECK-LABEL: name: test_trivial_insert_ptr
895; CHECK: [[STRUCT:%[0-9]+]]:_(p0) = COPY $x0
896; CHECK: [[VAL:%[0-9]+]]:_(p0) = COPY $x1
897; CHECK: $x0 = COPY [[VAL]]
898  %res = insertvalue [1 x i8*] %s, i8* %val, 0
899  ret [1 x i8*] %res
900}
901
902; CHECK-LABEL: name: test_insertvalue_agg
903; CHECK: %0:_(p0) = COPY $x0
904; CHECK: %1:_(p0) = COPY $x1
905; CHECK: [[LD1:%[0-9]+]]:_(s8) = G_LOAD %1(p0) :: (load 1 from %ir.addr2, align 4)
906; CHECK: [[CST1:%[0-9]+]]:_(s64) = G_CONSTANT i64 4
907; CHECK: [[GEP1:%[0-9]+]]:_(p0) = G_PTR_ADD %1, [[CST1]](s64)
908; CHECK: [[LD2:%[0-9]+]]:_(s32) = G_LOAD [[GEP1]](p0) :: (load 4 from %ir.addr2 + 4)
909; CHECK: [[LD3:%[0-9]+]]:_(s8) = G_LOAD %0(p0) :: (load 1 from %ir.addr, align 4)
910; CHECK: [[GEP2:%[0-9]+]]:_(p0) = G_PTR_ADD %0, [[CST1]](s64)
911; CHECK: [[LD4:%[0-9]+]]:_(s8) = G_LOAD [[GEP2]](p0) :: (load 1 from %ir.addr + 4, align 4)
912; CHECK: [[CST3:%[0-9]+]]:_(s64) = G_CONSTANT i64 8
913; CHECK: [[GEP3:%[0-9]+]]:_(p0) = G_PTR_ADD %0, [[CST3]](s64)
914; CHECK: [[LD5:%[0-9]+]]:_(s32) = G_LOAD [[GEP3]](p0) :: (load 4 from %ir.addr + 8)
915; CHECK: [[CST4:%[0-9]+]]:_(s64) = G_CONSTANT i64 12
916; CHECK: [[GEP4:%[0-9]+]]:_(p0) = G_PTR_ADD %0, [[CST4]](s64)
917; CHECK: [[LD6:%[0-9]+]]:_(s32) = G_LOAD [[GEP4]](p0) :: (load 4 from %ir.addr + 12)
918; CHECK: G_STORE [[LD3]](s8), %0(p0) :: (store 1 into %ir.addr, align 4)
919; CHECK: [[GEP5:%[0-9]+]]:_(p0) = G_PTR_ADD %0, [[CST1]](s64)
920; CHECK: G_STORE [[LD1]](s8), [[GEP5]](p0) :: (store 1 into %ir.addr + 4, align 4)
921; CHECK: [[GEP6:%[0-9]+]]:_(p0) = G_PTR_ADD %0, [[CST3]](s64)
922; CHECK: G_STORE [[LD2]](s32), [[GEP6]](p0) :: (store 4 into %ir.addr + 8)
923; CHECK: [[GEP7:%[0-9]+]]:_(p0) = G_PTR_ADD %0, [[CST4]](s64)
924; CHECK: G_STORE [[LD6]](s32), [[GEP7]](p0) :: (store 4 into %ir.addr + 12)
925define void @test_insertvalue_agg(%struct.nested* %addr, {i8, i32}* %addr2) {
926  %smallstruct = load {i8, i32}, {i8, i32}* %addr2
927  %struct = load %struct.nested, %struct.nested* %addr
928  %res = insertvalue %struct.nested %struct, {i8, i32} %smallstruct, 1
929  store %struct.nested %res, %struct.nested* %addr
930  ret void
931}
932
933; CHECK-LABEL: name: test_select
934; CHECK: [[TST_C:%[0-9]+]]:_(s32) = COPY $w0
935; CHECK: [[TST:%[0-9]+]]:_(s1) = G_TRUNC [[TST_C]]
936; CHECK: [[LHS:%[0-9]+]]:_(s32) = COPY $w1
937; CHECK: [[RHS:%[0-9]+]]:_(s32) = COPY $w2
938; CHECK: [[RES:%[0-9]+]]:_(s32) = G_SELECT [[TST]](s1), [[LHS]], [[RHS]]
939; CHECK: $w0 = COPY [[RES]]
940define i32 @test_select(i1 %tst, i32 %lhs, i32 %rhs) {
941  %res = select i1 %tst, i32 %lhs, i32 %rhs
942  ret i32 %res
943}
944
945; CHECK-LABEL: name: test_select_flags
946; CHECK:   [[COPY:%[0-9]+]]:_(s32) = COPY $w0
947; CHECK:   [[TRUNC:%[0-9]+]]:_(s1) = G_TRUNC [[COPY]](s32)
948; CHECK:   [[COPY1:%[0-9]+]]:_(s32) = COPY $s0
949; CHECK:   [[COPY2:%[0-9]+]]:_(s32) = COPY $s1
950; CHECK:   [[SELECT:%[0-9]+]]:_(s32) = nnan G_SELECT [[TRUNC]](s1), [[COPY1]], [[COPY2]]
951define float @test_select_flags(i1 %tst, float %lhs, float %rhs) {
952  %res = select nnan i1 %tst, float %lhs, float %rhs
953  ret float %res
954}
955
956; Don't take the flags from the compare condition
957; CHECK-LABEL: name: test_select_cmp_flags
958; CHECK:   [[COPY0:%[0-9]+]]:_(s32) = COPY $s0
959; CHECK:   [[COPY1:%[0-9]+]]:_(s32) = COPY $s1
960; CHECK:   [[COPY2:%[0-9]+]]:_(s32) = COPY $s2
961; CHECK:   [[COPY3:%[0-9]+]]:_(s32) = COPY $s3
962; CHECK:   [[CMP:%[0-9]+]]:_(s1) = nsz G_FCMP floatpred(oeq), [[COPY0]](s32), [[COPY1]]
963; CHECK:   [[SELECT:%[0-9]+]]:_(s32) = G_SELECT [[CMP]](s1), [[COPY2]], [[COPY3]]
964define float @test_select_cmp_flags(float %cmp0, float %cmp1, float %lhs, float %rhs) {
965  %tst = fcmp nsz oeq float %cmp0, %cmp1
966  %res = select i1 %tst, float %lhs, float %rhs
967  ret float %res
968}
969
970; CHECK-LABEL: name: test_select_ptr
971; CHECK: [[TST_C:%[0-9]+]]:_(s32) = COPY $w0
972; CHECK: [[TST:%[0-9]+]]:_(s1) = G_TRUNC [[TST_C]]
973; CHECK: [[LHS:%[0-9]+]]:_(p0) = COPY $x1
974; CHECK: [[RHS:%[0-9]+]]:_(p0) = COPY $x2
975; CHECK: [[RES:%[0-9]+]]:_(p0) = G_SELECT [[TST]](s1), [[LHS]], [[RHS]]
976; CHECK: $x0 = COPY [[RES]]
977define i8* @test_select_ptr(i1 %tst, i8* %lhs, i8* %rhs) {
978  %res = select i1 %tst, i8* %lhs, i8* %rhs
979  ret i8* %res
980}
981
982; CHECK-LABEL: name: test_select_vec
983; CHECK: [[TST_C:%[0-9]+]]:_(s32) = COPY $w0
984; CHECK: [[TST:%[0-9]+]]:_(s1) = G_TRUNC [[TST_C]]
985; CHECK: [[LHS:%[0-9]+]]:_(<4 x s32>) = COPY $q0
986; CHECK: [[RHS:%[0-9]+]]:_(<4 x s32>) = COPY $q1
987; CHECK: [[RES:%[0-9]+]]:_(<4 x s32>) = G_SELECT [[TST]](s1), [[LHS]], [[RHS]]
988; CHECK: $q0 = COPY [[RES]]
989define <4 x i32> @test_select_vec(i1 %tst, <4 x i32> %lhs, <4 x i32> %rhs) {
990  %res = select i1 %tst, <4 x i32> %lhs, <4 x i32> %rhs
991  ret <4 x i32> %res
992}
993
994; CHECK-LABEL: name: test_vselect_vec
995; CHECK: [[TST32:%[0-9]+]]:_(<4 x s32>) = COPY $q0
996; CHECK: [[LHS:%[0-9]+]]:_(<4 x s32>) = COPY $q1
997; CHECK: [[RHS:%[0-9]+]]:_(<4 x s32>) = COPY $q2
998; CHECK: [[TST:%[0-9]+]]:_(<4 x s1>) = G_TRUNC [[TST32]](<4 x s32>)
999; CHECK: [[RES:%[0-9]+]]:_(<4 x s32>) = G_SELECT [[TST]](<4 x s1>), [[LHS]], [[RHS]]
1000; CHECK: $q0 = COPY [[RES]]
1001define <4 x i32> @test_vselect_vec(<4 x i32> %tst32, <4 x i32> %lhs, <4 x i32> %rhs) {
1002  %tst = trunc <4 x i32> %tst32 to <4 x i1>
1003  %res = select <4 x i1> %tst, <4 x i32> %lhs, <4 x i32> %rhs
1004  ret <4 x i32> %res
1005}
1006
1007; CHECK-LABEL: name: test_fptosi
1008; CHECK: [[FPADDR:%[0-9]+]]:_(p0) = COPY $x0
1009; CHECK: [[FP:%[0-9]+]]:_(s32) = G_LOAD [[FPADDR]](p0)
1010; CHECK: [[RES:%[0-9]+]]:_(s64) = G_FPTOSI [[FP]](s32)
1011; CHECK: $x0 = COPY [[RES]]
1012define i64 @test_fptosi(float* %fp.addr) {
1013  %fp = load float, float* %fp.addr
1014  %res = fptosi float %fp to i64
1015  ret i64 %res
1016}
1017
1018; CHECK-LABEL: name: test_fptoui
1019; CHECK: [[FPADDR:%[0-9]+]]:_(p0) = COPY $x0
1020; CHECK: [[FP:%[0-9]+]]:_(s32) = G_LOAD [[FPADDR]](p0)
1021; CHECK: [[RES:%[0-9]+]]:_(s64) = G_FPTOUI [[FP]](s32)
1022; CHECK: $x0 = COPY [[RES]]
1023define i64 @test_fptoui(float* %fp.addr) {
1024  %fp = load float, float* %fp.addr
1025  %res = fptoui float %fp to i64
1026  ret i64 %res
1027}
1028
1029; CHECK-LABEL: name: test_sitofp
1030; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
1031; CHECK: [[IN:%[0-9]+]]:_(s32) = COPY $w1
1032; CHECK: [[FP:%[0-9]+]]:_(s64) = G_SITOFP [[IN]](s32)
1033; CHECK: G_STORE [[FP]](s64), [[ADDR]](p0)
1034define void @test_sitofp(double* %addr, i32 %in) {
1035  %fp = sitofp i32 %in to double
1036  store double %fp, double* %addr
1037  ret void
1038}
1039
1040; CHECK-LABEL: name: test_uitofp
1041; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
1042; CHECK: [[IN:%[0-9]+]]:_(s32) = COPY $w1
1043; CHECK: [[FP:%[0-9]+]]:_(s64) = G_UITOFP [[IN]](s32)
1044; CHECK: G_STORE [[FP]](s64), [[ADDR]](p0)
1045define void @test_uitofp(double* %addr, i32 %in) {
1046  %fp = uitofp i32 %in to double
1047  store double %fp, double* %addr
1048  ret void
1049}
1050
1051; CHECK-LABEL: name: test_fpext
1052; CHECK: [[IN:%[0-9]+]]:_(s32) = COPY $s0
1053; CHECK: [[RES:%[0-9]+]]:_(s64) = G_FPEXT [[IN]](s32)
1054; CHECK: $d0 = COPY [[RES]]
1055define double @test_fpext(float %in) {
1056  %res = fpext float %in to double
1057  ret double %res
1058}
1059
1060; CHECK-LABEL: name: test_fptrunc
1061; CHECK: [[IN:%[0-9]+]]:_(s64) = COPY $d0
1062; CHECK: [[RES:%[0-9]+]]:_(s32) = G_FPTRUNC [[IN]](s64)
1063; CHECK: $s0 = COPY [[RES]]
1064define float @test_fptrunc(double %in) {
1065  %res = fptrunc double %in to float
1066  ret float %res
1067}
1068
1069; CHECK-LABEL: name: test_constant_float
1070; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
1071; CHECK: [[TMP:%[0-9]+]]:_(s32) = G_FCONSTANT float 1.500000e+00
1072; CHECK: G_STORE [[TMP]](s32), [[ADDR]](p0)
1073define void @test_constant_float(float* %addr) {
1074  store float 1.5, float* %addr
1075  ret void
1076}
1077
1078; CHECK-LABEL: name: float_comparison
1079; CHECK: [[LHSADDR:%[0-9]+]]:_(p0) = COPY $x0
1080; CHECK: [[RHSADDR:%[0-9]+]]:_(p0) = COPY $x1
1081; CHECK: [[BOOLADDR:%[0-9]+]]:_(p0) = COPY $x2
1082; CHECK: [[LHS:%[0-9]+]]:_(s32) = G_LOAD [[LHSADDR]](p0)
1083; CHECK: [[RHS:%[0-9]+]]:_(s32) = G_LOAD [[RHSADDR]](p0)
1084; CHECK: [[TST:%[0-9]+]]:_(s1) = nnan ninf nsz arcp contract afn reassoc G_FCMP floatpred(oge), [[LHS]](s32), [[RHS]]
1085; CHECK: G_STORE [[TST]](s1), [[BOOLADDR]](p0)
1086define void @float_comparison(float* %a.addr, float* %b.addr, i1* %bool.addr) {
1087  %a = load float, float* %a.addr
1088  %b = load float, float* %b.addr
1089  %res = fcmp nnan ninf nsz arcp contract afn reassoc oge float %a, %b
1090  store i1 %res, i1* %bool.addr
1091  ret void
1092}
1093
1094; CHECK-LABEL: name: trivial_float_comparison
1095; CHECK: [[ENTRY_R1:%[0-9]+]]:_(s1) = G_CONSTANT i1 false
1096; CHECK: [[ENTRY_R2:%[0-9]+]]:_(s1) = G_CONSTANT i1 true
1097; CHECK: [[R1:%[0-9]+]]:_(s1) = COPY [[ENTRY_R1]](s1)
1098; CHECK: [[R2:%[0-9]+]]:_(s1) = COPY [[ENTRY_R2]](s1)
1099; CHECK: G_ADD [[R1]], [[R2]]
1100define i1 @trivial_float_comparison(double %a, double %b) {
1101  %r1 = fcmp false double %a, %b
1102  %r2 = fcmp true double %a, %b
1103  %sum = add i1 %r1, %r2
1104  ret i1 %sum
1105}
1106
1107@var = global i32 0
1108
1109define i32* @test_global() {
1110; CHECK-LABEL: name: test_global
1111; CHECK: [[TMP:%[0-9]+]]:_(p0) = G_GLOBAL_VALUE @var{{$}}
1112; CHECK: $x0 = COPY [[TMP]](p0)
1113
1114  ret i32* @var
1115}
1116
1117@var1 = addrspace(42) global i32 0
1118define i32 addrspace(42)* @test_global_addrspace() {
1119; CHECK-LABEL: name: test_global
1120; CHECK: [[TMP:%[0-9]+]]:_(p42) = G_GLOBAL_VALUE @var1{{$}}
1121; CHECK: $x0 = COPY [[TMP]](p42)
1122
1123  ret i32 addrspace(42)* @var1
1124}
1125
1126
1127define void()* @test_global_func() {
1128; CHECK-LABEL: name: test_global_func
1129; CHECK: [[TMP:%[0-9]+]]:_(p0) = G_GLOBAL_VALUE @allocai64{{$}}
1130; CHECK: $x0 = COPY [[TMP]](p0)
1131
1132  ret void()* @allocai64
1133}
1134
1135declare void @llvm.memcpy.p0i8.p0i8.i64(i8*, i8*, i64, i1)
1136define void @test_memcpy(i8* %dst, i8* %src, i64 %size) {
1137; CHECK-LABEL: name: test_memcpy
1138; CHECK: [[DST:%[0-9]+]]:_(p0) = COPY $x0
1139; CHECK: [[SRC:%[0-9]+]]:_(p0) = COPY $x1
1140; CHECK: [[SIZE:%[0-9]+]]:_(s64) = COPY $x2
1141; CHECK: G_MEMCPY [[DST]](p0), [[SRC]](p0), [[SIZE]](s64), 0 :: (store 1 into %ir.dst), (load 1 from %ir.src)
1142  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %size, i1 0)
1143  ret void
1144}
1145
1146define void @test_memcpy_tail(i8* %dst, i8* %src, i64 %size) {
1147; CHECK-LABEL: name: test_memcpy_tail
1148; CHECK: [[DST:%[0-9]+]]:_(p0) = COPY $x0
1149; CHECK: [[SRC:%[0-9]+]]:_(p0) = COPY $x1
1150; CHECK: [[SIZE:%[0-9]+]]:_(s64) = COPY $x2
1151; CHECK: G_MEMCPY [[DST]](p0), [[SRC]](p0), [[SIZE]](s64), 1 :: (store 1 into %ir.dst), (load 1 from %ir.src)
1152  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %size, i1 0)
1153  ret void
1154}
1155
1156declare void @llvm.memcpy.p1i8.p1i8.i64(i8 addrspace(1)*, i8 addrspace(1)*, i64, i1)
1157define void @test_memcpy_nonzero_as(i8 addrspace(1)* %dst, i8 addrspace(1) * %src, i64 %size) {
1158; CHECK-LABEL: name: test_memcpy_nonzero_as
1159; CHECK: [[DST:%[0-9]+]]:_(p1) = COPY $x0
1160; CHECK: [[SRC:%[0-9]+]]:_(p1) = COPY $x1
1161; CHECK: [[SIZE:%[0-9]+]]:_(s64) = COPY $x2
1162; CHECK: G_MEMCPY [[DST]](p1), [[SRC]](p1), [[SIZE]](s64), 0 :: (store 1 into %ir.dst, addrspace 1), (load 1 from %ir.src, addrspace 1)
1163  call void @llvm.memcpy.p1i8.p1i8.i64(i8 addrspace(1)* %dst, i8 addrspace(1)* %src, i64 %size, i1 0)
1164  ret void
1165}
1166
1167declare void @llvm.memmove.p0i8.p0i8.i64(i8*, i8*, i64, i1)
1168define void @test_memmove(i8* %dst, i8* %src, i64 %size) {
1169; CHECK-LABEL: name: test_memmove
1170; CHECK: [[DST:%[0-9]+]]:_(p0) = COPY $x0
1171; CHECK: [[SRC:%[0-9]+]]:_(p0) = COPY $x1
1172; CHECK: [[SIZE:%[0-9]+]]:_(s64) = COPY $x2
1173; CHECK: G_MEMMOVE [[DST]](p0), [[SRC]](p0), [[SIZE]](s64), 0 :: (store 1 into %ir.dst), (load 1 from %ir.src)
1174  call void @llvm.memmove.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %size, i1 0)
1175  ret void
1176}
1177
1178declare void @llvm.memset.p0i8.i64(i8*, i8, i64, i1)
1179define void @test_memset(i8* %dst, i8 %val, i64 %size) {
1180; CHECK-LABEL: name: test_memset
1181; CHECK: [[DST:%[0-9]+]]:_(p0) = COPY $x0
1182; CHECK: [[SRC_C:%[0-9]+]]:_(s32) = COPY $w1
1183; CHECK: [[SRC:%[0-9]+]]:_(s8) = G_TRUNC [[SRC_C]]
1184; CHECK: [[SIZE:%[0-9]+]]:_(s64) = COPY $x2
1185; CHECK: G_MEMSET [[DST]](p0), [[SRC]](s8), [[SIZE]](s64), 0 :: (store 1 into %ir.dst)
1186  call void @llvm.memset.p0i8.i64(i8* %dst, i8 %val, i64 %size, i1 0)
1187  ret void
1188}
1189
1190define void @test_large_const(i128* %addr) {
1191; CHECK-LABEL: name: test_large_const
1192; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
1193; CHECK: [[VAL:%[0-9]+]]:_(s128) = G_CONSTANT i128 42
1194; CHECK: G_STORE [[VAL]](s128), [[ADDR]](p0)
1195  store i128 42, i128* %addr
1196  ret void
1197}
1198
1199; When there was no formal argument handling (so the first BB was empty) we used
1200; to insert the constants at the end of the block, even if they were encountered
1201; after the block's terminators had been emitted. Also make sure the order is
1202; correct.
1203define i8* @test_const_placement() {
1204; CHECK-LABEL: name: test_const_placement
1205; CHECK: bb.{{[0-9]+}} (%ir-block.{{[0-9]+}}):
1206; CHECK:   [[VAL_INT:%[0-9]+]]:_(s32) = G_CONSTANT i32 42
1207; CHECK:   [[VAL:%[0-9]+]]:_(p0) = G_INTTOPTR [[VAL_INT]](s32)
1208; CHECK: bb.{{[0-9]+}}.{{[a-zA-Z0-9.]+}}:
1209  br label %next
1210
1211next:
1212  ret i8* inttoptr(i32 42 to i8*)
1213}
1214
1215declare void @llvm.va_end(i8*)
1216define void @test_va_end(i8* %list) {
1217; CHECK-LABEL: name: test_va_end
1218; CHECK-NOT: va_end
1219; CHECK-NOT: INTRINSIC
1220; CHECK: RET_ReallyLR
1221  call void @llvm.va_end(i8* %list)
1222  ret void
1223}
1224
1225define void @test_va_arg(i8* %list) {
1226; CHECK-LABEL: test_va_arg
1227; CHECK: [[LIST:%[0-9]+]]:_(p0) = COPY $x0
1228; CHECK: G_VAARG [[LIST]](p0), 8
1229; CHECK: G_VAARG [[LIST]](p0), 1
1230; CHECK: G_VAARG [[LIST]](p0), 16
1231
1232  %v0 = va_arg i8* %list, i64
1233  %v1 = va_arg i8* %list, i8
1234  %v2 = va_arg i8* %list, i128
1235  ret void
1236}
1237
1238declare float @llvm.pow.f32(float, float)
1239define float @test_pow_intrin(float %l, float %r) {
1240; CHECK-LABEL: name: test_pow_intrin
1241; CHECK: [[LHS:%[0-9]+]]:_(s32) = COPY $s0
1242; CHECK: [[RHS:%[0-9]+]]:_(s32) = COPY $s1
1243; CHECK: [[RES:%[0-9]+]]:_(s32) = nnan ninf nsz arcp contract afn reassoc G_FPOW [[LHS]], [[RHS]]
1244; CHECK: $s0 = COPY [[RES]]
1245  %res = call nnan ninf nsz arcp contract afn reassoc float @llvm.pow.f32(float %l, float %r)
1246  ret float %res
1247}
1248
1249declare float @llvm.powi.f32(float, i32)
1250define float @test_powi_intrin(float %l, i32 %r) {
1251; CHECK-LABEL: name: test_powi_intrin
1252; CHECK: [[LHS:%[0-9]+]]:_(s32) = COPY $s0
1253; CHECK: [[RHS:%[0-9]+]]:_(s32) = COPY $w0
1254; CHECK: [[RES:%[0-9]+]]:_(s32) = nnan ninf nsz arcp contract afn reassoc G_FPOWI [[LHS]], [[RHS]]
1255; CHECK: $s0 = COPY [[RES]]
1256  %res = call nnan ninf nsz arcp contract afn reassoc float @llvm.powi.f32(float %l, i32 %r)
1257  ret float %res
1258}
1259
1260declare float @llvm.fma.f32(float, float, float)
1261define float @test_fma_intrin(float %a, float %b, float %c) {
1262; CHECK-LABEL: name: test_fma_intrin
1263; CHECK: [[A:%[0-9]+]]:_(s32) = COPY $s0
1264; CHECK: [[B:%[0-9]+]]:_(s32) = COPY $s1
1265; CHECK: [[C:%[0-9]+]]:_(s32) = COPY $s2
1266; CHECK: [[RES:%[0-9]+]]:_(s32) = nnan ninf nsz arcp contract afn reassoc G_FMA [[A]], [[B]], [[C]]
1267; CHECK: $s0 = COPY [[RES]]
1268  %res = call nnan ninf nsz arcp contract afn reassoc float @llvm.fma.f32(float %a, float %b, float %c)
1269  ret float %res
1270}
1271
1272declare float @llvm.exp.f32(float)
1273define float @test_exp_intrin(float %a) {
1274; CHECK-LABEL: name: test_exp_intrin
1275; CHECK: [[A:%[0-9]+]]:_(s32) = COPY $s0
1276; CHECK: [[RES:%[0-9]+]]:_(s32) = nnan ninf nsz arcp contract afn reassoc G_FEXP [[A]]
1277; CHECK: $s0 = COPY [[RES]]
1278  %res = call nnan ninf nsz arcp contract afn reassoc float @llvm.exp.f32(float %a)
1279  ret float %res
1280}
1281
1282declare float @llvm.exp2.f32(float)
1283define float @test_exp2_intrin(float %a) {
1284; CHECK-LABEL: name: test_exp2_intrin
1285; CHECK: [[A:%[0-9]+]]:_(s32) = COPY $s0
1286; CHECK: [[RES:%[0-9]+]]:_(s32) = nnan ninf nsz arcp contract afn reassoc G_FEXP2 [[A]]
1287; CHECK: $s0 = COPY [[RES]]
1288  %res = call nnan ninf nsz arcp contract afn reassoc float @llvm.exp2.f32(float %a)
1289  ret float %res
1290}
1291
1292declare float @llvm.log.f32(float)
1293define float @test_log_intrin(float %a) {
1294; CHECK-LABEL: name: test_log_intrin
1295; CHECK: [[A:%[0-9]+]]:_(s32) = COPY $s0
1296; CHECK: [[RES:%[0-9]+]]:_(s32) = nnan ninf nsz arcp contract afn reassoc G_FLOG [[A]]
1297; CHECK: $s0 = COPY [[RES]]
1298  %res = call nnan ninf nsz arcp contract afn reassoc float @llvm.log.f32(float %a)
1299  ret float %res
1300}
1301
1302declare float @llvm.log2.f32(float)
1303define float @test_log2_intrin(float %a) {
1304; CHECK-LABEL: name: test_log2_intrin
1305; CHECK: [[A:%[0-9]+]]:_(s32) = COPY $s0
1306; CHECK: [[RES:%[0-9]+]]:_(s32) = G_FLOG2 [[A]]
1307; CHECK: $s0 = COPY [[RES]]
1308  %res = call float @llvm.log2.f32(float %a)
1309  ret float %res
1310}
1311
1312declare float @llvm.log10.f32(float)
1313define float @test_log10_intrin(float %a) {
1314; CHECK-LABEL: name: test_log10_intrin
1315; CHECK: [[A:%[0-9]+]]:_(s32) = COPY $s0
1316; CHECK: [[RES:%[0-9]+]]:_(s32) = nnan ninf nsz arcp contract afn reassoc G_FLOG10 [[A]]
1317; CHECK: $s0 = COPY [[RES]]
1318  %res = call nnan ninf nsz arcp contract afn reassoc float @llvm.log10.f32(float %a)
1319  ret float %res
1320}
1321
1322declare float @llvm.fabs.f32(float)
1323define float @test_fabs_intrin(float %a) {
1324; CHECK-LABEL: name: test_fabs_intrin
1325; CHECK: [[A:%[0-9]+]]:_(s32) = COPY $s0
1326; CHECK: [[RES:%[0-9]+]]:_(s32) = nnan ninf nsz arcp contract afn reassoc G_FABS [[A]]
1327; CHECK: $s0 = COPY [[RES]]
1328  %res = call nnan ninf nsz arcp contract afn reassoc float @llvm.fabs.f32(float %a)
1329  ret float %res
1330}
1331
1332declare float @llvm.copysign.f32(float, float)
1333define float @test_fcopysign_intrin(float %a, float %b) {
1334; CHECK-LABEL: name: test_fcopysign_intrin
1335; CHECK: [[A:%[0-9]+]]:_(s32) = COPY $s0
1336; CHECK: [[B:%[0-9]+]]:_(s32) = COPY $s1
1337; CHECK: [[RES:%[0-9]+]]:_(s32) = nnan ninf nsz arcp contract afn reassoc G_FCOPYSIGN [[A]], [[B]]
1338; CHECK: $s0 = COPY [[RES]]
1339
1340  %res = call nnan ninf nsz arcp contract afn reassoc float @llvm.copysign.f32(float %a, float %b)
1341  ret float %res
1342}
1343
1344declare float @llvm.canonicalize.f32(float)
1345define float @test_fcanonicalize_intrin(float %a) {
1346; CHECK-LABEL: name: test_fcanonicalize_intrin
1347; CHECK: [[A:%[0-9]+]]:_(s32) = COPY $s0
1348; CHECK: [[RES:%[0-9]+]]:_(s32) = nnan ninf nsz arcp contract afn reassoc G_FCANONICALIZE [[A]]
1349; CHECK: $s0 = COPY [[RES]]
1350  %res = call nnan ninf nsz arcp contract afn reassoc float @llvm.canonicalize.f32(float %a)
1351  ret float %res
1352}
1353
1354declare float @llvm.trunc.f32(float)
1355define float @test_intrinsic_trunc(float %a) {
1356; CHECK-LABEL: name: test_intrinsic_trunc
1357; CHECK: [[A:%[0-9]+]]:_(s32) = COPY $s0
1358; CHECK: [[RES:%[0-9]+]]:_(s32) = G_INTRINSIC_TRUNC [[A]]
1359; CHECK: $s0 = COPY [[RES]]
1360  %res = call float @llvm.trunc.f32(float %a)
1361  ret float %res
1362}
1363
1364declare float @llvm.round.f32(float)
1365define float @test_intrinsic_round(float %a) {
1366; CHECK-LABEL: name: test_intrinsic_round
1367; CHECK: [[A:%[0-9]+]]:_(s32) = COPY $s0
1368; CHECK: [[RES:%[0-9]+]]:_(s32) = G_INTRINSIC_ROUND [[A]]
1369; CHECK: $s0 = COPY [[RES]]
1370  %res = call float @llvm.round.f32(float %a)
1371  ret float %res
1372}
1373
1374declare i32 @llvm.lrint.i32.f32(float)
1375define i32 @test_intrinsic_lrint(float %a) {
1376; CHECK-LABEL: name: test_intrinsic_lrint
1377; CHECK: [[A:%[0-9]+]]:_(s32) = COPY $s0
1378; CHECK: [[RES:%[0-9]+]]:_(s32) = G_INTRINSIC_LRINT [[A]]
1379; CHECK: $w0 = COPY [[RES]]
1380  %res = call i32 @llvm.lrint.i32.f32(float %a)
1381  ret i32 %res
1382}
1383
1384declare i32 @llvm.ctlz.i32(i32, i1)
1385define i32 @test_ctlz_intrinsic_zero_not_undef(i32 %a) {
1386; CHECK-LABEL: name: test_ctlz_intrinsic_zero_not_undef
1387; CHECK: [[A:%[0-9]+]]:_(s32) = COPY $w0
1388; CHECK: [[RES:%[0-9]+]]:_(s32) = G_CTLZ [[A]]
1389; CHECK: $w0 = COPY [[RES]]
1390  %res = call i32 @llvm.ctlz.i32(i32 %a, i1 0)
1391  ret i32 %res
1392}
1393
1394declare i32 @llvm.cttz.i32(i32, i1)
1395define i32 @test_cttz_intrinsic_zero_undef(i32 %a) {
1396; CHECK-LABEL: name: test_cttz_intrinsic_zero_undef
1397; CHECK: [[A:%[0-9]+]]:_(s32) = COPY $w0
1398; CHECK: [[RES:%[0-9]+]]:_(s32) = G_CTTZ_ZERO_UNDEF [[A]]
1399; CHECK: $w0 = COPY [[RES]]
1400  %res = call i32 @llvm.cttz.i32(i32 %a, i1 1)
1401  ret i32 %res
1402}
1403
1404declare i32 @llvm.ctpop.i32(i32)
1405define i32 @test_ctpop_intrinsic(i32 %a) {
1406; CHECK-LABEL: name: test_ctpop
1407; CHECK: [[A:%[0-9]+]]:_(s32) = COPY $w0
1408; CHECK: [[RES:%[0-9]+]]:_(s32) = G_CTPOP [[A]]
1409; CHECK: $w0 = COPY [[RES]]
1410  %res = call i32 @llvm.ctpop.i32(i32 %a)
1411  ret i32 %res
1412}
1413
1414declare i32 @llvm.bitreverse.i32(i32)
1415define i32 @test_bitreverse_intrinsic(i32 %a) {
1416; CHECK-LABEL: name: test_bitreverse
1417; CHECK: [[A:%[0-9]+]]:_(s32) = COPY $w0
1418; CHECK: [[RES:%[0-9]+]]:_(s32) = G_BITREVERSE [[A]]
1419; CHECK: $w0 = COPY [[RES]]
1420  %res = call i32 @llvm.bitreverse.i32(i32 %a)
1421  ret i32 %res
1422}
1423
1424declare i32 @llvm.fshl.i32(i32, i32, i32)
1425define i32 @test_fshl_intrinsic(i32 %a, i32 %b, i32 %c) {
1426; CHECK-LABEL: name: test_fshl_intrinsic
1427; CHECK: [[A:%[0-9]+]]:_(s32) = COPY $w0
1428; CHECK: [[B:%[0-9]+]]:_(s32) = COPY $w1
1429; CHECK: [[C:%[0-9]+]]:_(s32) = COPY $w2
1430; CHECK: [[RES:%[0-9]+]]:_(s32) = G_FSHL [[A]], [[B]], [[C]]
1431; CHECK: $w0 = COPY [[RES]]
1432  %res = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
1433  ret i32 %res
1434}
1435
1436declare i32 @llvm.fshr.i32(i32, i32, i32)
1437define i32 @test_fshr_intrinsic(i32 %a, i32 %b, i32 %c) {
1438; CHECK-LABEL: name: test_fshr_intrinsic
1439; CHECK: [[A:%[0-9]+]]:_(s32) = COPY $w0
1440; CHECK: [[B:%[0-9]+]]:_(s32) = COPY $w1
1441; CHECK: [[C:%[0-9]+]]:_(s32) = COPY $w2
1442; CHECK: [[RES:%[0-9]+]]:_(s32) = G_FSHR [[A]], [[B]], [[C]]
1443; CHECK: $w0 = COPY [[RES]]
1444  %res = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c)
1445  ret i32 %res
1446}
1447
1448declare void @llvm.lifetime.start.p0i8(i64, i8*)
1449declare void @llvm.lifetime.end.p0i8(i64, i8*)
1450define void @test_lifetime_intrin() {
1451; CHECK-LABEL: name: test_lifetime_intrin
1452; CHECK: RET_ReallyLR
1453; O3-LABEL: name: test_lifetime_intrin
1454; O3: {{%[0-9]+}}:_(p0) = G_FRAME_INDEX %stack.0.slot
1455; O3-NEXT: LIFETIME_START %stack.0.slot
1456; O3-NEXT: LIFETIME_END %stack.0.slot
1457; O3-NEXT: RET_ReallyLR
1458  %slot = alloca i8, i32 4
1459  call void @llvm.lifetime.start.p0i8(i64 0, i8* %slot)
1460  call void @llvm.lifetime.end.p0i8(i64 0, i8* %slot)
1461  ret void
1462}
1463
1464define void @test_load_store_atomics(i8* %addr) {
1465; CHECK-LABEL: name: test_load_store_atomics
1466; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
1467; CHECK: [[V0:%[0-9]+]]:_(s8) = G_LOAD [[ADDR]](p0) :: (load unordered 1 from %ir.addr)
1468; CHECK: G_STORE [[V0]](s8), [[ADDR]](p0) :: (store monotonic 1 into %ir.addr)
1469; CHECK: [[V1:%[0-9]+]]:_(s8) = G_LOAD [[ADDR]](p0) :: (load acquire 1 from %ir.addr)
1470; CHECK: G_STORE [[V1]](s8), [[ADDR]](p0) :: (store release 1 into %ir.addr)
1471; CHECK: [[V2:%[0-9]+]]:_(s8) = G_LOAD [[ADDR]](p0) :: (load syncscope("singlethread") seq_cst 1 from %ir.addr)
1472; CHECK: G_STORE [[V2]](s8), [[ADDR]](p0) :: (store syncscope("singlethread") monotonic 1 into %ir.addr)
1473  %v0 = load atomic i8, i8* %addr unordered, align 1
1474  store atomic i8 %v0, i8* %addr monotonic, align 1
1475
1476  %v1 = load atomic i8, i8* %addr acquire, align 1
1477  store atomic i8 %v1, i8* %addr release, align 1
1478
1479  %v2 = load atomic i8, i8* %addr syncscope("singlethread") seq_cst, align 1
1480  store atomic i8 %v2, i8* %addr syncscope("singlethread") monotonic, align 1
1481
1482  ret void
1483}
1484
1485define float @test_fneg_f32(float %x) {
1486; CHECK-LABEL: name: test_fneg_f32
1487; CHECK: [[ARG:%[0-9]+]]:_(s32) = COPY $s0
1488; CHECK: [[RES:%[0-9]+]]:_(s32) = G_FNEG [[ARG]]
1489; CHECK: $s0 = COPY [[RES]](s32)
1490  %neg = fneg float %x
1491  ret float %neg
1492}
1493
1494define float @test_fneg_f32_fmf(float %x) {
1495; CHECK-LABEL: name: test_fneg_f32
1496; CHECK: [[ARG:%[0-9]+]]:_(s32) = COPY $s0
1497; CHECK: [[RES:%[0-9]+]]:_(s32) = nnan ninf nsz arcp contract afn reassoc G_FNEG [[ARG]]
1498; CHECK: $s0 = COPY [[RES]](s32)
1499  %neg = fneg fast float %x
1500  ret float %neg
1501}
1502
1503define double @test_fneg_f64(double %x) {
1504; CHECK-LABEL: name: test_fneg_f64
1505; CHECK: [[ARG:%[0-9]+]]:_(s64) = COPY $d0
1506; CHECK: [[RES:%[0-9]+]]:_(s64) = G_FNEG [[ARG]]
1507; CHECK: $d0 = COPY [[RES]](s64)
1508  %neg = fneg double %x
1509  ret double %neg
1510}
1511
1512define double @test_fneg_f64_fmf(double %x) {
1513; CHECK-LABEL: name: test_fneg_f64
1514; CHECK: [[ARG:%[0-9]+]]:_(s64) = COPY $d0
1515; CHECK: [[RES:%[0-9]+]]:_(s64) = nnan ninf nsz arcp contract afn reassoc G_FNEG [[ARG]]
1516; CHECK: $d0 = COPY [[RES]](s64)
1517  %neg = fneg fast double %x
1518  ret double %neg
1519}
1520
1521define void @test_trivial_inlineasm() {
1522; CHECK-LABEL: name: test_trivial_inlineasm
1523; CHECK: INLINEASM &wibble, 1
1524; CHECK: INLINEASM &wibble, 0
1525  call void asm sideeffect "wibble", ""()
1526  call void asm "wibble", ""()
1527  ret void
1528}
1529
1530define <2 x i32> @test_insertelement(<2 x i32> %vec, i32 %elt, i32 %idx){
1531; CHECK-LABEL: name: test_insertelement
1532; CHECK: [[VEC:%[0-9]+]]:_(<2 x s32>) = COPY $d0
1533; CHECK: [[ELT:%[0-9]+]]:_(s32) = COPY $w0
1534; CHECK: [[IDX:%[0-9]+]]:_(s32) = COPY $w1
1535; CHECK: [[RES:%[0-9]+]]:_(<2 x s32>) = G_INSERT_VECTOR_ELT [[VEC]], [[ELT]](s32), [[IDX]](s32)
1536; CHECK: $d0 = COPY [[RES]](<2 x s32>)
1537  %res = insertelement <2 x i32> %vec, i32 %elt, i32 %idx
1538  ret <2 x i32> %res
1539}
1540
1541define i32 @test_extractelement(<2 x i32> %vec, i32 %idx) {
1542; CHECK-LABEL: name: test_extractelement
1543; CHECK: [[VEC:%[0-9]+]]:_(<2 x s32>) = COPY $d0
1544; CHECK: [[IDX:%[0-9]+]]:_(s32) = COPY $w0
1545; CHECK: [[IDXEXT:%[0-9]+]]:_(s64) = G_SEXT [[IDX]]
1546; CHECK: [[RES:%[0-9]+]]:_(s32) = G_EXTRACT_VECTOR_ELT [[VEC]](<2 x s32>), [[IDXEXT]](s64)
1547; CHECK: $w0 = COPY [[RES]](s32)
1548  %res = extractelement <2 x i32> %vec, i32 %idx
1549  ret i32 %res
1550}
1551
1552define i32 @test_extractelement_const_idx(<2 x i32> %vec) {
1553; CHECK-LABEL: name: test_extractelement
1554; CHECK: [[VEC:%[0-9]+]]:_(<2 x s32>) = COPY $d0
1555; CHECK: [[IDX:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
1556; CHECK: [[RES:%[0-9]+]]:_(s32) = G_EXTRACT_VECTOR_ELT [[VEC]](<2 x s32>), [[IDX]](s64)
1557; CHECK: $w0 = COPY [[RES]](s32)
1558  %res = extractelement <2 x i32> %vec, i32 1
1559  ret i32 %res
1560}
1561
1562define i32 @test_singleelementvector(i32 %elt){
1563; CHECK-LABEL: name: test_singleelementvector
1564; CHECK: [[ELT:%[0-9]+]]:_(s32) = COPY $w0
1565; CHECK-NOT: G_INSERT_VECTOR_ELT
1566; CHECK-NOT: G_EXTRACT_VECTOR_ELT
1567; CHECK: $w0 = COPY [[ELT]](s32)
1568  %vec = insertelement <1 x i32> undef, i32 %elt, i32 0
1569  %res = extractelement <1 x i32> %vec, i32 0
1570  ret i32 %res
1571}
1572
1573define <2 x i32> @test_constantaggzerovector_v2i32() {
1574; CHECK-LABEL: name: test_constantaggzerovector_v2i32
1575; CHECK: [[ZERO:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
1576; CHECK: [[VEC:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[ZERO]](s32), [[ZERO]](s32)
1577; CHECK: $d0 = COPY [[VEC]](<2 x s32>)
1578  ret <2 x i32> zeroinitializer
1579}
1580
1581define <2 x float> @test_constantaggzerovector_v2f32() {
1582; CHECK-LABEL: name: test_constantaggzerovector_v2f32
1583; CHECK: [[ZERO:%[0-9]+]]:_(s32) = G_FCONSTANT float 0.000000e+00
1584; CHECK: [[VEC:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[ZERO]](s32), [[ZERO]](s32)
1585; CHECK: $d0 = COPY [[VEC]](<2 x s32>)
1586  ret <2 x float> zeroinitializer
1587}
1588
1589define i32 @test_constantaggzerovector_v3i32() {
1590; CHECK-LABEL: name: test_constantaggzerovector_v3i32
1591; CHECK: [[ZERO:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
1592; CHECK: [[VEC:%[0-9]+]]:_(<3 x s32>) = G_BUILD_VECTOR [[ZERO]](s32), [[ZERO]](s32), [[ZERO]](s32)
1593; CHECK: G_EXTRACT_VECTOR_ELT [[VEC]](<3 x s32>)
1594  %elt = extractelement <3 x i32> zeroinitializer, i32 1
1595  ret i32 %elt
1596}
1597
1598define <2 x i32> @test_constantdatavector_v2i32() {
1599; CHECK-LABEL: name: test_constantdatavector_v2i32
1600; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
1601; CHECK: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 2
1602; CHECK: [[VEC:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[C1]](s32), [[C2]](s32)
1603; CHECK: $d0 = COPY [[VEC]](<2 x s32>)
1604  ret <2 x i32> <i32 1, i32 2>
1605}
1606
1607define i32 @test_constantdatavector_v3i32() {
1608; CHECK-LABEL: name: test_constantdatavector_v3i32
1609; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
1610; CHECK: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 2
1611; CHECK: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 3
1612; CHECK: [[VEC:%[0-9]+]]:_(<3 x s32>) = G_BUILD_VECTOR [[C1]](s32), [[C2]](s32), [[C3]](s32)
1613; CHECK: G_EXTRACT_VECTOR_ELT [[VEC]](<3 x s32>)
1614  %elt = extractelement <3 x i32> <i32 1, i32 2, i32 3>, i32 1
1615  ret i32 %elt
1616}
1617
1618define <4 x i32> @test_constantdatavector_v4i32() {
1619; CHECK-LABEL: name: test_constantdatavector_v4i32
1620; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
1621; CHECK: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 2
1622; CHECK: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 3
1623; CHECK: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
1624; CHECK: [[VEC:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C1]](s32), [[C2]](s32), [[C3]](s32), [[C4]](s32)
1625; CHECK: $q0 = COPY [[VEC]](<4 x s32>)
1626  ret <4 x i32> <i32 1, i32 2, i32 3, i32 4>
1627}
1628
1629define <2 x double> @test_constantdatavector_v2f64() {
1630; CHECK-LABEL: name: test_constantdatavector_v2f64
1631; CHECK: [[FC1:%[0-9]+]]:_(s64) = G_FCONSTANT double 1.000000e+00
1632; CHECK: [[FC2:%[0-9]+]]:_(s64) = G_FCONSTANT double 2.000000e+00
1633; CHECK: [[VEC:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[FC1]](s64), [[FC2]](s64)
1634; CHECK: $q0 = COPY [[VEC]](<2 x s64>)
1635  ret <2 x double> <double 1.0, double 2.0>
1636}
1637
1638define i32 @test_constantaggzerovector_v1s32(i32 %arg){
1639; CHECK-LABEL: name: test_constantaggzerovector_v1s32
1640; CHECK: [[ARG:%[0-9]+]]:_(s32) = COPY $w0
1641; CHECK: [[C0:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
1642; CHECK-NOT: G_MERGE_VALUES
1643; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY [[C0]]
1644; CHECK-NOT: G_MERGE_VALUES
1645; CHECK: G_ADD [[ARG]], [[COPY]]
1646  %vec = insertelement <1 x i32> undef, i32 %arg, i32 0
1647  %add = add <1 x i32> %vec, zeroinitializer
1648  %res = extractelement <1 x i32> %add, i32 0
1649  ret i32 %res
1650}
1651
1652define i32 @test_constantdatavector_v1s32(i32 %arg){
1653; CHECK-LABEL: name: test_constantdatavector_v1s32
1654; CHECK: [[ARG:%[0-9]+]]:_(s32) = COPY $w0
1655; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
1656; CHECK-NOT: G_MERGE_VALUES
1657; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY [[C0]]
1658; CHECK-NOT: G_MERGE_VALUES
1659; CHECK: G_ADD [[ARG]], [[COPY]]
1660  %vec = insertelement <1 x i32> undef, i32 %arg, i32 0
1661  %add = add <1 x i32> %vec, <i32 1>
1662  %res = extractelement <1 x i32> %add, i32 0
1663  ret i32 %res
1664}
1665
1666declare ghccc float @different_call_conv_target(float %x)
1667define float @test_different_call_conv_target(float %x) {
1668; CHECK-LABEL: name: test_different_call_conv
1669; CHECK: [[X:%[0-9]+]]:_(s32) = COPY $s0
1670; CHECK: $s8 = COPY [[X]]
1671; CHECK: BL @different_call_conv_target, csr_aarch64_noregs, implicit-def $lr, implicit $sp, implicit $s8, implicit-def $s0
1672  %res = call ghccc float @different_call_conv_target(float %x)
1673  ret float %res
1674}
1675
1676define <2 x i32> @test_shufflevector_s32_v2s32(i32 %arg) {
1677; CHECK-LABEL: name: test_shufflevector_s32_v2s32
1678; CHECK: [[ARG:%[0-9]+]]:_(s32) = COPY $w0
1679; CHECK-DAG: [[UNDEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
1680; CHECK: [[VEC:%[0-9]+]]:_(<2 x s32>) = G_SHUFFLE_VECTOR [[ARG]](s32), [[UNDEF]], shufflemask(0, 0)
1681; CHECK: $d0 = COPY [[VEC]](<2 x s32>)
1682  %vec = insertelement <1 x i32> undef, i32 %arg, i32 0
1683  %res = shufflevector <1 x i32> %vec, <1 x i32> undef, <2 x i32> zeroinitializer
1684  ret <2 x i32> %res
1685}
1686
1687define i32 @test_shufflevector_v2s32_s32(<2 x i32> %arg) {
1688; CHECK-LABEL: name: test_shufflevector_v2s32_s32
1689; CHECK: [[ARG:%[0-9]+]]:_(<2 x s32>) = COPY $d0
1690; CHECK: [[RES:%[0-9]+]]:_(s32) = G_SHUFFLE_VECTOR [[ARG]](<2 x s32>), [[UNDEF]], shufflemask(1)
1691; CHECK: $w0 = COPY [[RES]](s32)
1692  %vec = shufflevector <2 x i32> %arg, <2 x i32> undef, <1 x i32> <i32 1>
1693  %res = extractelement <1 x i32> %vec, i32 0
1694  ret i32 %res
1695}
1696
1697define <2 x i32> @test_shufflevector_v2s32_v2s32_undef(<2 x i32> %arg) {
1698; CHECK-LABEL: name: test_shufflevector_v2s32_v2s32_undef
1699; CHECK: [[ARG:%[0-9]+]]:_(<2 x s32>) = COPY $d0
1700; CHECK-DAG: [[UNDEF:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF
1701; CHECK: [[VEC:%[0-9]+]]:_(<2 x s32>) = G_SHUFFLE_VECTOR [[ARG]](<2 x s32>), [[UNDEF]], shufflemask(undef, undef)
1702; CHECK: $d0 = COPY [[VEC]](<2 x s32>)
1703  %res = shufflevector <2 x i32> %arg, <2 x i32> undef, <2 x i32> undef
1704  ret <2 x i32> %res
1705}
1706
1707define <2 x i32> @test_shufflevector_v2s32_v2s32_undef_0(<2 x i32> %arg) {
1708; CHECK-LABEL: name: test_shufflevector_v2s32_v2s32_undef_0
1709; CHECK: [[ARG:%[0-9]+]]:_(<2 x s32>) = COPY $d0
1710; CHECK-DAG: [[UNDEF:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF
1711; CHECK: [[VEC:%[0-9]+]]:_(<2 x s32>) = G_SHUFFLE_VECTOR [[ARG]](<2 x s32>), [[UNDEF]], shufflemask(undef, 0)
1712; CHECK: $d0 = COPY [[VEC]](<2 x s32>)
1713  %res = shufflevector <2 x i32> %arg, <2 x i32> undef, <2 x i32> <i32 undef, i32 0>
1714  ret <2 x i32> %res
1715}
1716
1717define <2 x i32> @test_shufflevector_v2s32_v2s32_0_undef(<2 x i32> %arg) {
1718; CHECK-LABEL: name: test_shufflevector_v2s32_v2s32_0_undef
1719; CHECK: [[ARG:%[0-9]+]]:_(<2 x s32>) = COPY $d0
1720; CHECK-DAG: [[UNDEF:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF
1721; CHECK: [[VEC:%[0-9]+]]:_(<2 x s32>) = G_SHUFFLE_VECTOR [[ARG]](<2 x s32>), [[UNDEF]], shufflemask(0, undef)
1722; CHECK: $d0 = COPY [[VEC]](<2 x s32>)
1723  %res = shufflevector <2 x i32> %arg, <2 x i32> undef, <2 x i32> <i32 0, i32 undef>
1724  ret <2 x i32> %res
1725}
1726
1727define i32 @test_shufflevector_v2s32_v3s32(<2 x i32> %arg) {
1728; CHECK-LABEL: name: test_shufflevector_v2s32_v3s32
1729; CHECK: [[ARG:%[0-9]+]]:_(<2 x s32>) = COPY $d0
1730; CHECK-DAG: [[UNDEF:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF
1731; CHECK: [[VEC:%[0-9]+]]:_(<3 x s32>) = G_SHUFFLE_VECTOR [[ARG]](<2 x s32>), [[UNDEF]], shufflemask(1, 0, 1)
1732; CHECK: G_EXTRACT_VECTOR_ELT [[VEC]](<3 x s32>)
1733  %vec = shufflevector <2 x i32> %arg, <2 x i32> undef, <3 x i32> <i32 1, i32 0, i32 1>
1734  %res = extractelement <3 x i32> %vec, i32 0
1735  ret i32 %res
1736}
1737
1738define <4 x i32> @test_shufflevector_v2s32_v4s32(<2 x i32> %arg1, <2 x i32> %arg2) {
1739; CHECK-LABEL: name: test_shufflevector_v2s32_v4s32
1740; CHECK: [[ARG1:%[0-9]+]]:_(<2 x s32>) = COPY $d0
1741; CHECK: [[ARG2:%[0-9]+]]:_(<2 x s32>) = COPY $d1
1742; CHECK: [[VEC:%[0-9]+]]:_(<4 x s32>) = G_SHUFFLE_VECTOR [[ARG1]](<2 x s32>), [[ARG2]], shufflemask(0, 1, 2, 3)
1743; CHECK: $q0 = COPY [[VEC]](<4 x s32>)
1744  %res = shufflevector <2 x i32> %arg1, <2 x i32> %arg2, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
1745  ret <4 x i32> %res
1746}
1747
1748define <2 x i32> @test_shufflevector_v4s32_v2s32(<4 x i32> %arg) {
1749; CHECK-LABEL: name: test_shufflevector_v4s32_v2s32
1750; CHECK: [[ARG:%[0-9]+]]:_(<4 x s32>) = COPY $q0
1751; CHECK-DAG: [[UNDEF:%[0-9]+]]:_(<4 x s32>) = G_IMPLICIT_DEF
1752; CHECK: [[VEC:%[0-9]+]]:_(<2 x s32>) = G_SHUFFLE_VECTOR [[ARG]](<4 x s32>), [[UNDEF]], shufflemask(1, 3)
1753; CHECK: $d0 = COPY [[VEC]](<2 x s32>)
1754  %res = shufflevector <4 x i32> %arg, <4 x i32> undef, <2 x i32> <i32 1, i32 3>
1755  ret <2 x i32> %res
1756}
1757
1758
1759define <16 x i8> @test_shufflevector_v8s8_v16s8(<8 x i8> %arg1, <8 x i8> %arg2) {
1760; CHECK-LABEL: name: test_shufflevector_v8s8_v16s8
1761; CHECK: [[ARG1:%[0-9]+]]:_(<8 x s8>) = COPY $d0
1762; CHECK: [[ARG2:%[0-9]+]]:_(<8 x s8>) = COPY $d1
1763; CHECK: [[VEC:%[0-9]+]]:_(<16 x s8>) = G_SHUFFLE_VECTOR [[ARG1]](<8 x s8>), [[ARG2]], shufflemask(0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15)
1764; CHECK: $q0 = COPY [[VEC]](<16 x s8>)
1765  %res = shufflevector <8 x i8> %arg1, <8 x i8> %arg2, <16 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11, i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
1766  ret <16 x i8> %res
1767}
1768
1769; CHECK-LABEL: test_constant_vector
1770; CHECK: [[UNDEF:%[0-9]+]]:_(s16) = G_IMPLICIT_DEF
1771; CHECK: [[F:%[0-9]+]]:_(s16) = G_FCONSTANT half 0xH3C00
1772; CHECK: [[M:%[0-9]+]]:_(<4 x s16>) = G_BUILD_VECTOR [[UNDEF]](s16), [[UNDEF]](s16), [[UNDEF]](s16), [[F]](s16)
1773; CHECK: $d0 = COPY [[M]](<4 x s16>)
1774define <4 x half> @test_constant_vector() {
1775  ret <4 x half> <half undef, half undef, half undef, half 0xH3C00>
1776}
1777
1778define i32 @test_target_mem_intrinsic(i32* %addr) {
1779; CHECK-LABEL: name: test_target_mem_intrinsic
1780; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
1781; CHECK: [[VAL:%[0-9]+]]:_(s64) = G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aarch64.ldxr), [[ADDR]](p0) :: (volatile load 4 from %ir.addr)
1782; CHECK: G_TRUNC [[VAL]](s64)
1783  %val = call i64 @llvm.aarch64.ldxr.p0i32(i32* %addr)
1784  %trunc = trunc i64 %val to i32
1785  ret i32 %trunc
1786}
1787
1788declare i64 @llvm.aarch64.ldxr.p0i32(i32*) nounwind
1789
1790%zerosize_type = type {}
1791
1792define %zerosize_type @test_empty_load_store(%zerosize_type *%ptr, %zerosize_type %in) noinline optnone {
1793; CHECK-LABEL: name: test_empty_load_store
1794; CHECK-NOT: G_STORE
1795; CHECK-NOT: G_LOAD
1796; CHECK: RET_ReallyLR
1797entry:
1798  store %zerosize_type undef, %zerosize_type* undef, align 4
1799  %val = load %zerosize_type, %zerosize_type* %ptr, align 4
1800  ret %zerosize_type %in
1801}
1802
1803
1804define i64 @test_phi_loop(i32 %n) {
1805; CHECK-LABEL: name: test_phi_loop
1806; CHECK: [[ARG1:%[0-9]+]]:_(s32) = COPY $w0
1807; CHECK: [[CST1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
1808; CHECK: [[CST2:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
1809; CHECK: [[CST3:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
1810; CHECK: [[CST4:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
1811
1812; CHECK: [[PN1:%[0-9]+]]:_(s32) = G_PHI [[ARG1]](s32), %bb.1, [[SUB:%[0-9]+]](s32), %bb.2
1813; CHECK: [[PN2:%[0-9]+]]:_(s64) = G_PHI [[CST3]](s64), %bb.1, [[PN3:%[0-9]+]](s64), %bb.2
1814; CHECK: [[PN3]]:_(s64) = G_PHI [[CST4]](s64), %bb.1, [[ADD:%[0-9]+]](s64), %bb.2
1815; CHECK: [[ADD]]:_(s64) = G_ADD [[PN2]], [[PN3]]
1816; CHECK: [[SUB]]:_(s32) = G_SUB [[PN1]], [[CST1]]
1817; CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(sle), [[PN1]](s32), [[CST2]]
1818; CHECK: G_BRCOND [[CMP]](s1), %bb.3
1819; CHECK: G_BR %bb.2
1820
1821; CHECK: $x0 = COPY [[PN2]](s64)
1822; CHECK: RET_ReallyLR implicit $x0
1823entry:
1824  br label %loop
1825
1826loop:
1827  %counter = phi i32 [ %n, %entry ], [ %counter.dec, %loop ]
1828  %elem = phi { i64, i64 } [ { i64 0, i64 1 }, %entry ], [ %updated, %loop ]
1829  %prev = extractvalue { i64, i64 } %elem, 0
1830  %curr = extractvalue { i64, i64 } %elem, 1
1831  %next = add i64 %prev, %curr
1832  %shifted = insertvalue { i64, i64 } %elem, i64 %curr, 0
1833  %updated = insertvalue { i64, i64 } %shifted, i64 %next, 1
1834  %counter.dec = sub i32 %counter, 1
1835  %cond = icmp sle i32 %counter, 0
1836  br i1 %cond, label %exit, label %loop
1837
1838exit:
1839  %res = extractvalue { i64, i64 } %elem, 0
1840  ret i64 %res
1841}
1842
1843define void @test_phi_diamond({ i8, i16, i32 }* %a.ptr, { i8, i16, i32 }* %b.ptr, i1 %selector, { i8, i16, i32 }* %dst) {
1844; CHECK-LABEL: name: test_phi_diamond
1845; CHECK: [[ARG1:%[0-9]+]]:_(p0) = COPY $x0
1846; CHECK: [[ARG2:%[0-9]+]]:_(p0) = COPY $x1
1847; CHECK: [[ARG3:%[0-9]+]]:_(s32) = COPY $w2
1848; CHECK: [[TRUNC:%[0-9]+]]:_(s1) = G_TRUNC [[ARG3]](s32)
1849; CHECK: [[ARG4:%[0-9]+]]:_(p0) = COPY $x3
1850; CHECK: G_BRCOND [[TRUNC]](s1), %bb.2
1851; CHECK: G_BR %bb.3
1852
1853; CHECK: [[LD1:%[0-9]+]]:_(s8) = G_LOAD [[ARG1]](p0) :: (load 1 from %ir.a.ptr, align 4)
1854; CHECK: [[CST1:%[0-9]+]]:_(s64) = G_CONSTANT i64 2
1855; CHECK: [[GEP1:%[0-9]+]]:_(p0) = G_PTR_ADD [[ARG1]], [[CST1]](s64)
1856; CHECK: [[LD2:%[0-9]+]]:_(s16) = G_LOAD [[GEP1]](p0) :: (load 2 from %ir.a.ptr + 2)
1857; CHECK: [[CST2:%[0-9]+]]:_(s64) = G_CONSTANT i64 4
1858; CHECK: [[GEP2:%[0-9]+]]:_(p0) = G_PTR_ADD [[ARG1]], [[CST2]](s64)
1859; CHECK: [[LD3:%[0-9]+]]:_(s32) = G_LOAD [[GEP2]](p0) :: (load 4 from %ir.a.ptr + 4)
1860; CHECK: G_BR %bb.4
1861
1862; CHECK: [[LD4:%[0-9]+]]:_(s8) = G_LOAD [[ARG2]](p0) :: (load 1 from %ir.b.ptr, align 4)
1863; CHECK: [[CST3:%[0-9]+]]:_(s64) = G_CONSTANT i64 2
1864; CHECK: [[GEP3:%[0-9]+]]:_(p0) = G_PTR_ADD [[ARG2]], [[CST3]](s64)
1865; CHECK: [[LD5:%[0-9]+]]:_(s16) = G_LOAD [[GEP3]](p0) :: (load 2 from %ir.b.ptr + 2)
1866; CHECK: [[CST4:%[0-9]+]]:_(s64) = G_CONSTANT i64 4
1867; CHECK: [[GEP4:%[0-9]+]]:_(p0) = G_PTR_ADD [[ARG2]], [[CST4]](s64)
1868; CHECK: [[LD6:%[0-9]+]]:_(s32) = G_LOAD [[GEP4]](p0) :: (load 4 from %ir.b.ptr + 4)
1869
1870; CHECK: [[PN1:%[0-9]+]]:_(s8) = G_PHI [[LD1]](s8), %bb.2, [[LD4]](s8), %bb.3
1871; CHECK: [[PN2:%[0-9]+]]:_(s16) = G_PHI [[LD2]](s16), %bb.2, [[LD5]](s16), %bb.3
1872; CHECK: [[PN3:%[0-9]+]]:_(s32) = G_PHI [[LD3]](s32), %bb.2, [[LD6]](s32), %bb.3
1873; CHECK: G_STORE [[PN1]](s8), [[ARG4]](p0) :: (store 1 into %ir.dst, align 4)
1874; CHECK: [[CST5:%[0-9]+]]:_(s64) = G_CONSTANT i64 2
1875; CHECK: [[GEP5:%[0-9]+]]:_(p0) = G_PTR_ADD [[ARG4]], [[CST5]](s64)
1876; CHECK: G_STORE [[PN2]](s16), [[GEP5]](p0) :: (store 2 into %ir.dst + 2)
1877; CHECK: [[CST6:%[0-9]+]]:_(s64) = G_CONSTANT i64 4
1878; CHECK: [[GEP6:%[0-9]+]]:_(p0) = G_PTR_ADD [[ARG4]], [[CST6]](s64)
1879; CHECK: G_STORE [[PN3]](s32), [[GEP6]](p0) :: (store 4 into %ir.dst + 4)
1880; CHECK: RET_ReallyLR
1881
1882entry:
1883  br i1 %selector, label %store.a, label %store.b
1884
1885store.a:
1886  %a = load { i8, i16, i32 }, { i8, i16, i32 }* %a.ptr
1887  br label %join
1888
1889store.b:
1890  %b = load { i8, i16, i32 }, { i8, i16, i32 }* %b.ptr
1891  br label %join
1892
1893join:
1894  %v = phi { i8, i16, i32 } [ %a, %store.a ], [ %b, %store.b ]
1895  store { i8, i16, i32 } %v, { i8, i16, i32 }* %dst
1896  ret void
1897}
1898
1899%agg.inner.inner = type {i64, i64}
1900%agg.inner = type {i16, i8, %agg.inner.inner }
1901%agg.nested = type {i32, i32, %agg.inner, i32}
1902
1903define void @test_nested_aggregate_const(%agg.nested *%ptr) {
1904; CHECK-LABEL: name: test_nested_aggregate_const
1905; CHECK: [[BASE:%[0-9]+]]:_(p0) = COPY $x0
1906; CHECK: [[CST1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
1907; CHECK: [[CST2:%[0-9]+]]:_(s16) = G_CONSTANT i16 2
1908; CHECK: [[CST3:%[0-9]+]]:_(s8) = G_CONSTANT i8 3
1909; CHECK: [[CST4:%[0-9]+]]:_(s64) = G_CONSTANT i64 5
1910; CHECK: [[CST5:%[0-9]+]]:_(s64) = G_CONSTANT i64 8
1911; CHECK: [[CST6:%[0-9]+]]:_(s32) = G_CONSTANT i32 13
1912; CHECK: G_STORE [[CST1]](s32), [[BASE]](p0) :: (store 4 into %ir.ptr, align 8)
1913; CHECK: [[CST7:%[0-9]+]]:_(s64) = G_CONSTANT i64 4
1914; CHECK: [[GEP1:%[0-9]+]]:_(p0) = G_PTR_ADD [[BASE]], [[CST7]](s64)
1915; CHECK: G_STORE [[CST1]](s32), [[GEP1]](p0) :: (store 4 into %ir.ptr + 4)
1916; CHECK: [[CST8:%[0-9]+]]:_(s64) = G_CONSTANT i64 8
1917; CHECK: [[GEP2:%[0-9]+]]:_(p0) = G_PTR_ADD [[BASE]], [[CST8]](s64)
1918; CHECK: G_STORE [[CST2]](s16), [[GEP2]](p0) :: (store 2 into %ir.ptr + 8, align 8)
1919; CHECK: [[CST9:%[0-9]+]]:_(s64) = G_CONSTANT i64 10
1920; CHECK: [[GEP3:%[0-9]+]]:_(p0) = G_PTR_ADD [[BASE]], [[CST9]](s64)
1921; CHECK: G_STORE [[CST3]](s8), [[GEP3]](p0) :: (store 1 into %ir.ptr + 10, align 2)
1922; CHECK: [[CST10:%[0-9]+]]:_(s64) = G_CONSTANT i64 16
1923; CHECK: [[GEP4:%[0-9]+]]:_(p0) = G_PTR_ADD [[BASE]], [[CST10]](s64)
1924; CHECK: G_STORE [[CST4]](s64), [[GEP4]](p0) :: (store 8 into %ir.ptr + 16)
1925; CHECK: [[CST11:%[0-9]+]]:_(s64) = G_CONSTANT i64 24
1926; CHECK: [[GEP5:%[0-9]+]]:_(p0) = G_PTR_ADD [[BASE]], [[CST11]](s64)
1927; CHECK: G_STORE [[CST5]](s64), [[GEP5]](p0) :: (store 8 into %ir.ptr + 24)
1928; CHECK: [[CST12:%[0-9]+]]:_(s64) = G_CONSTANT i64 32
1929; CHECK: [[GEP6:%[0-9]+]]:_(p0) = G_PTR_ADD [[BASE]], [[CST12]](s64)
1930; CHECK: G_STORE [[CST6]](s32), [[GEP6]](p0) :: (store 4 into %ir.ptr + 32, align 8)
1931  store %agg.nested { i32 1, i32 1, %agg.inner { i16 2, i8 3, %agg.inner.inner {i64 5, i64 8} }, i32 13}, %agg.nested *%ptr
1932  ret void
1933}
1934
1935define i1 @return_i1_zext() {
1936; AAPCS ABI says that booleans can only be 1 or 0, so we need to zero-extend.
1937; CHECK-LABEL: name: return_i1_zext
1938; CHECK: [[CST:%[0-9]+]]:_(s1) = G_CONSTANT i1 true
1939; CHECK: [[ZEXT:%[0-9]+]]:_(s8) = G_ZEXT [[CST]](s1)
1940; CHECK: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[ZEXT]](s8)
1941; CHECK: $w0 = COPY [[ANYEXT]](s32)
1942; CHECK: RET_ReallyLR implicit $w0
1943  ret i1 true
1944}
1945
1946; Try one cmpxchg
1947define i32 @test_atomic_cmpxchg_1(i32* %addr) {
1948; CHECK-LABEL: name: test_atomic_cmpxchg_1
1949; CHECK:       bb.1.entry:
1950; CHECK-NEXT:  successors: %bb.{{[^)]+}}
1951; CHECK-NEXT:  liveins: $x0
1952; CHECK:         [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
1953; CHECK-NEXT:    [[OLDVAL:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
1954; CHECK-NEXT:    [[NEWVAL:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
1955; CHECK:       bb.2.repeat:
1956; CHECK-NEXT:    successors: %bb.3({{[^)]+}}), %bb.2({{[^)]+}})
1957; CHECK:         [[OLDVALRES:%[0-9]+]]:_(s32), [[SUCCESS:%[0-9]+]]:_(s1) = G_ATOMIC_CMPXCHG_WITH_SUCCESS [[ADDR]](p0), [[OLDVAL]], [[NEWVAL]] :: (load store monotonic monotonic 4 on %ir.addr)
1958; CHECK-NEXT:    G_BRCOND [[SUCCESS]](s1), %bb.3
1959; CHECK-NEXT:    G_BR %bb.2
1960; CHECK:       bb.3.done:
1961entry:
1962  br label %repeat
1963repeat:
1964  %val_success = cmpxchg i32* %addr, i32 0, i32 1 monotonic monotonic
1965  %value_loaded = extractvalue { i32, i1 } %val_success, 0
1966  %success = extractvalue { i32, i1 } %val_success, 1
1967  br i1 %success, label %done, label %repeat
1968done:
1969  ret i32 %value_loaded
1970}
1971
1972; Try one cmpxchg
1973define i32 @test_weak_atomic_cmpxchg_1(i32* %addr) {
1974; CHECK-LABEL: name: test_weak_atomic_cmpxchg_1
1975; CHECK:       bb.1.entry:
1976; CHECK-NEXT:  successors: %bb.{{[^)]+}}
1977; CHECK-NEXT:  liveins: $x0
1978; CHECK:         [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
1979; CHECK-NEXT:    [[OLDVAL:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
1980; CHECK-NEXT:    [[NEWVAL:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
1981; CHECK:       bb.2.repeat:
1982; CHECK-NEXT:    successors: %bb.3({{[^)]+}}), %bb.2({{[^)]+}})
1983; CHECK:         [[OLDVALRES:%[0-9]+]]:_(s32), [[SUCCESS:%[0-9]+]]:_(s1) = G_ATOMIC_CMPXCHG_WITH_SUCCESS [[ADDR]](p0), [[OLDVAL]], [[NEWVAL]] :: (load store monotonic monotonic 4 on %ir.addr)
1984; CHECK-NEXT:    G_BRCOND [[SUCCESS]](s1), %bb.3
1985; CHECK-NEXT:    G_BR %bb.2
1986; CHECK:       bb.3.done:
1987entry:
1988  br label %repeat
1989repeat:
1990  %val_success = cmpxchg weak i32* %addr, i32 0, i32 1 monotonic monotonic
1991  %value_loaded = extractvalue { i32, i1 } %val_success, 0
1992  %success = extractvalue { i32, i1 } %val_success, 1
1993  br i1 %success, label %done, label %repeat
1994done:
1995  ret i32 %value_loaded
1996}
1997
1998; Try one cmpxchg with a small type and high atomic ordering.
1999define i16 @test_atomic_cmpxchg_2(i16* %addr) {
2000; CHECK-LABEL: name: test_atomic_cmpxchg_2
2001; CHECK:       bb.1.entry:
2002; CHECK-NEXT:  successors: %bb.2({{[^)]+}})
2003; CHECK-NEXT:  liveins: $x0
2004; CHECK:         [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
2005; CHECK-NEXT:    [[OLDVAL:%[0-9]+]]:_(s16) = G_CONSTANT i16 0
2006; CHECK-NEXT:    [[NEWVAL:%[0-9]+]]:_(s16) = G_CONSTANT i16 1
2007; CHECK:       bb.2.repeat:
2008; CHECK-NEXT:    successors: %bb.3({{[^)]+}}), %bb.2({{[^)]+}})
2009; CHECK:         [[OLDVALRES:%[0-9]+]]:_(s16), [[SUCCESS:%[0-9]+]]:_(s1) = G_ATOMIC_CMPXCHG_WITH_SUCCESS [[ADDR]](p0), [[OLDVAL]], [[NEWVAL]] :: (load store seq_cst seq_cst 2 on %ir.addr)
2010; CHECK-NEXT:    G_BRCOND [[SUCCESS]](s1), %bb.3
2011; CHECK-NEXT:    G_BR %bb.2
2012; CHECK:       bb.3.done:
2013entry:
2014  br label %repeat
2015repeat:
2016  %val_success = cmpxchg i16* %addr, i16 0, i16 1 seq_cst seq_cst
2017  %value_loaded = extractvalue { i16, i1 } %val_success, 0
2018  %success = extractvalue { i16, i1 } %val_success, 1
2019  br i1 %success, label %done, label %repeat
2020done:
2021  ret i16 %value_loaded
2022}
2023
2024; Try one cmpxchg where the success order and failure order differ.
2025define i64 @test_atomic_cmpxchg_3(i64* %addr) {
2026; CHECK-LABEL: name: test_atomic_cmpxchg_3
2027; CHECK:       bb.1.entry:
2028; CHECK-NEXT:  successors: %bb.2({{[^)]+}})
2029; CHECK-NEXT:  liveins: $x0
2030; CHECK:         [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
2031; CHECK-NEXT:    [[OLDVAL:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
2032; CHECK-NEXT:    [[NEWVAL:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
2033; CHECK:       bb.2.repeat:
2034; CHECK-NEXT:    successors: %bb.3({{[^)]+}}), %bb.2({{[^)]+}})
2035; CHECK:         [[OLDVALRES:%[0-9]+]]:_(s64), [[SUCCESS:%[0-9]+]]:_(s1) = G_ATOMIC_CMPXCHG_WITH_SUCCESS [[ADDR]](p0), [[OLDVAL]], [[NEWVAL]] :: (load store seq_cst acquire 8 on %ir.addr)
2036; CHECK-NEXT:    G_BRCOND [[SUCCESS]](s1), %bb.3
2037; CHECK-NEXT:    G_BR %bb.2
2038; CHECK:       bb.3.done:
2039entry:
2040  br label %repeat
2041repeat:
2042  %val_success = cmpxchg i64* %addr, i64 0, i64 1 seq_cst acquire
2043  %value_loaded = extractvalue { i64, i1 } %val_success, 0
2044  %success = extractvalue { i64, i1 } %val_success, 1
2045  br i1 %success, label %done, label %repeat
2046done:
2047  ret i64 %value_loaded
2048}
2049
2050; Try a monotonic atomicrmw xchg
2051; AArch64 will expand some atomicrmw's at the LLVM-IR level so we use a wide type to avoid this.
2052define i32 @test_atomicrmw_xchg(i256* %addr) {
2053; CHECK-LABEL: name: test_atomicrmw_xchg
2054; CHECK:       bb.1 (%ir-block.{{[0-9]+}}):
2055; CHECK-NEXT:  liveins: $x0
2056; CHECK:         [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
2057; CHECK-NEXT:    [[VAL:%[0-9]+]]:_(s256) = G_CONSTANT i256 1
2058; CHECK-NEXT:    [[OLDVALRES:%[0-9]+]]:_(s256) = G_ATOMICRMW_XCHG [[ADDR]](p0), [[VAL]] :: (load store monotonic 32 on %ir.addr)
2059; CHECK-NEXT:    [[RES:%[0-9]+]]:_(s32) = G_TRUNC [[OLDVALRES]]
2060  %oldval = atomicrmw xchg i256* %addr, i256 1 monotonic
2061  ; FIXME: We currently can't lower 'ret i256' and it's not the purpose of this
2062  ;        test so work around it by truncating to i32 for now.
2063  %oldval.trunc = trunc i256 %oldval to i32
2064  ret i32 %oldval.trunc
2065}
2066
2067; Try an acquire atomicrmw add
2068; AArch64 will expand some atomicrmw's at the LLVM-IR level so we use a wide type to avoid this.
2069define i32 @test_atomicrmw_add(i256* %addr) {
2070; CHECK-LABEL: name: test_atomicrmw_add
2071; CHECK:       bb.1 (%ir-block.{{[0-9]+}}):
2072; CHECK-NEXT:  liveins: $x0
2073; CHECK:         [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
2074; CHECK-NEXT:    [[VAL:%[0-9]+]]:_(s256) = G_CONSTANT i256 1
2075; CHECK-NEXT:    [[OLDVALRES:%[0-9]+]]:_(s256) = G_ATOMICRMW_ADD [[ADDR]](p0), [[VAL]] :: (load store acquire 32 on %ir.addr)
2076; CHECK-NEXT:    [[RES:%[0-9]+]]:_(s32) = G_TRUNC [[OLDVALRES]]
2077  %oldval = atomicrmw add i256* %addr, i256 1 acquire
2078  ; FIXME: We currently can't lower 'ret i256' and it's not the purpose of this
2079  ;        test so work around it by truncating to i32 for now.
2080  %oldval.trunc = trunc i256 %oldval to i32
2081  ret i32 %oldval.trunc
2082}
2083
2084; Try a release atomicrmw sub
2085; AArch64 will expand some atomicrmw's at the LLVM-IR level so we use a wide type to avoid this.
2086define i32 @test_atomicrmw_sub(i256* %addr) {
2087; CHECK-LABEL: name: test_atomicrmw_sub
2088; CHECK:       bb.1 (%ir-block.{{[0-9]+}}):
2089; CHECK-NEXT:  liveins: $x0
2090; CHECK:         [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
2091; CHECK-NEXT:    [[VAL:%[0-9]+]]:_(s256) = G_CONSTANT i256 1
2092; CHECK-NEXT:    [[OLDVALRES:%[0-9]+]]:_(s256) = G_ATOMICRMW_SUB [[ADDR]](p0), [[VAL]] :: (load store release 32 on %ir.addr)
2093; CHECK-NEXT:    [[RES:%[0-9]+]]:_(s32) = G_TRUNC [[OLDVALRES]]
2094  %oldval = atomicrmw sub i256* %addr, i256 1 release
2095  ; FIXME: We currently can't lower 'ret i256' and it's not the purpose of this
2096  ;        test so work around it by truncating to i32 for now.
2097  %oldval.trunc = trunc i256 %oldval to i32
2098  ret i32 %oldval.trunc
2099}
2100
2101; Try an acq_rel atomicrmw and
2102; AArch64 will expand some atomicrmw's at the LLVM-IR level so we use a wide type to avoid this.
2103define i32 @test_atomicrmw_and(i256* %addr) {
2104; CHECK-LABEL: name: test_atomicrmw_and
2105; CHECK:       bb.1 (%ir-block.{{[0-9]+}}):
2106; CHECK-NEXT:  liveins: $x0
2107; CHECK:         [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
2108; CHECK-NEXT:    [[VAL:%[0-9]+]]:_(s256) = G_CONSTANT i256 1
2109; CHECK-NEXT:    [[OLDVALRES:%[0-9]+]]:_(s256) = G_ATOMICRMW_AND [[ADDR]](p0), [[VAL]] :: (load store acq_rel 32 on %ir.addr)
2110; CHECK-NEXT:    [[RES:%[0-9]+]]:_(s32) = G_TRUNC [[OLDVALRES]]
2111  %oldval = atomicrmw and i256* %addr, i256 1 acq_rel
2112  ; FIXME: We currently can't lower 'ret i256' and it's not the purpose of this
2113  ;        test so work around it by truncating to i32 for now.
2114  %oldval.trunc = trunc i256 %oldval to i32
2115  ret i32 %oldval.trunc
2116}
2117
2118; Try an seq_cst atomicrmw nand
2119; AArch64 will expand some atomicrmw's at the LLVM-IR level so we use a wide type to avoid this.
2120define i32 @test_atomicrmw_nand(i256* %addr) {
2121; CHECK-LABEL: name: test_atomicrmw_nand
2122; CHECK:       bb.1 (%ir-block.{{[0-9]+}}):
2123; CHECK-NEXT:  liveins: $x0
2124; CHECK:         [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
2125; CHECK-NEXT:    [[VAL:%[0-9]+]]:_(s256) = G_CONSTANT i256 1
2126; CHECK-NEXT:    [[OLDVALRES:%[0-9]+]]:_(s256) = G_ATOMICRMW_NAND [[ADDR]](p0), [[VAL]] :: (load store seq_cst 32 on %ir.addr)
2127; CHECK-NEXT:    [[RES:%[0-9]+]]:_(s32) = G_TRUNC [[OLDVALRES]]
2128  %oldval = atomicrmw nand i256* %addr, i256 1 seq_cst
2129  ; FIXME: We currently can't lower 'ret i256' and it's not the purpose of this
2130  ;        test so work around it by truncating to i32 for now.
2131  %oldval.trunc = trunc i256 %oldval to i32
2132  ret i32 %oldval.trunc
2133}
2134
2135; Try an seq_cst atomicrmw or
2136; AArch64 will expand some atomicrmw's at the LLVM-IR level so we use a wide type to avoid this.
2137define i32 @test_atomicrmw_or(i256* %addr) {
2138; CHECK-LABEL: name: test_atomicrmw_or
2139; CHECK:       bb.1 (%ir-block.{{[0-9]+}}):
2140; CHECK-NEXT:  liveins: $x0
2141; CHECK:         [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
2142; CHECK-NEXT:    [[VAL:%[0-9]+]]:_(s256) = G_CONSTANT i256 1
2143; CHECK-NEXT:    [[OLDVALRES:%[0-9]+]]:_(s256) = G_ATOMICRMW_OR [[ADDR]](p0), [[VAL]] :: (load store seq_cst 32 on %ir.addr)
2144; CHECK-NEXT:    [[RES:%[0-9]+]]:_(s32) = G_TRUNC [[OLDVALRES]]
2145  %oldval = atomicrmw or i256* %addr, i256 1 seq_cst
2146  ; FIXME: We currently can't lower 'ret i256' and it's not the purpose of this
2147  ;        test so work around it by truncating to i32 for now.
2148  %oldval.trunc = trunc i256 %oldval to i32
2149  ret i32 %oldval.trunc
2150}
2151
2152; Try an seq_cst atomicrmw xor
2153; AArch64 will expand some atomicrmw's at the LLVM-IR level so we use a wide type to avoid this.
2154define i32 @test_atomicrmw_xor(i256* %addr) {
2155; CHECK-LABEL: name: test_atomicrmw_xor
2156; CHECK:       bb.1 (%ir-block.{{[0-9]+}}):
2157; CHECK-NEXT:  liveins: $x0
2158; CHECK:         [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
2159; CHECK-NEXT:    [[VAL:%[0-9]+]]:_(s256) = G_CONSTANT i256 1
2160; CHECK-NEXT:    [[OLDVALRES:%[0-9]+]]:_(s256) = G_ATOMICRMW_XOR [[ADDR]](p0), [[VAL]] :: (load store seq_cst 32 on %ir.addr)
2161; CHECK-NEXT:    [[RES:%[0-9]+]]:_(s32) = G_TRUNC [[OLDVALRES]]
2162  %oldval = atomicrmw xor i256* %addr, i256 1 seq_cst
2163  ; FIXME: We currently can't lower 'ret i256' and it's not the purpose of this
2164  ;        test so work around it by truncating to i32 for now.
2165  %oldval.trunc = trunc i256 %oldval to i32
2166  ret i32 %oldval.trunc
2167}
2168
2169; Try an seq_cst atomicrmw min
2170; AArch64 will expand some atomicrmw's at the LLVM-IR level so we use a wide type to avoid this.
2171define i32 @test_atomicrmw_min(i256* %addr) {
2172; CHECK-LABEL: name: test_atomicrmw_min
2173; CHECK:       bb.1 (%ir-block.{{[0-9]+}}):
2174; CHECK-NEXT:  liveins: $x0
2175; CHECK:         [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
2176; CHECK-NEXT:    [[VAL:%[0-9]+]]:_(s256) = G_CONSTANT i256 1
2177; CHECK-NEXT:    [[OLDVALRES:%[0-9]+]]:_(s256) = G_ATOMICRMW_MIN [[ADDR]](p0), [[VAL]] :: (load store seq_cst 32 on %ir.addr)
2178; CHECK-NEXT:    [[RES:%[0-9]+]]:_(s32) = G_TRUNC [[OLDVALRES]]
2179  %oldval = atomicrmw min i256* %addr, i256 1 seq_cst
2180  ; FIXME: We currently can't lower 'ret i256' and it's not the purpose of this
2181  ;        test so work around it by truncating to i32 for now.
2182  %oldval.trunc = trunc i256 %oldval to i32
2183  ret i32 %oldval.trunc
2184}
2185
2186; Try an seq_cst atomicrmw max
2187; AArch64 will expand some atomicrmw's at the LLVM-IR level so we use a wide type to avoid this.
2188define i32 @test_atomicrmw_max(i256* %addr) {
2189; CHECK-LABEL: name: test_atomicrmw_max
2190; CHECK:       bb.1 (%ir-block.{{[0-9]+}}):
2191; CHECK-NEXT:  liveins: $x0
2192; CHECK:         [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
2193; CHECK-NEXT:    [[VAL:%[0-9]+]]:_(s256) = G_CONSTANT i256 1
2194; CHECK-NEXT:    [[OLDVALRES:%[0-9]+]]:_(s256) = G_ATOMICRMW_MAX [[ADDR]](p0), [[VAL]] :: (load store seq_cst 32 on %ir.addr)
2195; CHECK-NEXT:    [[RES:%[0-9]+]]:_(s32) = G_TRUNC [[OLDVALRES]]
2196  %oldval = atomicrmw max i256* %addr, i256 1 seq_cst
2197  ; FIXME: We currently can't lower 'ret i256' and it's not the purpose of this
2198  ;        test so work around it by truncating to i32 for now.
2199  %oldval.trunc = trunc i256 %oldval to i32
2200  ret i32 %oldval.trunc
2201}
2202
2203; Try an seq_cst atomicrmw unsigned min
2204; AArch64 will expand some atomicrmw's at the LLVM-IR level so we use a wide type to avoid this.
2205define i32 @test_atomicrmw_umin(i256* %addr) {
2206; CHECK-LABEL: name: test_atomicrmw_umin
2207; CHECK:       bb.1 (%ir-block.{{[0-9]+}}):
2208; CHECK-NEXT:  liveins: $x0
2209; CHECK:         [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
2210; CHECK-NEXT:    [[VAL:%[0-9]+]]:_(s256) = G_CONSTANT i256 1
2211; CHECK-NEXT:    [[OLDVALRES:%[0-9]+]]:_(s256) = G_ATOMICRMW_UMIN [[ADDR]](p0), [[VAL]] :: (load store seq_cst 32 on %ir.addr)
2212; CHECK-NEXT:    [[RES:%[0-9]+]]:_(s32) = G_TRUNC [[OLDVALRES]]
2213  %oldval = atomicrmw umin i256* %addr, i256 1 seq_cst
2214  ; FIXME: We currently can't lower 'ret i256' and it's not the purpose of this
2215  ;        test so work around it by truncating to i32 for now.
2216  %oldval.trunc = trunc i256 %oldval to i32
2217  ret i32 %oldval.trunc
2218}
2219
2220; Try an seq_cst atomicrmw unsigned max
2221; AArch64 will expand some atomicrmw's at the LLVM-IR level so we use a wide type to avoid this.
2222define i32 @test_atomicrmw_umax(i256* %addr) {
2223; CHECK-LABEL: name: test_atomicrmw_umax
2224; CHECK:       bb.1 (%ir-block.{{[0-9]+}}):
2225; CHECK-NEXT:  liveins: $x0
2226; CHECK:         [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
2227; CHECK-NEXT:    [[VAL:%[0-9]+]]:_(s256) = G_CONSTANT i256 1
2228; CHECK-NEXT:    [[OLDVALRES:%[0-9]+]]:_(s256) = G_ATOMICRMW_UMAX [[ADDR]](p0), [[VAL]] :: (load store seq_cst 32 on %ir.addr)
2229; CHECK-NEXT:    [[RES:%[0-9]+]]:_(s32) = G_TRUNC [[OLDVALRES]]
2230  %oldval = atomicrmw umax i256* %addr, i256 1 seq_cst
2231  ; FIXME: We currently can't lower 'ret i256' and it's not the purpose of this
2232  ;        test so work around it by truncating to i32 for now.
2233  %oldval.trunc = trunc i256 %oldval to i32
2234  ret i32 %oldval.trunc
2235}
2236
2237@addr = global i8* null
2238
2239define void @test_blockaddress() {
2240; CHECK-LABEL: name: test_blockaddress
2241; CHECK: [[BADDR:%[0-9]+]]:_(p0) = G_BLOCK_ADDR blockaddress(@test_blockaddress, %ir-block.block)
2242; CHECK: G_STORE [[BADDR]](p0)
2243  store i8* blockaddress(@test_blockaddress, %block), i8** @addr
2244  indirectbr i8* blockaddress(@test_blockaddress, %block), [label %block]
2245block:
2246  ret void
2247}
2248
2249%t = type { i32 }
2250declare {}* @llvm.invariant.start.p0i8(i64, i8* nocapture) readonly nounwind
2251declare void @llvm.invariant.end.p0i8({}*, i64, i8* nocapture) nounwind
2252define void @test_invariant_intrin() {
2253; CHECK-LABEL: name: test_invariant_intrin
2254; CHECK: %{{[0-9]+}}:_(s64) = G_IMPLICIT_DEF
2255; CHECK-NEXT: RET_ReallyLR
2256  %x = alloca %t
2257  %y = bitcast %t* %x to i8*
2258  %inv = call {}* @llvm.invariant.start.p0i8(i64 8, i8* %y)
2259  call void @llvm.invariant.end.p0i8({}* %inv, i64 8, i8* %y)
2260  ret void
2261}
2262
2263declare float @llvm.ceil.f32(float)
2264define float @test_ceil_f32(float %x) {
2265  ; CHECK-LABEL: name:            test_ceil_f32
2266  ; CHECK: %{{[0-9]+}}:_(s32) = G_FCEIL %{{[0-9]+}}
2267  %y = call float @llvm.ceil.f32(float %x)
2268  ret float %y
2269}
2270
2271declare double @llvm.ceil.f64(double)
2272define double @test_ceil_f64(double %x) {
2273  ; CHECK-LABEL: name:            test_ceil_f64
2274  ; CHECK: %{{[0-9]+}}:_(s64) = G_FCEIL %{{[0-9]+}}
2275  %y = call double @llvm.ceil.f64(double %x)
2276  ret double %y
2277}
2278
2279declare <2 x float> @llvm.ceil.v2f32(<2 x float>)
2280define <2 x float> @test_ceil_v2f32(<2 x float> %x) {
2281  ; CHECK-LABEL: name:            test_ceil_v2f32
2282  ; CHECK: %{{[0-9]+}}:_(<2 x s32>) = G_FCEIL %{{[0-9]+}}
2283  %y = call <2 x float> @llvm.ceil.v2f32(<2 x float> %x)
2284  ret <2 x float> %y
2285}
2286
2287declare <4 x float> @llvm.ceil.v4f32(<4 x float>)
2288define <4 x float> @test_ceil_v4f32(<4 x float> %x) {
2289  ; CHECK-LABEL: name:            test_ceil_v4f32
2290  ; CHECK: %{{[0-9]+}}:_(<4 x s32>) = G_FCEIL %{{[0-9]+}}
2291  ; SELECT: %{{[0-9]+}}:fpr128 = FRINTPv4f32 %{{[0-9]+}}
2292  %y = call <4 x float> @llvm.ceil.v4f32(<4 x float> %x)
2293  ret <4 x float> %y
2294}
2295
2296declare <2 x double> @llvm.ceil.v2f64(<2 x double>)
2297define <2 x double> @test_ceil_v2f64(<2 x double> %x) {
2298  ; CHECK-LABEL: name:            test_ceil_v2f64
2299  ; CHECK: %{{[0-9]+}}:_(<2 x s64>) = G_FCEIL %{{[0-9]+}}
2300  %y = call <2 x double> @llvm.ceil.v2f64(<2 x double> %x)
2301  ret <2 x double> %y
2302}
2303
2304declare float @llvm.cos.f32(float)
2305define float @test_cos_f32(float %x) {
2306  ; CHECK-LABEL: name:            test_cos_f32
2307  ; CHECK: %{{[0-9]+}}:_(s32) = G_FCOS %{{[0-9]+}}
2308  %y = call float @llvm.cos.f32(float %x)
2309  ret float %y
2310}
2311
2312declare float @llvm.sin.f32(float)
2313define float @test_sin_f32(float %x) {
2314  ; CHECK-LABEL: name:            test_sin_f32
2315  ; CHECK: %{{[0-9]+}}:_(s32) = G_FSIN %{{[0-9]+}}
2316  %y = call float @llvm.sin.f32(float %x)
2317  ret float %y
2318}
2319
2320declare float @llvm.sqrt.f32(float)
2321define float @test_sqrt_f32(float %x) {
2322  ; CHECK-LABEL: name:            test_sqrt_f32
2323  ; CHECK: %{{[0-9]+}}:_(s32) = G_FSQRT %{{[0-9]+}}
2324  %y = call float @llvm.sqrt.f32(float %x)
2325  ret float %y
2326}
2327
2328declare float @llvm.floor.f32(float)
2329define float @test_floor_f32(float %x) {
2330  ; CHECK-LABEL: name:            test_floor_f32
2331  ; CHECK: %{{[0-9]+}}:_(s32) = G_FFLOOR %{{[0-9]+}}
2332  %y = call float @llvm.floor.f32(float %x)
2333  ret float %y
2334}
2335
2336declare float @llvm.nearbyint.f32(float)
2337define float @test_nearbyint_f32(float %x) {
2338  ; CHECK-LABEL: name:            test_nearbyint_f32
2339  ; CHECK: %{{[0-9]+}}:_(s32) = G_FNEARBYINT %{{[0-9]+}}
2340  %y = call float @llvm.nearbyint.f32(float %x)
2341  ret float %y
2342}
2343
2344; CHECK-LABEL: name: test_llvm.aarch64.neon.ld3.v4i32.p0i32
2345; CHECK: %1:_(<4 x s32>), %2:_(<4 x s32>), %3:_(<4 x s32>) = G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aarch64.neon.ld3), %0(p0) :: (load 48 from %ir.ptr, align 64)
2346define void @test_llvm.aarch64.neon.ld3.v4i32.p0i32(i32* %ptr) {
2347  %arst = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld3.v4i32.p0i32(i32* %ptr)
2348  ret void
2349}
2350
2351declare { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld3.v4i32.p0i32(i32*) #3
2352
2353define void @test_i1_arg_zext(void (i1)* %f) {
2354; CHECK-LABEL: name: test_i1_arg_zext
2355; CHECK: [[I1:%[0-9]+]]:_(s1) = G_CONSTANT i1 true
2356; CHECK: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[I1]](s1)
2357; CHECK: $w0 = COPY [[ZEXT]](s32)
2358  call void %f(i1 true)
2359  ret void
2360}
2361
2362declare i8* @llvm.stacksave()
2363declare void @llvm.stackrestore(i8*)
2364define void @test_stacksaverestore() {
2365  ; CHECK-LABEL: name: test_stacksaverestore
2366  ; CHECK: [[SAVE:%[0-9]+]]:_(p0) = COPY $sp
2367  ; CHECK-NEXT: $sp = COPY [[SAVE]](p0)
2368  ; CHECK-NEXT: RET_ReallyLR
2369  %sp = call i8* @llvm.stacksave()
2370  call void @llvm.stackrestore(i8* %sp)
2371  ret void
2372}
2373
2374declare float @llvm.rint.f32(float)
2375define float @test_rint_f32(float %x) {
2376  ; CHECK-LABEL: name:            test_rint_f32
2377  ; CHECK: %{{[0-9]+}}:_(s32) = G_FRINT %{{[0-9]+}}
2378  %y = call float @llvm.rint.f32(float %x)
2379  ret float %y
2380}
2381
2382declare void @llvm.assume(i1)
2383define void @test_assume(i1 %x) {
2384  ; CHECK-LABEL: name:            test_assume
2385  ; CHECK-NOT: llvm.assume
2386  ; CHECK: RET_ReallyLR
2387  call void @llvm.assume(i1 %x)
2388  ret void
2389}
2390
2391declare void @llvm.sideeffect()
2392define void @test_sideeffect() {
2393  ; CHECK-LABEL: name:            test_sideeffect
2394  ; CHECK-NOT: llvm.sideeffect
2395  ; CHECK: RET_ReallyLR
2396  call void @llvm.sideeffect()
2397  ret void
2398}
2399
2400declare void @llvm.var.annotation(i8*, i8*, i8*, i32, i8*)
2401define void @test_var_annotation(i8*, i8*, i8*, i32) {
2402  ; CHECK-LABEL: name:            test_var_annotation
2403  ; CHECK-NOT: llvm.var.annotation
2404  ; CHECK: RET_ReallyLR
2405  call void @llvm.var.annotation(i8* %0, i8* %1, i8* %2, i32 %3, i8* null)
2406  ret void
2407}
2408
2409declare i64 @llvm.readcyclecounter()
2410define i64 @test_readcyclecounter() {
2411  ; CHECK-LABEL: name:            test_readcyclecounter
2412  ; CHECK: [[RES:%[0-9]+]]:_(s64) = G_READCYCLECOUNTER{{$}}
2413  ; CHECK-NEXT: $x0 = COPY [[RES]]
2414  ; CHECK-NEXT: RET_ReallyLR implicit $x0
2415  %res = call i64 @llvm.readcyclecounter()
2416  ret i64 %res
2417}
2418
2419define i64 @test_freeze(i64 %a) {
2420  ; CHECK-LABEL: name:            test_freeze
2421  ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
2422  ; CHECK-NEXT: [[RES:%[0-9]+]]:_(s64) = G_FREEZE [[COPY]]
2423  ; CHECK-NEXT: $x0 = COPY [[RES]]
2424  ; CHECK-NEXT: RET_ReallyLR implicit $x0
2425  %res = freeze i64 %a
2426  ret i64 %res
2427}
2428
2429define {i8, i32} @test_freeze_struct({ i8, i32 }* %addr) {
2430  ; CHECK-LABEL: name:            test_freeze_struct
2431  ; CHECK: [[COPY:%[0-9]+]]:_(p0) = COPY $x0
2432  ; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(s8) = G_LOAD [[COPY]](p0)
2433  ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 4
2434  ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C]]
2435  ; CHECK-NEXT: [[LOAD1:%[0-9]+]]:_(s32) = G_LOAD [[PTR_ADD]](p0)
2436  ; CHECK-NEXT: [[FREEZE:%[0-9]+]]:_(s8) = G_FREEZE [[LOAD]]
2437  ; CHECK-NEXT: [[FREEZE1:%[0-9]+]]:_(s32) = G_FREEZE [[LOAD1]]
2438  ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[FREEZE]]
2439  ; CHECK-NEXT: $w0 = COPY [[ANYEXT]]
2440  ; CHECK-NEXT: $w1 = COPY [[FREEZE1]]
2441  ; CHECK-NEXT: RET_ReallyLR implicit $w0, implicit $w1
2442  %load = load { i8, i32 }, { i8, i32 }* %addr
2443  %res = freeze {i8, i32} %load
2444  ret {i8, i32} %res
2445}
2446
2447!0 = !{ i64 0, i64 2 }
2448