| Duraid Madina | f221c26 | 2005-10-28 17:46:35 +0000 | [diff] [blame] | 1 | //===---- IA64ISelDAGToDAG.cpp - IA64 pattern matching inst selector ------===// | 
|  | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
|  | 5 | // This file was developed by Duraid Madina and is distributed under | 
|  | 6 | // the University of Illinois Open Source License. See LICENSE.TXT for details. | 
|  | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 | // | 
|  | 10 | // This file defines a pattern matching instruction selector for IA64, | 
|  | 11 | // converting a legalized dag to an IA64 dag. | 
|  | 12 | // | 
|  | 13 | //===----------------------------------------------------------------------===// | 
|  | 14 |  | 
|  | 15 | #include "IA64.h" | 
|  | 16 | #include "IA64TargetMachine.h" | 
|  | 17 | #include "IA64ISelLowering.h" | 
|  | 18 | #include "llvm/CodeGen/MachineInstrBuilder.h" | 
|  | 19 | #include "llvm/CodeGen/MachineFunction.h" | 
|  | 20 | #include "llvm/CodeGen/SSARegMap.h" | 
|  | 21 | #include "llvm/CodeGen/SelectionDAG.h" | 
|  | 22 | #include "llvm/CodeGen/SelectionDAGISel.h" | 
|  | 23 | #include "llvm/Target/TargetOptions.h" | 
|  | 24 | #include "llvm/ADT/Statistic.h" | 
|  | 25 | #include "llvm/Constants.h" | 
|  | 26 | #include "llvm/GlobalValue.h" | 
|  | 27 | #include "llvm/Support/Debug.h" | 
|  | 28 | #include "llvm/Support/MathExtras.h" | 
|  | 29 | using namespace llvm; | 
|  | 30 |  | 
|  | 31 | namespace { | 
|  | 32 | Statistic<> FusedFP ("ia64-codegen", "Number of fused fp operations"); | 
|  | 33 | Statistic<> FrameOff("ia64-codegen", "Number of frame idx offsets collapsed"); | 
|  | 34 |  | 
|  | 35 | //===--------------------------------------------------------------------===// | 
|  | 36 | /// IA64DAGToDAGISel - IA64 specific code to select IA64 machine | 
|  | 37 | /// instructions for SelectionDAG operations. | 
|  | 38 | /// | 
|  | 39 | class IA64DAGToDAGISel : public SelectionDAGISel { | 
|  | 40 | IA64TargetLowering IA64Lowering; | 
|  | 41 | unsigned GlobalBaseReg; | 
|  | 42 | public: | 
|  | 43 | IA64DAGToDAGISel(TargetMachine &TM) | 
|  | 44 | : SelectionDAGISel(IA64Lowering), IA64Lowering(TM) {} | 
|  | 45 |  | 
|  | 46 | virtual bool runOnFunction(Function &Fn) { | 
|  | 47 | // Make sure we re-emit a set of the global base reg if necessary | 
|  | 48 | GlobalBaseReg = 0; | 
|  | 49 | return SelectionDAGISel::runOnFunction(Fn); | 
|  | 50 | } | 
|  | 51 |  | 
|  | 52 | /// getI64Imm - Return a target constant with the specified value, of type | 
|  | 53 | /// i64. | 
|  | 54 | inline SDOperand getI64Imm(uint64_t Imm) { | 
|  | 55 | return CurDAG->getTargetConstant(Imm, MVT::i64); | 
|  | 56 | } | 
|  | 57 |  | 
|  | 58 | /// getGlobalBaseReg - insert code into the entry mbb to materialize the PIC | 
|  | 59 | /// base register.  Return the virtual register that holds this value. | 
|  | 60 | // SDOperand getGlobalBaseReg(); TODO: hmm | 
|  | 61 |  | 
|  | 62 | // Select - Convert the specified operand from a target-independent to a | 
|  | 63 | // target-specific node if it hasn't already been changed. | 
|  | 64 | SDOperand Select(SDOperand Op); | 
|  | 65 |  | 
|  | 66 | SDNode *SelectIntImmediateExpr(SDOperand LHS, SDOperand RHS, | 
|  | 67 | unsigned OCHi, unsigned OCLo, | 
|  | 68 | bool IsArithmetic = false, | 
|  | 69 | bool Negate = false); | 
|  | 70 | SDNode *SelectBitfieldInsert(SDNode *N); | 
|  | 71 |  | 
|  | 72 | /// SelectCC - Select a comparison of the specified values with the | 
|  | 73 | /// specified condition code, returning the CR# of the expression. | 
|  | 74 | SDOperand SelectCC(SDOperand LHS, SDOperand RHS, ISD::CondCode CC); | 
|  | 75 |  | 
|  | 76 | /// SelectAddr - Given the specified address, return the two operands for a | 
|  | 77 | /// load/store instruction, and return true if it should be an indexed [r+r] | 
|  | 78 | /// operation. | 
|  | 79 | bool SelectAddr(SDOperand Addr, SDOperand &Op1, SDOperand &Op2); | 
|  | 80 |  | 
|  | 81 | SDOperand BuildSDIVSequence(SDNode *N); | 
|  | 82 | SDOperand BuildUDIVSequence(SDNode *N); | 
|  | 83 |  | 
|  | 84 | /// InstructionSelectBasicBlock - This callback is invoked by | 
|  | 85 | /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. | 
|  | 86 | virtual void InstructionSelectBasicBlock(SelectionDAG &DAG); | 
|  | 87 |  | 
|  | 88 | virtual const char *getPassName() const { | 
|  | 89 | return "IA64 (Itanium) DAG->DAG Instruction Selector"; | 
|  | 90 | } | 
|  | 91 |  | 
|  | 92 | // Include the pieces autogenerated from the target description. | 
|  | 93 | #include "IA64GenDAGISel.inc" | 
|  | 94 |  | 
|  | 95 | private: | 
| Duraid Madina | 8edbf80 | 2005-11-21 14:14:54 +0000 | [diff] [blame] | 96 | SDOperand SelectDIV(SDOperand Op); | 
| Duraid Madina | f221c26 | 2005-10-28 17:46:35 +0000 | [diff] [blame] | 97 | }; | 
|  | 98 | } | 
|  | 99 |  | 
|  | 100 | /// InstructionSelectBasicBlock - This callback is invoked by | 
|  | 101 | /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. | 
|  | 102 | void IA64DAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) { | 
|  | 103 | DEBUG(BB->dump()); | 
|  | 104 |  | 
|  | 105 | // The selection process is inherently a bottom-up recursive process (users | 
|  | 106 | // select their uses before themselves).  Given infinite stack space, we | 
|  | 107 | // could just start selecting on the root and traverse the whole graph.  In | 
|  | 108 | // practice however, this causes us to run out of stack space on large basic | 
|  | 109 | // blocks.  To avoid this problem, select the entry node, then all its uses, | 
|  | 110 | // iteratively instead of recursively. | 
|  | 111 | std::vector<SDOperand> Worklist; | 
|  | 112 | Worklist.push_back(DAG.getEntryNode()); | 
|  | 113 |  | 
|  | 114 | // Note that we can do this in the IA64 target (scanning forward across token | 
|  | 115 | // chain edges) because no nodes ever get folded across these edges.  On a | 
|  | 116 | // target like X86 which supports load/modify/store operations, this would | 
|  | 117 | // have to be more careful. | 
|  | 118 | while (!Worklist.empty()) { | 
|  | 119 | SDOperand Node = Worklist.back(); | 
|  | 120 | Worklist.pop_back(); | 
|  | 121 |  | 
|  | 122 | // Chose from the least deep of the top two nodes. | 
|  | 123 | if (!Worklist.empty() && | 
|  | 124 | Worklist.back().Val->getNodeDepth() < Node.Val->getNodeDepth()) | 
|  | 125 | std::swap(Worklist.back(), Node); | 
|  | 126 |  | 
|  | 127 | if ((Node.Val->getOpcode() >= ISD::BUILTIN_OP_END && | 
|  | 128 | Node.Val->getOpcode() < IA64ISD::FIRST_NUMBER) || | 
|  | 129 | CodeGenMap.count(Node)) continue; | 
|  | 130 |  | 
|  | 131 | for (SDNode::use_iterator UI = Node.Val->use_begin(), | 
|  | 132 | E = Node.Val->use_end(); UI != E; ++UI) { | 
|  | 133 | // Scan the values.  If this use has a value that is a token chain, add it | 
|  | 134 | // to the worklist. | 
|  | 135 | SDNode *User = *UI; | 
|  | 136 | for (unsigned i = 0, e = User->getNumValues(); i != e; ++i) | 
|  | 137 | if (User->getValueType(i) == MVT::Other) { | 
|  | 138 | Worklist.push_back(SDOperand(User, i)); | 
|  | 139 | break; | 
|  | 140 | } | 
|  | 141 | } | 
|  | 142 |  | 
|  | 143 | // Finally, legalize this node. | 
|  | 144 | Select(Node); | 
|  | 145 | } | 
|  | 146 |  | 
|  | 147 | // Select target instructions for the DAG. | 
|  | 148 | DAG.setRoot(Select(DAG.getRoot())); | 
|  | 149 | CodeGenMap.clear(); | 
|  | 150 | DAG.RemoveDeadNodes(); | 
|  | 151 |  | 
|  | 152 | // Emit machine code to BB. | 
|  | 153 | ScheduleAndEmitDAG(DAG); | 
|  | 154 | } | 
|  | 155 |  | 
| Duraid Madina | 8edbf80 | 2005-11-21 14:14:54 +0000 | [diff] [blame] | 156 | SDOperand IA64DAGToDAGISel::SelectDIV(SDOperand Op) { | 
|  | 157 | SDNode *N = Op.Val; | 
|  | 158 | SDOperand Chain = Select(N->getOperand(0)); | 
|  | 159 |  | 
|  | 160 | SDOperand Tmp1 = Select(N->getOperand(0)); | 
|  | 161 | SDOperand Tmp2 = Select(N->getOperand(1)); | 
|  | 162 |  | 
|  | 163 | bool isFP=false; | 
|  | 164 |  | 
|  | 165 | if(MVT::isFloatingPoint(Tmp1.getValueType())) | 
|  | 166 | isFP=true; | 
|  | 167 |  | 
|  | 168 | bool isModulus=false; // is it a division or a modulus? | 
|  | 169 | bool isSigned=false; | 
|  | 170 |  | 
|  | 171 | switch(N->getOpcode()) { | 
|  | 172 | case ISD::FDIV: | 
|  | 173 | case ISD::SDIV:  isModulus=false; isSigned=true;  break; | 
|  | 174 | case ISD::UDIV:  isModulus=false; isSigned=false; break; | 
|  | 175 | case ISD::FREM: | 
|  | 176 | case ISD::SREM:  isModulus=true;  isSigned=true;  break; | 
|  | 177 | case ISD::UREM:  isModulus=true;  isSigned=false; break; | 
|  | 178 | } | 
|  | 179 |  | 
|  | 180 | // TODO: check for integer divides by powers of 2 (or other simple patterns?) | 
|  | 181 |  | 
|  | 182 | SDOperand TmpPR, TmpPR2; | 
|  | 183 | SDOperand TmpF1, TmpF2, TmpF3, TmpF4, TmpF5, TmpF6, TmpF7, TmpF8; | 
|  | 184 | SDOperand TmpF9, TmpF10,TmpF11,TmpF12,TmpF13,TmpF14,TmpF15; | 
|  | 185 | SDOperand Result; | 
| Duraid Madina | e995910 | 2006-01-16 14:33:04 +0000 | [diff] [blame] | 186 |  | 
|  | 187 | // we'll need copies of F0 and F1 | 
|  | 188 | SDOperand F0 = CurDAG->getRegister(IA64::F0, MVT::f64); | 
|  | 189 | SDOperand F1 = CurDAG->getRegister(IA64::F1, MVT::f64); | 
| Duraid Madina | 8edbf80 | 2005-11-21 14:14:54 +0000 | [diff] [blame] | 190 |  | 
|  | 191 | // OK, emit some code: | 
|  | 192 |  | 
|  | 193 | if(!isFP) { | 
|  | 194 | // first, load the inputs into FP regs. | 
|  | 195 | TmpF1 = CurDAG->getTargetNode(IA64::SETFSIG, MVT::f64, Tmp1); | 
|  | 196 | Chain = TmpF1.getValue(1); | 
|  | 197 | TmpF2 = CurDAG->getTargetNode(IA64::SETFSIG, MVT::f64, Tmp2); | 
|  | 198 | Chain = TmpF2.getValue(1); | 
|  | 199 |  | 
|  | 200 | // next, convert the inputs to FP | 
|  | 201 | if(isSigned) { | 
|  | 202 | TmpF3 = CurDAG->getTargetNode(IA64::FCVTXF, MVT::f64, TmpF1); | 
|  | 203 | Chain = TmpF3.getValue(1); | 
|  | 204 | TmpF4 = CurDAG->getTargetNode(IA64::FCVTXF, MVT::f64, TmpF2); | 
|  | 205 | Chain = TmpF4.getValue(1); | 
| Duraid Madina | ba18777 | 2006-01-16 06:33:38 +0000 | [diff] [blame] | 206 | } else { // is unsigned | 
| Duraid Madina | e995910 | 2006-01-16 14:33:04 +0000 | [diff] [blame] | 207 | TmpF3 = CurDAG->getTargetNode(IA64::FCVTXUFS1, MVT::f64, TmpF1); | 
|  | 208 | Chain = TmpF3.getValue(1); | 
|  | 209 | TmpF4 = CurDAG->getTargetNode(IA64::FCVTXUFS1, MVT::f64, TmpF2); | 
|  | 210 | Chain = TmpF4.getValue(1); | 
| Duraid Madina | 8edbf80 | 2005-11-21 14:14:54 +0000 | [diff] [blame] | 211 | } | 
|  | 212 |  | 
|  | 213 | } else { // this is an FP divide/remainder, so we 'leak' some temp | 
|  | 214 | // regs and assign TmpF3=Tmp1, TmpF4=Tmp2 | 
|  | 215 | TmpF3=Tmp1; | 
|  | 216 | TmpF4=Tmp2; | 
|  | 217 | } | 
|  | 218 |  | 
|  | 219 | // we start by computing an approximate reciprocal (good to 9 bits?) | 
|  | 220 | // note, this instruction writes _both_ TmpF5 (answer) and TmpPR (predicate) | 
| Duraid Madina | ba18777 | 2006-01-16 06:33:38 +0000 | [diff] [blame] | 221 | if(isFP) | 
|  | 222 | TmpF5 = CurDAG->getTargetNode(IA64::FRCPAS0, MVT::f64, MVT::i1, | 
| Duraid Madina | 8edbf80 | 2005-11-21 14:14:54 +0000 | [diff] [blame] | 223 | TmpF3, TmpF4); | 
| Duraid Madina | ba18777 | 2006-01-16 06:33:38 +0000 | [diff] [blame] | 224 | else | 
|  | 225 | TmpF5 = CurDAG->getTargetNode(IA64::FRCPAS1, MVT::f64, MVT::i1, | 
|  | 226 | TmpF3, TmpF4); | 
|  | 227 |  | 
| Duraid Madina | 8edbf80 | 2005-11-21 14:14:54 +0000 | [diff] [blame] | 228 | TmpPR = TmpF5.getValue(1); | 
|  | 229 | Chain = TmpF5.getValue(2); | 
|  | 230 |  | 
| Duraid Madina | ba18777 | 2006-01-16 06:33:38 +0000 | [diff] [blame] | 231 | SDOperand minusB; | 
|  | 232 | if(isModulus) { // for remainders, it'll be handy to have | 
|  | 233 | // copies of -input_b | 
|  | 234 | minusB = CurDAG->getTargetNode(IA64::SUB, MVT::i64, | 
|  | 235 | CurDAG->getRegister(IA64::r0, MVT::i64), Tmp2); | 
|  | 236 | Chain = minusB.getValue(1); | 
|  | 237 | } | 
|  | 238 |  | 
|  | 239 | SDOperand TmpE0, TmpY1, TmpE1, TmpY2; | 
|  | 240 |  | 
|  | 241 | TmpE0 = CurDAG->getTargetNode(IA64::CFNMAS1, MVT::f64, | 
| Duraid Madina | 8edbf80 | 2005-11-21 14:14:54 +0000 | [diff] [blame] | 242 | TmpF4, TmpF5, F1, TmpPR); | 
| Duraid Madina | ba18777 | 2006-01-16 06:33:38 +0000 | [diff] [blame] | 243 | Chain = TmpE0.getValue(1); | 
|  | 244 | TmpY1 = CurDAG->getTargetNode(IA64::CFMAS1, MVT::f64, | 
|  | 245 | TmpF5, TmpE0, TmpF5, TmpPR); | 
|  | 246 | Chain = TmpY1.getValue(1); | 
|  | 247 | TmpE1 = CurDAG->getTargetNode(IA64::CFMAS1, MVT::f64, | 
|  | 248 | TmpE0, TmpE0, F0, TmpPR); | 
|  | 249 | Chain = TmpE1.getValue(1); | 
|  | 250 | TmpY2 = CurDAG->getTargetNode(IA64::CFMAS1, MVT::f64, | 
|  | 251 | TmpY1, TmpE1, TmpY1, TmpPR); | 
|  | 252 | Chain = TmpY2.getValue(1); | 
| Duraid Madina | 8edbf80 | 2005-11-21 14:14:54 +0000 | [diff] [blame] | 253 |  | 
| Duraid Madina | ba18777 | 2006-01-16 06:33:38 +0000 | [diff] [blame] | 254 | if(isFP) { // if this is an FP divide, we finish up here and exit early | 
|  | 255 | if(isModulus) | 
|  | 256 | assert(0 && "Sorry, try another FORTRAN compiler."); | 
|  | 257 |  | 
|  | 258 | SDOperand TmpE2, TmpY3, TmpQ0, TmpR0; | 
|  | 259 |  | 
|  | 260 | TmpE2 = CurDAG->getTargetNode(IA64::CFMAS1, MVT::f64, | 
|  | 261 | TmpE1, TmpE1, F0, TmpPR); | 
|  | 262 | Chain = TmpE2.getValue(1); | 
|  | 263 | TmpY3 = CurDAG->getTargetNode(IA64::CFMAS1, MVT::f64, | 
|  | 264 | TmpY2, TmpE2, TmpY2, TmpPR); | 
|  | 265 | Chain = TmpY3.getValue(1); | 
|  | 266 | TmpQ0 = CurDAG->getTargetNode(IA64::CFMADS1, MVT::f64, // double prec! | 
|  | 267 | Tmp1, TmpY3, F0, TmpPR); | 
|  | 268 | Chain = TmpQ0.getValue(1); | 
|  | 269 | TmpR0 = CurDAG->getTargetNode(IA64::CFNMADS1, MVT::f64, // double prec! | 
|  | 270 | Tmp2, TmpQ0, Tmp1, TmpPR); | 
|  | 271 | Chain = TmpR0.getValue(1); | 
| Duraid Madina | 8edbf80 | 2005-11-21 14:14:54 +0000 | [diff] [blame] | 272 |  | 
| Duraid Madina | ba18777 | 2006-01-16 06:33:38 +0000 | [diff] [blame] | 273 | // we want Result to have the same target register as the frcpa, so | 
|  | 274 | // we two-address hack it. See the comment "for this to work..." on | 
|  | 275 | // page 48 of Intel application note #245415 | 
|  | 276 | Result = CurDAG->getTargetNode(IA64::TCFMADS0, MVT::f64, // d.p. s0 rndg! | 
| Duraid Madina | e995910 | 2006-01-16 14:33:04 +0000 | [diff] [blame] | 277 | TmpF5, TmpY3, TmpR0, TmpQ0, TmpPR); | 
| Duraid Madina | 8edbf80 | 2005-11-21 14:14:54 +0000 | [diff] [blame] | 278 | Chain = Result.getValue(1); | 
| Duraid Madina | ba18777 | 2006-01-16 06:33:38 +0000 | [diff] [blame] | 279 | return Result; // XXX: early exit! | 
|  | 280 | } else { // this is *not* an FP divide, so there's a bit left to do: | 
|  | 281 |  | 
|  | 282 | SDOperand TmpQ2, TmpR2, TmpQ3, TmpQ; | 
|  | 283 |  | 
|  | 284 | TmpQ2 = CurDAG->getTargetNode(IA64::CFMAS1, MVT::f64, | 
|  | 285 | TmpF3, TmpY2, F0, TmpPR); | 
|  | 286 | Chain = TmpQ2.getValue(1); | 
|  | 287 | TmpR2 = CurDAG->getTargetNode(IA64::CFNMAS1, MVT::f64, | 
|  | 288 | TmpF4, TmpQ2, TmpF3, TmpPR); | 
|  | 289 | Chain = TmpR2.getValue(1); | 
| Duraid Madina | c261469 | 2006-01-17 01:19:49 +0000 | [diff] [blame] | 290 |  | 
| Duraid Madina | e995910 | 2006-01-16 14:33:04 +0000 | [diff] [blame] | 291 | // we want TmpQ3 to have the same target register as the frcpa? maybe we | 
|  | 292 | // should two-address hack it. See the comment "for this to work..." on page | 
|  | 293 | // 48 of Intel application note #245415 | 
| Duraid Madina | c261469 | 2006-01-17 01:19:49 +0000 | [diff] [blame] | 294 | TmpQ3 = CurDAG->getTargetNode(IA64::TCFMAS1, MVT::f64, | 
|  | 295 | TmpF5, TmpR2, TmpY2, TmpQ2, TmpPR); | 
| Duraid Madina | ba18777 | 2006-01-16 06:33:38 +0000 | [diff] [blame] | 296 | Chain = TmpQ3.getValue(1); | 
| Duraid Madina | e995910 | 2006-01-16 14:33:04 +0000 | [diff] [blame] | 297 |  | 
| Duraid Madina | c261469 | 2006-01-17 01:19:49 +0000 | [diff] [blame] | 298 | // STORY: without these two-address instructions (TCFMAS1 and TCFMADS0) | 
|  | 299 | // the FPSWA won't be able to help out in the case of large/tiny | 
|  | 300 | // arguments. Other fun bugs may also appear, e.g. 0/x = x, not 0. | 
|  | 301 |  | 
| Duraid Madina | ba18777 | 2006-01-16 06:33:38 +0000 | [diff] [blame] | 302 | if(isSigned) | 
|  | 303 | TmpQ = CurDAG->getTargetNode(IA64::FCVTFXTRUNCS1, MVT::f64, TmpQ3); | 
|  | 304 | else | 
|  | 305 | TmpQ = CurDAG->getTargetNode(IA64::FCVTFXUTRUNCS1, MVT::f64, TmpQ3); | 
|  | 306 |  | 
|  | 307 | Chain = TmpQ.getValue(1); | 
|  | 308 |  | 
|  | 309 | if(isModulus) { | 
|  | 310 | SDOperand FPminusB = CurDAG->getTargetNode(IA64::SETFSIG, MVT::f64, | 
|  | 311 | minusB); | 
|  | 312 | Chain = FPminusB.getValue(1); | 
|  | 313 | SDOperand Remainder = CurDAG->getTargetNode(IA64::XMAL, MVT::f64, | 
|  | 314 | TmpQ, FPminusB, TmpF1); | 
|  | 315 | Chain = Remainder.getValue(1); | 
|  | 316 | Result = CurDAG->getTargetNode(IA64::GETFSIG, MVT::i64, Remainder); | 
|  | 317 | Chain = Result.getValue(1); | 
|  | 318 | } else { // just an integer divide | 
|  | 319 | Result = CurDAG->getTargetNode(IA64::GETFSIG, MVT::i64, TmpQ); | 
|  | 320 | Chain = Result.getValue(1); | 
|  | 321 | } | 
|  | 322 |  | 
|  | 323 | return Result; | 
|  | 324 | } // wasn't an FP divide | 
| Duraid Madina | 8edbf80 | 2005-11-21 14:14:54 +0000 | [diff] [blame] | 325 | } | 
|  | 326 |  | 
| Duraid Madina | f221c26 | 2005-10-28 17:46:35 +0000 | [diff] [blame] | 327 | // Select - Convert the specified operand from a target-independent to a | 
|  | 328 | // target-specific node if it hasn't already been changed. | 
|  | 329 | SDOperand IA64DAGToDAGISel::Select(SDOperand Op) { | 
|  | 330 | SDNode *N = Op.Val; | 
|  | 331 | if (N->getOpcode() >= ISD::BUILTIN_OP_END && | 
|  | 332 | N->getOpcode() < IA64ISD::FIRST_NUMBER) | 
|  | 333 | return Op;   // Already selected. | 
|  | 334 |  | 
|  | 335 | // If this has already been converted, use it. | 
|  | 336 | std::map<SDOperand, SDOperand>::iterator CGMI = CodeGenMap.find(Op); | 
|  | 337 | if (CGMI != CodeGenMap.end()) return CGMI->second; | 
|  | 338 |  | 
|  | 339 | switch (N->getOpcode()) { | 
|  | 340 | default: break; | 
|  | 341 |  | 
| Duraid Madina | 644e7db | 2005-12-22 13:29:14 +0000 | [diff] [blame] | 342 | case IA64ISD::BRCALL: { // XXX: this is also a hack! | 
|  | 343 | SDOperand Chain = Select(N->getOperand(0)); | 
|  | 344 | SDOperand InFlag;  // Null incoming flag value. | 
|  | 345 |  | 
|  | 346 | if(N->getNumOperands()==3) // we have an incoming chain, callee and flag | 
|  | 347 | InFlag = Select(N->getOperand(2)); | 
|  | 348 |  | 
|  | 349 | unsigned CallOpcode; | 
|  | 350 | SDOperand CallOperand; | 
| Duraid Madina | 644e7db | 2005-12-22 13:29:14 +0000 | [diff] [blame] | 351 |  | 
|  | 352 | // if we can call directly, do so | 
|  | 353 | if (GlobalAddressSDNode *GASD = | 
|  | 354 | dyn_cast<GlobalAddressSDNode>(N->getOperand(1))) { | 
|  | 355 | CallOpcode = IA64::BRCALL_IPREL_GA; | 
|  | 356 | CallOperand = CurDAG->getTargetGlobalAddress(GASD->getGlobal(), MVT::i64); | 
|  | 357 | } else if (ExternalSymbolSDNode *ESSDN = // FIXME: we currently NEED this | 
|  | 358 | // case for correctness, to avoid | 
|  | 359 | // "non-pic code with imm reloc.n | 
|  | 360 | // against dynamic symbol" errors | 
|  | 361 | dyn_cast<ExternalSymbolSDNode>(N->getOperand(1))) { | 
|  | 362 | CallOpcode = IA64::BRCALL_IPREL_ES; | 
|  | 363 | CallOperand = N->getOperand(1); | 
|  | 364 | } else { | 
|  | 365 | // otherwise we need to load the function descriptor, | 
|  | 366 | // load the branch target (function)'s entry point and GP, | 
|  | 367 | // branch (call) then restore the GP | 
|  | 368 | SDOperand FnDescriptor = Select(N->getOperand(1)); | 
|  | 369 |  | 
|  | 370 | // load the branch target's entry point [mem] and | 
|  | 371 | // GP value [mem+8] | 
|  | 372 | SDOperand targetEntryPoint=CurDAG->getTargetNode(IA64::LD8, MVT::i64, | 
|  | 373 | FnDescriptor); | 
|  | 374 | Chain = targetEntryPoint.getValue(1); | 
|  | 375 | SDOperand targetGPAddr=CurDAG->getTargetNode(IA64::ADDS, MVT::i64, | 
|  | 376 | FnDescriptor, CurDAG->getConstant(8, MVT::i64)); | 
|  | 377 | Chain = targetGPAddr.getValue(1); | 
|  | 378 | SDOperand targetGP=CurDAG->getTargetNode(IA64::LD8, MVT::i64, | 
|  | 379 | targetGPAddr); | 
|  | 380 | Chain = targetGP.getValue(1); | 
|  | 381 |  | 
|  | 382 | Chain = CurDAG->getCopyToReg(Chain, IA64::r1, targetGP, InFlag); | 
|  | 383 | InFlag = Chain.getValue(1); | 
|  | 384 | Chain = CurDAG->getCopyToReg(Chain, IA64::B6, targetEntryPoint, InFlag); // FLAG these? | 
|  | 385 | InFlag = Chain.getValue(1); | 
|  | 386 |  | 
|  | 387 | CallOperand = CurDAG->getRegister(IA64::B6, MVT::i64); | 
|  | 388 | CallOpcode = IA64::BRCALL_INDIRECT; | 
|  | 389 | } | 
|  | 390 |  | 
|  | 391 | // Finally, once everything is setup, emit the call itself | 
|  | 392 | if(InFlag.Val) | 
| Duraid Madina | 6b240e5 | 2005-12-25 14:09:08 +0000 | [diff] [blame] | 393 | Chain = CurDAG->getTargetNode(CallOpcode, MVT::Other, MVT::Flag, CallOperand, InFlag); | 
| Duraid Madina | 644e7db | 2005-12-22 13:29:14 +0000 | [diff] [blame] | 394 | else // there might be no arguments | 
|  | 395 | Chain = CurDAG->getTargetNode(CallOpcode, MVT::Other, MVT::Flag, CallOperand, Chain); | 
|  | 396 | InFlag = Chain.getValue(1); | 
|  | 397 |  | 
|  | 398 | std::vector<SDOperand> CallResults; | 
|  | 399 |  | 
|  | 400 | CallResults.push_back(Chain); | 
|  | 401 | CallResults.push_back(InFlag); | 
|  | 402 |  | 
|  | 403 | for (unsigned i = 0, e = CallResults.size(); i != e; ++i) | 
|  | 404 | CodeGenMap[Op.getValue(i)] = CallResults[i]; | 
|  | 405 | return CallResults[Op.ResNo]; | 
|  | 406 | } | 
| Duraid Madina | 8f6c86f | 2005-12-22 03:58:17 +0000 | [diff] [blame] | 407 |  | 
| Duraid Madina | 3692fa1 | 2005-12-22 07:14:45 +0000 | [diff] [blame] | 408 | case IA64ISD::GETFD: { | 
|  | 409 | SDOperand Input = Select(N->getOperand(0)); | 
| Duraid Madina | 0302e62 | 2006-01-11 03:50:40 +0000 | [diff] [blame] | 410 | SDOperand Result = CurDAG->getTargetNode(IA64::GETFD, MVT::i64, Input); | 
|  | 411 | CodeGenMap[Op] = Result; | 
|  | 412 | return Result; | 
| Duraid Madina | 3692fa1 | 2005-12-22 07:14:45 +0000 | [diff] [blame] | 413 | } | 
|  | 414 |  | 
| Duraid Madina | f221c26 | 2005-10-28 17:46:35 +0000 | [diff] [blame] | 415 | case ISD::CALL: | 
| Duraid Madina | 8f6c86f | 2005-12-22 03:58:17 +0000 | [diff] [blame] | 416 | case ISD::TAILCALL: { { | 
|  | 417 | // FIXME: This is a workaround for a bug in tblgen. | 
|  | 418 | // Pattern #47: (call:Flag (tglobaladdr:i32):$dst, ICC:Flag) | 
|  | 419 | // Emits: (CALL:void (tglobaladdr:i32):$dst) | 
|  | 420 | // Pattern complexity = 2  cost = 1 | 
|  | 421 | SDOperand N1 = N->getOperand(1); | 
|  | 422 | if (N1.getOpcode() != ISD::TargetGlobalAddress && | 
|  | 423 | N1.getOpcode() != ISD::ExternalSymbol) goto P47Fail; | 
|  | 424 | SDOperand InFlag = SDOperand(0, 0); | 
|  | 425 | SDOperand Chain = N->getOperand(0); | 
|  | 426 | SDOperand Tmp0 = N1; | 
|  | 427 | Chain = Select(Chain); | 
|  | 428 | SDOperand Result; | 
|  | 429 | if (N->getNumOperands() == 3) { | 
|  | 430 | InFlag = Select(N->getOperand(2)); | 
|  | 431 | Result = CurDAG->getTargetNode(IA64::BRCALL, MVT::Other, MVT::Flag, Tmp0, | 
|  | 432 | Chain, InFlag); | 
|  | 433 | } else { | 
|  | 434 | Result = CurDAG->getTargetNode(IA64::BRCALL, MVT::Other, MVT::Flag, Tmp0, | 
|  | 435 | Chain); | 
|  | 436 | } | 
|  | 437 | Chain = CodeGenMap[SDOperand(N, 0)] = Result.getValue(0); | 
|  | 438 | CodeGenMap[SDOperand(N, 1)] = Result.getValue(1); | 
|  | 439 | return Result.getValue(Op.ResNo); | 
|  | 440 | } | 
|  | 441 | P47Fail:; | 
|  | 442 |  | 
|  | 443 | } | 
| Duraid Madina | 8edbf80 | 2005-11-21 14:14:54 +0000 | [diff] [blame] | 444 |  | 
|  | 445 | case ISD::FDIV: | 
|  | 446 | case ISD::SDIV: | 
|  | 447 | case ISD::UDIV: | 
|  | 448 | case ISD::SREM: | 
|  | 449 | case ISD::UREM: return SelectDIV(Op); | 
| Duraid Madina | f221c26 | 2005-10-28 17:46:35 +0000 | [diff] [blame] | 450 |  | 
| Duraid Madina | 9abf165 | 2005-11-02 02:35:04 +0000 | [diff] [blame] | 451 | case ISD::ConstantFP: { | 
| Duraid Madina | 955ffaf | 2005-11-02 07:32:59 +0000 | [diff] [blame] | 452 | SDOperand Chain = CurDAG->getEntryNode(); // this is a constant, so.. | 
|  | 453 |  | 
| Duraid Madina | 9abf165 | 2005-11-02 02:35:04 +0000 | [diff] [blame] | 454 | if (cast<ConstantFPSDNode>(N)->isExactlyValue(+0.0)) | 
| Duraid Madina | 955ffaf | 2005-11-02 07:32:59 +0000 | [diff] [blame] | 455 | return CurDAG->getCopyFromReg(Chain, IA64::F0, MVT::f64); | 
| Duraid Madina | 9abf165 | 2005-11-02 02:35:04 +0000 | [diff] [blame] | 456 | else if (cast<ConstantFPSDNode>(N)->isExactlyValue(+1.0)) | 
| Duraid Madina | 955ffaf | 2005-11-02 07:32:59 +0000 | [diff] [blame] | 457 | return CurDAG->getCopyFromReg(Chain, IA64::F1, MVT::f64); | 
| Duraid Madina | 9abf165 | 2005-11-02 02:35:04 +0000 | [diff] [blame] | 458 | else | 
|  | 459 | assert(0 && "Unexpected FP constant!"); | 
|  | 460 | } | 
| Duraid Madina | f221c26 | 2005-10-28 17:46:35 +0000 | [diff] [blame] | 461 |  | 
|  | 462 | case ISD::FrameIndex: { // TODO: reduce creepyness | 
|  | 463 | int FI = cast<FrameIndexSDNode>(N)->getIndex(); | 
| Chris Lattner | a75694a | 2005-11-30 23:02:08 +0000 | [diff] [blame] | 464 | if (N->hasOneUse()) | 
|  | 465 | return CurDAG->SelectNodeTo(N, IA64::MOV, MVT::i64, | 
|  | 466 | CurDAG->getTargetFrameIndex(FI, MVT::i64)); | 
| Duraid Madina | f221c26 | 2005-10-28 17:46:35 +0000 | [diff] [blame] | 467 | return CurDAG->getTargetNode(IA64::MOV, MVT::i64, | 
|  | 468 | CurDAG->getTargetFrameIndex(FI, MVT::i64)); | 
|  | 469 | } | 
|  | 470 |  | 
| Duraid Madina | c8817d2 | 2006-01-15 09:45:23 +0000 | [diff] [blame] | 471 | case ISD::ConstantPool: { // TODO: nuke the constant pool | 
|  | 472 | //       (ia64 doesn't need one) | 
| Duraid Madina | 7abaf90 | 2005-10-29 16:08:30 +0000 | [diff] [blame] | 473 | Constant *C = cast<ConstantPoolSDNode>(N)->get(); | 
|  | 474 | SDOperand CPI = CurDAG->getTargetConstantPool(C, MVT::i64); | 
|  | 475 | return CurDAG->getTargetNode(IA64::ADDL_GA, MVT::i64, // ? | 
|  | 476 | CurDAG->getRegister(IA64::r1, MVT::i64), CPI); | 
|  | 477 | } | 
|  | 478 |  | 
| Duraid Madina | f221c26 | 2005-10-28 17:46:35 +0000 | [diff] [blame] | 479 | case ISD::GlobalAddress: { | 
|  | 480 | GlobalValue *GV = cast<GlobalAddressSDNode>(N)->getGlobal(); | 
|  | 481 | SDOperand GA = CurDAG->getTargetGlobalAddress(GV, MVT::i64); | 
|  | 482 | SDOperand Tmp = CurDAG->getTargetNode(IA64::ADDL_GA, MVT::i64, | 
|  | 483 | CurDAG->getRegister(IA64::r1, MVT::i64), GA); | 
|  | 484 | return CurDAG->getTargetNode(IA64::LD8, MVT::i64, Tmp); | 
|  | 485 | } | 
| Duraid Madina | 8f6c86f | 2005-12-22 03:58:17 +0000 | [diff] [blame] | 486 |  | 
|  | 487 | /* XXX  case ISD::ExternalSymbol: { | 
|  | 488 | SDOperand EA = CurDAG->getTargetExternalSymbol(cast<ExternalSymbolSDNode>(N)->getSymbol(), | 
|  | 489 | MVT::i64); | 
|  | 490 | SDOperand Tmp = CurDAG->getTargetNode(IA64::ADDL_EA, MVT::i64, | 
|  | 491 | CurDAG->getRegister(IA64::r1, MVT::i64), EA); | 
|  | 492 | return CurDAG->getTargetNode(IA64::LD8, MVT::i64, Tmp); | 
|  | 493 | } | 
|  | 494 | */ | 
|  | 495 |  | 
| Duraid Madina | f221c26 | 2005-10-28 17:46:35 +0000 | [diff] [blame] | 496 | case ISD::LOAD: | 
|  | 497 | case ISD::EXTLOAD: | 
|  | 498 | case ISD::ZEXTLOAD: { | 
|  | 499 | SDOperand Chain = Select(N->getOperand(0)); | 
|  | 500 | SDOperand Address = Select(N->getOperand(1)); | 
|  | 501 |  | 
|  | 502 | MVT::ValueType TypeBeingLoaded = (N->getOpcode() == ISD::LOAD) ? | 
|  | 503 | N->getValueType(0) : cast<VTSDNode>(N->getOperand(3))->getVT(); | 
|  | 504 | unsigned Opc; | 
|  | 505 | switch (TypeBeingLoaded) { | 
|  | 506 | default: N->dump(); assert(0 && "Cannot load this type!"); | 
| Duraid Madina | fc1d1b2 | 2005-11-04 09:59:06 +0000 | [diff] [blame] | 507 | case MVT::i1: { // this is a bool | 
|  | 508 | Opc = IA64::LD1; // first we load a byte, then compare for != 0 | 
| Duraid Madina | 8f6c86f | 2005-12-22 03:58:17 +0000 | [diff] [blame] | 509 | if(N->getValueType(0) == MVT::i1) // XXX: early exit! | 
|  | 510 | return CurDAG->SelectNodeTo(N, IA64::CMPNE, MVT::i1, MVT::Other, | 
| Chris Lattner | a75694a | 2005-11-30 23:02:08 +0000 | [diff] [blame] | 511 | CurDAG->getTargetNode(Opc, MVT::i64, Address), | 
|  | 512 | CurDAG->getRegister(IA64::r0, MVT::i64), | 
|  | 513 | Chain).getValue(Op.ResNo); | 
| Duraid Madina | 8f6c86f | 2005-12-22 03:58:17 +0000 | [diff] [blame] | 514 | /* otherwise, we want to load a bool into something bigger: LD1 | 
|  | 515 | will do that for us, so we just fall through */ | 
| Chris Lattner | a75694a | 2005-11-30 23:02:08 +0000 | [diff] [blame] | 516 | } | 
| Duraid Madina | f221c26 | 2005-10-28 17:46:35 +0000 | [diff] [blame] | 517 | case MVT::i8:  Opc = IA64::LD1; break; | 
|  | 518 | case MVT::i16: Opc = IA64::LD2; break; | 
|  | 519 | case MVT::i32: Opc = IA64::LD4; break; | 
|  | 520 | case MVT::i64: Opc = IA64::LD8; break; | 
|  | 521 |  | 
|  | 522 | case MVT::f32: Opc = IA64::LDF4; break; | 
|  | 523 | case MVT::f64: Opc = IA64::LDF8; break; | 
|  | 524 | } | 
|  | 525 |  | 
| Chris Lattner | a75694a | 2005-11-30 23:02:08 +0000 | [diff] [blame] | 526 | // TODO: comment this | 
|  | 527 | return CurDAG->SelectNodeTo(N, Opc, N->getValueType(0), MVT::Other, | 
|  | 528 | Address, Chain).getValue(Op.ResNo); | 
| Duraid Madina | f221c26 | 2005-10-28 17:46:35 +0000 | [diff] [blame] | 529 | } | 
|  | 530 |  | 
|  | 531 | case ISD::TRUNCSTORE: | 
|  | 532 | case ISD::STORE: { | 
|  | 533 | SDOperand Address = Select(N->getOperand(2)); | 
| Duraid Madina | 3c1c8c5 | 2005-11-07 03:11:02 +0000 | [diff] [blame] | 534 | SDOperand Chain = Select(N->getOperand(0)); | 
|  | 535 |  | 
| Duraid Madina | f221c26 | 2005-10-28 17:46:35 +0000 | [diff] [blame] | 536 | unsigned Opc; | 
|  | 537 | if (N->getOpcode() == ISD::STORE) { | 
|  | 538 | switch (N->getOperand(1).getValueType()) { | 
| Duraid Madina | 3c1c8c5 | 2005-11-07 03:11:02 +0000 | [diff] [blame] | 539 | default: assert(0 && "unknown type in store"); | 
|  | 540 | case MVT::i1: { // this is a bool | 
|  | 541 | Opc = IA64::ST1; // we store either 0 or 1 as a byte | 
| Duraid Madina | 0b94324 | 2006-01-13 10:28:25 +0000 | [diff] [blame] | 542 | // first load zero! | 
|  | 543 | SDOperand Initial = CurDAG->getCopyFromReg(Chain, IA64::r0, MVT::i64); | 
|  | 544 | Chain = Initial.getValue(1); | 
|  | 545 | // then load 1 iff the predicate to store is 1 | 
| Chris Lattner | a75694a | 2005-11-30 23:02:08 +0000 | [diff] [blame] | 546 | SDOperand Tmp = | 
| Duraid Madina | 0b94324 | 2006-01-13 10:28:25 +0000 | [diff] [blame] | 547 | CurDAG->getTargetNode(IA64::PADDS, MVT::i64, Initial, | 
| Chris Lattner | a75694a | 2005-11-30 23:02:08 +0000 | [diff] [blame] | 548 | CurDAG->getConstant(1, MVT::i64), | 
|  | 549 | Select(N->getOperand(1))); | 
|  | 550 | return CurDAG->SelectNodeTo(N, Opc, MVT::Other, Address, Tmp, Chain); | 
|  | 551 | } | 
| Duraid Madina | f221c26 | 2005-10-28 17:46:35 +0000 | [diff] [blame] | 552 | case MVT::i64: Opc = IA64::ST8;  break; | 
|  | 553 | case MVT::f64: Opc = IA64::STF8; break; | 
| Duraid Madina | 3c1c8c5 | 2005-11-07 03:11:02 +0000 | [diff] [blame] | 554 | } | 
| Duraid Madina | f221c26 | 2005-10-28 17:46:35 +0000 | [diff] [blame] | 555 | } else { //ISD::TRUNCSTORE | 
|  | 556 | switch(cast<VTSDNode>(N->getOperand(4))->getVT()) { | 
| Duraid Madina | 3c1c8c5 | 2005-11-07 03:11:02 +0000 | [diff] [blame] | 557 | default: assert(0 && "unknown type in truncstore"); | 
| Duraid Madina | f221c26 | 2005-10-28 17:46:35 +0000 | [diff] [blame] | 558 | case MVT::i8:  Opc = IA64::ST1;  break; | 
|  | 559 | case MVT::i16: Opc = IA64::ST2;  break; | 
|  | 560 | case MVT::i32: Opc = IA64::ST4;  break; | 
|  | 561 | case MVT::f32: Opc = IA64::STF4; break; | 
|  | 562 | } | 
|  | 563 | } | 
|  | 564 |  | 
| Chris Lattner | a75694a | 2005-11-30 23:02:08 +0000 | [diff] [blame] | 565 | return CurDAG->SelectNodeTo(N, Opc, MVT::Other, Select(N->getOperand(2)), | 
|  | 566 | Select(N->getOperand(1)), Chain); | 
| Duraid Madina | f221c26 | 2005-10-28 17:46:35 +0000 | [diff] [blame] | 567 | } | 
|  | 568 |  | 
|  | 569 | case ISD::BRCOND: { | 
|  | 570 | SDOperand Chain = Select(N->getOperand(0)); | 
|  | 571 | SDOperand CC = Select(N->getOperand(1)); | 
|  | 572 | MachineBasicBlock *Dest = | 
|  | 573 | cast<BasicBlockSDNode>(N->getOperand(2))->getBasicBlock(); | 
|  | 574 | //FIXME - we do NOT need long branches all the time | 
| Chris Lattner | a75694a | 2005-11-30 23:02:08 +0000 | [diff] [blame] | 575 | return CurDAG->SelectNodeTo(N, IA64::BRLCOND_NOTCALL, MVT::Other, CC, | 
|  | 576 | CurDAG->getBasicBlock(Dest), Chain); | 
| Duraid Madina | f221c26 | 2005-10-28 17:46:35 +0000 | [diff] [blame] | 577 | } | 
|  | 578 |  | 
|  | 579 | case ISD::CALLSEQ_START: | 
|  | 580 | case ISD::CALLSEQ_END: { | 
|  | 581 | int64_t Amt = cast<ConstantSDNode>(N->getOperand(1))->getValue(); | 
|  | 582 | unsigned Opc = N->getOpcode() == ISD::CALLSEQ_START ? | 
|  | 583 | IA64::ADJUSTCALLSTACKDOWN : IA64::ADJUSTCALLSTACKUP; | 
| Chris Lattner | a75694a | 2005-11-30 23:02:08 +0000 | [diff] [blame] | 584 | return CurDAG->SelectNodeTo(N, Opc, MVT::Other, | 
|  | 585 | getI64Imm(Amt), Select(N->getOperand(0))); | 
| Duraid Madina | f221c26 | 2005-10-28 17:46:35 +0000 | [diff] [blame] | 586 | } | 
|  | 587 |  | 
|  | 588 | case ISD::RET: { | 
|  | 589 | SDOperand Chain = Select(N->getOperand(0));     // Token chain. | 
| Duraid Madina | 8f6c86f | 2005-12-22 03:58:17 +0000 | [diff] [blame] | 590 | SDOperand InFlag; | 
| Duraid Madina | f221c26 | 2005-10-28 17:46:35 +0000 | [diff] [blame] | 591 |  | 
|  | 592 | switch (N->getNumOperands()) { | 
|  | 593 | default: | 
|  | 594 | assert(0 && "Unknown return instruction!"); | 
|  | 595 | case 2: { | 
|  | 596 | SDOperand RetVal = Select(N->getOperand(1)); | 
|  | 597 | switch (RetVal.getValueType()) { | 
|  | 598 | default: assert(0 && "I don't know how to return this type! (promote?)"); | 
|  | 599 | // FIXME: do I need to add support for bools here? | 
|  | 600 | // (return '0' or '1' in r8, basically...) | 
|  | 601 | // | 
|  | 602 | // FIXME: need to round floats - 80 bits is bad, the tester | 
|  | 603 | // told me so | 
|  | 604 | case MVT::i64: | 
|  | 605 | // we mark r8 as live on exit up above in LowerArguments() | 
|  | 606 | // BuildMI(BB, IA64::MOV, 1, IA64::r8).addReg(Tmp1); | 
|  | 607 | Chain = CurDAG->getCopyToReg(Chain, IA64::r8, RetVal); | 
| Duraid Madina | 8f6c86f | 2005-12-22 03:58:17 +0000 | [diff] [blame] | 608 | InFlag = Chain.getValue(1); | 
| Duraid Madina | f221c26 | 2005-10-28 17:46:35 +0000 | [diff] [blame] | 609 | break; | 
|  | 610 | case MVT::f64: | 
|  | 611 | // we mark F8 as live on exit up above in LowerArguments() | 
|  | 612 | // BuildMI(BB, IA64::FMOV, 1, IA64::F8).addReg(Tmp1); | 
|  | 613 | Chain = CurDAG->getCopyToReg(Chain, IA64::F8, RetVal); | 
| Duraid Madina | 8f6c86f | 2005-12-22 03:58:17 +0000 | [diff] [blame] | 614 | InFlag = Chain.getValue(1); | 
| Duraid Madina | f221c26 | 2005-10-28 17:46:35 +0000 | [diff] [blame] | 615 | break; | 
|  | 616 | } | 
|  | 617 | break; | 
|  | 618 | } | 
|  | 619 | case 1: | 
|  | 620 | break; | 
|  | 621 | } | 
|  | 622 |  | 
|  | 623 | // we need to copy VirtGPR (the vreg (to become a real reg)) that holds | 
|  | 624 | // the output of this function's alloc instruction back into ar.pfs | 
|  | 625 | // before we return. this copy must not float up above the last | 
|  | 626 | // outgoing call in this function!!! | 
|  | 627 | SDOperand AR_PFSVal = CurDAG->getCopyFromReg(Chain, IA64Lowering.VirtGPR, | 
|  | 628 | MVT::i64); | 
|  | 629 | Chain = AR_PFSVal.getValue(1); | 
|  | 630 | Chain = CurDAG->getCopyToReg(Chain, IA64::AR_PFS, AR_PFSVal); | 
|  | 631 |  | 
| Chris Lattner | a75694a | 2005-11-30 23:02:08 +0000 | [diff] [blame] | 632 | // and then just emit a 'ret' instruction | 
| Duraid Madina | f221c26 | 2005-10-28 17:46:35 +0000 | [diff] [blame] | 633 | // before returning, restore the ar.pfs register (set by the 'alloc' up top) | 
|  | 634 | // BuildMI(BB, IA64::MOV, 1).addReg(IA64::AR_PFS).addReg(IA64Lowering.VirtGPR); | 
|  | 635 | // | 
| Chris Lattner | a75694a | 2005-11-30 23:02:08 +0000 | [diff] [blame] | 636 | return CurDAG->SelectNodeTo(N, IA64::RET, MVT::Other, Chain); | 
| Duraid Madina | f221c26 | 2005-10-28 17:46:35 +0000 | [diff] [blame] | 637 | } | 
|  | 638 |  | 
|  | 639 | case ISD::BR: | 
|  | 640 | // FIXME: we don't need long branches all the time! | 
| Chris Lattner | a75694a | 2005-11-30 23:02:08 +0000 | [diff] [blame] | 641 | return CurDAG->SelectNodeTo(N, IA64::BRL_NOTCALL, MVT::Other, | 
|  | 642 | N->getOperand(1), Select(N->getOperand(0))); | 
| Duraid Madina | f221c26 | 2005-10-28 17:46:35 +0000 | [diff] [blame] | 643 | } | 
|  | 644 |  | 
|  | 645 | return SelectCode(Op); | 
|  | 646 | } | 
|  | 647 |  | 
|  | 648 |  | 
|  | 649 | /// createIA64DAGToDAGInstructionSelector - This pass converts a legalized DAG | 
|  | 650 | /// into an IA64-specific DAG, ready for instruction scheduling. | 
|  | 651 | /// | 
|  | 652 | FunctionPass *llvm::createIA64DAGToDAGInstructionSelector(TargetMachine &TM) { | 
|  | 653 | return new IA64DAGToDAGISel(TM); | 
|  | 654 | } | 
|  | 655 |  |