2017-08-03 17:14:59 +08:00
|
|
|
; RUN: llc -mtriple arm-unknown -verify-machineinstrs -global-isel -global-isel-abort=2 -pass-remarks-missed='gisel*' %s -o - 2>&1 | FileCheck %s -check-prefixes=CHECK
|
|
|
|
; RUN: llc -mtriple arm-unknown -verify-machineinstrs -global-isel -global-isel-abort=2 -pass-remarks-missed='gisel*' -relocation-model=pic %s -o - 2>&1 | FileCheck %s -check-prefixes=PIC
|
|
|
|
; RUN: llc -mtriple arm-unknown -verify-machineinstrs -global-isel -global-isel-abort=2 -pass-remarks-missed='gisel*' -relocation-model=ropi %s -o - 2>&1 | FileCheck %s -check-prefixes=ROPI
|
|
|
|
; RUN: llc -mtriple arm-unknown -verify-machineinstrs -global-isel -global-isel-abort=2 -pass-remarks-missed='gisel*' -relocation-model=rwpi %s -o - 2>&1 | FileCheck %s -check-prefixes=RWPI
|
|
|
|
; RUN: llc -mtriple arm-unknown -verify-machineinstrs -global-isel -global-isel-abort=2 -pass-remarks-missed='gisel*' -relocation-model=ropi-rwpi %s -o - 2>&1 | FileCheck %s -check-prefixes=ROPI-RWPI
|
2017-04-21 19:53:01 +08:00
|
|
|
|
|
|
|
; This file checks that we use the fallback path for things that are known to
|
|
|
|
; be unsupported on the ARM target. It should progressively shrink in size.
|
|
|
|
|
|
|
|
define <4 x i32> @test_int_vectors(<4 x i32> %a, <4 x i32> %b) {
|
|
|
|
; CHECK: remark: {{.*}} unable to lower arguments: <4 x i32> (<4 x i32>, <4 x i32>)*
|
|
|
|
; CHECK-LABEL: warning: Instruction selection used fallback path for test_int_vectors
|
|
|
|
%res = add <4 x i32> %a, %b
|
|
|
|
ret <4 x i32> %res
|
|
|
|
}
|
|
|
|
|
|
|
|
define <4 x float> @test_float_vectors(<4 x float> %a, <4 x float> %b) {
|
|
|
|
; CHECK: remark: {{.*}} unable to lower arguments: <4 x float> (<4 x float>, <4 x float>)*
|
|
|
|
; CHECK-LABEL: warning: Instruction selection used fallback path for test_float_vectors
|
|
|
|
%res = fadd <4 x float> %a, %b
|
|
|
|
ret <4 x float> %res
|
|
|
|
}
|
|
|
|
|
|
|
|
define i64 @test_i64(i64 %a, i64 %b) {
|
|
|
|
; CHECK: remark: {{.*}} unable to lower arguments: i64 (i64, i64)*
|
|
|
|
; CHECK-LABEL: warning: Instruction selection used fallback path for test_i64
|
|
|
|
%res = add i64 %a, %b
|
|
|
|
ret i64 %res
|
|
|
|
}
|
|
|
|
|
|
|
|
define i128 @test_i128(i128 %a, i128 %b) {
|
|
|
|
; CHECK: remark: {{.*}} unable to lower arguments: i128 (i128, i128)*
|
|
|
|
; CHECK-LABEL: warning: Instruction selection used fallback path for test_i128
|
|
|
|
%res = add i128 %a, %b
|
|
|
|
ret i128 %res
|
|
|
|
}
|
|
|
|
|
|
|
|
define i17 @test_funny_ints(i17 %a, i17 %b) {
|
|
|
|
; CHECK: remark: {{.*}} unable to lower arguments: i17 (i17, i17)*
|
|
|
|
; CHECK-LABEL: warning: Instruction selection used fallback path for test_funny_ints
|
|
|
|
%res = add i17 %a, %b
|
|
|
|
ret i17 %res
|
|
|
|
}
|
|
|
|
|
|
|
|
define half @test_half(half %a, half %b) {
|
[ARM] Armv8.2-A FP16 code generation (part 1/3)
This is the groundwork for Armv8.2-A FP16 code generation .
Clang passes and returns _Float16 values as floats, together with the required
bitconverts and truncs etc. to implement correct AAPCS behaviour, see D42318.
We will implement half-precision argument passing/returning lowering in the ARM
backend soon, but for now this means that this:
_Float16 sub(_Float16 a, _Float16 b) {
return a + b;
}
gets lowered to this:
define float @sub(float %a.coerce, float %b.coerce) {
entry:
%0 = bitcast float %a.coerce to i32
%tmp.0.extract.trunc = trunc i32 %0 to i16
%1 = bitcast i16 %tmp.0.extract.trunc to half
<SNIP>
%add = fadd half %1, %3
<SNIP>
}
When FullFP16 is *not* supported, we don't make f16 a legal type, and we get
legalization for "free", i.e. nothing changes and everything works as before.
And also f16 argument passing/returning is handled.
When FullFP16 is supported, we do make f16 a legal type, and have 2 places that
we need to patch up: f16 argument passing and returning, which involves minor
tweaks to avoid unnecessary code generation for some bitcasts.
As a "demonstrator" that this works for the different FP16, FullFP16, softfp
modes, etc., I've added match rules to the VSUB instruction description showing
that we can codegen this instruction from IR, but more importantly, also to
some conversion instructions. These conversions were causing issue before in
the FP16 and FullFP16 cases.
I've also added match rules to the VLDRH and VSTRH desriptions, so that we can
actually compile the entire half-precision sub code example above. This showed
that these loads and stores had the wrong addressing mode specified: AddrMode5
instead of AddrMode5FP16, which turned out not be implemented at all, so that
has also been added.
This is the minimal patch that shows all the different moving parts. In patch
2/3 I will add some efficient lowering of bitcasts, and in 2/3 I will add the
remaining Armv8.2-A FP16 instruction descriptions.
Thanks to Sam Parker and Oliver Stannard for their help and reviews!
Differential Revision: https://reviews.llvm.org/D38315
llvm-svn: 323512
2018-01-26 17:26:40 +08:00
|
|
|
; CHECK: remark: {{.*}} unable to lower arguments: half (half, half)* (in function: test_half)
|
2017-04-21 19:53:01 +08:00
|
|
|
; CHECK-LABEL: warning: Instruction selection used fallback path for test_half
|
|
|
|
%res = fadd half %a, %b
|
|
|
|
ret half %res
|
|
|
|
}
|
|
|
|
|
2017-05-29 15:01:52 +08:00
|
|
|
declare [16 x i32] @ret_demotion_target()
|
|
|
|
|
|
|
|
define [16 x i32] @test_ret_demotion() {
|
|
|
|
; CHECK: remark: {{.*}} unable to translate instruction: call{{.*}} @ret_demotion_target
|
|
|
|
; CHECK-LABEL: warning: Instruction selection used fallback path for test_ret_demotion
|
|
|
|
%res = call [16 x i32] @ret_demotion_target()
|
|
|
|
ret [16 x i32] %res
|
2017-04-21 19:53:01 +08:00
|
|
|
}
|
|
|
|
|
2017-06-02 18:16:48 +08:00
|
|
|
%large.struct = type { i32, i32, i32, i32, i32} ; Doesn't fit in R0-R3
|
|
|
|
|
|
|
|
declare %large.struct @large_struct_return_target()
|
|
|
|
|
|
|
|
define %large.struct @test_large_struct_return() {
|
|
|
|
; CHECK: remark: {{.*}} unable to translate instruction: call{{.*}} @large_struct_return_target
|
|
|
|
; CHECK-LABEL: warning: Instruction selection used fallback path for test_large_struct_return
|
|
|
|
%r = call %large.struct @large_struct_return_target()
|
|
|
|
ret %large.struct %r
|
2017-04-21 19:53:01 +08:00
|
|
|
}
|
|
|
|
|
2017-06-15 17:42:02 +08:00
|
|
|
%mixed.struct = type {i32*, float, i32}
|
|
|
|
|
|
|
|
define %mixed.struct @test_mixed_struct(%mixed.struct %x) {
|
|
|
|
; CHECK: remark: {{.*}} unable to lower arguments: %mixed.struct (%mixed.struct)*
|
|
|
|
; CHECK-LABEL: warning: Instruction selection used fallback path for test_mixed_struct
|
|
|
|
ret %mixed.struct %x
|
|
|
|
}
|
|
|
|
|
2017-04-21 19:53:01 +08:00
|
|
|
define void @test_vararg_definition(i32 %a, ...) {
|
|
|
|
; CHECK: remark: {{.*}} unable to lower arguments: void (i32, ...)*
|
|
|
|
; CHECK-LABEL: warning: Instruction selection used fallback path for test_vararg_definition
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
define void @test_vararg_call(i32 %a) {
|
|
|
|
; CHECK: remark: {{.*}} unable to translate instruction: call
|
|
|
|
; CHECK-LABEL: warning: Instruction selection used fallback path for test_vararg_call
|
|
|
|
call void(i32, ...) @test_vararg_definition(i32 %a, i32 %a, i32 %a)
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @test_thumb(i32 %a) #0 {
|
|
|
|
; CHECK: remark: {{.*}} unable to lower arguments: i32 (i32)*
|
|
|
|
; CHECK-LABEL: warning: Instruction selection used fallback path for test_thumb
|
|
|
|
ret i32 %a
|
|
|
|
}
|
|
|
|
|
2017-08-03 17:14:59 +08:00
|
|
|
@thread_local_global = thread_local global i32 42
|
|
|
|
|
|
|
|
define i32 @test_thread_local_global() {
|
|
|
|
; CHECK: remark: {{.*}} cannot select: {{.*}} G_GLOBAL_VALUE
|
|
|
|
; CHECK-LABEL: warning: Instruction selection used fallback path for test_thread_local_global
|
|
|
|
; PIC: remark: {{.*}} cannot select: {{.*}} G_GLOBAL_VALUE
|
|
|
|
; PIC-LABEL: warning: Instruction selection used fallback path for test_thread_local_global
|
|
|
|
; ROPI: remark: {{.*}} cannot select: {{.*}} G_GLOBAL_VALUE
|
|
|
|
; ROPI-LABEL: warning: Instruction selection used fallback path for test_thread_local_global
|
|
|
|
; RWPI: remark: {{.*}} cannot select: {{.*}} G_GLOBAL_VALUE
|
|
|
|
; RWPI-LABEL: warning: Instruction selection used fallback path for test_thread_local_global
|
|
|
|
; ROPI-RWPI: remark: {{.*}} cannot select: {{.*}} G_GLOBAL_VALUE
|
|
|
|
; ROPI-RWPI-LABEL: warning: Instruction selection used fallback path for test_thread_local_global
|
|
|
|
%v = load i32, i32* @thread_local_global
|
|
|
|
ret i32 %v
|
|
|
|
}
|
|
|
|
|
2017-11-30 20:23:44 +08:00
|
|
|
%byval.class = type { i32 }
|
|
|
|
|
|
|
|
define void @test_byval_arg(%byval.class* byval %x) {
|
|
|
|
; CHECK: remark: {{.*}} unable to lower arguments: void (%byval.class*)*
|
|
|
|
; CHECK-LABEL: warning: Instruction selection used fallback path for test_byval
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
define void @test_byval_param(%byval.class* %x) {
|
|
|
|
; CHECK: remark: {{.*}} unable to translate instruction: call
|
|
|
|
; CHECK-LABEL: warning: Instruction selection used fallback path for test_byval_param
|
|
|
|
call void @test_byval_arg(%byval.class* byval %x)
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
2017-04-21 19:53:01 +08:00
|
|
|
attributes #0 = { "target-features"="+thumb-mode" }
|