summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSaleem Abdulrasool <compnerd@compnerd.org>2016-11-06 19:46:54 +0000
committerSaleem Abdulrasool <compnerd@compnerd.org>2016-11-06 19:46:54 +0000
commit804e12eeb5db92e47ef696d064d596f923f481c9 (patch)
tree9cd55e36f6a71351523ee077b9825bd5ff41af32
parentf8d38d11b9323d875b85623193940b117c1ec4fa (diff)
downloadbcm5719-llvm-804e12eeb5db92e47ef696d064d596f923f481c9.tar.gz
bcm5719-llvm-804e12eeb5db92e47ef696d064d596f923f481c9.zip
ARM: lower fpowi appropriately for Windows ARM
This handles the last case of the builtin function calls that we would generate code which differed from Microsoft's ABI. Rather than generating a call to `__pow{d,s}i2` we now promote the parameter to a float or double and invoke `powf` or `pow` instead. Addresses PR30825! llvm-svn: 286082
-rw-r--r--llvm/lib/Target/ARM/ARMISelLowering.cpp57
-rw-r--r--llvm/test/CodeGen/ARM/Windows/powi.ll57
2 files changed, 114 insertions, 0 deletions
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index 7671c87a5f7..143c6d9c543 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -1017,6 +1017,10 @@ 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);
+
setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom);
@@ -7525,6 +7529,58 @@ 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 auto *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 {
switch (Op.getOpcode()) {
default: llvm_unreachable("Don't know how to custom lower this!");
@@ -7611,6 +7667,7 @@ 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();
}
}
diff --git a/llvm/test/CodeGen/ARM/Windows/powi.ll b/llvm/test/CodeGen/ARM/Windows/powi.ll
new file mode 100644
index 00000000000..4ec4b0abbdf
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/Windows/powi.ll
@@ -0,0 +1,57 @@
+; RUN: llc -mtriple thumbv7--windows-itanium -filetype asm -o - %s | FileCheck %s
+
+declare double @llvm.powi.f64(double, i32)
+declare float @llvm.powi.f32(float, i32)
+
+define arm_aapcs_vfpcc 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: vmov s[[REGISTER:[0-9]+]], r0
+; CHECK-NEXT: vcvt.f64.s32 d1, s[[REGISTER]]
+; CHECK-NEXT: b pow
+; CHECK-NOT: __powisf2
+
+define arm_aapcs_vfpcc 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: vmov s[[REGISTER:[0-9]+]], r0
+; CHECK-NEXT: vcvt.f32.s32 s1, s[[REGISTER]]
+; CHECK-NEXT: b pow
+; CHECK-NOT: __powisf2
+
+define arm_aapcs_vfpcc 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: vmov s[[REGISTER:[0-9]+]], r0
+; CHECK-NEXT: vcvt.f64.s32 d1, s[[REGISTER]]
+; CHECK-NEXT: bl pow
+; CHECK-NOT: bl __powidf2
+; CHECK-NEXT: vcvt.f32.f64 s0, d0
+
+define arm_aapcs_vfpcc 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: vmov s[[REGISTER:[0-9]+]], r0
+; CHECK-NEXT: vcvt.f32.s32 s1, s[[REGISTER]]
+; CHECK-NEXT: bl powf
+; CHECK-NOT: bl __powisf2
+; CHECK-NEXT: vcvt.f64.f32 d0, s0
+
OpenPOWER on IntegriCloud