; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; RUN: llc -mtriple=armv8m.main-none-eabi   < %s -frame-pointer=none -mattr=+fp-armv8d16 | FileCheck %s --check-prefix=LE
; RUN: llc -mtriple=armebv8m.main-none-eabi < %s -frame-pointer=none -mattr=+fp-armv8d16 | FileCheck %s --check-prefix=BE
; RUN: llc -mtriple=armv8m.main-none-eabi   < %s -frame-pointer=none -mattr=+fp-armv8d16,+fullfp16 | FileCheck %s --check-prefix=LE-FP16
; RUN: llc -mtriple=armebv8m.main-none-eabi < %s -frame-pointer=none -mattr=+fp-armv8d16,+fullfp16 | FileCheck %s --check-prefix=BE-FP16

;; Global ISel successfully generates code for some functions for little-endian
;; without +fullfp16, and falls back to SelectionDAG in all others.
; RUN: llc -mtriple=armv8m.main-none-eabi   < %s -frame-pointer=none -mattr=+fp-armv8d16 -global-isel=1 -global-isel-abort=2 | FileCheck %s --check-prefix=LE-GISEL
; RUN: llc -mtriple=armebv8m.main-none-eabi < %s -frame-pointer=none -mattr=+fp-armv8d16 -global-isel=1 -global-isel-abort=2 | FileCheck %s --check-prefix=BE
; RUN: llc -mtriple=armv8m.main-none-eabi   < %s -frame-pointer=none -mattr=+fp-armv8d16,+fullfp16 -global-isel=1 -global-isel-abort=2 | FileCheck %s --check-prefix=LE-FP16
; RUN: llc -mtriple=armebv8m.main-none-eabi < %s -frame-pointer=none -mattr=+fp-armv8d16,+fullfp16 -global-isel=1 -global-isel-abort=2 | FileCheck %s --check-prefix=BE-FP16

define arm_aapcscc half @callee_soft_half_in_reg(half %f) {
; LE-LABEL: callee_soft_half_in_reg:
; LE:       @ %bb.0: @ %entry
; LE-NEXT:    bx lr
;
; BE-LABEL: callee_soft_half_in_reg:
; BE:       @ %bb.0: @ %entry
; BE-NEXT:    bx lr
;
; LE-FP16-LABEL: callee_soft_half_in_reg:
; LE-FP16:       @ %bb.0: @ %entry
; LE-FP16-NEXT:    vmov.f16 s0, r0
; LE-FP16-NEXT:    vmov r0, s0
; LE-FP16-NEXT:    bx lr
;
; BE-FP16-LABEL: callee_soft_half_in_reg:
; BE-FP16:       @ %bb.0: @ %entry
; BE-FP16-NEXT:    vmov.f16 s0, r0
; BE-FP16-NEXT:    vmov r0, s0
; BE-FP16-NEXT:    bx lr
;
; LE-GISEL-LABEL: callee_soft_half_in_reg:
; LE-GISEL:       @ %bb.0: @ %entry
; LE-GISEL-NEXT:    bx lr
entry:
  ret half %f
}

define void @caller_soft_half_in_reg() {
; LE-LABEL: caller_soft_half_in_reg:
; LE:       @ %bb.0: @ %entry
; LE-NEXT:    .save {r7, lr}
; LE-NEXT:    push {r7, lr}
; LE-NEXT:    mov.w r0, #15360
; LE-NEXT:    bl callee_soft_half_in_reg
; LE-NEXT:    pop {r7, pc}
;
; BE-LABEL: caller_soft_half_in_reg:
; BE:       @ %bb.0: @ %entry
; BE-NEXT:    .save {r7, lr}
; BE-NEXT:    push {r7, lr}
; BE-NEXT:    mov.w r0, #15360
; BE-NEXT:    bl callee_soft_half_in_reg
; BE-NEXT:    pop {r7, pc}
;
; LE-FP16-LABEL: caller_soft_half_in_reg:
; LE-FP16:       @ %bb.0: @ %entry
; LE-FP16-NEXT:    .save {r7, lr}
; LE-FP16-NEXT:    push {r7, lr}
; LE-FP16-NEXT:    mov.w r0, #15360
; LE-FP16-NEXT:    bl callee_soft_half_in_reg
; LE-FP16-NEXT:    pop {r7, pc}
;
; BE-FP16-LABEL: caller_soft_half_in_reg:
; BE-FP16:       @ %bb.0: @ %entry
; BE-FP16-NEXT:    .save {r7, lr}
; BE-FP16-NEXT:    push {r7, lr}
; BE-FP16-NEXT:    mov.w r0, #15360
; BE-FP16-NEXT:    bl callee_soft_half_in_reg
; BE-FP16-NEXT:    pop {r7, pc}
;
; LE-GISEL-LABEL: caller_soft_half_in_reg:
; LE-GISEL:       @ %bb.0: @ %entry
; LE-GISEL-NEXT:    .save {r7, lr}
; LE-GISEL-NEXT:    push {r7, lr}
; LE-GISEL-NEXT:    mov.w r0, #15360
; LE-GISEL-NEXT:    bl callee_soft_half_in_reg
; LE-GISEL-NEXT:    pop {r7, pc}
entry:
  %ret = call arm_aapcscc half @callee_soft_half_in_reg(half 1.0)
  ret void
}

