[llvm] r283550 - [ARM] Reapply: Use __rt_div functions for divrem on Windows

Martin Storsjo via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 7 06:28:53 PDT 2016


Author: mstorsjo
Date: Fri Oct  7 08:28:53 2016
New Revision: 283550

URL: http://llvm.org/viewvc/llvm-project?rev=283550&view=rev
Log:
[ARM] Reapply: Use __rt_div functions for divrem on Windows

Reapplying r283383 after revert in r283442. The additional fix
is a getting rid of a stray space in a function name, in the
refactoring part of the commit.

This avoids falling back to calling out to the GCC rem functions
(__moddi3, __umoddi3) when targeting Windows.

The __rt_div functions have flipped the two arguments compared
to the __aeabi_divmod functions. To match MSVC, we emit a
check for division by zero before actually calling the library
function (even if the library function itself also might do
the same check).

Not all calls to __rt_div functions for division are currently
merged with calls to the same function with the same parameters
for the remainder. This is more wasteful than a div + mls as before,
but avoids calls to __moddi3.

Differential Revision: https://reviews.llvm.org/D25332

Modified:
    llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
    llvm/trunk/test/CodeGen/ARM/Windows/dbzchk.ll
    llvm/trunk/test/CodeGen/ARM/divmod-eabi.ll

Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp?rev=283550&r1=283549&r2=283550&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Fri Oct  7 08:28:53 2016
@@ -980,19 +980,26 @@ ARMTargetLowering::ARMTargetLowering(con
   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()) {
     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");
+    for (const auto &LC :
+         {RTLIB::SDIVREM_I8, RTLIB::SDIVREM_I16, RTLIB::SDIVREM_I32})
+      setLibcallName(LC, Subtarget->isTargetWindows() ? "__rt_sdiv"
+                                                      : "__aeabi_idivmod");
+    setLibcallName(RTLIB::SDIVREM_I64, Subtarget->isTargetWindows()
+                                           ? "__rt_sdiv64"
+                                           : "__aeabi_ldivmod");
+    for (const auto &LC :
+         {RTLIB::UDIVREM_I8, RTLIB::UDIVREM_I16, RTLIB::UDIVREM_I32})
+      setLibcallName(LC, Subtarget->isTargetWindows() ? "__rt_udiv"
+                                                      : "__aeabi_uidivmod");
+    setLibcallName(RTLIB::UDIVREM_I64, Subtarget->isTargetWindows()
+                                           ? "__rt_udiv64"
+                                           : "__aeabi_uldivmod");
 
     setLibcallCallingConv(RTLIB::SDIVREM_I8, CallingConv::ARM_AAPCS);
     setLibcallCallingConv(RTLIB::SDIVREM_I16, CallingConv::ARM_AAPCS);
@@ -7388,6 +7395,19 @@ SDValue ARMTargetLowering::LowerDIV_Wind
   return LowerWindowsDIVLibCall(Op, DAG, Signed, DBZCHK);
 }
 
+static SDValue WinDBZCheckDenominator(SelectionDAG &DAG, SDNode *N, SDValue InChain) {
+  SDLoc DL(N);
+  SDValue Op = N->getOperand(1);
+  if (N->getValueType(0) == MVT::i32)
+    return DAG.getNode(ARMISD::WIN__DBZCHK, DL, MVT::Other, InChain, Op);
+  SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, Op,
+                           DAG.getConstant(0, DL, MVT::i32));
+  SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, Op,
+                           DAG.getConstant(1, DL, MVT::i32));
+  return DAG.getNode(ARMISD::WIN__DBZCHK, DL, MVT::Other, InChain,
+                     DAG.getNode(ISD::OR, DL, MVT::i32, Lo, Hi));
+}
+
 void ARMTargetLowering::ExpandDIV_Windows(
     SDValue Op, SelectionDAG &DAG, bool Signed,
     SmallVectorImpl<SDValue> &Results) const {
@@ -7398,14 +7418,7 @@ void ARMTargetLowering::ExpandDIV_Window
          "unexpected type for custom lowering DIV");
   SDLoc dl(Op);
 
