llvm-project/llvm/test/CodeGen/AArch64/argument-blocks.ll
Oliver Stannard fd534e524d
[AArch64] Do not split bfloat HFA args between regs and stack (#128909)
In AAPCS64, __fp16 and __bf16 share the same machine type, so they
should be treated the same way for argument passing. In particular,
arrays of them need to be treated as homogeneous aggregates, and not
split between registers and the stack.
2025-02-27 11:38:41 +00:00

205 lines
6.2 KiB
LLVM

; RUN: llc -mtriple=aarch64-apple-ios7.0 -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-DARWINPCS
; RUN: llc -mtriple=aarch64-linux-gnu -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-AAPCS
declare void @callee(...)
define float @test_hfa_regs(float, [2 x float] %in) {
; CHECK-LABEL: test_hfa_regs:
; CHECK: fadd s0, s1, s2
%lhs = extractvalue [2 x float] %in, 0
%rhs = extractvalue [2 x float] %in, 1
%sum = fadd float %lhs, %rhs
ret float %sum
}
; Check that the array gets allocated to a contiguous block on the stack (rather
; than the default of 2 8-byte slots).
define float @test_hfa_block([7 x float], [2 x float] %in) {
; CHECK-LABEL: test_hfa_block:
; CHECK: ldp [[LHS:s[0-9]+]], [[RHS:s[0-9]+]], [sp]
; CHECK: fadd s0, [[LHS]], [[RHS]]
%lhs = extractvalue [2 x float] %in, 0
%rhs = extractvalue [2 x float] %in, 1
%sum = fadd float %lhs, %rhs
ret float %sum
}
; Check that an HFA prevents backfilling of VFP registers (i.e. %rhs must go on
; the stack rather than in s7).
define float @test_hfa_block_consume([7 x float], [2 x float] %in, float %rhs) {
; CHECK-LABEL: test_hfa_block_consume:
; CHECK-DAG: ldr [[LHS:s[0-9]+]], [sp]
; CHECK-DAG: ldr [[RHS:s[0-9]+]], [sp, #8]
; CHECK: fadd s0, [[LHS]], [[RHS]]
%lhs = extractvalue [2 x float] %in, 0
%sum = fadd float %lhs, %rhs
ret float %sum
}
define float @test_hfa_stackalign([8 x float], [1 x float], [2 x float] %in) {
; CHECK-LABEL: test_hfa_stackalign:
; CHECK-AAPCS: ldp [[LHS:s[0-9]+]], [[RHS:s[0-9]+]], [sp, #8]
; CHECK-DARWINPCS: ldp [[LHS:s[0-9]+]], [[RHS:s[0-9]+]], [sp, #4]
; CHECK: fadd s0, [[LHS]], [[RHS]]
%lhs = extractvalue [2 x float] %in, 0
%rhs = extractvalue [2 x float] %in, 1
%sum = fadd float %lhs, %rhs
ret float %sum
}
; An HFA that ends up on the stack should not have any effect on where
; integer-based arguments go.
define i64 @test_hfa_ignores_gprs([7 x float], [2 x float] %in, i64, i64 %res) {
; CHECK-LABEL: test_hfa_ignores_gprs:
; CHECK: mov x0, x1
ret i64 %res
}
; [2 x float] should not be promoted to double by the Darwin varargs handling,
; but should go in an 8-byte aligned slot and can be merged as integer stores.
define void @test_varargs_stackalign() {
; CHECK-LABEL: test_varargs_stackalign:
; CHECK-DARWINPCS: str {{x[0-9]+}}, [sp, #16]
call void(...) @callee([3 x float] undef, [2 x float] [float 1.0, float 2.0])
ret void
}
define i64 @test_smallstruct_block([7 x i64], [2 x i64] %in) {
; CHECK-LABEL: test_smallstruct_block:
; CHECK: ldp [[LHS:x[0-9]+]], [[RHS:x[0-9]+]], [sp]
; CHECK: add x0, [[LHS]], [[RHS]]
%lhs = extractvalue [2 x i64] %in, 0
%rhs = extractvalue [2 x i64] %in, 1
%sum = add i64 %lhs, %rhs
ret i64 %sum
}
; Check that a small struct prevents backfilling of registers (i.e. %rhs
; must go on the stack rather than in x7).
define i64 @test_smallstruct_block_consume([7 x i64], [2 x i64] %in, i64 %rhs) {
; CHECK-LABEL: test_smallstruct_block_consume:
; CHECK-DAG: ldr [[LHS:x[0-9]+]], [sp]
; CHECK-DAG: ldr [[RHS:x[0-9]+]], [sp, #16]
; CHECK: add x0, [[LHS]], [[RHS]]
%lhs = extractvalue [2 x i64] %in, 0
%sum = add i64 %lhs, %rhs
ret i64 %sum
}
define <1 x i64> @test_v1i64_blocked([7 x double], [2 x <1 x i64>] %in) {
; CHECK-LABEL: test_v1i64_blocked:
; CHECK: ldr d0, [sp]
%val = extractvalue [2 x <1 x i64>] %in, 0
ret <1 x i64> %val
}
define <1 x double> @test_v1f64_blocked([7 x double], [2 x <1 x double>] %in) {
; CHECK-LABEL: test_v1f64_blocked:
; CHECK: ldr d0, [sp]
%val = extractvalue [2 x <1 x double>] %in, 0
ret <1 x double> %val
}
define <2 x i32> @test_v2i32_blocked([7 x double], [2 x <2 x i32>] %in) {
; CHECK-LABEL: test_v2i32_blocked:
; CHECK: ldr d0, [sp]
%val = extractvalue [2 x <2 x i32>] %in, 0
ret <2 x i32> %val
}
define <2 x float> @test_v2f32_blocked([7 x double], [2 x <2 x float>] %in) {
; CHECK-LABEL: test_v2f32_blocked:
; CHECK: ldr d0, [sp]
%val = extractvalue [2 x <2 x float>] %in, 0
ret <2 x float> %val
}
define <4 x i16> @test_v4i16_blocked([7 x double], [2 x <4 x i16>] %in) {
; CHECK-LABEL: test_v4i16_blocked:
; CHECK: ldr d0, [sp]
%val = extractvalue [2 x <4 x i16>] %in, 0
ret <4 x i16> %val
}
define <4 x half> @test_v4f16_blocked([7 x double], [2 x <4 x half>] %in) {
; CHECK-LABEL: test_v4f16_blocked:
; CHECK: ldr d0, [sp]
%val = extractvalue [2 x <4 x half>] %in, 0
ret <4 x half> %val
}
define <8 x i8> @test_v8i8_blocked([7 x double], [2 x <8 x i8>] %in) {
; CHECK-LABEL: test_v8i8_blocked:
; CHECK: ldr d0, [sp]
%val = extractvalue [2 x <8 x i8>] %in, 0
ret <8 x i8> %val
}
define <2 x i64> @test_v2i64_blocked([7 x double], [2 x <2 x i64>] %in) {
; CHECK-LABEL: test_v2i64_blocked:
; CHECK: ldr q0, [sp]
%val = extractvalue [2 x <2 x i64>] %in, 0
ret <2 x i64> %val
}
define <2 x double> @test_v2f64_blocked([7 x double], [2 x <2 x double>] %in) {
; CHECK-LABEL: test_v2f64_blocked:
; CHECK: ldr q0, [sp]
%val = extractvalue [2 x <2 x double>] %in, 0
ret <2 x double> %val
}
define <4 x i32> @test_v4i32_blocked([7 x double], [2 x <4 x i32>] %in) {
; CHECK-LABEL: test_v4i32_blocked:
; CHECK: ldr q0, [sp]
%val = extractvalue [2 x <4 x i32>] %in, 0
ret <4 x i32> %val
}
define <4 x float> @test_v4f32_blocked([7 x double], [2 x <4 x float>] %in) {
; CHECK-LABEL: test_v4f32_blocked:
; CHECK: ldr q0, [sp]
%val = extractvalue [2 x <4 x float>] %in, 0
ret <4 x float> %val
}
define <8 x i16> @test_v8i16_blocked([7 x double], [2 x <8 x i16>] %in) {
; CHECK-LABEL: test_v8i16_blocked:
; CHECK: ldr q0, [sp]
%val = extractvalue [2 x <8 x i16>] %in, 0
ret <8 x i16> %val
}
define <8 x half> @test_v8f16_blocked([7 x double], [2 x <8 x half>] %in) {
; CHECK-LABEL: test_v8f16_blocked:
; CHECK: ldr q0, [sp]
%val = extractvalue [2 x <8 x half>] %in, 0
ret <8 x half> %val
}
define <16 x i8> @test_v16i8_blocked([7 x double], [2 x <16 x i8>] %in) {
; CHECK-LABEL: test_v16i8_blocked:
; CHECK: ldr q0, [sp]
%val = extractvalue [2 x <16 x i8>] %in, 0
ret <16 x i8> %val
}
define half @test_f16_blocked([7 x double], [2 x half] %in) {
; CHECK-LABEL: test_f16_blocked:
; CHECK: ldr h0, [sp]
%val = extractvalue [2 x half] %in, 0
ret half %val
}
define bfloat @test_bf16_blocked([7 x double], [2 x bfloat] %in) {
; CHECK-LABEL: test_bf16_blocked:
; CHECK: ldr h0, [sp]
%val = extractvalue [2 x bfloat] %in, 0
ret bfloat %val
}