diff options
author | Chris Lattner <sabre@nondot.org> | 2008-03-17 05:41:48 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2008-03-17 05:41:48 +0000 |
commit | c9d7b7de5f161cae49deb35b40eab9874e965c67 (patch) | |
tree | 3232586e09557d7cd98b76ba534cb3e25a4fd8f7 /lib/Target | |
parent | 36d23448afb1da985a0a8f6df34e4c0334253732 (diff) | |
download | external_llvm-c9d7b7de5f161cae49deb35b40eab9874e965c67.zip external_llvm-c9d7b7de5f161cae49deb35b40eab9874e965c67.tar.gz external_llvm-c9d7b7de5f161cae49deb35b40eab9874e965c67.tar.bz2 |
Start moving sparc to use SparcCallingConv.td, switching over
return lowering first. This fixes a bug where the top and bottom
of i64 values were returned in the wrong registers before.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@48443 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target')
-rw-r--r-- | lib/Target/Sparc/Makefile | 2 | ||||
-rw-r--r-- | lib/Target/Sparc/Sparc.td | 8 | ||||
-rw-r--r-- | lib/Target/Sparc/SparcCallingConv.td | 23 | ||||
-rw-r--r-- | lib/Target/Sparc/SparcISelLowering.cpp | 531 |
4 files changed, 291 insertions, 273 deletions
diff --git a/lib/Target/Sparc/Makefile b/lib/Target/Sparc/Makefile index a1b1054..69a4cf2 100644 --- a/lib/Target/Sparc/Makefile +++ b/lib/Target/Sparc/Makefile @@ -14,7 +14,7 @@ TARGET = Sparc BUILT_SOURCES = SparcGenRegisterInfo.h.inc SparcGenRegisterNames.inc \ SparcGenRegisterInfo.inc SparcGenInstrNames.inc \ SparcGenInstrInfo.inc SparcGenAsmWriter.inc \ - SparcGenDAGISel.inc SparcGenSubtarget.inc + SparcGenDAGISel.inc SparcGenSubtarget.inc SparcGenCallingConv.inc include $(LEVEL)/Makefile.common diff --git a/lib/Target/Sparc/Sparc.td b/lib/Target/Sparc/Sparc.td index b92ce23..b90fcde 100644 --- a/lib/Target/Sparc/Sparc.td +++ b/lib/Target/Sparc/Sparc.td @@ -31,15 +31,11 @@ def FeatureVIS "Enable UltraSPARC Visual Instruction Set extensions">; //===----------------------------------------------------------------------===// -// Register File Description +// Register File, Calling Conv, Instruction Descriptions //===----------------------------------------------------------------------===// include "SparcRegisterInfo.td" - -//===----------------------------------------------------------------------===// -// Instruction Descriptions -//===----------------------------------------------------------------------===// - +include "SparcCallingConv.td" include "SparcInstrInfo.td" def SparcInstrInfo : InstrInfo { diff --git a/lib/Target/Sparc/SparcCallingConv.td b/lib/Target/Sparc/SparcCallingConv.td new file mode 100644 index 0000000..02d2439 --- /dev/null +++ b/lib/Target/Sparc/SparcCallingConv.td @@ -0,0 +1,23 @@ +//===- SparcCallingConv.td - Calling Conventions Sparc -----*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This describes the calling conventions for the Sparc architectures. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Return Value Calling Conventions +//===----------------------------------------------------------------------===// + +// Sparc 32-bit C return-value convention. +def RetCC_Sparc32 : CallingConv<[ + CCIfType<[i32], CCAssignToReg<[I0, I1]>>, + CCIfType<[f32], CCAssignToReg<[F0]>>, + CCIfType<[f64], CCAssignToReg<[D0]>> +]>; diff --git a/lib/Target/Sparc/SparcISelLowering.cpp b/lib/Target/Sparc/SparcISelLowering.cpp index aceb023..e3674f4 100644 --- a/lib/Target/Sparc/SparcISelLowering.cpp +++ b/lib/Target/Sparc/SparcISelLowering.cpp @@ -14,8 +14,8 @@ #include "SparcISelLowering.h" #include "SparcTargetMachine.h" -#include "llvm/DerivedTypes.h" #include "llvm/Function.h" +#include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -23,228 +23,52 @@ #include "llvm/CodeGen/SelectionDAG.h" using namespace llvm; + //===----------------------------------------------------------------------===// -// TargetLowering Implementation +// Calling Convention Implementation //===----------------------------------------------------------------------===// -/// IntCondCCodeToICC - Convert a DAG integer condition code to a SPARC ICC -/// condition. -static SPCC::CondCodes IntCondCCodeToICC(ISD::CondCode CC) { - switch (CC) { - default: assert(0 && "Unknown integer condition code!"); - case ISD::SETEQ: return SPCC::ICC_E; - case ISD::SETNE: return SPCC::ICC_NE; - case ISD::SETLT: return SPCC::ICC_L; - case ISD::SETGT: return SPCC::ICC_G; - case ISD::SETLE: return SPCC::ICC_LE; - case ISD::SETGE: return SPCC::ICC_GE; - case ISD::SETULT: return SPCC::ICC_CS; - case ISD::SETULE: return SPCC::ICC_LEU; - case ISD::SETUGT: return SPCC::ICC_GU; - case ISD::SETUGE: return SPCC::ICC_CC; - } -} +#include "SparcGenCallingConv.inc" -/// FPCondCCodeToFCC - Convert a DAG floatingp oint condition code to a SPARC -/// FCC condition. -static SPCC::CondCodes FPCondCCodeToFCC(ISD::CondCode CC) { - switch (CC) { - default: assert(0 && "Unknown fp condition code!"); - case ISD::SETEQ: - case ISD::SETOEQ: return SPCC::FCC_E; - case ISD::SETNE: - case ISD::SETUNE: return SPCC::FCC_NE; - case ISD::SETLT: - case ISD::SETOLT: return SPCC::FCC_L; - case ISD::SETGT: - case ISD::SETOGT: return SPCC::FCC_G; - case ISD::SETLE: - case ISD::SETOLE: return SPCC::FCC_LE; - case ISD::SETGE: - case ISD::SETOGE: return SPCC::FCC_GE; - case ISD::SETULT: return SPCC::FCC_UL; - case ISD::SETULE: return SPCC::FCC_ULE; - case ISD::SETUGT: return SPCC::FCC_UG; - case ISD::SETUGE: return SPCC::FCC_UGE; - case ISD::SETUO: return SPCC::FCC_U; - case ISD::SETO: return SPCC::FCC_O; - case ISD::SETONE: return SPCC::FCC_LG; - case ISD::SETUEQ: return SPCC::FCC_UE; +static SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG) { + // CCValAssign - represent the assignment of the return value to locations. + SmallVector<CCValAssign, 16> RVLocs; + unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv(); + bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg(); + + // CCState - Info about the registers and stack slot. + CCState CCInfo(CC, isVarArg, DAG.getTarget(), RVLocs); + + // Analize return values of ISD::RET + CCInfo.AnalyzeReturn(Op.Val, RetCC_Sparc32); + + // If this is the first return lowered for this function, add the regs to the + // liveout set for the function. + if (DAG.getMachineFunction().getRegInfo().liveout_empty()) { + for (unsigned i = 0; i != RVLocs.size(); ++i) + if (RVLocs[i].isRegLoc()) + DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg()); } -} - - -SparcTargetLowering::SparcTargetLowering(TargetMachine &TM) - : TargetLowering(TM) { - // Set up the register classes. - addRegisterClass(MVT::i32, SP::IntRegsRegisterClass); - addRegisterClass(MVT::f32, SP::FPRegsRegisterClass); - addRegisterClass(MVT::f64, SP::DFPRegsRegisterClass); - - // Turn FP extload into load/fextend - setLoadXAction(ISD::EXTLOAD, MVT::f32, Expand); - // Sparc doesn't have i1 sign extending load - setLoadXAction(ISD::SEXTLOAD, MVT::i1, Promote); - // Turn FP truncstore into trunc + store. - setTruncStoreAction(MVT::f64, MVT::f32, Expand); - - // Custom legalize GlobalAddress nodes into LO/HI parts. - setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); - setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom); - setOperationAction(ISD::ConstantPool , MVT::i32, Custom); - - // Sparc doesn't have sext_inreg, replace them with shl/sra - setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand); - setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8 , Expand); - setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1 , Expand); - - // Sparc has no REM or DIVREM operations. - setOperationAction(ISD::UREM, MVT::i32, Expand); - setOperationAction(ISD::SREM, MVT::i32, Expand); - setOperationAction(ISD::SDIVREM, MVT::i32, Expand); - setOperationAction(ISD::UDIVREM, MVT::i32, Expand); - - // Custom expand fp<->sint - setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); - setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom); - - // Expand fp<->uint - setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand); - setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand); - - setOperationAction(ISD::BIT_CONVERT, MVT::f32, Expand); - setOperationAction(ISD::BIT_CONVERT, MVT::i32, Expand); - - // Sparc has no select or setcc: expand to SELECT_CC. - setOperationAction(ISD::SELECT, MVT::i32, Expand); - setOperationAction(ISD::SELECT, MVT::f32, Expand); - setOperationAction(ISD::SELECT, MVT::f64, Expand); - setOperationAction(ISD::SETCC, MVT::i32, Expand); - setOperationAction(ISD::SETCC, MVT::f32, Expand); - setOperationAction(ISD::SETCC, MVT::f64, Expand); - - // Sparc doesn't have BRCOND either, it has BR_CC. - setOperationAction(ISD::BRCOND, MVT::Other, Expand); - setOperationAction(ISD::BRIND, MVT::Other, Expand); - setOperationAction(ISD::BR_JT, MVT::Other, Expand); - setOperationAction(ISD::BR_CC, MVT::i32, Custom); - setOperationAction(ISD::BR_CC, MVT::f32, Custom); - setOperationAction(ISD::BR_CC, MVT::f64, Custom); - - setOperationAction(ISD::SELECT_CC, MVT::i32, Custom); - setOperationAction(ISD::SELECT_CC, MVT::f32, Custom); - setOperationAction(ISD::SELECT_CC, MVT::f64, Custom); - - // SPARC has no intrinsics for these particular operations. - setOperationAction(ISD::MEMMOVE, MVT::Other, Expand); - setOperationAction(ISD::MEMSET, MVT::Other, Expand); - setOperationAction(ISD::MEMCPY, MVT::Other, Expand); - setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand); - - setOperationAction(ISD::FSIN , MVT::f64, Expand); - setOperationAction(ISD::FCOS , MVT::f64, Expand); - setOperationAction(ISD::FREM , MVT::f64, Expand); - setOperationAction(ISD::FSIN , MVT::f32, Expand); - setOperationAction(ISD::FCOS , MVT::f32, Expand); - setOperationAction(ISD::FREM , MVT::f32, Expand); - setOperationAction(ISD::CTPOP, MVT::i32, Expand); - setOperationAction(ISD::CTTZ , MVT::i32, Expand); - setOperationAction(ISD::CTLZ , MVT::i32, Expand); - setOperationAction(ISD::ROTL , MVT::i32, Expand); - setOperationAction(ISD::ROTR , MVT::i32, Expand); - setOperationAction(ISD::BSWAP, MVT::i32, Expand); - setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand); - setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand); - setOperationAction(ISD::FPOW , MVT::f64, Expand); - setOperationAction(ISD::FPOW , MVT::f32, Expand); - - setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); - setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); - setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); + SDOperand Chain = Op.getOperand(0); + SDOperand Flag; - // FIXME: Sparc provides these multiplies, but we don't have them yet. - setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand); + // Copy the result values into the output registers. + for (unsigned i = 0; i != RVLocs.size(); ++i) { + CCValAssign &VA = RVLocs[i]; + assert(VA.isRegLoc() && "Can only return in registers!"); - // We don't have line number support yet. - setOperationAction(ISD::LOCATION, MVT::Other, Expand); - setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand); - setOperationAction(ISD::LABEL, MVT::Other, Expand); - - // RET must be custom lowered, to meet ABI requirements - setOperationAction(ISD::RET , MVT::Other, Custom); - - // VASTART needs to be custom lowered to use the VarArgsFrameIndex. - setOperationAction(ISD::VASTART , MVT::Other, Custom); - // VAARG needs to be lowered to not do unaligned accesses for doubles. - setOperationAction(ISD::VAARG , MVT::Other, Custom); - - // Use the default implementation. - setOperationAction(ISD::VACOPY , MVT::Other, Expand); - setOperationAction(ISD::VAEND , MVT::Other, Expand); - setOperationAction(ISD::STACKSAVE , MVT::Other, Expand); - setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand); - setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Custom); - - // No debug info support yet. - setOperationAction(ISD::LOCATION, MVT::Other, Expand); - setOperationAction(ISD::LABEL, MVT::Other, Expand); - setOperationAction(ISD::DECLARE, MVT::Other, Expand); + // ISD::RET => ret chain, (regnum1,val1), ... + // So i*2+1 index only the regnums. + Chain = DAG.getCopyToReg(Chain, VA.getLocReg(), Op.getOperand(i*2+1), Flag); - setStackPointerRegisterToSaveRestore(SP::O6); - - if (TM.getSubtarget<SparcSubtarget>().isV9()) - setOperationAction(ISD::CTPOP, MVT::i32, Legal); - - computeRegisterProperties(); -} - -const char *SparcTargetLowering::getTargetNodeName(unsigned Opcode) const { - switch (Opcode) { - default: return 0; - case SPISD::CMPICC: return "SPISD::CMPICC"; - case SPISD::CMPFCC: return "SPISD::CMPFCC"; - case SPISD::BRICC: return "SPISD::BRICC"; - case SPISD::BRFCC: return "SPISD::BRFCC"; - case SPISD::SELECT_ICC: return "SPISD::SELECT_ICC"; - case SPISD::SELECT_FCC: return "SPISD::SELECT_FCC"; - case SPISD::Hi: return "SPISD::Hi"; - case SPISD::Lo: return "SPISD::Lo"; - case SPISD::FTOI: return "SPISD::FTOI"; - case SPISD::ITOF: return "SPISD::ITOF"; - case SPISD::CALL: return "SPISD::CALL"; - case SPISD::RET_FLAG: return "SPISD::RET_FLAG"; + // Guarantee that all emitted copies are stuck together with flags. + Flag = Chain.getValue(1); } -} - -/// isMaskedValueZeroForTargetNode - Return true if 'Op & Mask' is known to -/// be zero. Op is expected to be a target specific node. Used by DAG -/// combiner. -void SparcTargetLowering::computeMaskedBitsForTargetNode(const SDOperand Op, - const APInt &Mask, - APInt &KnownZero, - APInt &KnownOne, - const SelectionDAG &DAG, - unsigned Depth) const { - APInt KnownZero2, KnownOne2; - KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0); // Don't know anything. - switch (Op.getOpcode()) { - default: break; - case SPISD::SELECT_ICC: - case SPISD::SELECT_FCC: - DAG.ComputeMaskedBits(Op.getOperand(1), Mask, KnownZero, KnownOne, - Depth+1); - DAG.ComputeMaskedBits(Op.getOperand(0), Mask, KnownZero2, KnownOne2, - Depth+1); - assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); - assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); - - // Only known if known in both the LHS and RHS. - KnownOne &= KnownOne2; - KnownZero &= KnownZero2; - break; - } + if (Flag.Val) + return DAG.getNode(SPISD::RET_FLAG, MVT::Other, Chain, Flag); + return DAG.getNode(SPISD::RET_FLAG, MVT::Other, Chain); } /// LowerArguments - V8 uses a very simple ABI, where all values are passed in @@ -387,7 +211,7 @@ SparcTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) { } // Store remaining ArgRegs to the stack if this is a varargs function. - if (F.getFunctionType()->isVarArg()) { + if (F.isVarArg()) { // Remember the vararg offset for the va_start implementation. VarArgsFrameOffset = ArgOffset; @@ -408,28 +232,6 @@ SparcTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) { DAG.setRoot(DAG.getNode(ISD::TokenFactor, MVT::Other, &OutChains[0], OutChains.size())); - // Finally, inform the code generator which regs we return values in. - switch (getValueType(F.getReturnType())) { - default: assert(0 && "Unknown type!"); - case MVT::isVoid: break; - case MVT::i1: - case MVT::i8: - case MVT::i16: - case MVT::i32: - MF.getRegInfo().addLiveOut(SP::I0); - break; - case MVT::i64: - MF.getRegInfo().addLiveOut(SP::I0); - MF.getRegInfo().addLiveOut(SP::I1); - break; - case MVT::f32: - MF.getRegInfo().addLiveOut(SP::F0); - break; - case MVT::f64: - MF.getRegInfo().addLiveOut(SP::D0); - break; - } - return ArgValues; } @@ -589,6 +391,7 @@ SparcTargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy, InFlag = Chain.getValue(1); MVT::ValueType RetTyVT = getValueType(RetTy); + SDOperand RetVal; if (RetTyVT != MVT::isVoid) { switch (RetTyVT) { @@ -642,6 +445,232 @@ SparcTargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy, return std::make_pair(RetVal, Chain); } + + +//===----------------------------------------------------------------------===// +// TargetLowering Implementation +//===----------------------------------------------------------------------===// + +/// IntCondCCodeToICC - Convert a DAG integer condition code to a SPARC ICC +/// condition. +static SPCC::CondCodes IntCondCCodeToICC(ISD::CondCode CC) { + switch (CC) { + default: assert(0 && "Unknown integer condition code!"); + case ISD::SETEQ: return SPCC::ICC_E; + case ISD::SETNE: return SPCC::ICC_NE; + case ISD::SETLT: return SPCC::ICC_L; + case ISD::SETGT: return SPCC::ICC_G; + case ISD::SETLE: return SPCC::ICC_LE; + case ISD::SETGE: return SPCC::ICC_GE; + case ISD::SETULT: return SPCC::ICC_CS; + case ISD::SETULE: return SPCC::ICC_LEU; + case ISD::SETUGT: return SPCC::ICC_GU; + case ISD::SETUGE: return SPCC::ICC_CC; + } +} + +/// FPCondCCodeToFCC - Convert a DAG floatingp oint condition code to a SPARC +/// FCC condition. +static SPCC::CondCodes FPCondCCodeToFCC(ISD::CondCode CC) { + switch (CC) { + default: assert(0 && "Unknown fp condition code!"); + case ISD::SETEQ: + case ISD::SETOEQ: return SPCC::FCC_E; + case ISD::SETNE: + case ISD::SETUNE: return SPCC::FCC_NE; + case ISD::SETLT: + case ISD::SETOLT: return SPCC::FCC_L; + case ISD::SETGT: + case ISD::SETOGT: return SPCC::FCC_G; + case ISD::SETLE: + case ISD::SETOLE: return SPCC::FCC_LE; + case ISD::SETGE: + case ISD::SETOGE: return SPCC::FCC_GE; + case ISD::SETULT: return SPCC::FCC_UL; + case ISD::SETULE: return SPCC::FCC_ULE; + case ISD::SETUGT: return SPCC::FCC_UG; + case ISD::SETUGE: return SPCC::FCC_UGE; + case ISD::SETUO: return SPCC::FCC_U; + case ISD::SETO: return SPCC::FCC_O; + case ISD::SETONE: return SPCC::FCC_LG; + case ISD::SETUEQ: return SPCC::FCC_UE; + } +} + + +SparcTargetLowering::SparcTargetLowering(TargetMachine &TM) + : TargetLowering(TM) { + + // Set up the register classes. + addRegisterClass(MVT::i32, SP::IntRegsRegisterClass); + addRegisterClass(MVT::f32, SP::FPRegsRegisterClass); + addRegisterClass(MVT::f64, SP::DFPRegsRegisterClass); + + // Turn FP extload into load/fextend + setLoadXAction(ISD::EXTLOAD, MVT::f32, Expand); + // Sparc doesn't have i1 sign extending load + setLoadXAction(ISD::SEXTLOAD, MVT::i1, Promote); + // Turn FP truncstore into trunc + store. + setTruncStoreAction(MVT::f64, MVT::f32, Expand); + + // Custom legalize GlobalAddress nodes into LO/HI parts. + setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); + setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom); + setOperationAction(ISD::ConstantPool , MVT::i32, Custom); + + // Sparc doesn't have sext_inreg, replace them with shl/sra + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand); + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8 , Expand); + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1 , Expand); + + // Sparc has no REM or DIVREM operations. + setOperationAction(ISD::UREM, MVT::i32, Expand); + setOperationAction(ISD::SREM, MVT::i32, Expand); + setOperationAction(ISD::SDIVREM, MVT::i32, Expand); + setOperationAction(ISD::UDIVREM, MVT::i32, Expand); + + // Custom expand fp<->sint + setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); + setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom); + + // Expand fp<->uint + setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand); + setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand); + + setOperationAction(ISD::BIT_CONVERT, MVT::f32, Expand); + setOperationAction(ISD::BIT_CONVERT, MVT::i32, Expand); + + // Sparc has no select or setcc: expand to SELECT_CC. + setOperationAction(ISD::SELECT, MVT::i32, Expand); + setOperationAction(ISD::SELECT, MVT::f32, Expand); + setOperationAction(ISD::SELECT, MVT::f64, Expand); + setOperationAction(ISD::SETCC, MVT::i32, Expand); + setOperationAction(ISD::SETCC, MVT::f32, Expand); + setOperationAction(ISD::SETCC, MVT::f64, Expand); + + // Sparc doesn't have BRCOND either, it has BR_CC. + setOperationAction(ISD::BRCOND, MVT::Other, Expand); + setOperationAction(ISD::BRIND, MVT::Other, Expand); + setOperationAction(ISD::BR_JT, MVT::Other, Expand); + setOperationAction(ISD::BR_CC, MVT::i32, Custom); + setOperationAction(ISD::BR_CC, MVT::f32, Custom); + setOperationAction(ISD::BR_CC, MVT::f64, Custom); + + setOperationAction(ISD::SELECT_CC, MVT::i32, Custom); + setOperationAction(ISD::SELECT_CC, MVT::f32, Custom); + setOperationAction(ISD::SELECT_CC, MVT::f64, Custom); + + // SPARC has no intrinsics for these particular operations. + setOperationAction(ISD::MEMMOVE, MVT::Other, Expand); + setOperationAction(ISD::MEMSET, MVT::Other, Expand); + setOperationAction(ISD::MEMCPY, MVT::Other, Expand); + setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand); + + setOperationAction(ISD::FSIN , MVT::f64, Expand); + setOperationAction(ISD::FCOS , MVT::f64, Expand); + setOperationAction(ISD::FREM , MVT::f64, Expand); + setOperationAction(ISD::FSIN , MVT::f32, Expand); + setOperationAction(ISD::FCOS , MVT::f32, Expand); + setOperationAction(ISD::FREM , MVT::f32, Expand); + setOperationAction(ISD::CTPOP, MVT::i32, Expand); + setOperationAction(ISD::CTTZ , MVT::i32, Expand); + setOperationAction(ISD::CTLZ , MVT::i32, Expand); + setOperationAction(ISD::ROTL , MVT::i32, Expand); + setOperationAction(ISD::ROTR , MVT::i32, Expand); + setOperationAction(ISD::BSWAP, MVT::i32, Expand); + setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand); + setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand); + setOperationAction(ISD::FPOW , MVT::f64, Expand); + setOperationAction(ISD::FPOW , MVT::f32, Expand); + + setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); + setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); + setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); + + // FIXME: Sparc provides these multiplies, but we don't have them yet. + setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand); + + // We don't have line number support yet. + setOperationAction(ISD::LOCATION, MVT::Other, Expand); + setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand); + setOperationAction(ISD::LABEL, MVT::Other, Expand); + + // RET must be custom lowered, to meet ABI requirements + setOperationAction(ISD::RET , MVT::Other, Custom); + + // VASTART needs to be custom lowered to use the VarArgsFrameIndex. + setOperationAction(ISD::VASTART , MVT::Other, Custom); + // VAARG needs to be lowered to not do unaligned accesses for doubles. + setOperationAction(ISD::VAARG , MVT::Other, Custom); + + // Use the default implementation. + setOperationAction(ISD::VACOPY , MVT::Other, Expand); + setOperationAction(ISD::VAEND , MVT::Other, Expand); + setOperationAction(ISD::STACKSAVE , MVT::Other, Expand); + setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand); + setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Custom); + + // No debug info support yet. + setOperationAction(ISD::LOCATION, MVT::Other, Expand); + setOperationAction(ISD::LABEL, MVT::Other, Expand); + setOperationAction(ISD::DECLARE, MVT::Other, Expand); + + setStackPointerRegisterToSaveRestore(SP::O6); + + if (TM.getSubtarget<SparcSubtarget>().isV9()) + setOperationAction(ISD::CTPOP, MVT::i32, Legal); + + computeRegisterProperties(); +} + +const char *SparcTargetLowering::getTargetNodeName(unsigned Opcode) const { + switch (Opcode) { + default: return 0; + case SPISD::CMPICC: return "SPISD::CMPICC"; + case SPISD::CMPFCC: return "SPISD::CMPFCC"; + case SPISD::BRICC: return "SPISD::BRICC"; + case SPISD::BRFCC: return "SPISD::BRFCC"; + case SPISD::SELECT_ICC: return "SPISD::SELECT_ICC"; + case SPISD::SELECT_FCC: return "SPISD::SELECT_FCC"; + case SPISD::Hi: return "SPISD::Hi"; + case SPISD::Lo: return "SPISD::Lo"; + case SPISD::FTOI: return "SPISD::FTOI"; + case SPISD::ITOF: return "SPISD::ITOF"; + case SPISD::CALL: return "SPISD::CALL"; + case SPISD::RET_FLAG: return "SPISD::RET_FLAG"; + } +} + +/// isMaskedValueZeroForTargetNode - Return true if 'Op & Mask' is known to +/// be zero. Op is expected to be a target specific node. Used by DAG +/// combiner. +void SparcTargetLowering::computeMaskedBitsForTargetNode(const SDOperand Op, + const APInt &Mask, + APInt &KnownZero, + APInt &KnownOne, + const SelectionDAG &DAG, + unsigned Depth) const { + APInt KnownZero2, KnownOne2; + KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0); // Don't know anything. + + switch (Op.getOpcode()) { + default: break; + case SPISD::SELECT_ICC: + case SPISD::SELECT_FCC: + DAG.ComputeMaskedBits(Op.getOperand(1), Mask, KnownZero, KnownOne, + Depth+1); + DAG.ComputeMaskedBits(Op.getOperand(0), Mask, KnownZero2, KnownOne2, + Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // Only known if known in both the LHS and RHS. + KnownOne &= KnownOne2; + KnownZero &= KnownZero2; + break; + } +} + // Look at LHS/RHS/CC and see if they are a lowered setcc instruction. If so // set LHS/RHS and SPCC to the LHS/RHS of the setcc and SPCC to the condition. static void LookThroughSetCC(SDOperand &LHS, SDOperand &RHS, @@ -818,36 +847,6 @@ static SDOperand LowerDYNAMIC_STACKALLOC(SDOperand Op, SelectionDAG &DAG) { return DAG.getNode(ISD::MERGE_VALUES, Tys, Ops, 2); } -static SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG) { - SDOperand Copy; - - switch(Op.getNumOperands()) { - default: - assert(0 && "Do not know how to return this many arguments!"); - abort(); - case 1: - return SDOperand(); // ret void is legal - case 3: { - unsigned ArgReg; - switch(Op.getOperand(1).getValueType()) { - default: assert(0 && "Unknown type to return!"); - case MVT::i32: ArgReg = SP::I0; break; - case MVT::f32: ArgReg = SP::F0; break; - case MVT::f64: ArgReg = SP::D0; break; - } - Copy = DAG.getCopyToReg(Op.getOperand(0), ArgReg, Op.getOperand(1), - SDOperand()); - break; - } - case 5: - Copy = DAG.getCopyToReg(Op.getOperand(0), SP::I0, Op.getOperand(3), - SDOperand()); - Copy = DAG.getCopyToReg(Copy, SP::I1, Op.getOperand(1), Copy.getValue(1)); - break; - } - return DAG.getNode(SPISD::RET_FLAG, MVT::Other, Copy, Copy.getValue(1)); -} - SDOperand SparcTargetLowering:: LowerOperation(SDOperand Op, SelectionDAG &DAG) { @@ -945,4 +944,4 @@ SparcTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, delete MI; // The pseudo instruction is gone now. return BB; } - + |