-  SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, Op.getOperand(1),
-                           DAG.getConstant(0, dl, MVT::i32));
-  SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, Op.getOperand(1),
-                           DAG.getConstant(1, dl, MVT::i32));
-  SDValue Or = DAG.getNode(ISD::OR, dl, MVT::i32, Lo, Hi);
-
-  SDValue DBZCHK =
-      DAG.getNode(ARMISD::WIN__DBZCHK, dl, MVT::Other, DAG.getEntryNode(), Or);
+  SDValue DBZCHK = WinDBZCheckDenominator(DAG, Op.getNode(), DAG.getEntryNode());
 
   SDValue Result = LowerWindowsDIVLibCall(Op, DAG, Signed, DBZCHK);
 
@@ -12406,7 +12419,7 @@ static RTLIB::Libcall getDivRemLibcall(
 }
 
 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");
@@ -12423,12 +12436,15 @@ static TargetLowering::ArgListTy getDivR
     Entry.isZExt = !isSigned;
     Args.push_back(Entry);
   }
+  if (Subtarget->isTargetWindows() && Args.size() >= 2)
+    std::swap(Args[0], Args[1]);
   return Args;
 }
 
 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) &&
@@ -12461,13 +12477,17 @@ SDValue ARMTargetLowering::LowerDivRem(S
   SDValue InChain = DAG.getEntryNode();
 
   TargetLowering::ArgListTy Args = getDivRemArgList(Op.getNode(),
-                                                    DAG.getContext());
+                                                    DAG.getContext(),
+                                                    Subtarget);
 
   SDValue Callee = DAG.getExternalSymbol(getLibcallName(LC),
                                          getPointerTy(DAG.getDataLayout()));
 
   Type *RetTy = (Type*)StructType::get(Ty, Ty, nullptr);
 
+  if (Subtarget->isTargetWindows())
+    InChain = WinDBZCheckDenominator(DAG, Op.getNode(), InChain);
+
   TargetLowering::CallLoweringInfo CLI(DAG);
   CLI.setDebugLoc(dl).setChain(InChain)
     .setCallee(getLibcallCallingConv(LC), RetTy, Callee, std::move(Args))
@@ -12500,11 +12520,15 @@ SDValue ARMTargetLowering::LowerREM(SDNo
   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()));
 
+  if (Subtarget->isTargetWindows())
+    InChain = WinDBZCheckDenominator(DAG, N, InChain);
+
   // Lower call
   CallLoweringInfo CLI(DAG);
   CLI.setChain(InChain)

Modified: llvm/trunk/test/CodeGen/ARM/Windows/dbzchk.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/Windows/dbzchk.ll?rev=283550&r1=283549&r2=283550&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/Windows/dbzchk.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/Windows/dbzchk.ll Fri Oct  7 08:28:53 2016
@@ -141,7 +141,7 @@ attributes #0 = { optsize }
 ; CHECK-CFG-ASM-NEXT: udf.w #249
 ; CHECK-CFG-ASM-LABEL: .LBB2_4:
 ; CHECK-CFG-ASM: bl __rt_udiv
-; CHECK-CFG-ASM: pop.w {{{.*}}, r11, pc}
+; CHECK-CFG-ASM: pop.w {r11, pc}
 
 ; RUN: llc -O0 -mtriple thumbv7--windows-itanium -verify-machineinstrs -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-WIN__DBZCHK
 

Modified: llvm/trunk/test/CodeGen/ARM/divmod-eabi.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/divmod-eabi.ll?rev=283550&r1=283549&r2=283550&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/divmod-eabi.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/divmod-eabi.ll Fri Oct  7 08:28:53 2016
@@ -42,15 +42,13 @@ entry:
 ; DARWIN-DEFAULT: add [[sum:r[0-9]+]], r0, [[div]]
 ; DARWIN-O0: mov [[rem:r[0-9]+]], r0
 ; WINDOWS: __rt_sdiv
-; WINDOWS-DEFAULT: mls [[rem:r[0-9]+]], r0,
-; WINDOWS-DEFAULT: adds [[sum:r[0-9]+]], [[rem]], r0
-; WINDOWS-O0: mov [[div:r[0-9]+]], r0
-; WINDOWS-O0: mls [[rem:r[0-9]+]], [[div]],
+; WINDOWS: __rt_sdiv
+; WINDOWS-DEFAULT: add [[sum:r[0-9]+]], r1
+; WINDOWS-O0: mov [[rem:r[0-9]+]], r1
   %rem8 = srem i32 %conv1, %conv
 ; EABI: __aeabi_idivmod
 ; DARWIN: __modsi3
 ; WINDOWS: __rt_sdiv
