[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