| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 1 | //===-- SparcISelDAGToDAG.cpp - A dag to dag inst selector for Sparc ------===// | 
|  | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
|  | 5 | // This file was developed by Chris Lattner and is distributed under | 
|  | 6 | // the University of Illinois Open Source License. See LICENSE.TXT for details. | 
|  | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 | // | 
|  | 10 | // This file defines an instruction selector for the SPARC target. | 
|  | 11 | // | 
|  | 12 | //===----------------------------------------------------------------------===// | 
|  | 13 |  | 
|  | 14 | #include "Sparc.h" | 
|  | 15 | #include "SparcTargetMachine.h" | 
|  | 16 | #include "llvm/DerivedTypes.h" | 
|  | 17 | #include "llvm/Function.h" | 
| Chris Lattner | 5d70a7c | 2006-03-25 06:47:10 +0000 | [diff] [blame] | 18 | #include "llvm/Intrinsics.h" | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 19 | #include "llvm/CodeGen/MachineFrameInfo.h" | 
|  | 20 | #include "llvm/CodeGen/MachineFunction.h" | 
|  | 21 | #include "llvm/CodeGen/MachineInstrBuilder.h" | 
|  | 22 | #include "llvm/CodeGen/SelectionDAG.h" | 
|  | 23 | #include "llvm/CodeGen/SelectionDAGISel.h" | 
|  | 24 | #include "llvm/CodeGen/SSARegMap.h" | 
|  | 25 | #include "llvm/Target/TargetLowering.h" | 
|  | 26 | #include "llvm/Support/Debug.h" | 
| Evan Cheng | b9d34bd | 2006-08-07 22:28:20 +0000 | [diff] [blame] | 27 | #include <queue> | 
| Evan Cheng | a28b764 | 2006-02-05 06:51:51 +0000 | [diff] [blame] | 28 | #include <set> | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 29 | using namespace llvm; | 
|  | 30 |  | 
|  | 31 | //===----------------------------------------------------------------------===// | 
|  | 32 | // TargetLowering Implementation | 
|  | 33 | //===----------------------------------------------------------------------===// | 
|  | 34 |  | 
|  | 35 | namespace SPISD { | 
|  | 36 | enum { | 
|  | 37 | FIRST_NUMBER = ISD::BUILTIN_OP_END+SP::INSTRUCTION_LIST_END, | 
|  | 38 | CMPICC,      // Compare two GPR operands, set icc. | 
|  | 39 | CMPFCC,      // Compare two FP operands, set fcc. | 
|  | 40 | BRICC,       // Branch to dest on icc condition | 
|  | 41 | BRFCC,       // Branch to dest on fcc condition | 
|  | 42 | SELECT_ICC,  // Select between two values using the current ICC flags. | 
|  | 43 | SELECT_FCC,  // Select between two values using the current FCC flags. | 
|  | 44 |  | 
|  | 45 | Hi, Lo,      // Hi/Lo operations, typically on a global address. | 
|  | 46 |  | 
|  | 47 | FTOI,        // FP to Int within a FP register. | 
|  | 48 | ITOF,        // Int to FP within a FP register. | 
|  | 49 |  | 
|  | 50 | CALL,        // A call instruction. | 
| Chris Lattner | aa237256 | 2006-05-24 17:04:05 +0000 | [diff] [blame] | 51 | RET_FLAG     // Return with a flag operand. | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 52 | }; | 
|  | 53 | } | 
|  | 54 |  | 
|  | 55 | /// IntCondCCodeToICC - Convert a DAG integer condition code to a SPARC ICC | 
|  | 56 | /// condition. | 
|  | 57 | static SPCC::CondCodes IntCondCCodeToICC(ISD::CondCode CC) { | 
|  | 58 | switch (CC) { | 
|  | 59 | default: assert(0 && "Unknown integer condition code!"); | 
|  | 60 | case ISD::SETEQ:  return SPCC::ICC_E; | 
|  | 61 | case ISD::SETNE:  return SPCC::ICC_NE; | 
|  | 62 | case ISD::SETLT:  return SPCC::ICC_L; | 
|  | 63 | case ISD::SETGT:  return SPCC::ICC_G; | 
|  | 64 | case ISD::SETLE:  return SPCC::ICC_LE; | 
|  | 65 | case ISD::SETGE:  return SPCC::ICC_GE; | 
|  | 66 | case ISD::SETULT: return SPCC::ICC_CS; | 
|  | 67 | case ISD::SETULE: return SPCC::ICC_LEU; | 
|  | 68 | case ISD::SETUGT: return SPCC::ICC_GU; | 
|  | 69 | case ISD::SETUGE: return SPCC::ICC_CC; | 
|  | 70 | } | 
|  | 71 | } | 
|  | 72 |  | 
|  | 73 | /// FPCondCCodeToFCC - Convert a DAG floatingp oint condition code to a SPARC | 
|  | 74 | /// FCC condition. | 
|  | 75 | static SPCC::CondCodes FPCondCCodeToFCC(ISD::CondCode CC) { | 
|  | 76 | switch (CC) { | 
|  | 77 | default: assert(0 && "Unknown fp condition code!"); | 
| Chris Lattner | dc1614d | 2006-05-25 22:26:02 +0000 | [diff] [blame] | 78 | case ISD::SETEQ: | 
|  | 79 | case ISD::SETOEQ: return SPCC::FCC_E; | 
|  | 80 | case ISD::SETNE: | 
|  | 81 | case ISD::SETUNE: return SPCC::FCC_NE; | 
|  | 82 | case ISD::SETLT: | 
|  | 83 | case ISD::SETOLT: return SPCC::FCC_L; | 
|  | 84 | case ISD::SETGT: | 
|  | 85 | case ISD::SETOGT: return SPCC::FCC_G; | 
|  | 86 | case ISD::SETLE: | 
|  | 87 | case ISD::SETOLE: return SPCC::FCC_LE; | 
|  | 88 | case ISD::SETGE: | 
|  | 89 | case ISD::SETOGE: return SPCC::FCC_GE; | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 90 | case ISD::SETULT: return SPCC::FCC_UL; | 
|  | 91 | case ISD::SETULE: return SPCC::FCC_ULE; | 
|  | 92 | case ISD::SETUGT: return SPCC::FCC_UG; | 
|  | 93 | case ISD::SETUGE: return SPCC::FCC_UGE; | 
|  | 94 | case ISD::SETUO:  return SPCC::FCC_U; | 
|  | 95 | case ISD::SETO:   return SPCC::FCC_O; | 
|  | 96 | case ISD::SETONE: return SPCC::FCC_LG; | 
|  | 97 | case ISD::SETUEQ: return SPCC::FCC_UE; | 
|  | 98 | } | 
|  | 99 | } | 
|  | 100 |  | 
|  | 101 | namespace { | 
|  | 102 | class SparcTargetLowering : public TargetLowering { | 
|  | 103 | int VarArgsFrameOffset;   // Frame offset to start of varargs area. | 
|  | 104 | public: | 
|  | 105 | SparcTargetLowering(TargetMachine &TM); | 
|  | 106 | virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG); | 
|  | 107 |  | 
| Nate Begeman | 8a77efe | 2006-02-16 21:11:51 +0000 | [diff] [blame] | 108 | /// computeMaskedBitsForTargetNode - Determine which of the bits specified | 
|  | 109 | /// in Mask are known to be either zero or one and return them in the | 
|  | 110 | /// KnownZero/KnownOne bitsets. | 
|  | 111 | virtual void computeMaskedBitsForTargetNode(const SDOperand Op, | 
|  | 112 | uint64_t Mask, | 
|  | 113 | uint64_t &KnownZero, | 
|  | 114 | uint64_t &KnownOne, | 
|  | 115 | unsigned Depth = 0) const; | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 116 |  | 
|  | 117 | virtual std::vector<SDOperand> | 
|  | 118 | LowerArguments(Function &F, SelectionDAG &DAG); | 
|  | 119 | virtual std::pair<SDOperand, SDOperand> | 
| Reid Spencer | e63b651 | 2006-12-31 05:55:36 +0000 | [diff] [blame] | 120 | LowerCallTo(SDOperand Chain, const Type *RetTy, bool RetTyIsSigned, | 
|  | 121 | bool isVarArg, unsigned CC, bool isTailCall, SDOperand Callee, | 
|  | 122 | ArgListTy &Args, SelectionDAG &DAG); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 123 | virtual MachineBasicBlock *InsertAtEndOfBasicBlock(MachineInstr *MI, | 
|  | 124 | MachineBasicBlock *MBB); | 
|  | 125 |  | 
|  | 126 | virtual const char *getTargetNodeName(unsigned Opcode) const; | 
|  | 127 | }; | 
|  | 128 | } | 
|  | 129 |  | 
|  | 130 | SparcTargetLowering::SparcTargetLowering(TargetMachine &TM) | 
|  | 131 | : TargetLowering(TM) { | 
|  | 132 |  | 
|  | 133 | // Set up the register classes. | 
|  | 134 | addRegisterClass(MVT::i32, SP::IntRegsRegisterClass); | 
|  | 135 | addRegisterClass(MVT::f32, SP::FPRegsRegisterClass); | 
|  | 136 | addRegisterClass(MVT::f64, SP::DFPRegsRegisterClass); | 
|  | 137 |  | 
| Evan Cheng | 5d9fd97 | 2006-10-04 00:56:09 +0000 | [diff] [blame] | 138 | // Turn FP extload into load/fextend | 
|  | 139 | setLoadXAction(ISD::EXTLOAD, MVT::f32, Expand); | 
|  | 140 |  | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 141 | // Custom legalize GlobalAddress nodes into LO/HI parts. | 
|  | 142 | setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); | 
|  | 143 | setOperationAction(ISD::ConstantPool , MVT::i32, Custom); | 
|  | 144 |  | 
|  | 145 | // Sparc doesn't have sext_inreg, replace them with shl/sra | 
|  | 146 | setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand); | 
|  | 147 | setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8 , Expand); | 
|  | 148 | setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1 , Expand); | 
|  | 149 |  | 
|  | 150 | // Sparc has no REM operation. | 
|  | 151 | setOperationAction(ISD::UREM, MVT::i32, Expand); | 
|  | 152 | setOperationAction(ISD::SREM, MVT::i32, Expand); | 
|  | 153 |  | 
|  | 154 | // Custom expand fp<->sint | 
|  | 155 | setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); | 
|  | 156 | setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom); | 
|  | 157 |  | 
|  | 158 | // Expand fp<->uint | 
|  | 159 | setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand); | 
|  | 160 | setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand); | 
|  | 161 |  | 
|  | 162 | setOperationAction(ISD::BIT_CONVERT, MVT::f32, Expand); | 
|  | 163 | setOperationAction(ISD::BIT_CONVERT, MVT::i32, Expand); | 
|  | 164 |  | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 165 | // Sparc has no select or setcc: expand to SELECT_CC. | 
|  | 166 | setOperationAction(ISD::SELECT, MVT::i32, Expand); | 
|  | 167 | setOperationAction(ISD::SELECT, MVT::f32, Expand); | 
|  | 168 | setOperationAction(ISD::SELECT, MVT::f64, Expand); | 
|  | 169 | setOperationAction(ISD::SETCC, MVT::i32, Expand); | 
|  | 170 | setOperationAction(ISD::SETCC, MVT::f32, Expand); | 
|  | 171 | setOperationAction(ISD::SETCC, MVT::f64, Expand); | 
|  | 172 |  | 
|  | 173 | // Sparc doesn't have BRCOND either, it has BR_CC. | 
|  | 174 | setOperationAction(ISD::BRCOND, MVT::Other, Expand); | 
| Evan Cheng | 0d41d19 | 2006-10-30 08:02:39 +0000 | [diff] [blame] | 175 | setOperationAction(ISD::BRIND, MVT::Other, Expand); | 
|  | 176 | setOperationAction(ISD::BR_JT, MVT::Other, Expand); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 177 | setOperationAction(ISD::BR_CC, MVT::i32, Custom); | 
|  | 178 | setOperationAction(ISD::BR_CC, MVT::f32, Custom); | 
|  | 179 | setOperationAction(ISD::BR_CC, MVT::f64, Custom); | 
|  | 180 |  | 
|  | 181 | setOperationAction(ISD::SELECT_CC, MVT::i32, Custom); | 
|  | 182 | setOperationAction(ISD::SELECT_CC, MVT::f32, Custom); | 
|  | 183 | setOperationAction(ISD::SELECT_CC, MVT::f64, Custom); | 
|  | 184 |  | 
|  | 185 | // SPARC has no intrinsics for these particular operations. | 
|  | 186 | setOperationAction(ISD::MEMMOVE, MVT::Other, Expand); | 
|  | 187 | setOperationAction(ISD::MEMSET, MVT::Other, Expand); | 
|  | 188 | setOperationAction(ISD::MEMCPY, MVT::Other, Expand); | 
|  | 189 |  | 
|  | 190 | setOperationAction(ISD::FSIN , MVT::f64, Expand); | 
|  | 191 | setOperationAction(ISD::FCOS , MVT::f64, Expand); | 
|  | 192 | setOperationAction(ISD::FSIN , MVT::f32, Expand); | 
|  | 193 | setOperationAction(ISD::FCOS , MVT::f32, Expand); | 
|  | 194 | setOperationAction(ISD::CTPOP, MVT::i32, Expand); | 
|  | 195 | setOperationAction(ISD::CTTZ , MVT::i32, Expand); | 
|  | 196 | setOperationAction(ISD::CTLZ , MVT::i32, Expand); | 
|  | 197 | setOperationAction(ISD::ROTL , MVT::i32, Expand); | 
|  | 198 | setOperationAction(ISD::ROTR , MVT::i32, Expand); | 
|  | 199 | setOperationAction(ISD::BSWAP, MVT::i32, Expand); | 
| Chris Lattner | 9c7f503 | 2006-03-05 05:08:37 +0000 | [diff] [blame] | 200 | setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand); | 
|  | 201 | setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 202 |  | 
|  | 203 | setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); | 
|  | 204 | setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); | 
|  | 205 | setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); | 
|  | 206 |  | 
|  | 207 | // We don't have line number support yet. | 
|  | 208 | setOperationAction(ISD::LOCATION, MVT::Other, Expand); | 
|  | 209 | setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand); | 
| Jim Laskey | f9e5445 | 2007-01-26 14:34:52 +0000 | [diff] [blame] | 210 | setOperationAction(ISD::LABEL, MVT::Other, Expand); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 211 |  | 
|  | 212 | // RET must be custom lowered, to meet ABI requirements | 
|  | 213 | setOperationAction(ISD::RET               , MVT::Other, Custom); | 
|  | 214 |  | 
|  | 215 | // VASTART needs to be custom lowered to use the VarArgsFrameIndex. | 
|  | 216 | setOperationAction(ISD::VASTART           , MVT::Other, Custom); | 
|  | 217 | // VAARG needs to be lowered to not do unaligned accesses for doubles. | 
|  | 218 | setOperationAction(ISD::VAARG             , MVT::Other, Custom); | 
|  | 219 |  | 
|  | 220 | // Use the default implementation. | 
|  | 221 | setOperationAction(ISD::VACOPY            , MVT::Other, Expand); | 
|  | 222 | setOperationAction(ISD::VAEND             , MVT::Other, Expand); | 
|  | 223 | setOperationAction(ISD::STACKSAVE         , MVT::Other, Expand); | 
|  | 224 | setOperationAction(ISD::STACKRESTORE      , MVT::Other, Expand); | 
| Chris Lattner | a9d0b58 | 2006-02-15 06:41:34 +0000 | [diff] [blame] | 225 | setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32  , Custom); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 226 |  | 
|  | 227 | setOperationAction(ISD::ConstantFP, MVT::f64, Expand); | 
|  | 228 | setOperationAction(ISD::ConstantFP, MVT::f32, Expand); | 
|  | 229 |  | 
|  | 230 | setStackPointerRegisterToSaveRestore(SP::O6); | 
|  | 231 |  | 
|  | 232 | if (TM.getSubtarget<SparcSubtarget>().isV9()) { | 
|  | 233 | setOperationAction(ISD::CTPOP, MVT::i32, Legal); | 
|  | 234 | } | 
|  | 235 |  | 
|  | 236 | computeRegisterProperties(); | 
|  | 237 | } | 
|  | 238 |  | 
|  | 239 | const char *SparcTargetLowering::getTargetNodeName(unsigned Opcode) const { | 
|  | 240 | switch (Opcode) { | 
|  | 241 | default: return 0; | 
|  | 242 | case SPISD::CMPICC:     return "SPISD::CMPICC"; | 
|  | 243 | case SPISD::CMPFCC:     return "SPISD::CMPFCC"; | 
|  | 244 | case SPISD::BRICC:      return "SPISD::BRICC"; | 
|  | 245 | case SPISD::BRFCC:      return "SPISD::BRFCC"; | 
|  | 246 | case SPISD::SELECT_ICC: return "SPISD::SELECT_ICC"; | 
|  | 247 | case SPISD::SELECT_FCC: return "SPISD::SELECT_FCC"; | 
|  | 248 | case SPISD::Hi:         return "SPISD::Hi"; | 
|  | 249 | case SPISD::Lo:         return "SPISD::Lo"; | 
|  | 250 | case SPISD::FTOI:       return "SPISD::FTOI"; | 
|  | 251 | case SPISD::ITOF:       return "SPISD::ITOF"; | 
|  | 252 | case SPISD::CALL:       return "SPISD::CALL"; | 
|  | 253 | case SPISD::RET_FLAG:   return "SPISD::RET_FLAG"; | 
|  | 254 | } | 
|  | 255 | } | 
|  | 256 |  | 
|  | 257 | /// isMaskedValueZeroForTargetNode - Return true if 'Op & Mask' is known to | 
|  | 258 | /// be zero. Op is expected to be a target specific node. Used by DAG | 
|  | 259 | /// combiner. | 
| Nate Begeman | 8a77efe | 2006-02-16 21:11:51 +0000 | [diff] [blame] | 260 | void SparcTargetLowering::computeMaskedBitsForTargetNode(const SDOperand Op, | 
|  | 261 | uint64_t Mask, | 
|  | 262 | uint64_t &KnownZero, | 
|  | 263 | uint64_t &KnownOne, | 
|  | 264 | unsigned Depth) const { | 
|  | 265 | uint64_t KnownZero2, KnownOne2; | 
|  | 266 | KnownZero = KnownOne = 0;   // Don't know anything. | 
|  | 267 |  | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 268 | switch (Op.getOpcode()) { | 
| Nate Begeman | 8a77efe | 2006-02-16 21:11:51 +0000 | [diff] [blame] | 269 | default: break; | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 270 | case SPISD::SELECT_ICC: | 
|  | 271 | case SPISD::SELECT_FCC: | 
| Nate Begeman | 8a77efe | 2006-02-16 21:11:51 +0000 | [diff] [blame] | 272 | ComputeMaskedBits(Op.getOperand(1), Mask, KnownZero, KnownOne, Depth+1); | 
|  | 273 | ComputeMaskedBits(Op.getOperand(0), Mask, KnownZero2, KnownOne2, Depth+1); | 
|  | 274 | assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); | 
|  | 275 | assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); | 
|  | 276 |  | 
|  | 277 | // Only known if known in both the LHS and RHS. | 
|  | 278 | KnownOne &= KnownOne2; | 
|  | 279 | KnownZero &= KnownZero2; | 
|  | 280 | break; | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 281 | } | 
|  | 282 | } | 
|  | 283 |  | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 284 | /// LowerArguments - V8 uses a very simple ABI, where all values are passed in | 
|  | 285 | /// either one or two GPRs, including FP values.  TODO: we should pass FP values | 
|  | 286 | /// in FP registers for fastcc functions. | 
|  | 287 | std::vector<SDOperand> | 
|  | 288 | SparcTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) { | 
|  | 289 | MachineFunction &MF = DAG.getMachineFunction(); | 
|  | 290 | SSARegMap *RegMap = MF.getSSARegMap(); | 
|  | 291 | std::vector<SDOperand> ArgValues; | 
|  | 292 |  | 
|  | 293 | static const unsigned ArgRegs[] = { | 
|  | 294 | SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5 | 
|  | 295 | }; | 
|  | 296 |  | 
|  | 297 | const unsigned *CurArgReg = ArgRegs, *ArgRegEnd = ArgRegs+6; | 
|  | 298 | unsigned ArgOffset = 68; | 
|  | 299 |  | 
|  | 300 | SDOperand Root = DAG.getRoot(); | 
|  | 301 | std::vector<SDOperand> OutChains; | 
|  | 302 |  | 
|  | 303 | for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) { | 
|  | 304 | MVT::ValueType ObjectVT = getValueType(I->getType()); | 
|  | 305 |  | 
|  | 306 | switch (ObjectVT) { | 
|  | 307 | default: assert(0 && "Unhandled argument type!"); | 
|  | 308 | case MVT::i1: | 
|  | 309 | case MVT::i8: | 
|  | 310 | case MVT::i16: | 
|  | 311 | case MVT::i32: | 
|  | 312 | if (I->use_empty()) {                // Argument is dead. | 
|  | 313 | if (CurArgReg < ArgRegEnd) ++CurArgReg; | 
|  | 314 | ArgValues.push_back(DAG.getNode(ISD::UNDEF, ObjectVT)); | 
|  | 315 | } else if (CurArgReg < ArgRegEnd) {  // Lives in an incoming GPR | 
|  | 316 | unsigned VReg = RegMap->createVirtualRegister(&SP::IntRegsRegClass); | 
|  | 317 | MF.addLiveIn(*CurArgReg++, VReg); | 
|  | 318 | SDOperand Arg = DAG.getCopyFromReg(Root, VReg, MVT::i32); | 
|  | 319 | if (ObjectVT != MVT::i32) { | 
| Reid Spencer | e63b651 | 2006-12-31 05:55:36 +0000 | [diff] [blame] | 320 | unsigned AssertOp = ISD::AssertSext; | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 321 | Arg = DAG.getNode(AssertOp, MVT::i32, Arg, | 
|  | 322 | DAG.getValueType(ObjectVT)); | 
|  | 323 | Arg = DAG.getNode(ISD::TRUNCATE, ObjectVT, Arg); | 
|  | 324 | } | 
|  | 325 | ArgValues.push_back(Arg); | 
|  | 326 | } else { | 
|  | 327 | int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset); | 
|  | 328 | SDOperand FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); | 
|  | 329 | SDOperand Load; | 
|  | 330 | if (ObjectVT == MVT::i32) { | 
| Evan Cheng | e71fe34d | 2006-10-09 20:57:25 +0000 | [diff] [blame] | 331 | Load = DAG.getLoad(MVT::i32, Root, FIPtr, NULL, 0); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 332 | } else { | 
| Reid Spencer | e63b651 | 2006-12-31 05:55:36 +0000 | [diff] [blame] | 333 | ISD::LoadExtType LoadOp = ISD::SEXTLOAD; | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 334 |  | 
|  | 335 | // Sparc is big endian, so add an offset based on the ObjectVT. | 
|  | 336 | unsigned Offset = 4-std::max(1U, MVT::getSizeInBits(ObjectVT)/8); | 
|  | 337 | FIPtr = DAG.getNode(ISD::ADD, MVT::i32, FIPtr, | 
|  | 338 | DAG.getConstant(Offset, MVT::i32)); | 
|  | 339 | Load = DAG.getExtLoad(LoadOp, MVT::i32, Root, FIPtr, | 
| Evan Cheng | e71fe34d | 2006-10-09 20:57:25 +0000 | [diff] [blame] | 340 | NULL, 0, ObjectVT); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 341 | Load = DAG.getNode(ISD::TRUNCATE, ObjectVT, Load); | 
|  | 342 | } | 
|  | 343 | ArgValues.push_back(Load); | 
|  | 344 | } | 
|  | 345 |  | 
|  | 346 | ArgOffset += 4; | 
|  | 347 | break; | 
|  | 348 | case MVT::f32: | 
|  | 349 | if (I->use_empty()) {                // Argument is dead. | 
|  | 350 | if (CurArgReg < ArgRegEnd) ++CurArgReg; | 
|  | 351 | ArgValues.push_back(DAG.getNode(ISD::UNDEF, ObjectVT)); | 
|  | 352 | } else if (CurArgReg < ArgRegEnd) {  // Lives in an incoming GPR | 
|  | 353 | // FP value is passed in an integer register. | 
|  | 354 | unsigned VReg = RegMap->createVirtualRegister(&SP::IntRegsRegClass); | 
|  | 355 | MF.addLiveIn(*CurArgReg++, VReg); | 
|  | 356 | SDOperand Arg = DAG.getCopyFromReg(Root, VReg, MVT::i32); | 
|  | 357 |  | 
|  | 358 | Arg = DAG.getNode(ISD::BIT_CONVERT, MVT::f32, Arg); | 
|  | 359 | ArgValues.push_back(Arg); | 
|  | 360 | } else { | 
|  | 361 | int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset); | 
|  | 362 | SDOperand FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); | 
| Evan Cheng | e71fe34d | 2006-10-09 20:57:25 +0000 | [diff] [blame] | 363 | SDOperand Load = DAG.getLoad(MVT::f32, Root, FIPtr, NULL, 0); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 364 | ArgValues.push_back(Load); | 
|  | 365 | } | 
|  | 366 | ArgOffset += 4; | 
|  | 367 | break; | 
|  | 368 |  | 
|  | 369 | case MVT::i64: | 
|  | 370 | case MVT::f64: | 
|  | 371 | if (I->use_empty()) {                // Argument is dead. | 
|  | 372 | if (CurArgReg < ArgRegEnd) ++CurArgReg; | 
|  | 373 | if (CurArgReg < ArgRegEnd) ++CurArgReg; | 
|  | 374 | ArgValues.push_back(DAG.getNode(ISD::UNDEF, ObjectVT)); | 
|  | 375 | } else if (/* FIXME: Apparently this isn't safe?? */ | 
|  | 376 | 0 && CurArgReg == ArgRegEnd && ObjectVT == MVT::f64 && | 
|  | 377 | ((CurArgReg-ArgRegs) & 1) == 0) { | 
|  | 378 | // If this is a double argument and the whole thing lives on the stack, | 
|  | 379 | // and the argument is aligned, load the double straight from the stack. | 
|  | 380 | // We can't do a load in cases like void foo([6ints], int,double), | 
|  | 381 | // because the double wouldn't be aligned! | 
|  | 382 | int FrameIdx = MF.getFrameInfo()->CreateFixedObject(8, ArgOffset); | 
|  | 383 | SDOperand FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); | 
| Evan Cheng | e71fe34d | 2006-10-09 20:57:25 +0000 | [diff] [blame] | 384 | ArgValues.push_back(DAG.getLoad(MVT::f64, Root, FIPtr, NULL, 0)); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 385 | } else { | 
|  | 386 | SDOperand HiVal; | 
|  | 387 | if (CurArgReg < ArgRegEnd) {  // Lives in an incoming GPR | 
|  | 388 | unsigned VRegHi = RegMap->createVirtualRegister(&SP::IntRegsRegClass); | 
|  | 389 | MF.addLiveIn(*CurArgReg++, VRegHi); | 
|  | 390 | HiVal = DAG.getCopyFromReg(Root, VRegHi, MVT::i32); | 
|  | 391 | } else { | 
|  | 392 | int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset); | 
|  | 393 | SDOperand FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); | 
| Evan Cheng | e71fe34d | 2006-10-09 20:57:25 +0000 | [diff] [blame] | 394 | HiVal = DAG.getLoad(MVT::i32, Root, FIPtr, NULL, 0); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 395 | } | 
|  | 396 |  | 
|  | 397 | SDOperand LoVal; | 
|  | 398 | if (CurArgReg < ArgRegEnd) {  // Lives in an incoming GPR | 
|  | 399 | unsigned VRegLo = RegMap->createVirtualRegister(&SP::IntRegsRegClass); | 
|  | 400 | MF.addLiveIn(*CurArgReg++, VRegLo); | 
|  | 401 | LoVal = DAG.getCopyFromReg(Root, VRegLo, MVT::i32); | 
|  | 402 | } else { | 
|  | 403 | int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset+4); | 
|  | 404 | SDOperand FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); | 
| Evan Cheng | e71fe34d | 2006-10-09 20:57:25 +0000 | [diff] [blame] | 405 | LoVal = DAG.getLoad(MVT::i32, Root, FIPtr, NULL, 0); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 406 | } | 
|  | 407 |  | 
|  | 408 | // Compose the two halves together into an i64 unit. | 
|  | 409 | SDOperand WholeValue = | 
|  | 410 | DAG.getNode(ISD::BUILD_PAIR, MVT::i64, LoVal, HiVal); | 
|  | 411 |  | 
|  | 412 | // If we want a double, do a bit convert. | 
|  | 413 | if (ObjectVT == MVT::f64) | 
|  | 414 | WholeValue = DAG.getNode(ISD::BIT_CONVERT, MVT::f64, WholeValue); | 
|  | 415 |  | 
|  | 416 | ArgValues.push_back(WholeValue); | 
|  | 417 | } | 
|  | 418 | ArgOffset += 8; | 
|  | 419 | break; | 
|  | 420 | } | 
|  | 421 | } | 
|  | 422 |  | 
|  | 423 | // Store remaining ArgRegs to the stack if this is a varargs function. | 
|  | 424 | if (F.getFunctionType()->isVarArg()) { | 
|  | 425 | // Remember the vararg offset for the va_start implementation. | 
|  | 426 | VarArgsFrameOffset = ArgOffset; | 
|  | 427 |  | 
|  | 428 | for (; CurArgReg != ArgRegEnd; ++CurArgReg) { | 
|  | 429 | unsigned VReg = RegMap->createVirtualRegister(&SP::IntRegsRegClass); | 
|  | 430 | MF.addLiveIn(*CurArgReg, VReg); | 
|  | 431 | SDOperand Arg = DAG.getCopyFromReg(DAG.getRoot(), VReg, MVT::i32); | 
|  | 432 |  | 
|  | 433 | int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset); | 
|  | 434 | SDOperand FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); | 
|  | 435 |  | 
| Evan Cheng | ab51cf2 | 2006-10-13 21:14:26 +0000 | [diff] [blame] | 436 | OutChains.push_back(DAG.getStore(DAG.getRoot(), Arg, FIPtr, NULL, 0)); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 437 | ArgOffset += 4; | 
|  | 438 | } | 
|  | 439 | } | 
|  | 440 |  | 
|  | 441 | if (!OutChains.empty()) | 
| Chris Lattner | c24a1d3 | 2006-08-08 02:23:42 +0000 | [diff] [blame] | 442 | DAG.setRoot(DAG.getNode(ISD::TokenFactor, MVT::Other, | 
|  | 443 | &OutChains[0], OutChains.size())); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 444 |  | 
|  | 445 | // Finally, inform the code generator which regs we return values in. | 
|  | 446 | switch (getValueType(F.getReturnType())) { | 
|  | 447 | default: assert(0 && "Unknown type!"); | 
|  | 448 | case MVT::isVoid: break; | 
|  | 449 | case MVT::i1: | 
|  | 450 | case MVT::i8: | 
|  | 451 | case MVT::i16: | 
|  | 452 | case MVT::i32: | 
|  | 453 | MF.addLiveOut(SP::I0); | 
|  | 454 | break; | 
|  | 455 | case MVT::i64: | 
|  | 456 | MF.addLiveOut(SP::I0); | 
|  | 457 | MF.addLiveOut(SP::I1); | 
|  | 458 | break; | 
|  | 459 | case MVT::f32: | 
|  | 460 | MF.addLiveOut(SP::F0); | 
|  | 461 | break; | 
|  | 462 | case MVT::f64: | 
|  | 463 | MF.addLiveOut(SP::D0); | 
|  | 464 | break; | 
|  | 465 | } | 
|  | 466 |  | 
|  | 467 | return ArgValues; | 
|  | 468 | } | 
|  | 469 |  | 
|  | 470 | std::pair<SDOperand, SDOperand> | 
|  | 471 | SparcTargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy, | 
| Reid Spencer | e63b651 | 2006-12-31 05:55:36 +0000 | [diff] [blame] | 472 | bool RetTyIsSigned, bool isVarArg, unsigned CC, | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 473 | bool isTailCall, SDOperand Callee, | 
|  | 474 | ArgListTy &Args, SelectionDAG &DAG) { | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 475 | // Count the size of the outgoing arguments. | 
|  | 476 | unsigned ArgsSize = 0; | 
|  | 477 | for (unsigned i = 0, e = Args.size(); i != e; ++i) { | 
| Reid Spencer | e63b651 | 2006-12-31 05:55:36 +0000 | [diff] [blame] | 478 | switch (getValueType(Args[i].Ty)) { | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 479 | default: assert(0 && "Unknown value type!"); | 
|  | 480 | case MVT::i1: | 
|  | 481 | case MVT::i8: | 
|  | 482 | case MVT::i16: | 
|  | 483 | case MVT::i32: | 
|  | 484 | case MVT::f32: | 
|  | 485 | ArgsSize += 4; | 
|  | 486 | break; | 
|  | 487 | case MVT::i64: | 
|  | 488 | case MVT::f64: | 
|  | 489 | ArgsSize += 8; | 
|  | 490 | break; | 
|  | 491 | } | 
|  | 492 | } | 
|  | 493 | if (ArgsSize > 4*6) | 
|  | 494 | ArgsSize -= 4*6;    // Space for first 6 arguments is prereserved. | 
|  | 495 | else | 
|  | 496 | ArgsSize = 0; | 
|  | 497 |  | 
|  | 498 | // Keep stack frames 8-byte aligned. | 
|  | 499 | ArgsSize = (ArgsSize+7) & ~7; | 
|  | 500 |  | 
| Chris Lattner | 62c3484 | 2006-02-13 09:00:43 +0000 | [diff] [blame] | 501 | Chain = DAG.getCALLSEQ_START(Chain,DAG.getConstant(ArgsSize, getPointerTy())); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 502 |  | 
| Evan Cheng | ab51cf2 | 2006-10-13 21:14:26 +0000 | [diff] [blame] | 503 | SDOperand StackPtr; | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 504 | std::vector<SDOperand> Stores; | 
|  | 505 | std::vector<SDOperand> RegValuesToPass; | 
|  | 506 | unsigned ArgOffset = 68; | 
|  | 507 | for (unsigned i = 0, e = Args.size(); i != e; ++i) { | 
| Reid Spencer | e63b651 | 2006-12-31 05:55:36 +0000 | [diff] [blame] | 508 | SDOperand Val = Args[i].Node; | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 509 | MVT::ValueType ObjectVT = Val.getValueType(); | 
|  | 510 | SDOperand ValToStore(0, 0); | 
|  | 511 | unsigned ObjSize; | 
|  | 512 | switch (ObjectVT) { | 
|  | 513 | default: assert(0 && "Unhandled argument type!"); | 
|  | 514 | case MVT::i1: | 
|  | 515 | case MVT::i8: | 
| Reid Spencer | e63b651 | 2006-12-31 05:55:36 +0000 | [diff] [blame] | 516 | case MVT::i16: { | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 517 | // Promote the integer to 32-bits.  If the input type is signed, use a | 
|  | 518 | // sign extend, otherwise use a zero extend. | 
| Anton Korobeynikov | ed4b303 | 2007-03-07 16:25:09 +0000 | [diff] [blame] | 519 | ISD::NodeType ExtendKind = ISD::ANY_EXTEND; | 
|  | 520 | if (Args[i].isSExt) | 
| Reid Spencer | e63b651 | 2006-12-31 05:55:36 +0000 | [diff] [blame] | 521 | ExtendKind = ISD::SIGN_EXTEND; | 
| Anton Korobeynikov | ed4b303 | 2007-03-07 16:25:09 +0000 | [diff] [blame] | 522 | else if (Args[i].isZExt) | 
|  | 523 | ExtendKind = ISD::ZERO_EXTEND; | 
| Reid Spencer | e63b651 | 2006-12-31 05:55:36 +0000 | [diff] [blame] | 524 | Val = DAG.getNode(ExtendKind, MVT::i32, Val); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 525 | // FALL THROUGH | 
| Reid Spencer | e63b651 | 2006-12-31 05:55:36 +0000 | [diff] [blame] | 526 | } | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 527 | case MVT::i32: | 
|  | 528 | ObjSize = 4; | 
|  | 529 |  | 
|  | 530 | if (RegValuesToPass.size() >= 6) { | 
|  | 531 | ValToStore = Val; | 
|  | 532 | } else { | 
|  | 533 | RegValuesToPass.push_back(Val); | 
|  | 534 | } | 
|  | 535 | break; | 
|  | 536 | case MVT::f32: | 
|  | 537 | ObjSize = 4; | 
|  | 538 | if (RegValuesToPass.size() >= 6) { | 
|  | 539 | ValToStore = Val; | 
|  | 540 | } else { | 
|  | 541 | // Convert this to a FP value in an int reg. | 
|  | 542 | Val = DAG.getNode(ISD::BIT_CONVERT, MVT::i32, Val); | 
|  | 543 | RegValuesToPass.push_back(Val); | 
|  | 544 | } | 
|  | 545 | break; | 
|  | 546 | case MVT::f64: | 
|  | 547 | ObjSize = 8; | 
|  | 548 | // If we can store this directly into the outgoing slot, do so.  We can | 
|  | 549 | // do this when all ArgRegs are used and if the outgoing slot is aligned. | 
|  | 550 | // FIXME: McGill/misr fails with this. | 
|  | 551 | if (0 && RegValuesToPass.size() >= 6 && ((ArgOffset-68) & 7) == 0) { | 
|  | 552 | ValToStore = Val; | 
|  | 553 | break; | 
|  | 554 | } | 
|  | 555 |  | 
|  | 556 | // Otherwise, convert this to a FP value in int regs. | 
|  | 557 | Val = DAG.getNode(ISD::BIT_CONVERT, MVT::i64, Val); | 
|  | 558 | // FALL THROUGH | 
|  | 559 | case MVT::i64: | 
|  | 560 | ObjSize = 8; | 
|  | 561 | if (RegValuesToPass.size() >= 6) { | 
|  | 562 | ValToStore = Val;    // Whole thing is passed in memory. | 
|  | 563 | break; | 
|  | 564 | } | 
|  | 565 |  | 
|  | 566 | // Split the value into top and bottom part.  Top part goes in a reg. | 
| Evan Cheng | 94bb93f | 2006-06-15 08:18:06 +0000 | [diff] [blame] | 567 | SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, getPointerTy(), Val, | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 568 | DAG.getConstant(1, MVT::i32)); | 
| Evan Cheng | 94bb93f | 2006-06-15 08:18:06 +0000 | [diff] [blame] | 569 | SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, getPointerTy(), Val, | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 570 | DAG.getConstant(0, MVT::i32)); | 
|  | 571 | RegValuesToPass.push_back(Hi); | 
|  | 572 |  | 
|  | 573 | if (RegValuesToPass.size() >= 6) { | 
|  | 574 | ValToStore = Lo; | 
|  | 575 | ArgOffset += 4; | 
|  | 576 | ObjSize = 4; | 
|  | 577 | } else { | 
|  | 578 | RegValuesToPass.push_back(Lo); | 
|  | 579 | } | 
|  | 580 | break; | 
|  | 581 | } | 
|  | 582 |  | 
|  | 583 | if (ValToStore.Val) { | 
|  | 584 | if (!StackPtr.Val) { | 
|  | 585 | StackPtr = DAG.getRegister(SP::O6, MVT::i32); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 586 | } | 
|  | 587 | SDOperand PtrOff = DAG.getConstant(ArgOffset, getPointerTy()); | 
|  | 588 | PtrOff = DAG.getNode(ISD::ADD, MVT::i32, StackPtr, PtrOff); | 
| Evan Cheng | ab51cf2 | 2006-10-13 21:14:26 +0000 | [diff] [blame] | 589 | Stores.push_back(DAG.getStore(Chain, ValToStore, PtrOff, NULL, 0)); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 590 | } | 
|  | 591 | ArgOffset += ObjSize; | 
|  | 592 | } | 
|  | 593 |  | 
|  | 594 | // Emit all stores, make sure the occur before any copies into physregs. | 
|  | 595 | if (!Stores.empty()) | 
| Chris Lattner | c24a1d3 | 2006-08-08 02:23:42 +0000 | [diff] [blame] | 596 | Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, &Stores[0],Stores.size()); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 597 |  | 
|  | 598 | static const unsigned ArgRegs[] = { | 
|  | 599 | SP::O0, SP::O1, SP::O2, SP::O3, SP::O4, SP::O5 | 
|  | 600 | }; | 
|  | 601 |  | 
|  | 602 | // Build a sequence of copy-to-reg nodes chained together with token chain | 
|  | 603 | // and flag operands which copy the outgoing args into O[0-5]. | 
|  | 604 | SDOperand InFlag; | 
|  | 605 | for (unsigned i = 0, e = RegValuesToPass.size(); i != e; ++i) { | 
|  | 606 | Chain = DAG.getCopyToReg(Chain, ArgRegs[i], RegValuesToPass[i], InFlag); | 
|  | 607 | InFlag = Chain.getValue(1); | 
|  | 608 | } | 
|  | 609 |  | 
|  | 610 | // If the callee is a GlobalAddress node (quite common, every direct call is) | 
|  | 611 | // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. | 
| Chris Lattner | fcb8a3a | 2006-02-10 07:35:42 +0000 | [diff] [blame] | 612 | // Likewise ExternalSymbol -> TargetExternalSymbol. | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 613 | if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) | 
|  | 614 | Callee = DAG.getTargetGlobalAddress(G->getGlobal(), MVT::i32); | 
| Chris Lattner | fcb8a3a | 2006-02-10 07:35:42 +0000 | [diff] [blame] | 615 | else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee)) | 
|  | 616 | Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 617 |  | 
|  | 618 | std::vector<MVT::ValueType> NodeTys; | 
|  | 619 | NodeTys.push_back(MVT::Other);   // Returns a chain | 
|  | 620 | NodeTys.push_back(MVT::Flag);    // Returns a flag for retval copy to use. | 
| Chris Lattner | c24a1d3 | 2006-08-08 02:23:42 +0000 | [diff] [blame] | 621 | SDOperand Ops[] = { Chain, Callee, InFlag }; | 
|  | 622 | Chain = DAG.getNode(SPISD::CALL, NodeTys, Ops, InFlag.Val ? 3 : 2); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 623 | InFlag = Chain.getValue(1); | 
|  | 624 |  | 
|  | 625 | MVT::ValueType RetTyVT = getValueType(RetTy); | 
|  | 626 | SDOperand RetVal; | 
|  | 627 | if (RetTyVT != MVT::isVoid) { | 
|  | 628 | switch (RetTyVT) { | 
|  | 629 | default: assert(0 && "Unknown value type to return!"); | 
|  | 630 | case MVT::i1: | 
|  | 631 | case MVT::i8: | 
| Reid Spencer | e63b651 | 2006-12-31 05:55:36 +0000 | [diff] [blame] | 632 | case MVT::i16: { | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 633 | RetVal = DAG.getCopyFromReg(Chain, SP::O0, MVT::i32, InFlag); | 
|  | 634 | Chain = RetVal.getValue(1); | 
|  | 635 |  | 
|  | 636 | // Add a note to keep track of whether it is sign or zero extended. | 
| Reid Spencer | e63b651 | 2006-12-31 05:55:36 +0000 | [diff] [blame] | 637 | ISD::NodeType AssertKind = ISD::AssertZext; | 
|  | 638 | if (RetTyIsSigned) | 
|  | 639 | AssertKind = ISD::AssertSext; | 
|  | 640 | RetVal = DAG.getNode(AssertKind, MVT::i32, RetVal, | 
|  | 641 | DAG.getValueType(RetTyVT)); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 642 | RetVal = DAG.getNode(ISD::TRUNCATE, RetTyVT, RetVal); | 
|  | 643 | break; | 
| Reid Spencer | e63b651 | 2006-12-31 05:55:36 +0000 | [diff] [blame] | 644 | } | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 645 | case MVT::i32: | 
|  | 646 | RetVal = DAG.getCopyFromReg(Chain, SP::O0, MVT::i32, InFlag); | 
|  | 647 | Chain = RetVal.getValue(1); | 
|  | 648 | break; | 
|  | 649 | case MVT::f32: | 
|  | 650 | RetVal = DAG.getCopyFromReg(Chain, SP::F0, MVT::f32, InFlag); | 
|  | 651 | Chain = RetVal.getValue(1); | 
|  | 652 | break; | 
|  | 653 | case MVT::f64: | 
|  | 654 | RetVal = DAG.getCopyFromReg(Chain, SP::D0, MVT::f64, InFlag); | 
|  | 655 | Chain = RetVal.getValue(1); | 
|  | 656 | break; | 
|  | 657 | case MVT::i64: | 
|  | 658 | SDOperand Lo = DAG.getCopyFromReg(Chain, SP::O1, MVT::i32, InFlag); | 
|  | 659 | SDOperand Hi = DAG.getCopyFromReg(Lo.getValue(1), SP::O0, MVT::i32, | 
|  | 660 | Lo.getValue(2)); | 
|  | 661 | RetVal = DAG.getNode(ISD::BUILD_PAIR, MVT::i64, Lo, Hi); | 
|  | 662 | Chain = Hi.getValue(1); | 
|  | 663 | break; | 
|  | 664 | } | 
|  | 665 | } | 
|  | 666 |  | 
|  | 667 | Chain = DAG.getNode(ISD::CALLSEQ_END, MVT::Other, Chain, | 
|  | 668 | DAG.getConstant(ArgsSize, getPointerTy())); | 
|  | 669 |  | 
|  | 670 | return std::make_pair(RetVal, Chain); | 
|  | 671 | } | 
|  | 672 |  | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 673 | // Look at LHS/RHS/CC and see if they are a lowered setcc instruction.  If so | 
|  | 674 | // set LHS/RHS and SPCC to the LHS/RHS of the setcc and SPCC to the condition. | 
|  | 675 | static void LookThroughSetCC(SDOperand &LHS, SDOperand &RHS, | 
|  | 676 | ISD::CondCode CC, unsigned &SPCC) { | 
|  | 677 | if (isa<ConstantSDNode>(RHS) && cast<ConstantSDNode>(RHS)->getValue() == 0 && | 
|  | 678 | CC == ISD::SETNE && | 
|  | 679 | ((LHS.getOpcode() == SPISD::SELECT_ICC && | 
|  | 680 | LHS.getOperand(3).getOpcode() == SPISD::CMPICC) || | 
|  | 681 | (LHS.getOpcode() == SPISD::SELECT_FCC && | 
|  | 682 | LHS.getOperand(3).getOpcode() == SPISD::CMPFCC)) && | 
|  | 683 | isa<ConstantSDNode>(LHS.getOperand(0)) && | 
|  | 684 | isa<ConstantSDNode>(LHS.getOperand(1)) && | 
|  | 685 | cast<ConstantSDNode>(LHS.getOperand(0))->getValue() == 1 && | 
|  | 686 | cast<ConstantSDNode>(LHS.getOperand(1))->getValue() == 0) { | 
|  | 687 | SDOperand CMPCC = LHS.getOperand(3); | 
|  | 688 | SPCC = cast<ConstantSDNode>(LHS.getOperand(2))->getValue(); | 
|  | 689 | LHS = CMPCC.getOperand(0); | 
|  | 690 | RHS = CMPCC.getOperand(1); | 
|  | 691 | } | 
|  | 692 | } | 
|  | 693 |  | 
|  | 694 |  | 
|  | 695 | SDOperand SparcTargetLowering:: | 
|  | 696 | LowerOperation(SDOperand Op, SelectionDAG &DAG) { | 
|  | 697 | switch (Op.getOpcode()) { | 
|  | 698 | default: assert(0 && "Should not custom lower this!"); | 
|  | 699 | case ISD::GlobalAddress: { | 
|  | 700 | GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); | 
|  | 701 | SDOperand GA = DAG.getTargetGlobalAddress(GV, MVT::i32); | 
|  | 702 | SDOperand Hi = DAG.getNode(SPISD::Hi, MVT::i32, GA); | 
|  | 703 | SDOperand Lo = DAG.getNode(SPISD::Lo, MVT::i32, GA); | 
|  | 704 | return DAG.getNode(ISD::ADD, MVT::i32, Lo, Hi); | 
|  | 705 | } | 
|  | 706 | case ISD::ConstantPool: { | 
| Evan Cheng | 9a083a4 | 2006-09-12 21:04:05 +0000 | [diff] [blame] | 707 | Constant *C = cast<ConstantPoolSDNode>(Op)->getConstVal(); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 708 | SDOperand CP = DAG.getTargetConstantPool(C, MVT::i32, | 
|  | 709 | cast<ConstantPoolSDNode>(Op)->getAlignment()); | 
|  | 710 | SDOperand Hi = DAG.getNode(SPISD::Hi, MVT::i32, CP); | 
|  | 711 | SDOperand Lo = DAG.getNode(SPISD::Lo, MVT::i32, CP); | 
|  | 712 | return DAG.getNode(ISD::ADD, MVT::i32, Lo, Hi); | 
|  | 713 | } | 
|  | 714 | case ISD::FP_TO_SINT: | 
|  | 715 | // Convert the fp value to integer in an FP register. | 
|  | 716 | assert(Op.getValueType() == MVT::i32); | 
|  | 717 | Op = DAG.getNode(SPISD::FTOI, MVT::f32, Op.getOperand(0)); | 
|  | 718 | return DAG.getNode(ISD::BIT_CONVERT, MVT::i32, Op); | 
|  | 719 | case ISD::SINT_TO_FP: { | 
|  | 720 | assert(Op.getOperand(0).getValueType() == MVT::i32); | 
|  | 721 | SDOperand Tmp = DAG.getNode(ISD::BIT_CONVERT, MVT::f32, Op.getOperand(0)); | 
|  | 722 | // Convert the int value to FP in an FP register. | 
|  | 723 | return DAG.getNode(SPISD::ITOF, Op.getValueType(), Tmp); | 
|  | 724 | } | 
|  | 725 | case ISD::BR_CC: { | 
|  | 726 | SDOperand Chain = Op.getOperand(0); | 
|  | 727 | ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get(); | 
|  | 728 | SDOperand LHS = Op.getOperand(2); | 
|  | 729 | SDOperand RHS = Op.getOperand(3); | 
|  | 730 | SDOperand Dest = Op.getOperand(4); | 
|  | 731 | unsigned Opc, SPCC = ~0U; | 
|  | 732 |  | 
|  | 733 | // If this is a br_cc of a "setcc", and if the setcc got lowered into | 
|  | 734 | // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values. | 
|  | 735 | LookThroughSetCC(LHS, RHS, CC, SPCC); | 
|  | 736 |  | 
|  | 737 | // Get the condition flag. | 
|  | 738 | SDOperand CompareFlag; | 
|  | 739 | if (LHS.getValueType() == MVT::i32) { | 
|  | 740 | std::vector<MVT::ValueType> VTs; | 
|  | 741 | VTs.push_back(MVT::i32); | 
|  | 742 | VTs.push_back(MVT::Flag); | 
| Chris Lattner | c24a1d3 | 2006-08-08 02:23:42 +0000 | [diff] [blame] | 743 | SDOperand Ops[2] = { LHS, RHS }; | 
|  | 744 | CompareFlag = DAG.getNode(SPISD::CMPICC, VTs, Ops, 2).getValue(1); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 745 | if (SPCC == ~0U) SPCC = IntCondCCodeToICC(CC); | 
|  | 746 | Opc = SPISD::BRICC; | 
|  | 747 | } else { | 
|  | 748 | CompareFlag = DAG.getNode(SPISD::CMPFCC, MVT::Flag, LHS, RHS); | 
|  | 749 | if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC); | 
|  | 750 | Opc = SPISD::BRFCC; | 
|  | 751 | } | 
|  | 752 | return DAG.getNode(Opc, MVT::Other, Chain, Dest, | 
|  | 753 | DAG.getConstant(SPCC, MVT::i32), CompareFlag); | 
|  | 754 | } | 
|  | 755 | case ISD::SELECT_CC: { | 
|  | 756 | SDOperand LHS = Op.getOperand(0); | 
|  | 757 | SDOperand RHS = Op.getOperand(1); | 
|  | 758 | ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get(); | 
|  | 759 | SDOperand TrueVal = Op.getOperand(2); | 
|  | 760 | SDOperand FalseVal = Op.getOperand(3); | 
|  | 761 | unsigned Opc, SPCC = ~0U; | 
|  | 762 |  | 
|  | 763 | // If this is a select_cc of a "setcc", and if the setcc got lowered into | 
|  | 764 | // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values. | 
|  | 765 | LookThroughSetCC(LHS, RHS, CC, SPCC); | 
|  | 766 |  | 
|  | 767 | SDOperand CompareFlag; | 
|  | 768 | if (LHS.getValueType() == MVT::i32) { | 
|  | 769 | std::vector<MVT::ValueType> VTs; | 
|  | 770 | VTs.push_back(LHS.getValueType());   // subcc returns a value | 
|  | 771 | VTs.push_back(MVT::Flag); | 
| Chris Lattner | c24a1d3 | 2006-08-08 02:23:42 +0000 | [diff] [blame] | 772 | SDOperand Ops[2] = { LHS, RHS }; | 
|  | 773 | CompareFlag = DAG.getNode(SPISD::CMPICC, VTs, Ops, 2).getValue(1); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 774 | Opc = SPISD::SELECT_ICC; | 
|  | 775 | if (SPCC == ~0U) SPCC = IntCondCCodeToICC(CC); | 
|  | 776 | } else { | 
|  | 777 | CompareFlag = DAG.getNode(SPISD::CMPFCC, MVT::Flag, LHS, RHS); | 
|  | 778 | Opc = SPISD::SELECT_FCC; | 
|  | 779 | if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC); | 
|  | 780 | } | 
|  | 781 | return DAG.getNode(Opc, TrueVal.getValueType(), TrueVal, FalseVal, | 
|  | 782 | DAG.getConstant(SPCC, MVT::i32), CompareFlag); | 
|  | 783 | } | 
|  | 784 | case ISD::VASTART: { | 
|  | 785 | // vastart just stores the address of the VarArgsFrameIndex slot into the | 
|  | 786 | // memory location argument. | 
|  | 787 | SDOperand Offset = DAG.getNode(ISD::ADD, MVT::i32, | 
|  | 788 | DAG.getRegister(SP::I6, MVT::i32), | 
|  | 789 | DAG.getConstant(VarArgsFrameOffset, MVT::i32)); | 
| Evan Cheng | ab51cf2 | 2006-10-13 21:14:26 +0000 | [diff] [blame] | 790 | SrcValueSDNode *SV = cast<SrcValueSDNode>(Op.getOperand(2)); | 
| Evan Cheng | df9ac47 | 2006-10-05 23:01:46 +0000 | [diff] [blame] | 791 | return DAG.getStore(Op.getOperand(0), Offset, | 
| Evan Cheng | ab51cf2 | 2006-10-13 21:14:26 +0000 | [diff] [blame] | 792 | Op.getOperand(1), SV->getValue(), SV->getOffset()); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 793 | } | 
|  | 794 | case ISD::VAARG: { | 
|  | 795 | SDNode *Node = Op.Val; | 
|  | 796 | MVT::ValueType VT = Node->getValueType(0); | 
|  | 797 | SDOperand InChain = Node->getOperand(0); | 
|  | 798 | SDOperand VAListPtr = Node->getOperand(1); | 
| Evan Cheng | e71fe34d | 2006-10-09 20:57:25 +0000 | [diff] [blame] | 799 | SrcValueSDNode *SV = cast<SrcValueSDNode>(Node->getOperand(2)); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 800 | SDOperand VAList = DAG.getLoad(getPointerTy(), InChain, VAListPtr, | 
| Evan Cheng | e71fe34d | 2006-10-09 20:57:25 +0000 | [diff] [blame] | 801 | SV->getValue(), SV->getOffset()); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 802 | // Increment the pointer, VAList, to the next vaarg | 
|  | 803 | SDOperand NextPtr = DAG.getNode(ISD::ADD, getPointerTy(), VAList, | 
|  | 804 | DAG.getConstant(MVT::getSizeInBits(VT)/8, | 
|  | 805 | getPointerTy())); | 
|  | 806 | // Store the incremented VAList to the legalized pointer | 
| Evan Cheng | df9ac47 | 2006-10-05 23:01:46 +0000 | [diff] [blame] | 807 | InChain = DAG.getStore(VAList.getValue(1), NextPtr, | 
| Evan Cheng | ab51cf2 | 2006-10-13 21:14:26 +0000 | [diff] [blame] | 808 | VAListPtr, SV->getValue(), SV->getOffset()); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 809 | // Load the actual argument out of the pointer VAList, unless this is an | 
|  | 810 | // f64 load. | 
|  | 811 | if (VT != MVT::f64) { | 
| Evan Cheng | e71fe34d | 2006-10-09 20:57:25 +0000 | [diff] [blame] | 812 | return DAG.getLoad(VT, InChain, VAList, NULL, 0); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 813 | } else { | 
|  | 814 | // Otherwise, load it as i64, then do a bitconvert. | 
| Evan Cheng | e71fe34d | 2006-10-09 20:57:25 +0000 | [diff] [blame] | 815 | SDOperand V = DAG.getLoad(MVT::i64, InChain, VAList, NULL, 0); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 816 | std::vector<MVT::ValueType> Tys; | 
|  | 817 | Tys.push_back(MVT::f64); | 
|  | 818 | Tys.push_back(MVT::Other); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 819 | // Bit-Convert the value to f64. | 
| Chris Lattner | c24a1d3 | 2006-08-08 02:23:42 +0000 | [diff] [blame] | 820 | SDOperand Ops[2] = { DAG.getNode(ISD::BIT_CONVERT, MVT::f64, V), | 
|  | 821 | V.getValue(1) }; | 
|  | 822 | return DAG.getNode(ISD::MERGE_VALUES, Tys, Ops, 2); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 823 | } | 
|  | 824 | } | 
| Chris Lattner | a9d0b58 | 2006-02-15 06:41:34 +0000 | [diff] [blame] | 825 | case ISD::DYNAMIC_STACKALLOC: { | 
|  | 826 | SDOperand Chain = Op.getOperand(0);  // Legalize the chain. | 
|  | 827 | SDOperand Size  = Op.getOperand(1);  // Legalize the size. | 
|  | 828 |  | 
|  | 829 | unsigned SPReg = SP::O6; | 
|  | 830 | SDOperand SP = DAG.getCopyFromReg(Chain, SPReg, MVT::i32); | 
|  | 831 | SDOperand NewSP = DAG.getNode(ISD::SUB, MVT::i32, SP, Size);    // Value | 
|  | 832 | Chain = DAG.getCopyToReg(SP.getValue(1), SPReg, NewSP);      // Output chain | 
|  | 833 |  | 
|  | 834 | // The resultant pointer is actually 16 words from the bottom of the stack, | 
|  | 835 | // to provide a register spill area. | 
|  | 836 | SDOperand NewVal = DAG.getNode(ISD::ADD, MVT::i32, NewSP, | 
|  | 837 | DAG.getConstant(96, MVT::i32)); | 
|  | 838 | std::vector<MVT::ValueType> Tys; | 
|  | 839 | Tys.push_back(MVT::i32); | 
|  | 840 | Tys.push_back(MVT::Other); | 
| Chris Lattner | c24a1d3 | 2006-08-08 02:23:42 +0000 | [diff] [blame] | 841 | SDOperand Ops[2] = { NewVal, Chain }; | 
|  | 842 | return DAG.getNode(ISD::MERGE_VALUES, Tys, Ops, 2); | 
| Chris Lattner | a9d0b58 | 2006-02-15 06:41:34 +0000 | [diff] [blame] | 843 | } | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 844 | case ISD::RET: { | 
|  | 845 | SDOperand Copy; | 
|  | 846 |  | 
|  | 847 | switch(Op.getNumOperands()) { | 
|  | 848 | default: | 
|  | 849 | assert(0 && "Do not know how to return this many arguments!"); | 
|  | 850 | abort(); | 
|  | 851 | case 1: | 
|  | 852 | return SDOperand(); // ret void is legal | 
| Evan Cheng | a3add0f | 2006-05-26 23:10:12 +0000 | [diff] [blame] | 853 | case 3: { | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 854 | unsigned ArgReg; | 
|  | 855 | switch(Op.getOperand(1).getValueType()) { | 
|  | 856 | default: assert(0 && "Unknown type to return!"); | 
|  | 857 | case MVT::i32: ArgReg = SP::I0; break; | 
|  | 858 | case MVT::f32: ArgReg = SP::F0; break; | 
|  | 859 | case MVT::f64: ArgReg = SP::D0; break; | 
|  | 860 | } | 
|  | 861 | Copy = DAG.getCopyToReg(Op.getOperand(0), ArgReg, Op.getOperand(1), | 
|  | 862 | SDOperand()); | 
|  | 863 | break; | 
|  | 864 | } | 
| Evan Cheng | a3add0f | 2006-05-26 23:10:12 +0000 | [diff] [blame] | 865 | case 5: | 
|  | 866 | Copy = DAG.getCopyToReg(Op.getOperand(0), SP::I0, Op.getOperand(3), | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 867 | SDOperand()); | 
|  | 868 | Copy = DAG.getCopyToReg(Copy, SP::I1, Op.getOperand(1), Copy.getValue(1)); | 
|  | 869 | break; | 
|  | 870 | } | 
|  | 871 | return DAG.getNode(SPISD::RET_FLAG, MVT::Other, Copy, Copy.getValue(1)); | 
|  | 872 | } | 
| Nate Begeman | eda5997 | 2007-01-29 22:58:52 +0000 | [diff] [blame] | 873 | // Frame & Return address.  Currently unimplemented | 
|  | 874 | case ISD::RETURNADDR:         break; | 
|  | 875 | case ISD::FRAMEADDR:          break; | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 876 | } | 
| Nate Begeman | eda5997 | 2007-01-29 22:58:52 +0000 | [diff] [blame] | 877 | return SDOperand(); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 878 | } | 
|  | 879 |  | 
|  | 880 | MachineBasicBlock * | 
|  | 881 | SparcTargetLowering::InsertAtEndOfBasicBlock(MachineInstr *MI, | 
|  | 882 | MachineBasicBlock *BB) { | 
| Evan Cheng | 20350c4 | 2006-11-27 23:37:22 +0000 | [diff] [blame] | 883 | const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo(); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 884 | unsigned BROpcode; | 
|  | 885 | unsigned CC; | 
|  | 886 | // Figure out the conditional branch opcode to use for this select_cc. | 
|  | 887 | switch (MI->getOpcode()) { | 
|  | 888 | default: assert(0 && "Unknown SELECT_CC!"); | 
|  | 889 | case SP::SELECT_CC_Int_ICC: | 
|  | 890 | case SP::SELECT_CC_FP_ICC: | 
|  | 891 | case SP::SELECT_CC_DFP_ICC: | 
|  | 892 | BROpcode = SP::BCOND; | 
|  | 893 | break; | 
|  | 894 | case SP::SELECT_CC_Int_FCC: | 
|  | 895 | case SP::SELECT_CC_FP_FCC: | 
|  | 896 | case SP::SELECT_CC_DFP_FCC: | 
|  | 897 | BROpcode = SP::FBCOND; | 
|  | 898 | break; | 
|  | 899 | } | 
|  | 900 |  | 
|  | 901 | CC = (SPCC::CondCodes)MI->getOperand(3).getImmedValue(); | 
|  | 902 |  | 
|  | 903 | // To "insert" a SELECT_CC instruction, we actually have to insert the diamond | 
|  | 904 | // control-flow pattern.  The incoming instruction knows the destination vreg | 
|  | 905 | // to set, the condition code register to branch on, the true/false values to | 
|  | 906 | // select between, and a branch opcode to use. | 
|  | 907 | const BasicBlock *LLVM_BB = BB->getBasicBlock(); | 
|  | 908 | ilist<MachineBasicBlock>::iterator It = BB; | 
|  | 909 | ++It; | 
|  | 910 |  | 
|  | 911 | //  thisMBB: | 
|  | 912 | //  ... | 
|  | 913 | //   TrueVal = ... | 
|  | 914 | //   [f]bCC copy1MBB | 
|  | 915 | //   fallthrough --> copy0MBB | 
|  | 916 | MachineBasicBlock *thisMBB = BB; | 
|  | 917 | MachineBasicBlock *copy0MBB = new MachineBasicBlock(LLVM_BB); | 
|  | 918 | MachineBasicBlock *sinkMBB = new MachineBasicBlock(LLVM_BB); | 
| Evan Cheng | 20350c4 | 2006-11-27 23:37:22 +0000 | [diff] [blame] | 919 | BuildMI(BB, TII.get(BROpcode)).addMBB(sinkMBB).addImm(CC); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 920 | MachineFunction *F = BB->getParent(); | 
|  | 921 | F->getBasicBlockList().insert(It, copy0MBB); | 
|  | 922 | F->getBasicBlockList().insert(It, sinkMBB); | 
| Nate Begeman | ed728c1 | 2006-03-27 01:32:24 +0000 | [diff] [blame] | 923 | // Update machine-CFG edges by first adding all successors of the current | 
|  | 924 | // block to the new block which will contain the Phi node for the select. | 
|  | 925 | for(MachineBasicBlock::succ_iterator i = BB->succ_begin(), | 
|  | 926 | e = BB->succ_end(); i != e; ++i) | 
|  | 927 | sinkMBB->addSuccessor(*i); | 
|  | 928 | // Next, remove all successors of the current block, and add the true | 
|  | 929 | // and fallthrough blocks as its successors. | 
|  | 930 | while(!BB->succ_empty()) | 
|  | 931 | BB->removeSuccessor(BB->succ_begin()); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 932 | BB->addSuccessor(copy0MBB); | 
|  | 933 | BB->addSuccessor(sinkMBB); | 
|  | 934 |  | 
|  | 935 | //  copy0MBB: | 
|  | 936 | //   %FalseValue = ... | 
|  | 937 | //   # fallthrough to sinkMBB | 
|  | 938 | BB = copy0MBB; | 
|  | 939 |  | 
|  | 940 | // Update machine-CFG edges | 
|  | 941 | BB->addSuccessor(sinkMBB); | 
|  | 942 |  | 
|  | 943 | //  sinkMBB: | 
|  | 944 | //   %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] | 
|  | 945 | //  ... | 
|  | 946 | BB = sinkMBB; | 
| Evan Cheng | 20350c4 | 2006-11-27 23:37:22 +0000 | [diff] [blame] | 947 | BuildMI(BB, TII.get(SP::PHI), MI->getOperand(0).getReg()) | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 948 | .addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB) | 
|  | 949 | .addReg(MI->getOperand(1).getReg()).addMBB(thisMBB); | 
|  | 950 |  | 
|  | 951 | delete MI;   // The pseudo instruction is gone now. | 
|  | 952 | return BB; | 
|  | 953 | } | 
|  | 954 |  | 
|  | 955 | //===----------------------------------------------------------------------===// | 
|  | 956 | // Instruction Selector Implementation | 
|  | 957 | //===----------------------------------------------------------------------===// | 
|  | 958 |  | 
|  | 959 | //===--------------------------------------------------------------------===// | 
|  | 960 | /// SparcDAGToDAGISel - SPARC specific code to select SPARC machine | 
|  | 961 | /// instructions for SelectionDAG operations. | 
|  | 962 | /// | 
|  | 963 | namespace { | 
|  | 964 | class SparcDAGToDAGISel : public SelectionDAGISel { | 
|  | 965 | SparcTargetLowering Lowering; | 
|  | 966 |  | 
|  | 967 | /// Subtarget - Keep a pointer to the Sparc Subtarget around so that we can | 
|  | 968 | /// make the right decision when generating code for different targets. | 
|  | 969 | const SparcSubtarget &Subtarget; | 
|  | 970 | public: | 
|  | 971 | SparcDAGToDAGISel(TargetMachine &TM) | 
|  | 972 | : SelectionDAGISel(Lowering), Lowering(TM), | 
|  | 973 | Subtarget(TM.getSubtarget<SparcSubtarget>()) { | 
|  | 974 | } | 
|  | 975 |  | 
| Evan Cheng | 61413a3 | 2006-08-26 05:34:46 +0000 | [diff] [blame] | 976 | SDNode *Select(SDOperand Op); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 977 |  | 
|  | 978 | // Complex Pattern Selectors. | 
| Evan Cheng | 6cd0909 | 2006-11-08 20:34:28 +0000 | [diff] [blame] | 979 | bool SelectADDRrr(SDOperand Op, SDOperand N, SDOperand &R1, SDOperand &R2); | 
|  | 980 | bool SelectADDRri(SDOperand Op, SDOperand N, SDOperand &Base, | 
|  | 981 | SDOperand &Offset); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 982 |  | 
|  | 983 | /// InstructionSelectBasicBlock - This callback is invoked by | 
|  | 984 | /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. | 
|  | 985 | virtual void InstructionSelectBasicBlock(SelectionDAG &DAG); | 
|  | 986 |  | 
|  | 987 | virtual const char *getPassName() const { | 
|  | 988 | return "SPARC DAG->DAG Pattern Instruction Selection"; | 
|  | 989 | } | 
|  | 990 |  | 
|  | 991 | // Include the pieces autogenerated from the target description. | 
|  | 992 | #include "SparcGenDAGISel.inc" | 
|  | 993 | }; | 
|  | 994 | }  // end anonymous namespace | 
|  | 995 |  | 
|  | 996 | /// InstructionSelectBasicBlock - This callback is invoked by | 
|  | 997 | /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. | 
|  | 998 | void SparcDAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) { | 
|  | 999 | DEBUG(BB->dump()); | 
|  | 1000 |  | 
|  | 1001 | // Select target instructions for the DAG. | 
| Evan Cheng | a28b764 | 2006-02-05 06:51:51 +0000 | [diff] [blame] | 1002 | DAG.setRoot(SelectRoot(DAG.getRoot())); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 1003 | DAG.RemoveDeadNodes(); | 
|  | 1004 |  | 
|  | 1005 | // Emit machine code to BB. | 
|  | 1006 | ScheduleAndEmitDAG(DAG); | 
|  | 1007 | } | 
|  | 1008 |  | 
| Evan Cheng | 6cd0909 | 2006-11-08 20:34:28 +0000 | [diff] [blame] | 1009 | bool SparcDAGToDAGISel::SelectADDRri(SDOperand Op, SDOperand Addr, | 
|  | 1010 | SDOperand &Base, SDOperand &Offset) { | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 1011 | if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { | 
|  | 1012 | Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); | 
|  | 1013 | Offset = CurDAG->getTargetConstant(0, MVT::i32); | 
|  | 1014 | return true; | 
|  | 1015 | } | 
| Chris Lattner | fcb8a3a | 2006-02-10 07:35:42 +0000 | [diff] [blame] | 1016 | if (Addr.getOpcode() == ISD::TargetExternalSymbol || | 
|  | 1017 | Addr.getOpcode() == ISD::TargetGlobalAddress) | 
|  | 1018 | return false;  // direct calls. | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 1019 |  | 
|  | 1020 | if (Addr.getOpcode() == ISD::ADD) { | 
|  | 1021 | if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) { | 
|  | 1022 | if (Predicate_simm13(CN)) { | 
|  | 1023 | if (FrameIndexSDNode *FIN = | 
|  | 1024 | dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) { | 
|  | 1025 | // Constant offset from frame ref. | 
|  | 1026 | Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); | 
|  | 1027 | } else { | 
| Chris Lattner | 463fa70 | 2006-02-05 08:35:50 +0000 | [diff] [blame] | 1028 | Base = Addr.getOperand(0); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 1029 | } | 
|  | 1030 | Offset = CurDAG->getTargetConstant(CN->getValue(), MVT::i32); | 
|  | 1031 | return true; | 
|  | 1032 | } | 
|  | 1033 | } | 
|  | 1034 | if (Addr.getOperand(0).getOpcode() == SPISD::Lo) { | 
| Chris Lattner | 463fa70 | 2006-02-05 08:35:50 +0000 | [diff] [blame] | 1035 | Base = Addr.getOperand(1); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 1036 | Offset = Addr.getOperand(0).getOperand(0); | 
|  | 1037 | return true; | 
|  | 1038 | } | 
|  | 1039 | if (Addr.getOperand(1).getOpcode() == SPISD::Lo) { | 
| Chris Lattner | 463fa70 | 2006-02-05 08:35:50 +0000 | [diff] [blame] | 1040 | Base = Addr.getOperand(0); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 1041 | Offset = Addr.getOperand(1).getOperand(0); | 
|  | 1042 | return true; | 
|  | 1043 | } | 
|  | 1044 | } | 
| Chris Lattner | 463fa70 | 2006-02-05 08:35:50 +0000 | [diff] [blame] | 1045 | Base = Addr; | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 1046 | Offset = CurDAG->getTargetConstant(0, MVT::i32); | 
|  | 1047 | return true; | 
|  | 1048 | } | 
|  | 1049 |  | 
| Evan Cheng | 6cd0909 | 2006-11-08 20:34:28 +0000 | [diff] [blame] | 1050 | bool SparcDAGToDAGISel::SelectADDRrr(SDOperand Op, SDOperand Addr, | 
|  | 1051 | SDOperand &R1,  SDOperand &R2) { | 
| Chris Lattner | fcb8a3a | 2006-02-10 07:35:42 +0000 | [diff] [blame] | 1052 | if (Addr.getOpcode() == ISD::FrameIndex) return false; | 
|  | 1053 | if (Addr.getOpcode() == ISD::TargetExternalSymbol || | 
|  | 1054 | Addr.getOpcode() == ISD::TargetGlobalAddress) | 
|  | 1055 | return false;  // direct calls. | 
|  | 1056 |  | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 1057 | if (Addr.getOpcode() == ISD::ADD) { | 
|  | 1058 | if (isa<ConstantSDNode>(Addr.getOperand(1)) && | 
|  | 1059 | Predicate_simm13(Addr.getOperand(1).Val)) | 
|  | 1060 | return false;  // Let the reg+imm pattern catch this! | 
|  | 1061 | if (Addr.getOperand(0).getOpcode() == SPISD::Lo || | 
|  | 1062 | Addr.getOperand(1).getOpcode() == SPISD::Lo) | 
|  | 1063 | return false;  // Let the reg+imm pattern catch this! | 
| Chris Lattner | 463fa70 | 2006-02-05 08:35:50 +0000 | [diff] [blame] | 1064 | R1 = Addr.getOperand(0); | 
|  | 1065 | R2 = Addr.getOperand(1); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 1066 | return true; | 
|  | 1067 | } | 
|  | 1068 |  | 
| Chris Lattner | 463fa70 | 2006-02-05 08:35:50 +0000 | [diff] [blame] | 1069 | R1 = Addr; | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 1070 | R2 = CurDAG->getRegister(SP::G0, MVT::i32); | 
|  | 1071 | return true; | 
|  | 1072 | } | 
|  | 1073 |  | 
| Evan Cheng | 61413a3 | 2006-08-26 05:34:46 +0000 | [diff] [blame] | 1074 | SDNode *SparcDAGToDAGISel::Select(SDOperand Op) { | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 1075 | SDNode *N = Op.Val; | 
|  | 1076 | if (N->getOpcode() >= ISD::BUILTIN_OP_END && | 
| Evan Cheng | 61413a3 | 2006-08-26 05:34:46 +0000 | [diff] [blame] | 1077 | N->getOpcode() < SPISD::FIRST_NUMBER) | 
| Evan Cheng | bd1c5a8 | 2006-08-11 09:08:15 +0000 | [diff] [blame] | 1078 | return NULL;   // Already selected. | 
| Evan Cheng | 6dc90ca | 2006-02-09 00:37:58 +0000 | [diff] [blame] | 1079 |  | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 1080 | switch (N->getOpcode()) { | 
|  | 1081 | default: break; | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 1082 | case ISD::SDIV: | 
|  | 1083 | case ISD::UDIV: { | 
|  | 1084 | // FIXME: should use a custom expander to expose the SRA to the dag. | 
| Evan Cheng | ab8297f | 2006-08-26 01:07:58 +0000 | [diff] [blame] | 1085 | SDOperand DivLHS = N->getOperand(0); | 
|  | 1086 | SDOperand DivRHS = N->getOperand(1); | 
|  | 1087 | AddToISelQueue(DivLHS); | 
|  | 1088 | AddToISelQueue(DivRHS); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 1089 |  | 
|  | 1090 | // Set the Y register to the high-part. | 
|  | 1091 | SDOperand TopPart; | 
|  | 1092 | if (N->getOpcode() == ISD::SDIV) { | 
| Evan Cheng | d1b82d8 | 2006-02-09 07:17:49 +0000 | [diff] [blame] | 1093 | TopPart = SDOperand(CurDAG->getTargetNode(SP::SRAri, MVT::i32, DivLHS, | 
|  | 1094 | CurDAG->getTargetConstant(31, MVT::i32)), 0); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 1095 | } else { | 
|  | 1096 | TopPart = CurDAG->getRegister(SP::G0, MVT::i32); | 
|  | 1097 | } | 
| Evan Cheng | d1b82d8 | 2006-02-09 07:17:49 +0000 | [diff] [blame] | 1098 | TopPart = SDOperand(CurDAG->getTargetNode(SP::WRYrr, MVT::Flag, TopPart, | 
|  | 1099 | CurDAG->getRegister(SP::G0, MVT::i32)), 0); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 1100 |  | 
|  | 1101 | // FIXME: Handle div by immediate. | 
|  | 1102 | unsigned Opcode = N->getOpcode() == ISD::SDIV ? SP::SDIVrr : SP::UDIVrr; | 
| Evan Cheng | 63d178f | 2006-08-16 07:30:09 +0000 | [diff] [blame] | 1103 | return CurDAG->SelectNodeTo(N, Opcode, MVT::i32, DivLHS, DivRHS, | 
| Evan Cheng | 34b70ee | 2006-08-26 08:00:10 +0000 | [diff] [blame] | 1104 | TopPart); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 1105 | } | 
|  | 1106 | case ISD::MULHU: | 
|  | 1107 | case ISD::MULHS: { | 
|  | 1108 | // FIXME: Handle mul by immediate. | 
| Evan Cheng | ab8297f | 2006-08-26 01:07:58 +0000 | [diff] [blame] | 1109 | SDOperand MulLHS = N->getOperand(0); | 
|  | 1110 | SDOperand MulRHS = N->getOperand(1); | 
|  | 1111 | AddToISelQueue(MulLHS); | 
|  | 1112 | AddToISelQueue(MulRHS); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 1113 | unsigned Opcode = N->getOpcode() == ISD::MULHU ? SP::UMULrr : SP::SMULrr; | 
| Evan Cheng | d1b82d8 | 2006-02-09 07:17:49 +0000 | [diff] [blame] | 1114 | SDNode *Mul = CurDAG->getTargetNode(Opcode, MVT::i32, MVT::Flag, | 
| Chris Lattner | fcb8a3a | 2006-02-10 07:35:42 +0000 | [diff] [blame] | 1115 | MulLHS, MulRHS); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 1116 | // The high part is in the Y register. | 
| Evan Cheng | 34b70ee | 2006-08-26 08:00:10 +0000 | [diff] [blame] | 1117 | return CurDAG->SelectNodeTo(N, SP::RDY, MVT::i32, SDOperand(Mul, 1)); | 
| Evan Cheng | bd1c5a8 | 2006-08-11 09:08:15 +0000 | [diff] [blame] | 1118 | return NULL; | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 1119 | } | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 1120 | } | 
|  | 1121 |  | 
| Evan Cheng | 61413a3 | 2006-08-26 05:34:46 +0000 | [diff] [blame] | 1122 | return SelectCode(Op); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 1123 | } | 
|  | 1124 |  | 
|  | 1125 |  | 
|  | 1126 | /// createSparcISelDag - This pass converts a legalized DAG into a | 
|  | 1127 | /// SPARC-specific DAG, ready for instruction scheduling. | 
|  | 1128 | /// | 
|  | 1129 | FunctionPass *llvm::createSparcISelDag(TargetMachine &TM) { | 
|  | 1130 | return new SparcDAGToDAGISel(TM); | 
|  | 1131 | } |