-; WINDOWS: mls [[rem1:r[0-9]+]], r0,
   %add = add nsw i32 %rem, %div
   %add13 = add nsw i32 %add, %rem8
   %conv14 = trunc i32 %add13 to i16
@@ -60,9 +58,10 @@ entry:
 ; DARWIN-O0: add [[sum:r[0-9]+]], [[rem]], [[div]]
 ; DARWIN-O0: add [[res:r[0-9]+]], [[sum]], r0
 ; DARWIN: sxth r0, [[res]]
-; WINDOWS-O0: adds [[sum:r[0-9]+]], [[rem]], [[div]]
-; WINDOWS: add [[rem1]], [[sum]]
-; WINDOWS: sxth [[res:r[0-9]+]], [[rem1]]
+; WINDOWS-DEFAULT: adds [[sum1:r[0-9]+]], [[sum]], r1
+; WINDOWS-O0: adds [[sum:r[0-9]+]], [[rem]],
+; WINDOWS-O0: add [[sum1:r[0-9]+]], r1
+; WINDOWS: sxth [[res:r[0-9]+]], [[sum1]]
   ret i16 %conv14
 }
 
@@ -84,22 +83,20 @@ entry:
 ; WINDOWS: __rt_sdiv
 ; WINDOWS: mov [[div:r[0-9]+]], r0
 ; WINDOWS: __rt_sdiv
-; WINDOWS: mls [[rem:r[0-9]+]], r0,
-; WINDOWS-DEFAULT: add [[div]], [[rem]]
+; WINDOWS-DEFAULT: add [[div]], r1
   %rem1 = srem i32 %b, %a
 ; EABI: __aeabi_idivmod
 ; DARWIN: __modsi3
 ; WINDOWS: __rt_sdiv
-; WINDOWS: mls [[rem1:r[0-9]+]], r0,
   %add = add nsw i32 %rem, %div
   %add2 = add nsw i32 %add, %rem1
 ; EABI: add r0{{.*}}r1
 ; DARWIN-DEFAULT: add r0, [[sum]], r0
 ; DARWIN-O0: add [[sum:r[0-9]+]], [[rem]], [[div]]
 ; DARWIN-O0: add [[res:r[0-9]+]], [[sum]], r0
-; WINDOWS-DEFAULT: add [[rem1]], [[div]]
+; WINDOWS-DEFAULT: adds r0, [[div]], r1
 ; WINDOWS-O0: adds [[sum:r[0-9]+]], [[rem]], [[div]]
-; WINDOWS-O0: add [[rem1]], [[sum]]
+; WINDOWS-O0: add [[sum]], r1
   ret i32 %add2
 }
 
@@ -119,22 +116,20 @@ entry:
 ; WINDOWS: __rt_udiv
 ; WINDOWS: mov [[div:r[0-9]+]], r0
 ; WINDOWS: __rt_udiv
-; WINDOWS: mls [[rem:r[0-9]+]], r0,
-; WINDOWS-DEFAULT: add [[div]], [[rem]]
+; WINDOWS-DEFAULT: add [[div]], r1
   %rem1 = urem i32 %b, %a
 ; EABI: __aeabi_uidivmod
 ; DARWIN: __umodsi3
 ; WINDOWS: __rt_udiv
-; WINDOWS: mls [[rem1:r[0-9]+]], r0,
   %add = add nuw i32 %rem, %div
   %add2 = add nuw i32 %add, %rem1
 ; EABI: add r0{{.*}}r1
 ; DARWIN-DEFAULT: add r0, [[sum]], r0
 ; DARWIN-O0: add [[sum:r[0-9]+]], [[rem]], [[div]]
 ; DARWIN-O0: add [[res:r[0-9]+]], [[sum]], r0
