[PATCH] AEABI Divmod lowering

Renato Golin renato.golin at linaro.org
Thu Jun 27 04:33:28 PDT 2013


Hi t.p.northover,

Change LowerDivRem to understand target-specific requirements, and teach ARM lowering about AEABI requirements.

This patch is not working, probably not correct in many ways, but it's my approach to understand how it will work on the final commit without changing many other parts of the selection DAG.

The main thing I want now is to understand why this is not working (DAG-wise). When that is solved, I'll start thinking (and would like ideas) on how to make that better structured.

http://llvm-reviews.chandlerc.com/D1055

Files:
  include/llvm/Target/TargetLowering.h
  lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
  lib/Target/ARM/ARMISelLowering.cpp
  lib/Target/ARM/ARMISelLowering.h

Index: include/llvm/Target/TargetLowering.h
===================================================================
--- include/llvm/Target/TargetLowering.h
+++ include/llvm/Target/TargetLowering.h
@@ -25,6 +25,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/CodeGen/DAGCombine.h"
 #include "llvm/CodeGen/RuntimeLibcalls.h"
+#include "llvm/CodeGen/SelectionDAG.h"
 #include "llvm/CodeGen/SelectionDAGNodes.h"
 #include "llvm/IR/Attributes.h"
 #include "llvm/IR/CallingConv.h"
@@ -1880,6 +1881,13 @@
     return false;
   }
 
+  /// usesRegistersForDivRem - This method tells the DAG Legalizer if
+  /// the target's ABI (ex. ARM EABI) return the values of the remainder
+  /// on registers (ex. R1) instead of the stack, like GNU's ABI.
+  virtual bool usesRegistersForDivRem() const {
+    return false;
+  }
+
   //===--------------------------------------------------------------------===//
   // Lowering methods - These methods must be implemented by targets so that
   // the SelectionDAGBuilder code knows how to lower these.
@@ -1900,6 +1908,16 @@
     llvm_unreachable("Not Implemented");
   }
 
+  /// LowerReminderArgument - This hook sets the correct reminder argument
+  /// on DivRem library calls, depending on the ABI. The default is to
+  /// follow GNU's ABI and use the stack.
+  /// FIXME: Should this be implemented on all back-ends instead of here?
+  virtual SDValue LowerReminderArgument(EVT Type, SelectionDAG &DAG) const {
+    if (usesRegistersForDivRem())
+      llvm_unreachable("Register implementation of div/rem is target-specific");
+    return DAG.CreateStackTemporary(Type);
+  }
+
   struct ArgListEntry {
     SDValue Node;
     Type* Ty;
Index: lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
===================================================================
--- lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -2047,6 +2047,7 @@
                                           SmallVectorImpl<SDValue> &Results) {
   unsigned Opcode = Node->getOpcode();
   bool isSigned = Opcode == ISD::SDIVREM;
+  bool isPairedReturn = TLI.usesRegistersForDivRem();
 
   RTLIB::Libcall LC;
   switch (Node->getValueType(0).getSimpleVT().SimpleTy) {
@@ -2077,8 +2078,8 @@
     Args.push_back(Entry);
   }
 
-  // Also pass the return address of the remainder.
-  SDValue FIPtr = DAG.CreateStackTemporary(RetVT);
+  // Also pass the remainder (register or stack).
+  SDValue FIPtr = TLI.LowerReminderArgument(RetVT, DAG);
   Entry.Node = FIPtr;
   Entry.Ty = RetTy->getPointerTo();
   Entry.isSExt = isSigned;
@@ -2096,9 +2097,11 @@
                     Callee, Args, DAG, dl);
   std::pair<SDValue, SDValue> CallInfo = TLI.LowerCallTo(CLI);
 
-  // Remainder is loaded back from the stack frame.
-  SDValue Rem = DAG.getLoad(RetVT, dl, CallInfo.second, FIPtr,
-                            MachinePointerInfo(), false, false, false, 0);
+  // Remainder is loaded back from the stack frame or in regs.
+  SDValue Rem = FIPtr;
+  if (!isPairedReturn)
+    Rem = DAG.getLoad(RetVT, dl, CallInfo.second, FIPtr,
+                      MachinePointerInfo(), false, false, false, 0);
   Results.push_back(CallInfo.first);
   Results.push_back(Rem);
 }
