The attached patches implement most of the ARM AAPCS-VFP hard float
authorAnton Korobeynikov <asl@math.spbu.ru>
Mon, 8 Jun 2009 22:53:56 +0000 (22:53 +0000)
committerAnton Korobeynikov <asl@math.spbu.ru>
Mon, 8 Jun 2009 22:53:56 +0000 (22:53 +0000)
ABI. The missing piece is support for putting "homogeneous aggregates"
into registers.

Patch by Sandeep Patel!

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@73095 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Target/TargetMachine.h
include/llvm/Target/TargetOptions.h
lib/Target/ARM/ARMCallingConv.td
lib/Target/ARM/ARMISelDAGToDAG.cpp
lib/Target/ARM/ARMISelLowering.cpp
lib/Target/ARM/ARMRegisterInfo.td
lib/Target/ARM/ARMSubtarget.cpp
lib/Target/TargetMachine.cpp
lib/Target/X86/X86Subtarget.cpp

index bdcc4eff675fb3b65438e8f267d2e77350ab9cae..a8db68c597892aecc80639c705f6bfdca34725ac 100644 (file)
@@ -78,6 +78,14 @@ namespace CodeGenOpt {
   };
 }
 
+namespace FloatABI {
+  enum ABIType {
+    Default,
+    Soft,
+    Hard
+  };
+}
+
 //===----------------------------------------------------------------------===//
 ///
 /// TargetMachine - Primary interface to the complete machine description for
