forked from OSchip/llvm-project
[AArch64][X86] Don't assume __powidf2 is available on Windows.
We had some code for this for 32-bit ARM, but this doesn't really need to be in target-specific code; generalize it. (I think this started showing up recently because we added an optimization that converts pow to powi.) Differential Revision: https://reviews.llvm.org/D69013
This commit is contained in:
parent
9f08ce0d21
commit
5df3a87224
|
@ -3961,11 +3961,31 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
|
|||
RTLIB::ROUND_PPCF128));
|
||||
break;
|
||||
case ISD::FPOWI:
|
||||
case ISD::STRICT_FPOWI:
|
||||
case ISD::STRICT_FPOWI: {
|
||||
RTLIB::Libcall LC;
|
||||
switch (Node->getSimpleValueType(0).SimpleTy) {
|
||||
default: llvm_unreachable("Unexpected request for libcall!");
|
||||
case MVT::f32: LC = RTLIB::POWI_F32; break;
|
||||
case MVT::f64: LC = RTLIB::POWI_F64; break;
|
||||
case MVT::f80: LC = RTLIB::POWI_F80; break;
|
||||
case MVT::f128: LC = RTLIB::POWI_F128; break;
|
||||
case MVT::ppcf128: LC = RTLIB::POWI_PPCF128; break;
|
||||
}
|
||||
if (!TLI.getLibcallName(LC)) {
|
||||
// Some targets don't have a powi libcall; use pow instead.
|
||||
SDValue Exponent = DAG.getNode(ISD::SINT_TO_FP, SDLoc(Node),
|
||||
Node->getValueType(0),
|
||||
Node->getOperand(1));
|
||||
Results.push_back(DAG.getNode(ISD::FPOW, SDLoc(Node),
|
||||
Node->getValueType(0), Node->getOperand(0),
|
||||
Exponent));
|
||||
break;
|
||||
}
|
||||
Results.push_back(ExpandFPLibCall(Node, RTLIB::POWI_F32, RTLIB::POWI_F64,
|
||||
RTLIB::POWI_F80, RTLIB::POWI_F128,
|
||||
RTLIB::POWI_PPCF128));
|
||||
break;
|
||||
}
|
||||
case ISD::FPOW:
|
||||
case ISD::STRICT_FPOW:
|
||||
if (CanUseFiniteLibCall && DAG.getLibInfo().has(LibFunc_pow_finite))
|
||||
|
|
|
@ -587,19 +587,26 @@ SDValue DAGTypeLegalizer::SoftenFloatRes_FPOW(SDNode *N) {
|
|||
SDValue DAGTypeLegalizer::SoftenFloatRes_FPOWI(SDNode *N) {
|
||||
assert(N->getOperand(1).getValueType() == MVT::i32 &&
|
||||
"Unsupported power type!");
|
||||
RTLIB::Libcall LC = GetFPLibCall(N->getValueType(0),
|
||||
RTLIB::POWI_F32,
|
||||
RTLIB::POWI_F64,
|
||||
RTLIB::POWI_F80,
|
||||
RTLIB::POWI_F128,
|
||||
RTLIB::POWI_PPCF128);
|
||||
if (!TLI.getLibcallName(LC)) {
|
||||
// Some targets don't have a powi libcall; use pow instead.
|
||||
// FIXME: Implement this if some target needs it.
|
||||
DAG.getContext()->emitError("Don't know how to soften fpowi to fpow");
|
||||
return DAG.getUNDEF(N->getValueType(0));
|
||||
}
|
||||
|
||||
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
|
||||
SDValue Ops[2] = { GetSoftenedFloat(N->getOperand(0)), N->getOperand(1) };
|
||||
TargetLowering::MakeLibCallOptions CallOptions;
|
||||
EVT OpsVT[2] = { N->getOperand(0).getValueType(),
|
||||
N->getOperand(1).getValueType() };
|
||||
CallOptions.setTypeListBeforeSoften(OpsVT, N->getValueType(0), true);
|
||||
return TLI.makeLibCall(DAG, GetFPLibCall(N->getValueType(0),
|
||||
RTLIB::POWI_F32,
|
||||
RTLIB::POWI_F64,
|
||||
RTLIB::POWI_F80,
|
||||
RTLIB::POWI_F128,
|
||||
RTLIB::POWI_PPCF128),
|
||||
NVT, Ops, CallOptions, SDLoc(N)).first;
|
||||
return TLI.makeLibCall(DAG, LC, NVT, Ops, CallOptions, SDLoc(N)).first;
|
||||
}
|
||||
|
||||
SDValue DAGTypeLegalizer::SoftenFloatRes_FREM(SDNode *N) {
|
||||
|
|
|
@ -532,6 +532,12 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
|
|||
setOperationAction(ISD::FSINCOS, MVT::f32, Expand);
|
||||
}
|
||||
|
||||
if (Subtarget->getTargetTriple().isOSMSVCRT()) {
|
||||
// MSVCRT doesn't have powi; fall back to pow
|
||||
setLibcallName(RTLIB::POWI_F32, nullptr);
|
||||
setLibcallName(RTLIB::POWI_F64, nullptr);
|
||||
}
|
||||
|
||||
// Make floating-point constants legal for the large code model, so they don't
|
||||
// become loads from the constant pool.
|
||||
if (Subtarget->isTargetMachO() && TM.getCodeModel() == CodeModel::Large) {
|
||||
|
|
|
@ -1170,9 +1170,11 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM,
|
|||
setOperationAction(ISD::UDIVREM, MVT::i32, Expand);
|
||||
}
|
||||
|
||||
if (Subtarget->isTargetWindows() && Subtarget->getTargetTriple().isOSMSVCRT())
|
||||
for (auto &VT : {MVT::f32, MVT::f64})
|
||||
setOperationAction(ISD::FPOWI, VT, Custom);
|
||||
if (Subtarget->getTargetTriple().isOSMSVCRT()) {
|
||||
// MSVCRT doesn't have powi; fall back to pow
|
||||
setLibcallName(RTLIB::POWI_F32, nullptr);
|
||||
setLibcallName(RTLIB::POWI_F64, nullptr);
|
||||
}
|
||||
|
||||
setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
|
||||
setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
|
||||
|
@ -9093,58 +9095,6 @@ static void ReplaceCMP_SWAP_64Results(SDNode *N,
|
|||
Results.push_back(SDValue(CmpSwap, 2));
|
||||
}
|
||||
|
||||
static SDValue LowerFPOWI(SDValue Op, const ARMSubtarget &Subtarget,
|
||||
SelectionDAG &DAG) {
|
||||
const auto &TLI = DAG.getTargetLoweringInfo();
|
||||
|
||||
assert(Subtarget.getTargetTriple().isOSMSVCRT() &&
|
||||
"Custom lowering is MSVCRT specific!");
|
||||
|
||||
SDLoc dl(Op);
|
||||
SDValue Val = Op.getOperand(0);
|
||||
MVT Ty = Val->getSimpleValueType(0);
|
||||
SDValue Exponent = DAG.getNode(ISD::SINT_TO_FP, dl, Ty, Op.getOperand(1));
|
||||
SDValue Callee = DAG.getExternalSymbol(Ty == MVT::f32 ? "powf" : "pow",
|
||||
TLI.getPointerTy(DAG.getDataLayout()));
|
||||
|
||||
TargetLowering::ArgListTy Args;
|
||||
TargetLowering::ArgListEntry Entry;
|
||||
|
||||
Entry.Node = Val;
|
||||
Entry.Ty = Val.getValueType().getTypeForEVT(*DAG.getContext());
|
||||
Entry.IsZExt = true;
|
||||
Args.push_back(Entry);
|
||||
|
||||
Entry.Node = Exponent;
|
||||
Entry.Ty = Exponent.getValueType().getTypeForEVT(*DAG.getContext());
|
||||
Entry.IsZExt = true;
|
||||
Args.push_back(Entry);
|
||||
|
||||
Type *LCRTy = Val.getValueType().getTypeForEVT(*DAG.getContext());
|
||||
|
||||
// In the in-chain to the call is the entry node If we are emitting a
|
||||
// tailcall, the chain will be mutated if the node has a non-entry input
|
||||
// chain.
|
||||
SDValue InChain = DAG.getEntryNode();
|
||||
SDValue TCChain = InChain;
|
||||
|
||||
const Function &F = DAG.getMachineFunction().getFunction();
|
||||
bool IsTC = TLI.isInTailCallPosition(DAG, Op.getNode(), TCChain) &&
|
||||
F.getReturnType() == LCRTy;
|
||||
if (IsTC)
|
||||
InChain = TCChain;
|
||||
|
||||
TargetLowering::CallLoweringInfo CLI(DAG);
|
||||
CLI.setDebugLoc(dl)
|
||||
.setChain(InChain)
|
||||
.setCallee(CallingConv::ARM_AAPCS_VFP, LCRTy, Callee, std::move(Args))
|
||||
.setTailCall(IsTC);
|
||||
std::pair<SDValue, SDValue> CI = TLI.LowerCallTo(CLI);
|
||||
|
||||
// Return the chain (the DAG root) if it is a tail call
|
||||
return !CI.second.getNode() ? DAG.getRoot() : CI.first;
|
||||
}
|
||||
|
||||
SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
|
||||
LLVM_DEBUG(dbgs() << "Lowering node: "; Op.dump());
|
||||
switch (Op.getOpcode()) {
|
||||
|
@ -9234,7 +9184,6 @@ SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
|
|||
llvm_unreachable("Don't know how to custom lower this!");
|
||||
case ISD::FP_ROUND: return LowerFP_ROUND(Op, DAG);
|
||||
case ISD::FP_EXTEND: return LowerFP_EXTEND(Op, DAG);
|
||||
case ISD::FPOWI: return LowerFPOWI(Op, *Subtarget, DAG);
|
||||
case ARMISD::WIN__DBZCHK: return SDValue();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -154,6 +154,12 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
|
|||
setLibcallCallingConv(RTLIB::MUL_I64, CallingConv::X86_StdCall);
|
||||
}
|
||||
|
||||
if (Subtarget.getTargetTriple().isOSMSVCRT()) {
|
||||
// MSVCRT doesn't have powi; fall back to pow
|
||||
setLibcallName(RTLIB::POWI_F32, nullptr);
|
||||
setLibcallName(RTLIB::POWI_F64, nullptr);
|
||||
}
|
||||
|
||||
if (Subtarget.isTargetDarwin()) {
|
||||
// Darwin should use _setjmp/_longjmp instead of setjmp/longjmp.
|
||||
setUseUnderscoreSetJmp(false);
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
; RUN: llc -mtriple aarch64-windows < %s | FileCheck %s
|
||||
|
||||
declare double @llvm.powi.f64(double, i32)
|
||||
declare float @llvm.powi.f32(float, i32)
|
||||
|
||||
define double @d(double %d, i32 %i) {
|
||||
entry:
|
||||
%0 = tail call double @llvm.powi.f64(double %d, i32 %i)
|
||||
ret double %0
|
||||
}
|
||||
|
||||
; CHECK-LABEL: d:
|
||||
; CHECK: scvtf d1, w0
|
||||
; CHECK-NEXT: b pow
|
||||
|
||||
define float @f(float %f, i32 %i) {
|
||||
entry:
|
||||
%0 = tail call float @llvm.powi.f32(float %f, i32 %i)
|
||||
ret float %0
|
||||
}
|
||||
|
||||
; CHECK-LABEL: f:
|
||||
; CHECK: scvtf s1, w0
|
||||
; CHECK-NEXT: b powf
|
||||
|
||||
define float @g(double %d, i32 %i) {
|
||||
entry:
|
||||
%0 = tail call double @llvm.powi.f64(double %d, i32 %i)
|
||||
%conv = fptrunc double %0 to float
|
||||
ret float %conv
|
||||
}
|
||||
|
||||
; CHECK-LABEL: g:
|
||||
; CHECK: scvtf d1, w0
|
||||
; CHECK-NEXT: bl pow
|
||||
|
||||
define double @h(float %f, i32 %i) {
|
||||
entry:
|
||||
%0 = tail call float @llvm.powi.f32(float %f, i32 %i)
|
||||
%conv = fpext float %0 to double
|
||||
ret double %conv
|
||||
}
|
||||
|
||||
; CHECK-LABEL: h:
|
||||
; CHECK: scvtf s1, w0
|
||||
; CHECK-NEXT: bl powf
|
|
@ -0,0 +1,46 @@
|
|||
; RUN: llc -mtriple x86_64-windows < %s | FileCheck %s
|
||||
|
||||
declare double @llvm.powi.f64(double, i32)
|
||||
declare float @llvm.powi.f32(float, i32)
|
||||
|
||||
define double @d(double %d, i32 %i) {
|
||||
entry:
|
||||
%0 = tail call double @llvm.powi.f64(double %d, i32 %i)
|
||||
ret double %0
|
||||
}
|
||||
|
||||
; CHECK-LABEL: d:
|
||||
; CHECK: cvtsi2sd %edx, %xmm1
|
||||
; CHECK-NEXT: jmp pow
|
||||
|
||||
define float @f(float %f, i32 %i) {
|
||||
entry:
|
||||
%0 = tail call float @llvm.powi.f32(float %f, i32 %i)
|
||||
ret float %0
|
||||
}
|
||||
|
||||
; CHECK-LABEL: f:
|
||||
; CHECK: cvtsi2ss %edx, %xmm1
|
||||
; CHECK-NEXT: jmp powf
|
||||
|
||||
define float @g(double %d, i32 %i) {
|
||||
entry:
|
||||
%0 = tail call double @llvm.powi.f64(double %d, i32 %i)
|
||||
%conv = fptrunc double %0 to float
|
||||
ret float %conv
|
||||
}
|
||||
|
||||
; CHECK-LABEL: g:
|
||||
; CHECK: cvtsi2sd %edx, %xmm1
|
||||
; CHECK-NEXT: callq pow
|
||||
|
||||
define double @h(float %f, i32 %i) {
|
||||
entry:
|
||||
%0 = tail call float @llvm.powi.f32(float %f, i32 %i)
|
||||
%conv = fpext float %0 to double
|
||||
ret double %conv
|
||||
}
|
||||
|
||||
; CHECK-LABEL: h:
|
||||
; CHECK: cvtsi2ss %edx, %xmm1
|
||||
; CHECK-NEXT: callq powf
|
Loading…
Reference in New Issue