Index: lib/Target/ARM/ARMISelLowering.cpp
===================================================================
--- lib/Target/ARM/ARMISelLowering.cpp
+++ lib/Target/ARM/ARMISelLowering.cpp
@@ -392,7 +392,7 @@
     setLibcallCallingConv(RTLIB::SRA_I64, CallingConv::ARM_AAPCS);
 
     // Integer division functions
-    // RTABI chapter 4.3.1
+    // RTABI chapter 4.2 and 4.3.1
     setLibcallName(RTLIB::SDIV_I8,  "__aeabi_idiv");
     setLibcallName(RTLIB::SDIV_I16, "__aeabi_idiv");
     setLibcallName(RTLIB::SDIV_I32, "__aeabi_idiv");
@@ -401,6 +401,14 @@
     setLibcallName(RTLIB::UDIV_I16, "__aeabi_uidiv");
     setLibcallName(RTLIB::UDIV_I32, "__aeabi_uidiv");
     setLibcallName(RTLIB::UDIV_I64, "__aeabi_uldivmod");
+    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::SDIV_I8, CallingConv::ARM_AAPCS);
     setLibcallCallingConv(RTLIB::SDIV_I16, CallingConv::ARM_AAPCS);
     setLibcallCallingConv(RTLIB::SDIV_I32, CallingConv::ARM_AAPCS);
@@ -409,6 +417,14 @@
     setLibcallCallingConv(RTLIB::UDIV_I16, CallingConv::ARM_AAPCS);
     setLibcallCallingConv(RTLIB::UDIV_I32, CallingConv::ARM_AAPCS);
     setLibcallCallingConv(RTLIB::UDIV_I64, CallingConv::ARM_AAPCS);
+    setLibcallCallingConv(RTLIB::SDIVREM_I8, CallingConv::ARM_AAPCS);
+    setLibcallCallingConv(RTLIB::SDIVREM_I16, CallingConv::ARM_AAPCS);
+    setLibcallCallingConv(RTLIB::SDIVREM_I32, CallingConv::ARM_AAPCS);
+    setLibcallCallingConv(RTLIB::SDIVREM_I64, CallingConv::ARM_AAPCS);
+    setLibcallCallingConv(RTLIB::UDIVREM_I8, CallingConv::ARM_AAPCS);
+    setLibcallCallingConv(RTLIB::UDIVREM_I16, CallingConv::ARM_AAPCS);
+    setLibcallCallingConv(RTLIB::UDIVREM_I32, CallingConv::ARM_AAPCS);
+    setLibcallCallingConv(RTLIB::UDIVREM_I64, CallingConv::ARM_AAPCS);
 
     // Memory operations
     // RTABI chapter 4.3.4
@@ -10558,6 +10574,23 @@
   return false;
 }
 
+bool
+ARMTargetLowering::usesRegistersForDivRem() const {
+  // FIXME: AAPCS is NOT! AEABI!
+  return Subtarget->isAAPCS_ABI() && !Subtarget->isTargetDarwin();
+}
+
+SDValue
+ARMTargetLowering::LowerReminderArgument(EVT Type, SelectionDAG &DAG) const {
+  if (!usesRegistersForDivRem())
+    return DAG.CreateStackTemporary(Type);
+  assert(Type.isInteger() && "Wrong type for reminder");
+  // R1 for i32, {R2,R3} for i64
+  unsigned Reg = (Type == MVT::i64) ? ARM::R2 : ARM::R1;
+  return DAG.getRegister(Reg, Type);
+}
+
+
 /// getTgtMemIntrinsic - Represent NEON load and store intrinsics as
 /// MemIntrinsicNodes.  The associated MachineMemOperands record the alignment
 /// specified in the intrinsic calls.
Index: lib/Target/ARM/ARMISelLowering.h
===================================================================
--- lib/Target/ARM/ARMISelLowering.h
+++ lib/Target/ARM/ARMISelLowering.h
@@ -390,6 +390,11 @@
     virtual bool getTgtMemIntrinsic(IntrinsicInfo &Info,
                                     const CallInst &I,
                                     unsigned Intrinsic) const;
+
+    virtual bool usesRegistersForDivRem() const;
+
+    virtual SDValue LowerReminderArgument(EVT Type, SelectionDAG &DAG) const;
+
   protected:
     std::pair<const TargetRegisterClass*, uint8_t>
     findRepresentativeClass(MVT VT) const;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D1055.1.patch
Type: text/x-patch
Size: 6865 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130627/4e11a1fc/attachment.bin>


More information about the llvm-commits mailing list