[PATCH] D24076: [ARM] Use __rt_div functions for DIVREM on Windows
Martin Storsjö via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 31 06:33:16 PDT 2016
mstorsjo created this revision.
mstorsjo added reviewers: rengolin, compnerd, jmolloy.
mstorsjo added a subscriber: llvm-commits.
Herald added subscribers: samparker, rengolin, aemerson.
This avoids falling back to calling out to the GCC specific rem functions (__moddi3, __umoddi3) when targeting Windows.
The __rt_div functions have flipped the two arguments compared to the __aeabi_divmod functions.
This seems to work in practice when compiling a real-world codebase, but I'm not sure if the flipped argument order will break in some optimizations/combinations that don't happen in my test.
This breaks two tests; CodeGen/ARM/divmod-eabi.ll and CodeGen/ARM/Windows/dbzchk.ll. The output in divmod-eabi.ll changes from two __rt_sdiv calls into three, so there's clearly something still missing.
https://reviews.llvm.org/D24076
Files:
lib/Target/ARM/ARMISelLowering.cpp
Index: lib/Target/ARM/ARMISelLowering.cpp
===================================================================
--- lib/Target/ARM/ARMISelLowering.cpp
+++ lib/Target/ARM/ARMISelLowering.cpp
@@ -796,19 +796,31 @@
setOperationAction(ISD::UREM, MVT::i32, Expand);
// Register based DivRem for AEABI (RTABI 4.2)
if (Subtarget->isTargetAEABI() || Subtarget->isTargetAndroid() ||
- Subtarget->isTargetGNUAEABI() || Subtarget->isTargetMuslAEABI()) {
+ Subtarget->isTargetGNUAEABI() || Subtarget->isTargetMuslAEABI() ||
+ (Subtarget->isTargetWindows() && !Subtarget->hasDivide())) {
setOperationAction(ISD::SREM, MVT::i64, Custom);
setOperationAction(ISD::UREM, MVT::i64, Custom);
HasStandaloneRem = false;
- setLibcallName(RTLIB::SDIVREM_I8, "__aeabi_idivmod");
- setLibcallName(RTLIB::SDIVREM_I16, "__aeabi_idivmod");
- setLibcallName(RTLIB::SDIVREM_I32, "__aeabi_idivmod");
- setLibcallName(RTLIB::SDIVREM_I64, "__aeabi_ldivmod");
- setLibcallName(RTLIB::UDIVREM_I8, "__aeabi_uidivmod");
- setLibcallName(RTLIB::UDIVREM_I16, "__aeabi_uidivmod");
- setLibcallName(RTLIB::UDIVREM_I32, "__aeabi_uidivmod");
- setLibcallName(RTLIB::UDIVREM_I64, "__aeabi_uldivmod");
+ if (Subtarget->isTargetWindows()) {
+ setLibcallName(RTLIB::SDIVREM_I8, "__rt_sdiv");
+ setLibcallName(RTLIB::SDIVREM_I16, "__rt_sdiv");
+ setLibcallName(RTLIB::SDIVREM_I32, "__rt_sdiv");
+ setLibcallName(RTLIB::SDIVREM_I64, "__rt_sdiv64");
+ setLibcallName(RTLIB::UDIVREM_I8, "__rt_udiv");
+ setLibcallName(RTLIB::UDIVREM_I16, "__rt_udiv");
+ setLibcallName(RTLIB::UDIVREM_I32, "__rt_udiv");
+ setLibcallName(RTLIB::UDIVREM_I64, "__rt_udiv64");
+ } else {
+ setLibcallName(RTLIB::SDIVREM_I8, "__aeabi_idivmod");
+ setLibcallName(RTLIB::SDIVREM_I16, "__aeabi_idivmod");
+ setLibcallName(RTLIB::SDIVREM_I32, "__aeabi_idivmod");
+ setLibcallName(RTLIB::SDIVREM_I64, "__aeabi_ldivmod");
+ setLibcallName(RTLIB::UDIVREM_I8, "__aeabi_uidivmod");
+ setLibcallName(RTLIB::UDIVREM_I16, "__aeabi_uidivmod");
+ setLibcallName(RTLIB::UDIVREM_I32, "__aeabi_uidivmod");
+ setLibcallName(RTLIB::UDIVREM_I64, "__aeabi_uldivmod");
+ }
setLibcallCallingConv(RTLIB::SDIVREM_I8, CallingConv::ARM_AAPCS);
setLibcallCallingConv(RTLIB::SDIVREM_I16, CallingConv::ARM_AAPCS);
@@ -12066,18 +12078,19 @@
}
static TargetLowering::ArgListTy getDivRemArgList(
- const SDNode *N, LLVMContext *Context) {
+ const SDNode *N, LLVMContext *Context, const ARMSubtarget *Subtarget) {
assert((N->getOpcode() == ISD::SDIVREM || N->getOpcode() == ISD::UDIVREM ||
N->getOpcode() == ISD::SREM || N->getOpcode() == ISD::UREM) &&
"Unhandled Opcode in getDivRemArgList");
bool isSigned = N->getOpcode() == ISD::SDIVREM ||
N->getOpcode() == ISD::SREM;
TargetLowering::ArgListTy Args;
TargetLowering::ArgListEntry Entry;
for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
- EVT ArgVT = N->getOperand(i).getValueType();
+ unsigned src = Subtarget->isTargetWindows() ? e - 1 - i : i;
+ EVT ArgVT = N->getOperand(src).getValueType();
Type *ArgTy = ArgVT.getTypeForEVT(*Context);
- Entry.Node = N->getOperand(i);
+ Entry.Node = N->getOperand(src);
Entry.Ty = ArgTy;
Entry.isSExt = isSigned;
Entry.isZExt = !isSigned;
@@ -12088,7 +12101,8 @@
SDValue ARMTargetLowering::LowerDivRem(SDValue Op, SelectionDAG &DAG) const {
assert((Subtarget->isTargetAEABI() || Subtarget->isTargetAndroid() ||
- Subtarget->isTargetGNUAEABI() || Subtarget->isTargetMuslAEABI()) &&
+ Subtarget->isTargetGNUAEABI() || Subtarget->isTargetMuslAEABI() ||
+ Subtarget->isTargetWindows()) &&
"Register-based DivRem lowering only");
unsigned Opcode = Op->getOpcode();
assert((Opcode == ISD::SDIVREM || Opcode == ISD::UDIVREM) &&
@@ -12102,7 +12116,8 @@
SDValue InChain = DAG.getEntryNode();
TargetLowering::ArgListTy Args = getDivRemArgList(Op.getNode(),
- DAG.getContext());
+ DAG.getContext(),
+ Subtarget);
SDValue Callee = DAG.getExternalSymbol(getLibcallName(LC),
getPointerTy(DAG.getDataLayout()));
@@ -12142,7 +12157,8 @@
RTLIB::Libcall LC = getDivRemLibcall(N, N->getValueType(0).getSimpleVT().
SimpleTy);
SDValue InChain = DAG.getEntryNode();
- TargetLowering::ArgListTy Args = getDivRemArgList(N, DAG.getContext());
+ TargetLowering::ArgListTy Args = getDivRemArgList(N, DAG.getContext(),
+ Subtarget);
bool isSigned = N->getOpcode() == ISD::SREM;
SDValue Callee = DAG.getExternalSymbol(getLibcallName(LC),
getPointerTy(DAG.getDataLayout()));
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D24076.69841.patch
Type: text/x-patch
Size: 5042 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160831/8f667f9f/attachment.bin>
More information about the llvm-commits
mailing list