define arm_aapcscc half @callee_soft_half_on_stack(float %r0, float %r1, float %r2, float %r3, half %f) {
; LE-LABEL: callee_soft_half_on_stack:
; LE:       @ %bb.0: @ %entry
; LE-NEXT:    ldr r0, [sp]
; LE-NEXT:    bx lr
;
; BE-LABEL: callee_soft_half_on_stack:
; BE:       @ %bb.0: @ %entry
; BE-NEXT:    ldr r0, [sp]
; BE-NEXT:    bx lr
;
; LE-FP16-LABEL: callee_soft_half_on_stack:
; LE-FP16:       @ %bb.0: @ %entry
; LE-FP16-NEXT:    vldr.16 s0, [sp]
; LE-FP16-NEXT:    vmov r0, s0
; LE-FP16-NEXT:    bx lr
;
; BE-FP16-LABEL: callee_soft_half_on_stack:
; BE-FP16:       @ %bb.0: @ %entry
; BE-FP16-NEXT:    vldr.16 s0, [sp, #2]
; BE-FP16-NEXT:    vmov r0, s0
; BE-FP16-NEXT:    bx lr
;
; LE-GISEL-LABEL: callee_soft_half_on_stack:
; LE-GISEL:       @ %bb.0: @ %entry
; LE-GISEL-NEXT:    mov r0, sp
; LE-GISEL-NEXT:    ldr r0, [r0]
; LE-GISEL-NEXT:    bx lr
entry:
  ret half %f
}

define void @caller_soft_half_on_stack() {
; LE-LABEL: caller_soft_half_on_stack:
; LE:       @ %bb.0: @ %entry
; LE-NEXT:    .save {r7, lr}
; LE-NEXT:    push {r7, lr}
; LE-NEXT:    .pad #8
; LE-NEXT:    sub sp, #8
; LE-NEXT:    mov.w r0, #15360
; LE-NEXT:    str r0, [sp]
; LE-NEXT:    bl callee_soft_half_on_stack
; LE-NEXT:    add sp, #8
; LE-NEXT:    pop {r7, pc}
;
; BE-LABEL: caller_soft_half_on_stack:
; BE:       @ %bb.0: @ %entry
; BE-NEXT:    .save {r7, lr}
; BE-NEXT:    push {r7, lr}
; BE-NEXT:    .pad #8
; BE-NEXT:    sub sp, #8
; BE-NEXT:    mov.w r0, #15360
; BE-NEXT:    str r0, [sp]
; BE-NEXT:    bl callee_soft_half_on_stack
; BE-NEXT:    add sp, #8
; BE-NEXT:    pop {r7, pc}
;
; LE-FP16-LABEL: caller_soft_half_on_stack:
; LE-FP16:       @ %bb.0: @ %entry
; LE-FP16-NEXT:    .save {r7, lr}
; LE-FP16-NEXT:    push {r7, lr}
; LE-FP16-NEXT:    .pad #8
; LE-FP16-NEXT:    sub sp, #8
; LE-FP16-NEXT:    mov.w r0, #15360
; LE-FP16-NEXT:    str r0, [sp]
; LE-FP16-NEXT:    bl callee_soft_half_on_stack
; LE-FP16-NEXT:    add sp, #8
; LE-FP16-NEXT:    pop {r7, pc}
;
; BE-FP16-LABEL: caller_soft_half_on_stack:
; BE-FP16:       @ %bb.0: @ %entry
; BE-FP16-NEXT:    .save {r7, lr}
; BE-FP16-NEXT:    push {r7, lr}
; BE-FP16-NEXT:    .pad #8
; BE-FP16-NEXT:    sub sp, #8
; BE-FP16-NEXT:    mov.w r0, #15360
; BE-FP16-NEXT:    str r0, [sp]
; BE-FP16-NEXT:    bl callee_soft_half_on_stack
; BE-FP16-NEXT:    add sp, #8
; BE-FP16-NEXT:    pop {r7, pc}
;
; LE-GISEL-LABEL: caller_soft_half_on_stack:
; LE-GISEL:       @ %bb.0: @ %entry
; LE-GISEL-NEXT:    .save {r7, lr}
; LE-GISEL-NEXT:    push {r7, lr}
; LE-GISEL-NEXT:    .pad #8
; LE-GISEL-NEXT:    sub sp, #8
; LE-GISEL-NEXT:    mov.w r0, #15360
; LE-GISEL-NEXT:    str r0, [sp]
; LE-GISEL-NEXT:    bl callee_soft_half_on_stack
; LE-GISEL-NEXT:    add sp, #8
; LE-GISEL-NEXT:    pop {r7, pc}
entry:
  %ret = call arm_aapcscc half @callee_soft_half_on_stack(float poison, float poison, float poison, float poison, half 1.0)
  ret void
}

define arm_aapcs_vfpcc half @callee_hard_half_in_reg(half %f) {
; LE-LABEL: callee_hard_half_in_reg:
; LE:       @ %bb.0: @ %entry
; LE-NEXT:    bx lr
;
; BE-LABEL: callee_hard_half_in_reg:
; BE:       @ %bb.0: @ %entry
; BE-NEXT:    bx lr
;
; LE-FP16-LABEL: callee_hard_half_in_reg:
; LE-FP16:       @ %bb.0: @ %entry
; LE-FP16-NEXT:    bx lr
;
; BE-FP16-LABEL: callee_hard_half_in_reg:
; BE-FP16:       @ %bb.0: @ %entry
; BE-FP16-NEXT:    bx lr
;
; LE-GISEL-LABEL: callee_hard_half_in_reg:
; LE-GISEL:       @ %bb.0: @ %entry
; LE-GISEL-NEXT:    bx lr
entry:
  ret half %f
}

define void @caller_hard_half_in_reg() {
; LE-LABEL: caller_hard_half_in_reg:
; LE:       @ %bb.0: @ %entry
; LE-NEXT:    .save {r7, lr}
; LE-NEXT:    push {r7, lr}
; LE-NEXT:    vldr s0, .LCPI5_0
; LE-NEXT:    bl callee_hard_half_in_reg
; LE-NEXT:    pop {r7, pc}
; LE-NEXT:    .p2align 2
; LE-NEXT:  @ %bb.1:
; LE-NEXT:  .LCPI5_0:
; LE-NEXT:    .long 0x00003c00 @ float 2.15239444E-41
;
; BE-LABEL: caller_hard_half_in_reg:
; BE:       @ %bb.0: @ %entry
; BE-NEXT:    .save {r7, lr}
; BE-NEXT:    push {r7, lr}
; BE-NEXT:    vldr s0, .LCPI5_0
; BE-NEXT:    bl callee_hard_half_in_reg
; BE-NEXT:    pop {r7, pc}
; BE-NEXT:    .p2align 2
; BE-NEXT:  @ %bb.1:
; BE-NEXT:  .LCPI5_0:
; BE-NEXT:    .long 0x00003c00 @ float 2.15239444E-41
;
; LE-FP16-LABEL: caller_hard_half_in_reg:
; LE-FP16:       @ %bb.0: @ %entry
; LE-FP16-NEXT:    .save {r7, lr}
; LE-FP16-NEXT:    push {r7, lr}
; LE-FP16-NEXT:    vmov.f16 s0, #1.000000e+00
; LE-FP16-NEXT:    bl callee_hard_half_in_reg
; LE-FP16-NEXT:    pop {r7, pc}
;
; BE-FP16-LABEL: caller_hard_half_in_reg:
; BE-FP16:       @ %bb.0: @ %entry
; BE-FP16-NEXT:    .save {r7, lr}
; BE-FP16-NEXT:    push {r7, lr}
; BE-FP16-NEXT:    vmov.f16 s0, #1.000000e+00
; BE-FP16-NEXT:    bl callee_hard_half_in_reg
; BE-FP16-NEXT:    pop {r7, pc}
;
; LE-GISEL-LABEL: caller_hard_half_in_reg:
; LE-GISEL:       @ %bb.0: @ %entry
; LE-GISEL-NEXT:    .save {r7, lr}
; LE-GISEL-NEXT:    push {r7, lr}
; LE-GISEL-NEXT:    vldr s0, .LCPI5_0
; LE-GISEL-NEXT:    bl callee_hard_half_in_reg
; LE-GISEL-NEXT:    pop {r7, pc}
; LE-GISEL-NEXT:    .p2align 2
; LE-GISEL-NEXT:  @ %bb.1:
; LE-GISEL-NEXT:  .LCPI5_0:
; LE-GISEL-NEXT:    .long 0x00003c00 @ float 2.15239444E-41
entry:
  %ret = call arm_aapcs_vfpcc half @callee_hard_half_in_reg(half 1.0)
  ret void
}

define arm_aapcs_vfpcc half @callee_hard_half_on_stack(float %s0, float %s1, float %s2, float %s3, float %s4, float %s5, float %s6, float %s7,float %s8, float %s9, float %s10, float %s11, float %s12, float %s13, float %s14, float %s15, half %f) {
; LE-LABEL: callee_hard_half_on_stack:
; LE:       @ %bb.0: @ %entry
; LE-NEXT:    vldr s0, [sp]
; LE-NEXT:    bx lr
;
; BE-LABEL: callee_hard_half_on_stack:
; BE:       @ %bb.0: @ %entry
; BE-NEXT:    vldr s0, [sp]
; BE-NEXT:    bx lr
;
; LE-FP16-LABEL: callee_hard_half_on_stack:
; LE-FP16:       @ %bb.0: @ %entry
; LE-FP16-NEXT:    vldr.16 s0, [sp]
; LE-FP16-NEXT:    bx lr
;
; BE-FP16-LABEL: callee_hard_half_on_stack:
; BE-FP16:       @ %bb.0: @ %entry
; BE-FP16-NEXT:    vldr.16 s0, [sp, #2]
; BE-FP16-NEXT:    bx lr
;
; LE-GISEL-LABEL: callee_hard_half_on_stack:
; LE-GISEL:       @ %bb.0: @ %entry
; LE-GISEL-NEXT:    mov r0, sp
; LE-GISEL-NEXT:    ldr r0, [r0]
; LE-GISEL-NEXT:    vmov s0, r0
; LE-GISEL-NEXT:    bx lr
entry:
  ret half %f
}


define void @caller_hard_half_on_stack() {
; LE-LABEL: caller_hard_half_on_stack:
; LE:       @ %bb.0: @ %entry
; LE-NEXT:    .save {r7, lr}
; LE-NEXT:    push {r7, lr}
; LE-NEXT:    .pad #8
; LE-NEXT:    sub sp, #8
; LE-NEXT:    mov.w r0, #15360
; LE-NEXT:    str r0, [sp]
; LE-NEXT:    bl callee_hard_half_on_stack
; LE-NEXT:    add sp, #8
; LE-NEXT:    pop {r7, pc}
;
; BE-LABEL: caller_hard_half_on_stack:
; BE:       @ %bb.0: @ %entry
; BE-NEXT:    .save {r7, lr}
; BE-NEXT:    push {r7, lr}
; BE-NEXT:    .pad #8
; BE-NEXT:    sub sp, #8
; BE-NEXT:    mov.w r0, #15360
; BE-NEXT:    str r0, [sp]
; BE-NEXT:    bl callee_hard_half_on_stack
; BE-NEXT:    add sp, #8
; BE-NEXT:    pop {r7, pc}
;
; LE-FP16-LABEL: caller_hard_half_on_stack:
; LE-FP16:       @ %bb.0: @ %entry
; LE-FP16-NEXT:    .save {r7, lr}
; LE-FP16-NEXT:    push {r7, lr}
; LE-FP16-NEXT:    .pad #8
; LE-FP16-NEXT:    sub sp, #8
; LE-FP16-NEXT:    mov.w r0, #15360
; LE-FP16-NEXT:    str r0, [sp]
; LE-FP16-NEXT:    bl callee_hard_half_on_stack
; LE-FP16-NEXT:    add sp, #8
; LE-FP16-NEXT:    pop {r7, pc}
;
; BE-FP16-LABEL: caller_hard_half_on_stack:
; BE-FP16:       @ %bb.0: @ %entry
; BE-FP16-NEXT:    .save {r7, lr}
; BE-FP16-NEXT:    push {r7, lr}
; BE-FP16-NEXT:    .pad #8
; BE-FP16-NEXT:    sub sp, #8
; BE-FP16-NEXT:    mov.w r0, #15360
; BE-FP16-NEXT:    str r0, [sp]
; BE-FP16-NEXT:    bl callee_hard_half_on_stack
; BE-FP16-NEXT:    add sp, #8
; BE-FP16-NEXT:    pop {r7, pc}
;
; LE-GISEL-LABEL: caller_hard_half_on_stack:
; LE-GISEL:       @ %bb.0: @ %entry
; LE-GISEL-NEXT:    .save {r7, lr}
; LE-GISEL-NEXT:    push {r7, lr}
; LE-GISEL-NEXT:    .pad #8
; LE-GISEL-NEXT:    sub sp, #8
; LE-GISEL-NEXT:    mov.w r0, #15360
; LE-GISEL-NEXT:    str r0, [sp]
; LE-GISEL-NEXT:    bl callee_hard_half_on_stack
; LE-GISEL-NEXT:    add sp, #8
; LE-GISEL-NEXT:    pop {r7, pc}
entry:
  %ret = call arm_aapcs_vfpcc half @callee_hard_half_on_stack(float poison, float poison, float poison, float poison, float poison, float poison, float poison, float poison, float poison, float poison, float poison, float poison, float poison, float poison, float poison, float poison, half 1.0)
  ret void
}
