Index: test/CodeGen/ARM/float-helpers.s =================================================================== --- /dev/null +++ test/CodeGen/ARM/float-helpers.s @@ -0,0 +1,738 @@ +; RUN: llc -asm-verbose=false -mattr=-vfp2 < %s | FileCheck %s -check-prefix=CHECK-ALL -check-prefix=CHECK-SOFT +; RUN: llc -asm-verbose=false -mattr=-vfp2 -meabi=gnu < %s | FileCheck %s -check-prefix=CHECK-ALL -check-prefix=CHECK-SOFT +; RUN: llc -asm-verbose=false -mattr=+vfp3 < %s | FileCheck %s -check-prefix=CHECK-ALL -check-prefix=CHECK-SOFTFP +; RUN: llc -asm-verbose=false -mattr=+vfp3 -meabi=gnu < %s | FileCheck %s -check-prefix=CHECK-ALL -check-prefix=CHECK-SOFTFP +; RUN: llc -asm-verbose=false -mattr=+vfp3 -float-abi=hard < %s | FileCheck %s -check-prefix=CHECK-ALL -check-prefix=CHECK-HARDFP-SP -check-prefix=CHECK-HARDFP-DP +; RUN: llc -asm-verbose=false -mattr=+vfp3 -float-abi=hard -meabi=gnu < %s | FileCheck %s -check-prefix=CHECK-ALL -check-prefix=CHECK-HARDFP-SP -check-prefix=CHECK-HARDFP-DP +; RUN: llc -asm-verbose=false -mattr=+vfp3,+fp-only-sp -float-abi=hard < %s | FileCheck %s -check-prefix=CHECK-ALL -check-prefix=CHECK-HARDFP-SP -check-prefix=CHECK-HARDFP-SPONLY +; RUN: llc -asm-verbose=false -mattr=+vfp3,+fp-only-sp -float-abi=hard -meabi=gnu < %s | FileCheck %s -check-prefix=CHECK-ALL -check-prefix=CHECK-HARDFP-SP -check-prefix=CHECK-HARDFP-SPONLY + +; The Runtime ABI for the ARM Architecture IHI0043 section 4.1.2 The +; floating-point helper functions to always use the base AAPCS (soft-float) +; calling convention. + +; In this test we cover the following configurations: +; CHECK-SOFT -mfloat-abi=soft +; * expect no use of floating point instructions +; * expect to use __aeabi_ helper function in each function +; CHECK-SOFTFP -mfloat-abi=softfp +; * all functions use base AAPCS +; * floating point instructions permitted, so __aeabi_ helpers only +; expected when there is no available instruction. +; CHECK-HARD-FP-SP -mfloat-abi=hardfp (single precision instructions) +; * all non Runtime ABI helper functions use AAPCS VFP +; * floating point instructions permitted, so __aeabi_ helpers only +; expected when there is no available instruction. +; CHECK-HARD-FP-DP -mfloat-abi=hardfp (double precision instructions) +; CHECK-HARD_FP_SPONLY -mfloat-abi=hardfp (double precision but single +; precision only FPU) +; * as CHECK-HARD-FP-SP, but we split up the double precision helper +; functions so we can test a single precision only FPU, which has to use +; helper function for all double precision operations. + +; In all cases we must use base AAPCS when calling a helper function from +; section 4.1.2. + +target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" +target triple = "armv7--linux-gnueabi" + +; CHECK-ALL-LABEL: fadd: +; CHECK-SOFT: bl __aeabi_fadd + +; CHECK-SOFTFP: vmov s0, r1 +; CHECK-SOFTFP-NEXT: vmov s2, r0 +; CHECK-SOFTFP-NEXT: vadd.f32 s0, s2, s0 +; CHECK-SOFTFP-NEXT: vmov r0, s0 + +; CHECK-HARDFP-SP: vadd.f32 s0, s0, s1 +define float @fadd(float %a, float %b) #0 { +entry: + %add = fadd float %a, %b + ret float %add +} + +; CHECK-ALL-LABEL: fdiv: +; CHECK-SOFT: bl __aeabi_fdiv + +; CHECK-SOFTFP: vmov s0, r1 +; CHECK-SOFTFP-NEXT: vmov s2, r0 +; CHECK-SOFTFP-NEXT: vdiv.f32 s0, s2, s0 +; CHECK-SOFTFP-NEXT: vmov r0, s0 + +; CHECK-HARDFP-SP: vdiv.f32 s0, s0, s1 +define float @fdiv(float %a, float %b) #0 { +entry: + %div = fdiv float %a, %b + ret float %div +} + +; CHECK-ALL-LABEL: fmul: +; CHECK-SOFT: bl __aeabi_fmul + +; CHECK-SOFTFP: vmov s0, r1 +; CHECK-SOFTFP-NEXT: vmov s2, r0 +; CHECK-SOFTFP-NEXT: vmul.f32 s0, s2, s0 +; CHECK-SOFTFP-NEXT: vmov r0, s0 + +; CHECK-HARDFP-SP: vmul.f32 s0, s0, s1 +define float @fmul(float %a, float %b) #0 { +entry: + %mul = fmul float %a, %b + ret float %mul +} + +; CHECK-ALL-LABEL: fsub: +; CHECK-SOFT: bl __aeabi_fsub + +; CHECK-SOFTFP: vmov s0, r1 +; CHECK-SOFTFP-NEXT: vmov s2, r0 +; CHECK-SOFTFP-NEXT: vsub.f32 s0, s2, s0 +; CHECK-SOFTFP-NEXT: vmov r0, s0 + +; CHECK-HARDFP-SP: vsub.f32 s0, s0, s1 +define float @fsub(float %a, float %b) #0 { +entry: + %sub = fsub float %a, %b + ret float %sub +} + +; CHECK-ALL-LABEL: fcmpeq: +; CHECK-SOFT: bl __aeabi_fcmpeq + +; CHECK-SOFTFP: vmov s2, r0 +; CHECK-SOFTFP-NEXT: mov r0, #0 +; CHECK-SOFTFP-NEXT: vmov s0, r1 +; CHECK-SOFTFP-NEXT: vcmp.f32 s2, s0 +; CHECK-SOFTFP-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-SOFTFP-NEXT: movweq r0, #1 + +; CHECK-HARDFP-SP: vcmp.f32 s0, s1 +; CHECK-HARDFP-SP-NEXT: mov r0, #0 +; CHECK-HARDFP-SP-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-HARDFP-SP-NEXT: movweq r0, #1 +define i32 @fcmpeq(float %a, float %b) #0 { +entry: + %cmp = fcmp oeq float %a, %b + %conv = zext i1 %cmp to i32 + ret i32 %conv +} + +; CHECK-ALL-LABEL: fcmplt: +; CHECK-SOFT: bl __aeabi_fcmplt + +; CHECK-SOFTFP: vmov s2, r0 +; CHECK-SOFTFP-NEXT: mov r0, #0 +; CHECK-SOFTFP-NEXT: vmov s0, r1 +; CHECK-SOFTFP-NEXT: vcmpe.f32 s2, s0 +; CHECK-SOFTFP-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-SOFTFP-NEXT: movwmi r0, #1 + +; CHECK-HARDFP-SP: vcmpe.f32 s0, s1 +; CHECK-HARDFP-SP-NEXT: mov r0, #0 +; CHECK-HARDFP-SP-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-HARDFP-SP-NEXT: movwmi r0, #1 +define i32 @fcmplt(float %a, float %b) #0 { +entry: + %cmp = fcmp olt float %a, %b + %conv = zext i1 %cmp to i32 + ret i32 %conv +} + +; CHECK-ALL-LABEL: fcmple: +; CHECK-SOFT: bl __aeabi_fcmple + +; CHECK-SOFTFP: vmov s2, r0 +; CHECK-SOFTFP-NEXT: mov r0, #0 +; CHECK-SOFTFP-NEXT: vmov s0, r1 +; CHECK-SOFTFP-NEXT: vcmpe.f32 s2, s0 +; CHECK-SOFTFP-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-SOFTFP-NEXT: movwls r0, #1 + +; CHECK-HARDFP-SP: vcmpe.f32 s0, s1 +; CHECK-HARDFP-SP-NEXT: mov r0, #0 +; CHECK-HARDFP-SP-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-HARDFP-SP-NEXT: movwls r0, #1 +define i32 @fcmple(float %a, float %b) #0 { +entry: + %cmp = fcmp ole float %a, %b + %conv = zext i1 %cmp to i32 + ret i32 %conv +} + +; CHECK-ALL-LABEL: fcmpge: +; CHECK-SOFT: bl __aeabi_fcmpge + +; CHECK-SOFTFP: vmov s2, r0 +; CHECK-SOFTFP-NEXT: mov r0, #0 +; CHECK-SOFTFP-NEXT: vmov s0, r1 +; CHECK-SOFTFP-NEXT: vcmpe.f32 s2, s0 +; CHECK-SOFTFP-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-SOFTFP-NEXT: movwge r0, #1 + +; CHECK-HARDFP-SP: vcmpe.f32 s0, s1 +; CHECK-HARDFP-SP-NEXT: mov r0, #0 +; CHECK-HARDFP-SP-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-HARDFP-SP-NEXT: movwge r0, #1 +define i32 @fcmpge(float %a, float %b) #0 { +entry: + %cmp = fcmp oge float %a, %b + %conv = zext i1 %cmp to i32 + ret i32 %conv +} + +; CHECK-ALL-LABEL: fcmpgt: +; CHECK-SOFT: bl __aeabi_fcmpgt + +; CHECK-SOFTFP: vmov s2, r0 +; CHECK-SOFTFP-NEXT: mov r0, #0 +; CHECK-SOFTFP-NEXT: vmov s0, r1 +; CHECK-SOFTFP-NEXT: vcmpe.f32 s2, s0 +; CHECK-SOFTFP-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-SOFTFP-NEXT: movwgt r0, #1 + +; CHECK-HARDFP-SP: vcmpe.f32 s0, s1 +; CHECK-HARDFP-SP-NEXT: mov r0, #0 +; CHECK-HARDFP-SP-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-HARDFP-SP-NEXT: movwgt r0, #1 +define i32 @fcmpgt(float %a, float %b) #0 { +entry: + %cmp = fcmp ogt float %a, %b + %conv = zext i1 %cmp to i32 + ret i32 %conv +} + +; CHECK-ALL-LABEL: fcmpun: +; CHECK-SOFT: bl __aeabi_fcmpun + +; CHECK-SOFTFP: vmov s2, r0 +; CHECK-SOFTFP-NEXT: mov r0, #0 +; CHECK-SOFTFP-NEXT: vmov s0, r1 +; CHECK-SOFTFP-NEXT: vcmpe.f32 s2, s0 +; CHECK-SOFTFP-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-SOFTFP-NEXT: movwvs r0, #1 + +; CHECK-HARDFP-SP: vcmpe.f32 s0, s1 +; CHECK-HARDFP-SP-NEXT: mov r0, #0 +; CHECK-HARDFP-SP-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-HARDFP-SP-NEXT: movwvs r0, #1 +define i32 @fcmpun(float %a, float %b) #0 { +entry: + %cmp = fcmp uno float %a, %b + %0 = zext i1 %cmp to i32 + ret i32 %0 +} + +; CHECK-ALL-LABEL: dadd: +; CHECK-SOFT: bl __aeabi_dadd + +; CHECK-SOFTFP: vmov d16, r2, r3 +; CHECK-SOFTFP-SP-NEXT: vmov d17, r0, r1 +; CHECK-SOFTFP-SP-NEXT: vadd.f64 d16, d17, d16 +; CHECK-SOFTFP-SP-NEXT: vmov r0, r1, d16 +; CHECK-SOFTFP-SP-NEXT: bx lr + +; CHECK-HARDFP-DP: vadd.f64 d0, d0, d1 + +; CHECK-HARDFP-SPONLY: vmov r0, r1, d0 +; CHECK-HARDFP-SPONLY-NEXT: vmov r2, r3, d1 +; CHECK-HARDFP-SPONLY-NEXT: bl __aeabi_dadd +; CHECK-HARDFP-SPONLY-NEXT: vmov d0, r0, r1 +define double @dadd(double %a, double %b) #0 { +entry: + %add = fadd double %a, %b + ret double %add +} + +; CHECK-ALL-LABEL: ddiv: +; CHECK-SOFT: bl __aeabi_ddiv + +; CHECK-SOFTFP: vmov d16, r2, r3 +; CHECK-SOFTFP-NEXT: vmov d17, r0, r1 +; CHECK-SOFTFP-NEXT: vdiv.f64 d16, d17, d16 +; CHECK-SOFTFP-NEXT: vmov r0, r1, d16 + +; CHECK-HARDFP-DP: vdiv.f64 d0, d0, d1 + +; CHECK-HARDFP-SPONLY: vmov r0, r1, d0 +; CHECK-HARDFP-SPONLY-NEXT: vmov r2, r3, d1 +; CHECK-HARDFP-SPONLY-NEXT: bl __aeabi_ddiv +; CHECK-HARDFP-SPONLY-NEXT: vmov d0, r0, r1 +define double @ddiv(double %a, double %b) #0 { +entry: + %div = fdiv double %a, %b + ret double %div +} + +; CHECK-ALL-LABEL: dmul: +; CHECK-SOFT: bl __aeabi_dmul + +; CHECK-SOFTFP: vmov d16, r2, r3 +; CHECK-SOFTFP-NEXT: vmov d17, r0, r1 +; CHECK-SOFTFP-NEXT: vmul.f64 d16, d17, d16 +; CHECK-SOFTFP-NEXT: vmov r0, r1, d16 + +; CHECK-HARDFP-DP: vmul.f64 d0, d0, d1 + +; CHECK-HARDFP-SPONLY: vmov r0, r1, d0 +; CHECK-HARDFP-SPONLY-NEXT: vmov r2, r3, d1 +; CHECK-HARDFP-SPONLY-NEXT: bl __aeabi_dmul +; CHECK-HARDFP-SPONLY-NEXT: vmov d0, r0, r1 +define double @dmul(double %a, double %b) #0 { +entry: + %mul = fmul double %a, %b + ret double %mul +} + +; CHECK-ALL-LABEL: dsub: +; CHECK-SOFT: bl __aeabi_dsub + +; CHECK-SOFTFP: vmov d16, r2, r3 +; CHECK-SOFTFP-NEXT: vmov d17, r0, r1 +; CHECK-SOFTFP-NEXT: vsub.f64 d16, d17, d16 +; CHECK-SOFTFP-NEXT: vmov r0, r1, d16 + +; CHECK-HARDFP-DP: vsub.f64 d0, d0, d1 + +; CHECK-HARDFP-SPONLY: vmov r0, r1, d0 +; CHECK-HARDFP-SPONLY-NEXT: vmov r2, r3, d1 +; CHECK-HARDFP-SPONLY-NEXT: bl __aeabi_dsub +; CHECK-HARDFP-SPONLY-NEXT: vmov d0, r0, r1 +define double @dsub(double %a, double %b) #0 { +entry: + %sub = fsub double %a, %b + ret double %sub +} + +; CHECK-ALL-LABEL: dcmpeq: +; CHECK-SOFT: bl __aeabi_dcmpeq + +; CHECK-SOFTFP: vmov d16, r2, r3 +; CHECK-SOFTFP-NEXT: vmov d17, r0, r1 +; CHECK-SOFTFP-NEXT: mov r0, #0 +; CHECK-SOFTFP-NEXT: vcmp.f64 d17, d16 +; CHECK-SOFTFP-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-SOFTFP-NEXT: movweq r0, #1 + +; CHECK-HARDFP-DP: vcmp.f64 d0, d1 +; CHECK-HARDFP-DP-NEXT: mov r0, #0 +; CHECK-HARDFP-DP-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-HARDFP-DP-NEXT: movweq r0, #1 + +; CHECK-HARDFP-SPONLY: vmov r0, r1, d0 +; CHECK-HARDFP-SPONLY-NEXT: vmov r2, r3, d1 +; CHECK-HARDFP-SPONLY-NEXT: bl __aeabi_dcmpeq +; CHECK-HARDFP-SPONLY-NEXT: cmp r0, #0 +; CHECK-HARDFP-SPONLY-NEXT: movwne r0, #1 +define i32 @dcmpeq(double %a, double %b) #0 { +entry: + %cmp = fcmp oeq double %a, %b + %conv = zext i1 %cmp to i32 + ret i32 %conv +} + +; CHECK-ALL-LABEL: dcmplt: +; CHECK-SOFT: bl __aeabi_dcmplt + +; CHECK-SOFTFP: vmov d16, r2, r3 +; CHECK-SOFTFP-NEXT: vmov d17, r0, r1 +; CHECK-SOFTFP-NEXT: mov r0, #0 +; CHECK-SOFTFP-NEXT: vcmpe.f64 d17, d16 +; CHECK-SOFTFP-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-SOFTFP-NEXT: movwmi r0, #1 + +; CHECK-HARDFP-DP: vcmpe.f64 d0, d1 +; CHECK-HARDFP-DP-NEXT: mov r0, #0 +; CHECK-HARDFP-DP-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-HARDFP-DP-NEXT: movwmi r0, #1 + +; CHECK-HARDFP-SPONLY: vmov r0, r1, d0 +; CHECK-HARDFP-SPONLY-NEXT: vmov r2, r3, d1 +; CHECK-HARDFP-SPONLY-NEXT: bl __aeabi_dcmplt +; CHECK-HARDFP-SPONLY-NEXT: cmp r0, #0 +; CHECK-HARDFP-SPONLY-NEXT: movwne r0, #1 +define i32 @dcmplt(double %a, double %b) #0 { +entry: + %cmp = fcmp olt double %a, %b + %conv = zext i1 %cmp to i32 + ret i32 %conv +} + +; CHECK-ALL-LABEL: dcmple: +; CHECK-SOFT: bl __aeabi_dcmple + +; CHECK-SOFTFP: vmov d16, r2, r3 +; CHECK-SOFTFP-NEXT: vmov d17, r0, r1 +; CHECK-SOFTFP-NEXT: mov r0, #0 +; CHECK-SOFTFP-NEXT: vcmpe.f64 d17, d16 +; CHECK-SOFTFP-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-SOFTFP-NEXT: movwls r0, #1 + +; CHECK-HARDFP-DP: vcmpe.f64 d0, d1 +; CHECK-HARDFP-DP-NEXT: mov r0, #0 +; CHECK-HARDFP-DP-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-HARDFP-DP-NEXT: movwls r0, #1 + +; CHECK-HARDFP-SPONLY: vmov r0, r1, d0 +; CHECK-HARDFP-SPONLY-NEXT: vmov r2, r3, d1 +; CHECK-HARDFP-SPONLY-NEXT: bl __aeabi_dcmple +; CHECK-HARDFP-SPONLY-NEXT: cmp r0, #0 +; CHECK-HARDFP-SPONLY-NEXT: movwne r0, #1 +define i32 @dcmple(double %a, double %b) #0 { +entry: + %cmp = fcmp ole double %a, %b + %conv = zext i1 %cmp to i32 + ret i32 %conv +} + +; CHECK-ALL-LABEL: dcmpge: +; CHECK-SOFT: bl __aeabi_dcmpge + +; CHECK-SOFTFP: vmov d16, r2, r3 +; CHECK-SOFTFP-NEXT: vmov d17, r0, r1 +; CHECK-SOFTFP-NEXT: mov r0, #0 +; CHECK-SOFTFP-NEXT: vcmpe.f64 d17, d16 +; CHECK-SOFTFP-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-SOFTFP-NEXT: movwge r0, #1 + +; CHECK-HARDFP-DP: vcmpe.f64 d0, d1 +; CHECK-HARDFP-DP-NEXT: mov r0, #0 +; CHECK-HARDFP-DP-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-HARDFP-DP-NEXT: movwge r0, #1 + +; CHECK-HARDFP-SPONLY: vmov r0, r1, d0 +; CHECK-HARDFP-SPONLY-NEXT: vmov r2, r3, d1 +; CHECK-HARDFP-SPONLY-NEXT: bl __aeabi_dcmpge +; CHECK-HARDFP-SPONLY-NEXT: cmp r0, #0 +; CHECK-HARDFP-SPONLY-NEXT: movwne r0, #1 +define i32 @dcmpge(double %a, double %b) #0 { +entry: + %cmp = fcmp oge double %a, %b + %conv = zext i1 %cmp to i32 + ret i32 %conv +} + +; CHECK-ALL-LABEL: dcmpgt: +; CHECK-SOFT: bl __aeabi_dcmpgt + +; CHECK-SOFTFP: vmov d16, r2, r3 +; CHECK-SOFTFP-NEXT: vmov d17, r0, r1 +; CHECK-SOFTFP-NEXT: mov r0, #0 +; CHECK-SOFTFP-NEXT: vcmpe.f64 d17, d16 +; CHECK-SOFTFP-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-SOFTFP-NEXT: movwgt r0, #1 + +; CHECK-HARDFP-DP: vcmpe.f64 d0, d1 +; CHECK-HARDFP-DP-NEXT: mov r0, #0 +; CHECK-HARDFP-DP-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-HARDFP-DP-NEXT: movwgt r0, #1 + +; CHECK-HARDFP-SPONLY: vmov r0, r1, d0 +; CHECK-HARDFP-SPONLY-NEXT: vmov r2, r3, d1 +; CHECK-HARDFP-SPONLY-NEXT: bl __aeabi_dcmpgt +; CHECK-HARDFP-SPONLY-NEXT: cmp r0, #0 +; CHECK-HARDFP-SPONLY-NEXT: movwne r0, #1 +define i32 @dcmpgt(double %a, double %b) #0 { +entry: + %cmp = fcmp ogt double %a, %b + %conv = zext i1 %cmp to i32 + ret i32 %conv +} + +; CHECK-ALL-LABEL: dcmpun: +; CHECK-SOFT: bl __aeabi_dcmpun + +; CHECK-SOFTFP: vmov d16, r2, r3 +; CHECK-SOFTFP-NEXT: vmov d17, r0, r1 +; CHECK-SOFTFP-NEXT: mov r0, #0 +; CHECK-SOFTFP-NEXT: vcmpe.f64 d17, d16 +; CHECK-SOFTFP-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-SOFTFP-NEXT: movwvs r0, #1 + +; CHECK-HARDFP-DP: vcmpe.f64 d0, d1 +; CHECK-HARDFP-DP-NEXT: mov r0, #0 +; CHECK-HARDFP-DP-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-HARDFP-DP-NEXT: movwvs r0, #1 + +; CHECK-HARDFP-SPONLY: vmov r0, r1, d0 +; CHECK-HARDFP-SPONLY-NEXT: vmov r2, r3, d1 +; CHECK-HARDFP-SPONLY-NEXT: bl __aeabi_dcmpun +; CHECK-HARDFP-SPONLY-NEXT: cmp r0, #0 +; CHECK-HARDFP-SPONLY-NEXT: movwne r0, #1 +define i32 @dcmpun(double %a, double %b) #0 { +entry: + %cmp = fcmp uno double %a, %b + %0 = zext i1 %cmp to i32 + ret i32 %0 +} + +; CHECK-ALL-LABEL: d2iz: +; CHECK-SOFT: bl __aeabi_d2iz + +; CHECK-SOFTFP: vmov d16, r0, r1 +; CHECK-SOFTFP-NEXT: vcvt.s32.f64 s0, d16 +; CHECK-SOFTFP-NEXT: vmov r0, s0 + +; CHECK-HARDFP-DP: vcvt.s32.f64 s0, d0 +; CHECK-HARDFP-DP-NEXT: vmov r0, s0 + +; CHECK-HARDFP-SPONLY: vmov r0, r1, d0 +; CHECK-HARDFP-SPONLY-NEXT: bl __aeabi_d2iz +define i32 @d2iz(double %a) #0 { +entry: + %conv = fptosi double %a to i32 + ret i32 %conv +} + +; CHECK-ALL-LABEL: d2uiz: +; CHECK-SOFT: bl __aeabi_d2uiz +; CHECK-SOFTFP: vmov d16, r0, r1 +; CHECK-SOFTFP-NEXT: vcvt.u32.f64 s0, d16 +; CHECK-SOFTFP-NEXT: vmov r0, s0 + +; CHECK-HARDFP-DP: vcvt.u32.f64 s0, d0 +; CHECK-HARDFP-DP-NEXT: vmov r0, s0 +; CHECK-HARDFP-SPONLY: vmov r0, r1, d0 +; CHECK-HARDFP-SPONLY-NEXT: bl __aeabi_d2uiz +define i32 @d2uiz(double %a) #0 { +entry: + %conv = fptoui double %a to i32 + ret i32 %conv +} + +; CHECK-ALL-LABEL: d2lz: +; CHECK-SOFT: bl __aeabi_d2lz + +; CHECK-SOFTFP: bl __aeabi_d2lz + +; CHECK-HARDFP-DP: vmov r0, r1, d0 +; CHECK-HARDFP-DP-NEXT: bl __aeabi_d2lz + +; CHECK-HARDFP-SPONLY: vmov r0, r1, d0 +; CHECK-HARDFP-SPONLY-NEXT: bl __aeabi_d2lz +define i64 @d2lz(double %a) #0 { +entry: + %conv = fptosi double %a to i64 + ret i64 %conv +} + +; CHECK-ALL-LABEL: d2ulz: +; CHECK-SOFT: bl __aeabi_d2ulz + +; CHECK-SOFTFP: bl __aeabi_d2ulz + +; CHECK-HARDFP-DP: vmov r0, r1, d0 +; CHECK-HARDFP-DP-NEXT: bl __aeabi_d2ulz + +; CHECK-HARDFP-SPONLY: vmov r0, r1, d0 +; CHECK-HARDFP-SPONLY-NEXT: bl __aeabi_d2ulz +define i64 @d2ulz(double %a) #0 { +entry: + %conv = fptoui double %a to i64 + ret i64 %conv +} + +; CHECK-ALL-LABEL: f2iz: +; CHECK-SOFT: bl __aeabi_f2iz + +; CHECK-SOFTFP: vmov s0, r0 +; CHECK-SOFTFP-NEXT: vcvt.s32.f32 s0, s0 +; CHECK-SOFTFP-NEXT: vmov r0, s0 + +; CHECK-HARDFP-SP: vcvt.s32.f32 s0, s0 +; CHECK-HARDFP-SP-NEXT: vmov r0, s0 +define i32 @f2iz(float %a) #0 { +entry: + %conv = fptosi float %a to i32 + ret i32 %conv +} + +; CHECK-ALL-LABEL: f2uiz: +; CHECK-SOFT: bl __aeabi_f2uiz +; CHECK-SOFTFP: vmov s0, r0 +; CHECK-SOFTFP-NEXT: vcvt.u32.f32 s0, s0 +; CHECK-SOFTFP-NEXT: vmov r0, s0 +; CHECK-HARDFP-SP: vcvt.u32.f32 s0, s0 +; CHECK-HARDFP-SP-NEXT: vmov r0, s0 +define i32 @f2uiz(float %a) #0 { +entry: + %conv = fptoui float %a to i32 + ret i32 %conv +} + +; CHECK-ALL-LABEL: f2lz: +; CHECK-SOFT: bl __aeabi_f2lz + +; CHECK-SOFTFP: bl __aeabi_f2lz + +; CHECK-HARDFP-SP: vmov r0, s0 +; CHECK-HARDFP-SP-NEXT: bl __aeabi_f2lz +define i64 @f2lz(float %a) #0 { +entry: + %conv = fptosi float %a to i64 + ret i64 %conv +} + +; CHECK-ALL-LABEL: f2ulz: +; CHECK-SOFT: bl __aeabi_f2ulz + +; CHECK-SOFTFP: bl __aeabi_f2ulz + +; CHECK-HARDFP-SP: vmov r0, s0 +; CHECK-HARDFP-SP-NEXT: bl __aeabi_f2ulz +define i64 @f2ulz(float %a) #0 { +entry: + %conv = fptoui float %a to i64 + ret i64 %conv +} + +; CHECK-ALL-LABEL: d2f: +; CHECK-SOFT: bl __aeabi_d2f + +; CHECK-SOFTFP: vmov d16, r0, r1 +; CHECK-SOFTFP-NEXT: vcvt.f32.f64 s0, d16 +; CHECK-SOFTFP-NEXT: vmov r0, s0 + +; CHECK-HARDFP-DP: vcvt.f32.f64 s0, d0 +; CHECK-HARDFP-SPONLY: vmov r0, r1, d0 +; CHECK-HARDFP-SPONLY-NEXT: bl __aeabi_d2f +define float @d2f(double %a) #0 { +entry: + %conv = fptrunc double %a to float + ret float %conv +} + +; CHECK-ALL-LABEL: f2d: +; CHECK-SOFT: bl __aeabi_f2d + +; CHECK-SOFTFP: vmov s0, r0 +; CHECK-SOFTFP-NEXT: vcvt.f64.f32 d16, s0 +; CHECK-SOFTFP-NEXT: vmov r0, r1, d16 + +; CHECK-HARDFP-DP: vcvt.f64.f32 d0, s0 + +; CHECK-HARDFP-SPONLY: vmov r0, s0 +; CHECK-HARDFP-SPONLY-NEXT: bl __aeabi_f2d +; CHECK-HARDFP-SPONLY-NEXT: vmov d0, r0, r1 +define double @f2d(float %a) #0 { +entry: + %conv = fpext float %a to double + ret double %conv +} + +; CHECK-ALL-LABEL: i2d: +; CHECK-SOFT: bl __aeabi_i2d + +; CHECK-SOFTFP: vmov s0, r0 +; CHECK-SOFTFP-NEXT: vcvt.f64.s32 d16, s0 +; CHECK-SOFTFP-NEXT: vmov r0, r1, d16 + +; CHECK-HARDFP-DP: vmov s0, r0 +; CHECK-HARDFP-DP-NEXT: vcvt.f64.s32 d0, s0 + +; CHECK-HARDFP-SPONLY: bl __aeabi_i2d +; CHECK-HARDFP-SPONLY-NEXT: vmov d0, r0, r1 +define double @i2d(i32 %a) #0 { +entry: + %conv = sitofp i32 %a to double + ret double %conv +} + +; CHECK-ALL-LABEL: ui2d: +; CHECK-SOFT: bl __aeabi_ui2d + +; CHECK-SOFTFP: vcvt.f64.u32 d16, s0 +; CHECK-SOFTFP-NEXT: vmov r0, r1, d16 +; CHECK-SOFTFP-NEXT: bx lr + +; CHECK-HARDFP-DP: vmov s0, r0 +; CHECK-HARDFP-DP-NEXT: vcvt.f64.u32 d0, s0 +; CHECK-HARDFP-SPONLY: bl __aeabi_ui2d +; CHECK-HARDFP-SPONLY-NEXT: vmov d0, r0, r1 +define double @ui2d(i32 %a) #0 { +entry: + %conv = uitofp i32 %a to double + ret double %conv +} + +; CHECK-ALL-LABEL: l2d: +; CHECK-SOFT: bl __aeabi_l2d + +; CHECK-SOFTFP: bl __aeabi_l2d + +; CHECK-HARDFP-SP: bl __aeabi_l2d +; CHECK-HARDFP-SP-NEXT: vmov d0, r0, r1 +define double @l2d(i64 %a) #0 { +entry: + %conv = sitofp i64 %a to double + ret double %conv +} + +; CHECK-ALL-LABEL: ul2d: +; CHECK-SOFT: bl __aeabi_ul2d + +; CHECK-SOFTFP: bl __aeabi_ul2d + +; CHECK-HARDFP-SP: bl __aeabi_ul2d +; CHECK-HARDFP-SP-NEXT: vmov d0, r0, r1 +define double @ul2d(i64 %a) #0 { +entry: + %conv = uitofp i64 %a to double + ret double %conv +} + +; CHECK-ALL-LABEL: i2f: +; CHECK-SOFT: bl __aeabi_i2f + +; CHECK-SOFT-FP: vmov s0, r0 +; CHECK-SOFT-FP-NEXT: vcvt.f32.s32 s0, s0 +; CHECK-SOFT-FP-NEXT: vmov r0, s0 + +; CHECK-HARDFP-SP: vmov s0, r0 +; CHECK-HARDFP-SP-NEXT: vcvt.f32.s32 s0, s0 +define float @i2f(i32 %a) #0 { +entry: + %conv = sitofp i32 %a to float + ret float %conv +} + +; CHECK-ALL-LABEL: ui2f: +; CHECK-SOFT: bl __aeabi_ui2f + +; CHECK-SOFTFP: vmov s0, r0 +; CHECK-SOFTFP-NEXT: vcvt.f32.u32 s0, s0 +; CHECK-SOFTFP-NEXT: vmov r0, s0 + +; CHECK-HARDFP-SP: vmov s0, r0 +; CHECK-HARDFP-SP-NEXT: vcvt.f32.u32 s0, s0 +define float @ui2f(i32 %a) #0 { +entry: + %conv = uitofp i32 %a to float + ret float %conv +} + +; CHECK-ALL-LABEL: l2f: +; CHECK-SOFT: bl __aeabi_l2f + +; CHECK-SOFTFP: bl __aeabi_l2f + +; CHECK-HARDFP-SP: bl __aeabi_l2f +; CHECK-HARDFP-SP-NEXT: vmov s0, r0 +define float @l2f(i64 %a) #0 { +entry: + %conv = sitofp i64 %a to float + ret float %conv +} + +; CHECK-ALL-LABEL: ul2f: +; CHECK-SOFT: bl __aeabi_ul2f + +; CHECK-SOFTFP: bl __aeabi_ul2f + +; CHECK-HARDFP-SP: bl __aeabi_ul2f +; CHECK-HARDFP-SP-NEXT: vmov s0, r0 +define float @ul2f(i64 %a) #0 { +entry: + %conv = uitofp i64 %a to float + ret float %conv +} +attributes #0 = { nounwind }