1; RUN: not --crash llc -O0 -global-isel -global-isel-abort=1 -verify-machineinstrs %s -o - 2>&1 | FileCheck %s --check-prefix=ERROR
2; RUN: llc -O0 -global-isel -global-isel-abort=0 -verify-machineinstrs %s -o - 2>&1 | FileCheck %s --check-prefix=FALLBACK
3; RUN: llc -O0 -global-isel -global-isel-abort=2 -pass-remarks-missed='gisel*' -verify-machineinstrs %s -o %t.out 2> %t.err
4; RUN: FileCheck %s --check-prefix=FALLBACK-WITH-REPORT-OUT < %t.out
5; RUN: FileCheck %s --check-prefix=FALLBACK-WITH-REPORT-ERR < %t.err
6; RUN: not --crash llc -global-isel -mtriple aarch64_be %s -o - 2>&1 | FileCheck %s --check-prefix=BIG-ENDIAN
7; This file checks that the fallback path to selection dag works.
8; The test is fragile in the sense that it must be updated to expose
9; something that fails with global-isel.
10; When we cannot produce a test case anymore, that means we can remove
11; the fallback path.
12
13target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
14target triple = "aarch64--"
15
16; BIG-ENDIAN: unable to translate in big endian mode
17
18; We use __fixunstfti as the common denominator for __fixunstfti on Linux and
19; ___fixunstfti on iOS
20; ERROR: unable to translate instruction: ret
21; FALLBACK: ldr q0,
22; FALLBACK-NEXT: bl __fixunstfti
23;
24; FALLBACK-WITH-REPORT-ERR: unable to translate instruction: ret
25; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for ABIi128
26; FALLBACK-WITH-REPORT-OUT-LABEL: ABIi128:
27; FALLBACK-WITH-REPORT-OUT: ldr q0,
28; FALLBACK-WITH-REPORT-OUT-NEXT: bl __fixunstfti
29define i128 @ABIi128(i128 %arg1) {
30  %farg1 =       bitcast i128 %arg1 to fp128
31  %res = fptoui fp128 %farg1 to i128
32  ret i128 %res
33}
34
35; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: G_STORE %1:_(<7 x s32>), %0:_(p0) :: (store 28 into %ir.addr, align 32) (in function: odd_vector)
36; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for odd_vector
37; FALLBACK-WITH-REPORT-OUT-LABEL: odd_vector:
38define void @odd_vector(<7 x i32>* %addr) {
39  %vec = load <7 x i32>, <7 x i32>* %addr
40  store <7 x i32> %vec, <7 x i32>* %addr
41  ret void
42}
43
44  ; AArch64 was asserting instead of returning an invalid mapping for unknown
45  ; sizes.
46; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to translate instruction: ret: '  ret i128 undef' (in function: sequence_sizes)
47; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for sequence_sizes
48; FALLBACK-WITH-REPORT-LABEL: sequence_sizes:
49define i128 @sequence_sizes([8 x i8] %in) {
50  ret i128 undef
51}
52
53; Make sure we don't mess up metadata arguments.
54declare void @llvm.write_register.i64(metadata, i64)
55
56; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: G_WRITE_REGISTER !0, %0:_(s64) (in function: test_write_register_intrin)
57; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for test_write_register_intrin
58; FALLBACK-WITH-REPORT-LABEL: test_write_register_intrin:
59define void @test_write_register_intrin() {
60  call void @llvm.write_register.i64(metadata !{!"sp"}, i64 0)
61  ret void
62}
63
64@_ZTIi = external global i8*
65declare i32 @__gxx_personality_v0(...)
66
67; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: %0:_(s128) = G_FCONSTANT fp128 0xL00000000000000004000000000000000
68; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for test_quad_dump
69; FALLBACK-WITH-REPORT-OUT-LABEL: test_quad_dump:
70define fp128 @test_quad_dump() {
71  ret fp128 0xL00000000000000004000000000000000
72}
73
74; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: %2:_(<2 x p0>) = G_INSERT_VECTOR_ELT %0:_, %{{[0-9]+}}:_(p0), %{{[0-9]+}}:_(s32) (in function: vector_of_pointers_insertelement)
75; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for vector_of_pointers_insertelement
76; FALLBACK-WITH-REPORT-OUT-LABEL: vector_of_pointers_insertelement:
77define void @vector_of_pointers_insertelement() {
78  br label %end
79
80block:
81  %dummy = insertelement <2 x i16*> %vec, i16* null, i32 0
82  store <2 x i16*> %dummy, <2 x i16*>* undef
83  ret void
84
85end:
86  %vec = load <2 x i16*>, <2 x i16*>* undef
87  br label %block
88}
89
90; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: %{{[0-9]+}}:_(s96) = G_ADD %{{[0-9]+}}:_, %{{[0-9]+}}:_ (in function: nonpow2_add_narrowing)
91; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for nonpow2_add_narrowing
92; FALLBACK-WITH-REPORT-OUT-LABEL: nonpow2_add_narrowing:
93define void @nonpow2_add_narrowing(i128 %x, i128 %y) {
94  %a = add i128 %x, %y
95  %b = trunc i128 %a to i96
96  %dummy = add i96 %b, %b
97  store i96 %dummy, i96* undef
98  ret void
99}
100
101; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: %{{[0-9]+}}:_(s96) = G_INSERT %{{[0-9]+}}:_, %{{[0-9]+}}:_(s32), 64 (in function: nonpow2_or_narrowing)
102; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for nonpow2_or_narrowing
103; FALLBACK-WITH-REPORT-OUT-LABEL: nonpow2_or_narrowing:
104define void @nonpow2_or_narrowing() {
105  %a = add i128 undef, undef
106  %b = trunc i128 %a to i96
107  %a2 = add i128 undef, undef
108  %b2 = trunc i128 %a2 to i96
109  %dummy = or i96 %b, %b2
110  store i96 %dummy, i96* undef
111  ret void
112}
113
114; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: %0:_(s96) = G_INSERT %10:_, %8:_(s32), 64 (in function: nonpow2_load_narrowing)
115; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for nonpow2_load_narrowing
116; FALLBACK-WITH-REPORT-OUT-LABEL: nonpow2_load_narrowing:
117define void @nonpow2_load_narrowing() {
118  %dummy = load i96, i96* undef
119  store i96 %dummy, i96* undef
120  ret void
121}
122
123; Currently can't handle vector lengths that aren't an exact multiple of
124; natively supported vector lengths. Test that the fall-back works for those.
125; FALLBACK-WITH-REPORT-ERR-G_IMPLICIT_DEF-LEGALIZABLE: (FIXME: this is what is expected once we can legalize non-pow-of-2 G_IMPLICIT_DEF) remark: <unknown>:0:0: unable to legalize instruction: %1:_(<7 x s64>) = G_ADD %0, %0 (in function: nonpow2_vector_add_fewerelements
126; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: %{{[0-9]+}}:_(s64) = G_EXTRACT_VECTOR_ELT %{{[0-9]+}}:_(<7 x s64>), %{{[0-9]+}}:_(s64) (in function: nonpow2_vector_add_fewerelements)
127; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for nonpow2_vector_add_fewerelements
128; FALLBACK-WITH-REPORT-OUT-LABEL: nonpow2_vector_add_fewerelements:
129define void @nonpow2_vector_add_fewerelements() {
130  %dummy = add <7 x i64> undef, undef
131  %ex = extractelement <7 x i64> %dummy, i64 0
132  store i64 %ex, i64* undef
133  ret void
134}
135
136; Currently can't handle dealing with a split type (s128 -> 2 x s64) on the stack yet.
137declare void @use_s128(i128 %a, i128 %b)
138; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to lower arguments: i32 (i32, i128, i32, i32, i32, i128, i32)* (in function: fn1)
139; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for fn1
140; FALLBACK-WITH-REPORT-OUT-LABEL: fn1:
141define i32 @fn1(i32 %p1, i128 %p2, i32 %p3, i32 %p4, i32 %p5, i128 %p6, i32 %p7) {
142entry:
143  call void @use_s128(i128 %p2, i128 %p6)
144  ret i32 0
145}
146
147; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: cannot select: RET_ReallyLR implicit $x0 (in function: strict_align_feature)
148; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for strict_align_feature
149; FALLBACK-WITH-REPORT-OUT-LABEL: strict_align_feature
150define i64 @strict_align_feature(i64* %p) #0 {
151  %x = load i64, i64* %p, align 1
152  ret i64 %x
153}
154
155attributes #0 = { "target-features"="+strict-align" }
156
157; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to translate instruction: call
158; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for direct_mem
159; FALLBACK-WITH-REPORT-OUT-LABEL: direct_mem
160define void @direct_mem(i32 %x, i32 %y) {
161entry:
162  tail call void asm sideeffect "", "imr,imr,~{memory}"(i32 %x, i32 %y)
163  ret void
164}
165
166; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to lower function{{.*}}scalable_arg
167; FALLBACK-WITH-REPORT-OUT-LABEL: scalable_arg
168define <vscale x 16 x i8> @scalable_arg(<vscale x 16 x i1> %pred, i8* %addr) #1 {
169  %res = call <vscale x 16 x i8> @llvm.aarch64.sve.ld1.nxv16i8(<vscale x 16 x i1> %pred, i8* %addr)
170  ret <vscale x 16 x i8> %res
171}
172
173; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to lower function{{.*}}scalable_ret
174; FALLBACK-WITH-REPORT-OUT-LABEL: scalable_ret
175define <vscale x 16 x i8> @scalable_ret(i8* %addr) #1 {
176  %pred = call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue.nxv16i1(i32 0)
177  %res = call <vscale x 16 x i8> @llvm.aarch64.sve.ld1.nxv16i8(<vscale x 16 x i1> %pred, i8* %addr)
178  ret <vscale x 16 x i8> %res
179}
180
181; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to translate instruction{{.*}}scalable_call
182; FALLBACK-WITH-REPORT-OUT-LABEL: scalable_call
183define i8 @scalable_call(i8* %addr) #1 {
184  %pred = call <vscale x 16 x i1> @llvm.aarch64.sve.ptrue.nxv16i1(i32 0)
185  %vec = call <vscale x 16 x i8> @llvm.aarch64.sve.ld1.nxv16i8(<vscale x 16 x i1> %pred, i8* %addr)
186  %res = extractelement <vscale x 16 x i8> %vec, i32 0
187  ret i8 %res
188}
189
190; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to translate instruction{{.*}}scalable_alloca
191; FALLBACK-WITH-REPORT-OUT-LABEL: scalable_alloca
192define void @scalable_alloca() #1 {
193  %local0 = alloca <vscale x 16 x i8>
194  load volatile <vscale x 16 x i8>, <vscale x 16 x i8>* %local0
195  ret void
196}
197
198; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to translate instruction{{.*}}asm_indirect_output
199; FALLBACK-WITH-REPORT-OUT-LABEL: asm_indirect_output
200define void @asm_indirect_output() {
201entry:
202  %ap = alloca i8*, align 8
203  %0 = load i8*, i8** %ap, align 8
204  call void asm sideeffect "", "=*r|m,0,~{memory}"(i8** %ap, i8* %0)
205  ret void
206}
207
208attributes #1 = { "target-features"="+sve" }
209
210declare <vscale x 16 x i1> @llvm.aarch64.sve.ptrue.nxv16i1(i32 %pattern)
211declare <vscale x 16 x i8> @llvm.aarch64.sve.ld1.nxv16i8(<vscale x 16 x i1>, i8*)
212