@@ -88,7 +96,7 @@ class TargetMachine {
   TargetMachine(const TargetMachine &);   // DO NOT IMPLEMENT
   void operator=(const TargetMachine &);  // DO NOT IMPLEMENT
 protected: // Can only create subclasses.
-  TargetMachine() : AsmInfo(0) { }
+  TargetMachine();
 
   /// getSubtargetImpl - virtual method implemented by subclasses that returns
   /// a reference to that target's TargetSubtarget-derived member variable.
index 0c74fa1f2c1eee8fce7d01105e7b80f71ddcf969..377e03f95c4728a23cb78220bc595bcbf62d60a8 100644 (file)
@@ -73,6 +73,14 @@ namespace llvm {
   /// target FP instructions.
   extern bool UseSoftFloat;
 
+  /// FloatABIType - This setting is set by -float-abi=xxx option is specfied
+  /// on the command line. This setting may either be Default, Soft, or Hard.
+  /// Default selects the target's default behavior. Soft selects the ABI for
+  /// UseSoftFloat, but does not inidcate that FP hardware may not be used.
+  /// Such a combination is unfortunately popular (e.g. arm-apple-darwin).
+  /// Hard presumes that the normal FP ABI is used.
+  extern FloatABI::ABIType FloatABIType;
+
   /// NoZerosInBSS - By default some codegens place zero-initialized data to
   /// .bss section. This flag disables such behaviour (necessary, e.g. for
   /// crt*.o compiling).
index 6cd786eed4d55a203ff5377ff6f0f25b010da616..1c5ec5f2901f02cff708f647f3efb8960850dbed 100644 (file)
@@ -17,6 +17,11 @@ class CCIfSubtarget<string F, CCAction A>:
 class CCIfAlign<string Align, CCAction A>:
   CCIf<!strconcat("ArgFlags.getOrigAlign() == ", Align), A>;
 
+/// CCIfFloatABI - Match of the float ABI and the arg. ABIType may be "Hard" or
+///                "Soft".
+class CCIfFloatABI<string ABIType, CCAction A>:
+  CCIf<!strconcat("llvm::FloatABIType == llvm::FloatABI::", ABIType), A>;
+
 //===----------------------------------------------------------------------===//
 // ARM APCS Calling Convention
 //===----------------------------------------------------------------------===//
@@ -43,9 +48,10 @@ def RetCC_ARM_APCS : CallingConv<[
 ]>;
 
 //===----------------------------------------------------------------------===//
-// ARM AAPCS (EABI) Calling Convention
+// ARM AAPCS (EABI) Calling Convention, common parts
 //===----------------------------------------------------------------------===//
-def CC_ARM_AAPCS : CallingConv<[
+
+def CC_ARM_AAPCS_Common : CallingConv<[
 
   CCIfType<[i8, i16], CCPromoteToType<i32>>,
 
@@ -53,23 +59,51 @@ def CC_ARM_AAPCS : CallingConv<[
   // i64 is 8-aligned i32 here, so we may need to eat R1 as a pad register
   // (and the same is true for f64 if VFP is not enabled)
   CCIfType<[i32], CCIfAlign<"8", CCAssignToRegWithShadow<[R0, R2], [R0, R1]>>>,
-  CCIfType<[f64], CCCustom<"CC_ARM_AAPCS_Custom_f64">>,
-
-  CCIfType<[f32], CCBitConvertToType<i32>>,
   CCIfType<[i32], CCIf<"State.getNextStackOffset() == 0 &&"
                        "ArgFlags.getOrigAlign() != 8",
                        CCAssignToReg<[R0, R1, R2, R3]>>>,
 
-  CCIfType<[i32], CCAssignToStack<4, 4>>,
+  CCIfType<[i32, f32], CCAssignToStack<4, 4>>,
   CCIfType<[f64], CCAssignToStack<8, 8>>
 ]>;
 
-def RetCC_ARM_AAPCS : CallingConv<[
+def RetCC_ARM_AAPCS_Common : CallingConv<[
+  CCIfType<[i32], CCAssignToReg<[R0, R1, R2, R3]>>
+  CCIfType<[i64], CCAssignToRegWithShadow<[R0, R2], [R1, R3]>>
+]>;
+
+//===----------------------------------------------------------------------===//
+// ARM AAPCS (EABI) Calling Convention
+//===----------------------------------------------------------------------===//
+
+def CC_ARM_AAPCS : CallingConv<[
+  CCIfType<[f64], CCCustom<"CC_ARM_AAPCS_Custom_f64">>,
   CCIfType<[f32], CCBitConvertToType<i32>>,
+  CCDelegateTo<CC_ARM_AAPCS_Common>
+]>;
+
+def RetCC_ARM_AAPCS : CallingConv<[
   CCIfType<[f64], CCCustom<"RetCC_ARM_AAPCS_Custom_f64">>,
+  CCIfType<[f32], CCBitConvertToType<i32>>,
+  CCDelegateTo<RetCC_ARM_AAPCS_Common>
+]>;
 
-  CCIfType<[i32], CCAssignToReg<[R0, R1, R2, R3]>>,
-  CCIfType<[i64], CCAssignToRegWithShadow<[R0, R2], [R1, R3]>>
+//===----------------------------------------------------------------------===//
+// ARM AAPCS-VFP (EABI) Calling Convention
+//===----------------------------------------------------------------------===//
+
+def CC_ARM_AAPCS_VFP : CallingConv<[
+  CCIfType<[f64], CCAssignToReg<[D0, D1, D2, D3, D4, D5, D6, D7]>>,
+  CCIfType<[f32], CCAssignToReg<[S0, S1, S2, S3, S4, S5, S6, S7, S8,
+                                 S9, S10, S11, S12, S13, S14, S15]>>,
+  CCDelegateTo<CC_ARM_AAPCS_Common>
+]>;
+
+def RetCC_ARM_AAPCS_VFP : CallingConv<[
+  CCIfType<[f64], CCAssignToReg<[D0, D1, D2, D3, D4, D5, D6, D7]>>,
+  CCIfType<[f32], CCAssignToReg<[S0, S1, S2, S3, S4, S5, S6, S7, S8,
+                                 S9, S10, S11, S12, S13, S14, S15]>>,
+  CCDelegateTo<RetCC_ARM_AAPCS_Common>
 ]>;
 
 //===----------------------------------------------------------------------===//
@@ -77,11 +111,19 @@ def RetCC_ARM_AAPCS : CallingConv<[
 //===----------------------------------------------------------------------===//
 
 def CC_ARM : CallingConv<[
+  CCIfSubtarget<"isAAPCS_ABI()",
+                CCIfSubtarget<"hasVFP2()",
+                              CCIfFloatABI<"Hard",
+                                           CCDelegateTo<CC_ARM_AAPCS_VFP>>>>,
   CCIfSubtarget<"isAAPCS_ABI()", CCDelegateTo<CC_ARM_AAPCS>>,
   CCDelegateTo<CC_ARM_APCS>
 ]>;
 
 def RetCC_ARM : CallingConv<[
+  CCIfSubtarget<"isAAPCS_ABI()",
+                CCIfSubtarget<"hasVFP2()",
+                              CCIfFloatABI<"Hard",
+                                           CCDelegateTo<RetCC_ARM_AAPCS_VFP>>>>,
   CCIfSubtarget<"isAAPCS_ABI()", CCDelegateTo<RetCC_ARM_AAPCS>>,
   CCDelegateTo<RetCC_ARM_APCS>
 ]>;
index ca3a9cb4032921a640f03d7fd70db5321b4c37fd..a413ee6f3e0c41fcc1fce9d577f4a3f4ba42a9f2 100644 (file)
@@ -549,6 +549,10 @@ SDNode *ARMDAGToDAGISel::Select(SDValue Op) {
   switch (N->getOpcode()) {
   default: break;
   case ISD::Constant: {
+    // ARMv6T2 and later should materialize imms via MOV / MOVT pair.
+    if (Subtarget->hasV6T2Ops())
+      break;
+
     unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
     bool UseCP = true;
     if (Subtarget->isThumb())
@@ -559,6 +563,7 @@ SDNode *ARMDAGToDAGISel::Select(SDValue Op) {
       UseCP = (ARM_AM::getSOImmVal(Val) == -1 &&     // MOV
                ARM_AM::getSOImmVal(~Val) == -1 &&    // MVN
                !ARM_AM::isSOImmTwoPartVal(Val));     // two instrs.
+
     if (UseCP) {
       SDValue CPIdx =
         CurDAG->getTargetConstantPool(ConstantInt::get(Type::Int32Ty, Val),
@@ -570,7 +575,7 @@ SDNode *ARMDAGToDAGISel::Select(SDValue Op) {
                                         CPIdx, CurDAG->getEntryNode());
       else {
         SDValue Ops[] = {
-          CPIdx, 
+          CPIdx,
           CurDAG->getRegister(0, MVT::i32),
           CurDAG->getTargetConstant(0, MVT::i32),
           getAL(CurDAG),
@@ -583,7 +588,7 @@ SDNode *ARMDAGToDAGISel::Select(SDValue Op) {
       ReplaceUses(Op, SDValue(ResNode, 0));
       return NULL;
     }
-      
+
     // Other cases are autogenerated.
     break;
   }
index c0fd9dcd10729a4d9c093fc0dd1e3a3b8078d2be..ec8bd1f8b31a64a1c36f055ffab22f61f6f97a11 100644 (file)
@@ -1101,7 +1101,12 @@ ARMTargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG) {
       else
         RC = ARM::GPRRegisterClass;
 
-      if (RegVT == MVT::f64) {
+      if (FloatABIType == FloatABI::Hard) {
+        if (RegVT == MVT::f32)
+          RC = ARM::SPRRegisterClass;
+        else if (RegVT == MVT::f64)
+          RC = ARM::DPRRegisterClass;
+      } else if (RegVT == MVT::f64) {
         // f64 is passed in pairs of GPRs and must be combined.
         RegVT = MVT::i32;
       } else if (!((RegVT == MVT::i32) || (RegVT == MVT::f32)))
index b95d1f93aba5e87af48f4663743b430e2cb35bc3..ebe7d582a664b2f836043d4d45f1c7595abf738c 100644 (file)
@@ -219,3 +219,18 @@ def DPR : RegisterClass<"ARM", [f64], 64, [D0, D1, D2, D3, D4, D5, D6, D7, D8,
 
 // Condition code registers.
 def CCR : RegisterClass<"ARM", [i32], 32, [CPSR]>;
+
+//===----------------------------------------------------------------------===//
+// Subregister Set Definitions... now that we have all of the pieces, define the
+// sub registers for each register.
+//
+
+def : SubRegSet<1, [D0, D1, D2, D3, D4, D5, D6, D7,
+                    D8, D9, D10, D11, D12, D13, D14, D15],
+                   [S0, S2, S4, S6, S8, S10, S12, S14,
+                    S16, S18, S20, S22, S24, S26, S28, S30]>;
+
+def : SubRegSet<2, [D0, D1, D2, D3, D4, D5, D6, D7,
+                    D8, D9, D10, D11, D12, D13, D14, D15],
+                   [S1, S3, S5, S7, S9, S11, S13, S15,
+                    S17, S19, S21, S23, S25, S27, S29, S31]>;
index ef78cd52d85a23236f8ad50c81ce2c0bc18ebb84..a978380b627f8e60783f3a52dc19845ce5e2bf7a 100644 (file)
@@ -14,6 +14,8 @@
 #include "ARMSubtarget.h"
 #include "ARMGenSubtarget.inc"
 #include "llvm/Module.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
 using namespace llvm;
 
 ARMSubtarget::ARMSubtarget(const Module &M, const std::string &FS,
@@ -28,6 +30,10 @@ ARMSubtarget::ARMSubtarget(const Module &M, const std::string &FS,
   , CPUString("generic")
   , TargetType(isELF) // Default to ELF unless otherwise specified.
   , TargetABI(ARM_ABI_APCS) {
+  // default to soft float ABI
+  if (FloatABIType == FloatABI::Default)
+    FloatABIType = FloatABI::Soft;
+
   // Determine default and user specified characteristics
 
   // Parse features string.
index dea293b502ca870afe841276dc340ab744a35b20..c487cb805306ab221becf4ede0f19ca9184da639 100644 (file)
@@ -30,6 +30,7 @@ namespace llvm {
   bool FiniteOnlyFPMathOption;
   bool HonorSignDependentRoundingFPMathOption;
   bool UseSoftFloat;
+  FloatABI::ABIType FloatABIType;
   bool NoImplicitFloat;
   bool NoZerosInBSS;
   bool ExceptionHandling;
@@ -84,6 +85,19 @@ GenerateSoftFloatCalls("soft-float",
   cl::desc("Generate software floating point library calls"),
   cl::location(UseSoftFloat),
   cl::init(false));
+static cl::opt<llvm::FloatABI::ABIType, true>
+FloatABIForCalls("float-abi",
+  cl::desc("Choose float ABI type"),
+  cl::location(FloatABIType),
+  cl::init(FloatABI::Default),
+  cl::values(
+    clEnumValN(FloatABI::Default, "default",
+               "Target default float ABI type"),
+    clEnumValN(FloatABI::Soft, "soft",
+               "Soft float ABI (implied by -soft-float)"),
+    clEnumValN(FloatABI::Hard, "hard",
+               "Hard float ABI (uses FP registers)"),
+    clEnumValEnd));
 static cl::opt<bool, true>
 DontPlaceZerosInBSS("nozero-initialized-in-bss",
   cl::desc("Don't place zero-initialized symbols into bss section"),
@@ -162,6 +176,14 @@ EnableStrongPHIElim(cl::Hidden, "strong-phi-elim",
 // TargetMachine Class
 //
 
+TargetMachine::TargetMachine() 
+  : AsmInfo(0) {
+  // Typically it will be subtargets that will adjust FloatABIType from Default
+  // to Soft or Hard.
+  if (UseSoftFloat)
+    FloatABIType = FloatABI::Soft;
+}
+
 TargetMachine::~TargetMachine() {
   delete AsmInfo;
 }
index 03ce1aee0e8ad663a77683f8debb81e7dcf310c0..56983ce7f166ce512ec12158a85aa3ad7fa09416 100644 (file)
@@ -350,6 +350,10 @@ X86Subtarget::X86Subtarget(const Module &M, const std::string &FS, bool is64Bit)
   , MaxInlineSizeThreshold(128)
   , Is64Bit(is64Bit)
   , TargetType(isELF) { // Default to ELF unless otherwise specified.
+
+  // default to hard float ABI
+  if (FloatABIType == FloatABI::Default)
+    FloatABIType = FloatABI::Hard;
     
   // Determine default and user specified characteristics
   if (!FS.empty()) {