-; WINDOWS-DEFAULT: add [[rem1]], [[div]]
-; WINDOWS-O0: adds [[sum:r[0-9]+]], [[rem]], [[div]]
-; WINDOWS-O0: add [[rem1]], [[sum]]
+; WINDOWS-DEFAULT: adds [[sum:r[0-9]+]], [[div]], r1
+; WINDOWS-O0: adds [[sum:r[0-9]+]],
+; WINDOWS-O0: add [[sum]], r1
   ret i32 %add2
 }
 
@@ -154,14 +149,11 @@ entry:
 ; DARWIN: mov [[div2:r[0-9]+]], r1
 ; DARWIN: __moddi3
 ; WINDOWS: __rt_sdiv64
-; WINDOWS: mov [[div1:r[0-9]+]], r0
-; WINDOWS: mov [[div2:r[0-9]+]], r1
-; WINDOWS: __moddi3
   %add = add nsw i64 %rem, %div
 ; DARWIN: adds r0{{.*}}[[div1]]
 ; DARWIN: adc r1{{.*}}[[div2]]
-; WINDOWS: adds.w r0, r0, [[div1]]
-; WINDOWS: adc.w r1, r1, [[div2]]
+; WINDOWS: adds r0, r0, r2
+; WINDOWS: adcs r1, r3
   ret i64 %add
 }
 
@@ -179,11 +171,10 @@ entry:
 ; WINDOWS: __rt_sdiv
 ; WINDOWS: mov [[div:r[0-9]+]], r0
 ; WINDOWS: __rt_sdiv
-; WINDOWS: mls [[rem:r[0-9]+]], r0,
   %add = add nsw i16 %rem, %div
 ; EABI: add r0, r1
 ; DARWIN: add r0{{.*}}[[div1]]
-; WINDOWS: add [[rem]], [[div]]
+; WINDOWS: adds r0, r1, [[div]]
   ret i16 %add
 }
 
@@ -201,11 +192,10 @@ entry:
 ; WINDOWS: __rt_sdiv
 ; WINDOWS: mov [[div:r[0-9]+]], r0
 ; WINDOWS: __rt_sdiv
-; WINDOWS: mls [[rem:r[0-9]+]], r0,
   %add = add nsw i32 %rem, %div
 ; EABI:	add	r0{{.*}}r1
 ; DARWIN: add r0{{.*}}[[sum]]
-; WINDOWS: add [[rem]], [[div]]
+; WINDOWS: adds r0, r1, [[div]]
   ret i32 %add
 }
 
@@ -221,7 +211,7 @@ entry:
 ; WINDOWS: __rt_sdiv
   ret i32 %rem
 ; EABI:	mov	r0, r1
-; WINDOWS: mls r0, r0,
+; WINDOWS: mov  r0, r1
 }
 
 define i32 @g3(i32 %a, i32 %b) {
@@ -235,16 +225,15 @@ entry:
 ; DARWIN: __modsi3
 ; DARWIN: mov [[sum:r[0-9]+]], r0
 ; WINDOWS: __rt_sdiv
-; WINDOWS: mls [[rem:r[0-9]+]], r0,
+; WINDOWS: mov [[rem:r[0-9]+]], r1
   %rem1 = srem i32 %b, %rem
 ; EABI: __aeabi_idivmod
 ; DARWIN: __modsi3
 ; WINDOWS: __rt_sdiv
-; WINDOWS: mls [[rem1:r[0-9]+]], r0,
   %add = add nsw i32 %rem1, %rem
 ; EABI: add r0, r1, [[mod]]
 ; DARWIN: add r0{{.*}}[[sum]]
-; WINDOWS: add [[rem1]], [[rem]]
+; WINDOWS: adds r0, r1, [[rem]]
   ret i32 %add
 }
 
@@ -264,10 +253,9 @@ entry:
 ; EABI: __aeabi_idivmod
 ; DARWIN: __modsi3
 ; WINDOWS: __rt_sdiv
-; WINDOWS: mls [[rem:r[0-9]+]], r0,
   %add = add nsw i32 %rem, %div
 ; EABI: add r0, r1, [[div]]
 ; DARWIN: add r0{{.*}}[[sum]]
-; WINDOWS: add [[rem]], [[div]]
+; WINDOWS: adds r0, r1, [[div]]
   ret i32 %add
 }




More information about the llvm-commits mailing list