ARM: match GCC's behaviour for builtins

GCC changes the CC between the user-code and the builtins based on the
value of `-target` rather than `-mfloat-abi`.  When a HF target is used,
the VFP variant of the AAPCS CC is used.  Otherwise, the AAPCS variant
is used.  In all cases, the AEABI functions use the AAPCS CC.  Adjust
the calling convention based on the target.

Resolves PR30543!

llvm-svn: 291909
This commit is contained in:
Saleem Abdulrasool 2017-01-13 16:25:33 +00:00
parent 1e799942b3
commit 6ef45916c6
5 changed files with 59 additions and 170 deletions

View File

@ -97,171 +97,6 @@ namespace {
};
}
void ARMTargetLowering::InitLibcallCallingConvs() {
// The builtins on ARM always use AAPCS, irrespective of wheter C is AAPCS or
// AAPCS_VFP.
for (const auto LC : {
RTLIB::SHL_I16,
RTLIB::SHL_I32,
RTLIB::SHL_I64,
RTLIB::SHL_I128,
RTLIB::SRL_I16,
RTLIB::SRL_I32,
RTLIB::SRL_I64,
RTLIB::SRL_I128,
RTLIB::SRA_I16,
RTLIB::SRA_I32,
RTLIB::SRA_I64,
RTLIB::SRA_I128,
RTLIB::MUL_I8,
RTLIB::MUL_I16,
RTLIB::MUL_I32,
RTLIB::MUL_I64,
RTLIB::MUL_I128,
RTLIB::MULO_I32,
RTLIB::MULO_I64,
RTLIB::MULO_I128,
RTLIB::SDIV_I8,
RTLIB::SDIV_I16,
RTLIB::SDIV_I32,
RTLIB::SDIV_I64,
RTLIB::SDIV_I128,
RTLIB::UDIV_I8,
RTLIB::UDIV_I16,
RTLIB::UDIV_I32,
RTLIB::UDIV_I64,
RTLIB::UDIV_I128,
RTLIB::SREM_I8,
RTLIB::SREM_I16,
RTLIB::SREM_I32,
RTLIB::SREM_I64,
RTLIB::SREM_I128,
RTLIB::UREM_I8,
RTLIB::UREM_I16,
RTLIB::UREM_I32,
RTLIB::UREM_I64,
RTLIB::UREM_I128,
RTLIB::SDIVREM_I8,
RTLIB::SDIVREM_I16,
RTLIB::SDIVREM_I32,
RTLIB::SDIVREM_I64,
RTLIB::SDIVREM_I128,
RTLIB::UDIVREM_I8,
RTLIB::UDIVREM_I16,
RTLIB::UDIVREM_I32,
RTLIB::UDIVREM_I64,
RTLIB::UDIVREM_I128,
RTLIB::NEG_I32,
RTLIB::NEG_I64,
RTLIB::ADD_F32,
RTLIB::ADD_F64,
RTLIB::ADD_F80,
RTLIB::ADD_F128,
RTLIB::SUB_F32,
RTLIB::SUB_F64,
RTLIB::SUB_F80,
RTLIB::SUB_F128,
RTLIB::MUL_F32,
RTLIB::MUL_F64,
RTLIB::MUL_F80,
RTLIB::MUL_F128,
RTLIB::DIV_F32,
RTLIB::DIV_F64,
RTLIB::DIV_F80,
RTLIB::DIV_F128,
RTLIB::POWI_F32,
RTLIB::POWI_F64,
RTLIB::POWI_F80,
RTLIB::POWI_F128,
RTLIB::FPEXT_F64_F128,
RTLIB::FPEXT_F32_F128,
RTLIB::FPEXT_F32_F64,
RTLIB::FPEXT_F16_F32,
RTLIB::FPROUND_F32_F16,
RTLIB::FPROUND_F64_F16,
RTLIB::FPROUND_F80_F16,
RTLIB::FPROUND_F128_F16,
RTLIB::FPROUND_F64_F32,
RTLIB::FPROUND_F80_F32,
RTLIB::FPROUND_F128_F32,
RTLIB::FPROUND_F80_F64,
RTLIB::FPROUND_F128_F64,
RTLIB::FPTOSINT_F32_I32,
RTLIB::FPTOSINT_F32_I64,
RTLIB::FPTOSINT_F32_I128,
RTLIB::FPTOSINT_F64_I32,
RTLIB::FPTOSINT_F64_I64,
RTLIB::FPTOSINT_F64_I128,
RTLIB::FPTOSINT_F80_I32,
RTLIB::FPTOSINT_F80_I64,
RTLIB::FPTOSINT_F80_I128,
RTLIB::FPTOSINT_F128_I32,
RTLIB::FPTOSINT_F128_I64,
RTLIB::FPTOSINT_F128_I128,
RTLIB::FPTOUINT_F32_I32,
RTLIB::FPTOUINT_F32_I64,
RTLIB::FPTOUINT_F32_I128,
RTLIB::FPTOUINT_F64_I32,
RTLIB::FPTOUINT_F64_I64,
RTLIB::FPTOUINT_F64_I128,
RTLIB::FPTOUINT_F80_I32,
RTLIB::FPTOUINT_F80_I64,
RTLIB::FPTOUINT_F80_I128,
RTLIB::FPTOUINT_F128_I32,
RTLIB::FPTOUINT_F128_I64,
RTLIB::FPTOUINT_F128_I128,
RTLIB::SINTTOFP_I32_F32,
RTLIB::SINTTOFP_I32_F64,
RTLIB::SINTTOFP_I32_F80,
RTLIB::SINTTOFP_I32_F128,
RTLIB::SINTTOFP_I64_F32,
RTLIB::SINTTOFP_I64_F64,
RTLIB::SINTTOFP_I64_F80,
RTLIB::SINTTOFP_I64_F128,
RTLIB::SINTTOFP_I128_F32,
RTLIB::SINTTOFP_I128_F64,
RTLIB::SINTTOFP_I128_F80,
RTLIB::SINTTOFP_I128_F128,
RTLIB::UINTTOFP_I32_F32,
RTLIB::UINTTOFP_I32_F64,
RTLIB::UINTTOFP_I32_F80,
RTLIB::UINTTOFP_I32_F128,
RTLIB::UINTTOFP_I64_F32,
RTLIB::UINTTOFP_I64_F64,
RTLIB::UINTTOFP_I64_F80,
RTLIB::UINTTOFP_I64_F128,
RTLIB::UINTTOFP_I128_F32,
RTLIB::UINTTOFP_I128_F64,
RTLIB::UINTTOFP_I128_F80,
RTLIB::UINTTOFP_I128_F128,
RTLIB::OEQ_F32,
RTLIB::OEQ_F64,
RTLIB::OEQ_F128,
RTLIB::UNE_F32,
RTLIB::UNE_F64,
RTLIB::UNE_F128,
RTLIB::OGE_F32,
RTLIB::OGE_F64,
RTLIB::OGE_F128,
RTLIB::OLT_F32,
RTLIB::OLT_F64,
RTLIB::OLT_F128,
RTLIB::OLE_F32,
RTLIB::OLE_F64,
RTLIB::OLE_F128,
RTLIB::OGT_F32,
RTLIB::OGT_F64,
RTLIB::OGT_F128,
RTLIB::UO_F32,
RTLIB::UO_F64,
RTLIB::UO_F128,
RTLIB::O_F32,
RTLIB::O_F64,
RTLIB::O_F128,
})
setLibcallCallingConv(LC, CallingConv::ARM_AAPCS);
}
// The APCS parameter registers.
static const MCPhysReg GPRArgRegs[] = {
ARM::R0, ARM::R1, ARM::R2, ARM::R3
@ -349,7 +184,22 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM,
setBooleanVectorContents(ZeroOrNegativeOneBooleanContent);
InitLibcallCallingConvs();
if (!Subtarget->isTargetDarwin() && !Subtarget->isTargetIOS() &&
!Subtarget->isTargetWatchOS()) {
const auto &E = Subtarget->getTargetTriple().getEnvironment();
bool IsHFTarget = E == Triple::EABIHF || E == Triple::GNUEABIHF ||
E == Triple::MuslEABIHF;
// Windows is a special case. Technically, we will replace all of the "GNU"
// calls with calls to MSVCRT if appropriate and adjust the calling
// convention then.
IsHFTarget = IsHFTarget || Subtarget->isTargetWindows();
for (int LCID = 0; LCID < RTLIB::UNKNOWN_LIBCALL; ++LCID)
setLibcallCallingConv(static_cast<RTLIB::Libcall>(LCID),
IsHFTarget ? CallingConv::ARM_AAPCS_VFP
: CallingConv::ARM_AAPCS);
}
if (Subtarget->isTargetMachO()) {
// Uses VFP for Thumb libfuncs if available.

View File

@ -538,8 +538,6 @@ class InstrItineraryData;
bool HasStandaloneRem = true;
void InitLibcallCallingConvs();
void addTypeForNEON(MVT VT, MVT PromotedLdStVT, MVT PromotedBitwiseVT);
void addDRTypeForNEON(MVT VT);
void addQRTypeForNEON(MVT VT);

View File

@ -18,7 +18,7 @@ declare double @llvm.powi.f64(double %Val, i32 %power)
define double @powi_d(double %a, i32 %b) {
; CHECK-LABEL: powi_d:
; SOFT: {{(bl|b)}} __powidf2
; HARD: bl __powidf2
; HARD: b __powidf2
%1 = call double @llvm.powi.f64(double %a, i32 %b)
ret double %1
}

View File

@ -18,7 +18,7 @@ declare float @llvm.powi.f32(float %Val, i32 %power)
define float @powi_f(float %a, i32 %b) {
; CHECK-LABEL: powi_f:
; SOFT: bl __powisf2
; HARD: bl __powisf2
; HARD: b __powisf2
%1 = call float @llvm.powi.f32(float %a, i32 %b)
ret float %1
}

View File

@ -0,0 +1,41 @@
; RUN: llc -mtriple thumbv7-unknown-none-eabi -float-abi soft -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-MATCH
; RUN: llc -mtriple thumbv7-unknown-none-eabi -float-abi hard -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-MISMATCH -check-prefix CHECK-TO-SOFT
; RUN: llc -mtriple thumbv7-unknown-none-eabihf -float-abi soft -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-MISMATCH -check-prefix CHECK-TO-HARD
; RUN: llc -mtriple thumbv7-unknown-none-eabihf -float-abi hard -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-MATCH
; RUN: llc -mtriple thumbv7-unknown-none-gnueabi -float-abi soft -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-MATCH
; RUN: llc -mtriple thumbv7-unknown-none-gnueabi -float-abi hard -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-MISMATCH -check-prefix CHECK-TO-SOFT
; RUN: llc -mtriple thumbv7-unknown-none-gnueabihf -float-abi soft -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-MISMATCH -check-prefix CHECK-TO-HARD
; RUN: llc -mtriple thumbv7-unknown-none-gnueabihf -float-abi hard -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-MATCH
; RUN: llc -mtriple thumbv7-unknown-none-musleabi -float-abi soft -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-MATCH
; RUN: llc -mtriple thumbv7-unknown-none-musleabi -float-abi hard -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-MISMATCH -check-prefix CHECK-TO-SOFT
; RUN: llc -mtriple thumbv7-unknown-none-musleabihf -float-abi soft -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-MISMATCH -check-prefix CHECK-TO-HARD
; RUN: llc -mtriple thumbv7-unknown-none-musleabihf -float-abi hard -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-MATCH
declare float @llvm.powi.f32(float, i32)
define float @f(float %f, i32 %i) {
entry:
%0 = call float @llvm.powi.f32(float %f, i32 %i)
ret float %0
}
; CHECK-MATCH: b __powisf2
; CHECK-MISMATCH: bl __powisf2
; CHECK-TO-SOFT: vmov s0, r0
; CHECK-TO-HARD: vmov r0, s0
declare double @llvm.powi.f64(double, i32)
define double @g(double %d, i32 %i) {
entry:
%0 = call double @llvm.powi.f64(double %d, i32 %i)
ret double %0
}
; CHECK-MATCH: b __powidf2
; CHECK-MISMATCH: bl __powidf2
; CHECK-TO-SOFT: vmov d0, r0, r1
; CHECK-TO-HARD: vmov r0, r1, d0