From 0eebf653a7b2978e7761f8d068b6fbec22aea0f6 Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Mon, 8 Jun 2009 22:53:56 +0000 Subject: [PATCH] The attached patches implement most of the ARM AAPCS-VFP hard float 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 | 10 ++++- include/llvm/Target/TargetOptions.h | 8 ++++ lib/Target/ARM/ARMCallingConv.td | 60 ++++++++++++++++++++++++----- lib/Target/ARM/ARMISelDAGToDAG.cpp | 9 ++++- lib/Target/ARM/ARMISelLowering.cpp | 7 +++- lib/Target/ARM/ARMRegisterInfo.td | 15 ++++++++ lib/Target/ARM/ARMSubtarget.cpp | 6 +++ lib/Target/TargetMachine.cpp | 22 +++++++++++ lib/Target/X86/X86Subtarget.cpp | 4 ++ 9 files changed, 128 insertions(+), 13 deletions(-) diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h index bdcc4eff675..a8db68c5978 100644 --- a/include/llvm/Target/TargetMachine.h +++ b/include/llvm/Target/TargetMachine.h @@ -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. diff --git a/include/llvm/Target/TargetOptions.h b/include/llvm/Target/TargetOptions.h index 0c74fa1f2c1..377e03f95c4 100644 --- a/include/llvm/Target/TargetOptions.h +++ b/include/llvm/Target/TargetOptions.h @@ -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). diff --git a/lib/Target/ARM/ARMCallingConv.td b/lib/Target/ARM/ARMCallingConv.td index 6cd786eed4d..1c5ec5f2901 100644 --- a/lib/Target/ARM/ARMCallingConv.td +++ b/lib/Target/ARM/ARMCallingConv.td @@ -17,6 +17,11 @@ class CCIfSubtarget: class CCIfAlign: CCIf; +/// CCIfFloatABI - Match of the float ABI and the arg. ABIType may be "Hard" or +/// "Soft". +class CCIfFloatABI: + CCIf; + //===----------------------------------------------------------------------===// // 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>, @@ -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>, 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>, + CCDelegateTo +]>; + +def RetCC_ARM_AAPCS : CallingConv<[ CCIfType<[f64], CCCustom<"RetCC_ARM_AAPCS_Custom_f64">>, + CCIfType<[f32], CCBitConvertToType>, + CCDelegateTo +]>; - 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 +]>; + +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 ]>; //===----------------------------------------------------------------------===// @@ -77,11 +111,19 @@ def RetCC_ARM_AAPCS : CallingConv<[ //===----------------------------------------------------------------------===// def CC_ARM : CallingConv<[ + CCIfSubtarget<"isAAPCS_ABI()", + CCIfSubtarget<"hasVFP2()", + CCIfFloatABI<"Hard", + CCDelegateTo>>>, CCIfSubtarget<"isAAPCS_ABI()", CCDelegateTo>, CCDelegateTo ]>; def RetCC_ARM : CallingConv<[ + CCIfSubtarget<"isAAPCS_ABI()", + CCIfSubtarget<"hasVFP2()", + CCIfFloatABI<"Hard", + CCDelegateTo>>>, CCIfSubtarget<"isAAPCS_ABI()", CCDelegateTo>, CCDelegateTo ]>; diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp index ca3a9cb4032..a413ee6f3e0 100644 --- a/lib/Target/ARM/ARMISelDAGToDAG.cpp +++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -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(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; } diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index c0fd9dcd107..ec8bd1f8b31 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -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))) diff --git a/lib/Target/ARM/ARMRegisterInfo.td b/lib/Target/ARM/ARMRegisterInfo.td index b95d1f93aba..ebe7d582a66 100644 --- a/lib/Target/ARM/ARMRegisterInfo.td +++ b/lib/Target/ARM/ARMRegisterInfo.td @@ -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]>; diff --git a/lib/Target/ARM/ARMSubtarget.cpp b/lib/Target/ARM/ARMSubtarget.cpp index ef78cd52d85..a978380b627 100644 --- a/lib/Target/ARM/ARMSubtarget.cpp +++ b/lib/Target/ARM/ARMSubtarget.cpp @@ -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. diff --git a/lib/Target/TargetMachine.cpp b/lib/Target/TargetMachine.cpp index dea293b502c..c487cb80530 100644 --- a/lib/Target/TargetMachine.cpp +++ b/lib/Target/TargetMachine.cpp @@ -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 +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 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; } diff --git a/lib/Target/X86/X86Subtarget.cpp b/lib/Target/X86/X86Subtarget.cpp index 03ce1aee0e8..56983ce7f16 100644 --- a/lib/Target/X86/X86Subtarget.cpp +++ b/lib/Target/X86/X86Subtarget.cpp @@ -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()) { -- 2.34.1