| Andrew Lenharth | 2d6f022 | 2005-01-24 19:44:07 +0000 | [diff] [blame] | 1 | //===- AlphaISelPattern.cpp - A pattern matching inst selector for Alpha -===// | 
| Andrew Lenharth | 304d0f3 | 2005-01-22 23:41:55 +0000 | [diff] [blame] | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
|  | 5 | // This file was developed by the LLVM research group 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 Alpha. | 
|  | 11 | // | 
|  | 12 | //===----------------------------------------------------------------------===// | 
|  | 13 |  | 
|  | 14 | #include "Alpha.h" | 
| Andrew Lenharth | 304d0f3 | 2005-01-22 23:41:55 +0000 | [diff] [blame] | 15 | #include "AlphaRegisterInfo.h" | 
|  | 16 | #include "llvm/Constants.h"                   // FIXME: REMOVE | 
|  | 17 | #include "llvm/Function.h" | 
|  | 18 | #include "llvm/CodeGen/MachineInstrBuilder.h" | 
|  | 19 | #include "llvm/CodeGen/MachineConstantPool.h" // FIXME: REMOVE | 
|  | 20 | #include "llvm/CodeGen/MachineFunction.h" | 
|  | 21 | #include "llvm/CodeGen/MachineFrameInfo.h" | 
|  | 22 | #include "llvm/CodeGen/SelectionDAG.h" | 
|  | 23 | #include "llvm/CodeGen/SelectionDAGISel.h" | 
|  | 24 | #include "llvm/CodeGen/SSARegMap.h" | 
|  | 25 | #include "llvm/Target/TargetData.h" | 
|  | 26 | #include "llvm/Target/TargetLowering.h" | 
|  | 27 | #include "llvm/Support/MathExtras.h" | 
|  | 28 | #include "llvm/ADT/Statistic.h" | 
|  | 29 | #include <set> | 
|  | 30 | using namespace llvm; | 
|  | 31 |  | 
|  | 32 | //===----------------------------------------------------------------------===// | 
|  | 33 | //  AlphaTargetLowering - Alpha Implementation of the TargetLowering interface | 
|  | 34 | namespace { | 
|  | 35 | class AlphaTargetLowering : public TargetLowering { | 
|  | 36 | int VarArgsFrameIndex;            // FrameIndex for start of varargs area. | 
|  | 37 | unsigned GP; //GOT vreg | 
|  | 38 | public: | 
|  | 39 | AlphaTargetLowering(TargetMachine &TM) : TargetLowering(TM) { | 
|  | 40 | // Set up the TargetLowering object. | 
|  | 41 | addRegisterClass(MVT::i64, Alpha::GPRCRegisterClass); | 
|  | 42 | addRegisterClass(MVT::f64, Alpha::FPRCRegisterClass); | 
|  | 43 |  | 
|  | 44 | setOperationAction(ISD::EXTLOAD          , MVT::i1   , Expand); | 
| Andrew Lenharth | 2f8fb77 | 2005-01-25 00:35:34 +0000 | [diff] [blame] | 45 |  | 
| Andrew Lenharth | 304d0f3 | 2005-01-22 23:41:55 +0000 | [diff] [blame] | 46 | setOperationAction(ISD::ZEXTLOAD         , MVT::i1   , Expand); | 
| Andrew Lenharth | 304d0f3 | 2005-01-22 23:41:55 +0000 | [diff] [blame] | 47 | setOperationAction(ISD::ZEXTLOAD         , MVT::i32  , Expand); | 
| Andrew Lenharth | 2f8fb77 | 2005-01-25 00:35:34 +0000 | [diff] [blame] | 48 |  | 
| Andrew Lenharth | 304d0f3 | 2005-01-22 23:41:55 +0000 | [diff] [blame] | 49 | setOperationAction(ISD::SEXTLOAD         , MVT::i1   , Expand); | 
|  | 50 | setOperationAction(ISD::SEXTLOAD         , MVT::i8   , Expand); | 
|  | 51 | setOperationAction(ISD::SEXTLOAD         , MVT::i16  , Expand); | 
|  | 52 |  | 
|  | 53 | computeRegisterProperties(); | 
|  | 54 |  | 
| Andrew Lenharth | 304d0f3 | 2005-01-22 23:41:55 +0000 | [diff] [blame] | 55 | //      addLegalFPImmediate(+0.0); // FLD0 | 
|  | 56 | //      addLegalFPImmediate(+1.0); // FLD1 | 
|  | 57 | //      addLegalFPImmediate(-0.0); // FLD0/FCHS | 
|  | 58 | //      addLegalFPImmediate(-1.0); // FLD1/FCHS | 
|  | 59 | } | 
|  | 60 |  | 
|  | 61 | /// LowerArguments - This hook must be implemented to indicate how we should | 
|  | 62 | /// lower the arguments for the specified function, into the specified DAG. | 
|  | 63 | virtual std::vector<SDOperand> | 
|  | 64 | LowerArguments(Function &F, SelectionDAG &DAG); | 
|  | 65 |  | 
|  | 66 | /// LowerCallTo - This hook lowers an abstract call to a function into an | 
|  | 67 | /// actual call. | 
|  | 68 | virtual std::pair<SDOperand, SDOperand> | 
|  | 69 | LowerCallTo(SDOperand Chain, const Type *RetTy, SDOperand Callee, | 
|  | 70 | ArgListTy &Args, SelectionDAG &DAG); | 
|  | 71 |  | 
|  | 72 | virtual std::pair<SDOperand, SDOperand> | 
|  | 73 | LowerVAStart(SDOperand Chain, SelectionDAG &DAG); | 
|  | 74 |  | 
|  | 75 | virtual std::pair<SDOperand,SDOperand> | 
|  | 76 | LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList, | 
|  | 77 | const Type *ArgTy, SelectionDAG &DAG); | 
|  | 78 |  | 
|  | 79 | virtual std::pair<SDOperand, SDOperand> | 
|  | 80 | LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth, | 
|  | 81 | SelectionDAG &DAG); | 
|  | 82 |  | 
|  | 83 | void restoreGP(MachineBasicBlock* BB) | 
|  | 84 | { | 
|  | 85 | BuildMI(BB, Alpha::BIS, 2, Alpha::R29).addReg(GP).addReg(GP); | 
|  | 86 | } | 
|  | 87 | }; | 
|  | 88 | } | 
|  | 89 |  | 
|  | 90 | //http://www.cs.arizona.edu/computer.help/policy/DIGITAL_unix/AA-PY8AC-TET1_html/callCH3.html#BLOCK21 | 
|  | 91 |  | 
|  | 92 | //For now, just use variable size stack frame format | 
|  | 93 |  | 
|  | 94 | //In a standard call, the first six items are passed in registers $16 | 
|  | 95 | //- $21 and/or registers $f16 - $f21. (See Section 4.1.2 for details | 
|  | 96 | //of argument-to-register correspondence.) The remaining items are | 
|  | 97 | //collected in a memory argument list that is a naturally aligned | 
|  | 98 | //array of quadwords. In a standard call, this list, if present, must | 
|  | 99 | //be passed at 0(SP). | 
|  | 100 | //7 ... n  	  	  	0(SP) ... (n-7)*8(SP) | 
|  | 101 |  | 
|  | 102 | std::vector<SDOperand> | 
|  | 103 | AlphaTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) | 
|  | 104 | { | 
|  | 105 | std::vector<SDOperand> ArgValues; | 
|  | 106 |  | 
|  | 107 | // //#define FP    $15 | 
|  | 108 | // //#define RA    $26 | 
|  | 109 | // //#define PV    $27 | 
|  | 110 | // //#define GP    $29 | 
|  | 111 | // //#define SP    $30 | 
|  | 112 |  | 
|  | 113 | //  assert(0 && "TODO"); | 
|  | 114 | MachineFunction &MF = DAG.getMachineFunction(); | 
|  | 115 | MachineFrameInfo *MFI = MF.getFrameInfo(); | 
|  | 116 |  | 
|  | 117 | GP = MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::i64)); | 
|  | 118 | MachineBasicBlock& BB = MF.front(); | 
|  | 119 |  | 
|  | 120 | //Handle the return address | 
|  | 121 | //BuildMI(&BB, Alpha::IDEF, 0, Alpha::R26); | 
|  | 122 |  | 
|  | 123 | unsigned args[] = {Alpha::R16, Alpha::R17, Alpha::R18, | 
|  | 124 | Alpha::R19, Alpha::R20, Alpha::R21}; | 
|  | 125 | std::vector<unsigned> argVreg; | 
|  | 126 |  | 
|  | 127 | int count = 0; | 
|  | 128 | for (Function::aiterator I = F.abegin(), E = F.aend(); I != E; ++I) | 
|  | 129 | { | 
|  | 130 | ++count; | 
|  | 131 | assert(count <= 6 && "More than 6 args not supported"); | 
|  | 132 | assert(getValueType(I->getType()) != MVT::f64 && "No floats yet"); | 
|  | 133 | BuildMI(&BB, Alpha::IDEF, 0, args[count - 1]); | 
|  | 134 | argVreg.push_back(MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::i64))); | 
|  | 135 | } | 
|  | 136 |  | 
|  | 137 | BuildMI(&BB, Alpha::IDEF, 0, Alpha::R29); | 
|  | 138 | BuildMI(&BB, Alpha::BIS, 2, GP).addReg(Alpha::R29).addReg(Alpha::R29); | 
|  | 139 | count = 0; | 
|  | 140 | for (Function::aiterator I = F.abegin(), E = F.aend(); I != E; ++I) | 
|  | 141 | { | 
|  | 142 | BuildMI(&BB, Alpha::BIS, 2, argVreg[count]).addReg(args[count]).addReg(args[count]); | 
|  | 143 |  | 
|  | 144 | SDOperand argt, newroot; | 
|  | 145 | switch (getValueType(I->getType())) | 
|  | 146 | { | 
|  | 147 | case MVT::i64: | 
|  | 148 | argt = newroot = DAG.getCopyFromReg(argVreg[count], MVT::i64, DAG.getRoot()); | 
|  | 149 | break; | 
|  | 150 | case MVT::i32: | 
|  | 151 | argt = newroot = DAG.getCopyFromReg(argVreg[count], MVT::i32, DAG.getRoot()); | 
|  | 152 | break; | 
|  | 153 | default: | 
|  | 154 | newroot = DAG.getCopyFromReg(argVreg[count], MVT::i64, DAG.getRoot()); | 
|  | 155 | argt =  DAG.getNode(ISD::TRUNCATE, getValueType(I->getType()), newroot); | 
|  | 156 | } | 
|  | 157 | DAG.setRoot(newroot.getValue(1)); | 
|  | 158 | ArgValues.push_back(argt); | 
|  | 159 | ++count; | 
|  | 160 | } | 
|  | 161 | return ArgValues; | 
|  | 162 | } | 
|  | 163 |  | 
|  | 164 | std::pair<SDOperand, SDOperand> | 
|  | 165 | AlphaTargetLowering::LowerCallTo(SDOperand Chain, | 
|  | 166 | const Type *RetTy, SDOperand Callee, | 
|  | 167 | ArgListTy &Args, SelectionDAG &DAG) { | 
|  | 168 | int NumBytes = 0; | 
|  | 169 | Chain = DAG.getNode(ISD::ADJCALLSTACKDOWN, MVT::Other, Chain, | 
|  | 170 | DAG.getConstant(NumBytes, getPointerTy())); | 
|  | 171 | std::vector<SDOperand> args_to_use; | 
|  | 172 | for (unsigned i = 0, e = Args.size(); i != e; ++i) | 
|  | 173 | { | 
|  | 174 | switch (getValueType(Args[i].second)) { | 
|  | 175 | default: assert(0 && "Unexpected ValueType for argument!"); | 
|  | 176 | case MVT::i1: | 
|  | 177 | case MVT::i8: | 
|  | 178 | case MVT::i16: | 
|  | 179 | case MVT::i32: | 
|  | 180 | // Promote the integer to 64 bits.  If the input type is signed use a | 
|  | 181 | // sign extend, otherwise use a zero extend. | 
|  | 182 | if (Args[i].second->isSigned()) | 
|  | 183 | Args[i].first = DAG.getNode(ISD::SIGN_EXTEND, MVT::i64, Args[i].first); | 
|  | 184 | else | 
|  | 185 | Args[i].first = DAG.getNode(ISD::ZERO_EXTEND, MVT::i64, Args[i].first); | 
|  | 186 | break; | 
|  | 187 | case MVT::i64: | 
|  | 188 | break; | 
|  | 189 | } | 
|  | 190 | args_to_use.push_back(Args[i].first); | 
|  | 191 | } | 
|  | 192 |  | 
|  | 193 | std::vector<MVT::ValueType> RetVals; | 
|  | 194 | MVT::ValueType RetTyVT = getValueType(RetTy); | 
|  | 195 | if (RetTyVT != MVT::isVoid) | 
|  | 196 | RetVals.push_back(RetTyVT); | 
|  | 197 | RetVals.push_back(MVT::Other); | 
|  | 198 |  | 
|  | 199 | SDOperand TheCall = SDOperand(DAG.getCall(RetVals, Chain, Callee, args_to_use), 0); | 
|  | 200 | Chain = TheCall.getValue(RetTyVT != MVT::isVoid); | 
|  | 201 | Chain = DAG.getNode(ISD::ADJCALLSTACKUP, MVT::Other, Chain, | 
|  | 202 | DAG.getConstant(NumBytes, getPointerTy())); | 
|  | 203 | return std::make_pair(TheCall, Chain); | 
|  | 204 | } | 
|  | 205 |  | 
|  | 206 | std::pair<SDOperand, SDOperand> | 
|  | 207 | AlphaTargetLowering::LowerVAStart(SDOperand Chain, SelectionDAG &DAG) { | 
|  | 208 | //vastart just returns the address of the VarArgsFrameIndex slot. | 
|  | 209 | return std::make_pair(DAG.getFrameIndex(VarArgsFrameIndex, MVT::i64), Chain); | 
|  | 210 | } | 
|  | 211 |  | 
|  | 212 | std::pair<SDOperand,SDOperand> AlphaTargetLowering:: | 
|  | 213 | LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList, | 
|  | 214 | const Type *ArgTy, SelectionDAG &DAG) { | 
|  | 215 | abort(); | 
|  | 216 | } | 
|  | 217 |  | 
|  | 218 |  | 
|  | 219 | std::pair<SDOperand, SDOperand> AlphaTargetLowering:: | 
|  | 220 | LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth, | 
|  | 221 | SelectionDAG &DAG) { | 
|  | 222 | abort(); | 
|  | 223 | } | 
|  | 224 |  | 
|  | 225 |  | 
|  | 226 |  | 
|  | 227 |  | 
|  | 228 |  | 
|  | 229 | namespace { | 
|  | 230 |  | 
|  | 231 | //===--------------------------------------------------------------------===// | 
|  | 232 | /// ISel - Alpha specific code to select Alpha machine instructions for | 
|  | 233 | /// SelectionDAG operations. | 
|  | 234 | /// | 
|  | 235 | class ISel : public SelectionDAGISel { | 
|  | 236 |  | 
|  | 237 | /// AlphaLowering - This object fully describes how to lower LLVM code to an | 
|  | 238 | /// Alpha-specific SelectionDAG. | 
|  | 239 | AlphaTargetLowering AlphaLowering; | 
|  | 240 |  | 
|  | 241 |  | 
|  | 242 | /// ExprMap - As shared expressions are codegen'd, we keep track of which | 
|  | 243 | /// vreg the value is produced in, so we only emit one copy of each compiled | 
|  | 244 | /// tree. | 
|  | 245 | std::map<SDOperand, unsigned> ExprMap; | 
|  | 246 | std::set<SDOperand> LoweredTokens; | 
|  | 247 |  | 
|  | 248 | public: | 
|  | 249 | ISel(TargetMachine &TM) : SelectionDAGISel(AlphaLowering), AlphaLowering(TM) { | 
|  | 250 | } | 
|  | 251 |  | 
|  | 252 | /// InstructionSelectBasicBlock - This callback is invoked by | 
|  | 253 | /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. | 
|  | 254 | virtual void InstructionSelectBasicBlock(SelectionDAG &DAG) { | 
|  | 255 | // Codegen the basic block. | 
|  | 256 | Select(DAG.getRoot()); | 
|  | 257 |  | 
|  | 258 | // Clear state used for selection. | 
|  | 259 | ExprMap.clear(); | 
|  | 260 | LoweredTokens.clear(); | 
|  | 261 | } | 
|  | 262 |  | 
|  | 263 | unsigned SelectExpr(SDOperand N); | 
|  | 264 | void Select(SDOperand N); | 
|  | 265 | }; | 
|  | 266 | } | 
|  | 267 |  | 
|  | 268 | unsigned ISel::SelectExpr(SDOperand N) { | 
|  | 269 | unsigned Result; | 
|  | 270 | unsigned Tmp1, Tmp2, Tmp3; | 
|  | 271 | unsigned Opc = 0; | 
|  | 272 |  | 
|  | 273 | SDNode *Node = N.Val; | 
|  | 274 |  | 
|  | 275 | unsigned &Reg = ExprMap[N]; | 
|  | 276 | if (Reg) return Reg; | 
|  | 277 |  | 
|  | 278 | if (N.getOpcode() != ISD::CALL) | 
|  | 279 | Reg = Result = (N.getValueType() != MVT::Other) ? | 
|  | 280 | MakeReg(N.getValueType()) : 1; | 
|  | 281 | else { | 
|  | 282 | // If this is a call instruction, make sure to prepare ALL of the result | 
|  | 283 | // values as well as the chain. | 
|  | 284 | if (Node->getNumValues() == 1) | 
|  | 285 | Reg = Result = 1;  // Void call, just a chain. | 
|  | 286 | else { | 
|  | 287 | Result = MakeReg(Node->getValueType(0)); | 
|  | 288 | ExprMap[N.getValue(0)] = Result; | 
|  | 289 | for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i) | 
|  | 290 | ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i)); | 
|  | 291 | ExprMap[SDOperand(Node, Node->getNumValues()-1)] = 1; | 
|  | 292 | } | 
|  | 293 | } | 
|  | 294 |  | 
|  | 295 | switch (N.getOpcode()) { | 
|  | 296 | default: | 
|  | 297 | Node->dump(); | 
|  | 298 | assert(0 && "Node not handled!\n"); | 
|  | 299 |  | 
|  | 300 | case ISD::FrameIndex: | 
|  | 301 | Tmp1 = cast<FrameIndexSDNode>(N)->getIndex(); | 
|  | 302 | BuildMI(BB, Alpha::LDA, 2, Result).addImm(Tmp1 * 8).addReg(Alpha::R30); | 
|  | 303 | return Result; | 
|  | 304 |  | 
|  | 305 | case ISD::EXTLOAD: | 
| Andrew Lenharth | 2f8fb77 | 2005-01-25 00:35:34 +0000 | [diff] [blame] | 306 | // Make sure we generate both values. | 
|  | 307 | if (Result != 1) | 
|  | 308 | ExprMap[N.getValue(1)] = 1;   // Generate the token | 
|  | 309 | else | 
|  | 310 | Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType()); | 
|  | 311 |  | 
|  | 312 | Select(Node->getOperand(0)); // chain | 
|  | 313 | Tmp1 = SelectExpr(Node->getOperand(1)); | 
|  | 314 |  | 
|  | 315 | switch(Node->getValueType(0)) { | 
|  | 316 | default: assert(0 && "Unknown type to sign extend to."); | 
|  | 317 | case MVT::i64: | 
|  | 318 | switch (cast<MVTSDNode>(Node)->getExtraValueType()) { | 
|  | 319 | default: | 
| Andrew Lenharth | d279b41 | 2005-01-25 19:58:40 +0000 | [diff] [blame^] | 320 | std::cerr << cast<MVTSDNode>(Node)->getExtraValueType() | 
|  | 321 | << "(i1 is " << MVT::i1 | 
|  | 322 | << " i8 is " << MVT::i8 | 
|  | 323 | << " i16 is " << MVT::i16 | 
|  | 324 | << " i32 is " << MVT::i32 | 
|  | 325 | << " i64 is " << MVT::i64 | 
|  | 326 | << ")\n"; | 
|  | 327 | assert(0 && "Bad extend load!"); | 
|  | 328 | case MVT::i64: | 
|  | 329 | BuildMI(BB, Alpha::LDQ, 2, Result).addImm(0).addReg(Tmp1); | 
|  | 330 | break; | 
| Andrew Lenharth | 2f8fb77 | 2005-01-25 00:35:34 +0000 | [diff] [blame] | 331 | case MVT::i32: | 
|  | 332 | BuildMI(BB, Alpha::LDL, 2, Result).addImm(0).addReg(Tmp1); | 
|  | 333 | break; | 
|  | 334 | case MVT::i16: | 
|  | 335 | BuildMI(BB, Alpha::LDWU, 2, Result).addImm(0).addReg(Tmp1); | 
|  | 336 | break; | 
|  | 337 | case MVT::i8: | 
| Andrew Lenharth | d279b41 | 2005-01-25 19:58:40 +0000 | [diff] [blame^] | 338 | case MVT::i1: //FIXME: DAG does not expand i8?? | 
| Andrew Lenharth | 2f8fb77 | 2005-01-25 00:35:34 +0000 | [diff] [blame] | 339 | BuildMI(BB, Alpha::LDBU, 2, Result).addImm(0).addReg(Tmp1); | 
|  | 340 | break; | 
|  | 341 | } | 
|  | 342 | break; | 
|  | 343 | } | 
|  | 344 | return Result; | 
|  | 345 |  | 
| Andrew Lenharth | 304d0f3 | 2005-01-22 23:41:55 +0000 | [diff] [blame] | 346 | case ISD::SEXTLOAD: | 
|  | 347 | // Make sure we generate both values. | 
|  | 348 | if (Result != 1) | 
|  | 349 | ExprMap[N.getValue(1)] = 1;   // Generate the token | 
|  | 350 | else | 
|  | 351 | Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType()); | 
|  | 352 |  | 
|  | 353 | Select(Node->getOperand(0)); // chain | 
|  | 354 | Tmp1 = SelectExpr(Node->getOperand(1)); | 
|  | 355 | switch(Node->getValueType(0)) { | 
|  | 356 | default: assert(0 && "Unknown type to sign extend to."); | 
|  | 357 | case MVT::i64: | 
|  | 358 | switch (cast<MVTSDNode>(Node)->getExtraValueType()) { | 
|  | 359 | default: | 
|  | 360 | assert(0 && "Bad sign extend!"); | 
|  | 361 | case MVT::i32: | 
|  | 362 | BuildMI(BB, Alpha::LDL, 2, Result).addImm(0).addReg(Tmp1); | 
|  | 363 | break; | 
| Andrew Lenharth | 2f8fb77 | 2005-01-25 00:35:34 +0000 | [diff] [blame] | 364 | //       case MVT::i16: | 
|  | 365 | // 	BuildMI(BB, Alpha::LDW, 2, Result).addImm(0).addReg(Tmp1); | 
|  | 366 | //         break; | 
|  | 367 | //       case MVT::i8: | 
|  | 368 | // 	BuildMI(BB, Alpha::LDB, 2, Result).addImm(0).addReg(Tmp1); | 
|  | 369 | //         break; | 
|  | 370 | } | 
|  | 371 | break; | 
|  | 372 | } | 
|  | 373 | return Result; | 
|  | 374 |  | 
|  | 375 | case ISD::ZEXTLOAD: | 
|  | 376 | // Make sure we generate both values. | 
|  | 377 | if (Result != 1) | 
|  | 378 | ExprMap[N.getValue(1)] = 1;   // Generate the token | 
|  | 379 | else | 
|  | 380 | Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType()); | 
|  | 381 |  | 
|  | 382 | Select(Node->getOperand(0)); // chain | 
|  | 383 | Tmp1 = SelectExpr(Node->getOperand(1)); | 
|  | 384 | switch(Node->getValueType(0)) { | 
|  | 385 | default: assert(0 && "Unknown type to zero extend to."); | 
|  | 386 | case MVT::i64: | 
|  | 387 | switch (cast<MVTSDNode>(Node)->getExtraValueType()) { | 
|  | 388 | default: | 
|  | 389 | assert(0 && "Bad sign extend!"); | 
| Andrew Lenharth | 304d0f3 | 2005-01-22 23:41:55 +0000 | [diff] [blame] | 390 | case MVT::i16: | 
| Andrew Lenharth | 2f8fb77 | 2005-01-25 00:35:34 +0000 | [diff] [blame] | 391 | BuildMI(BB, Alpha::LDWU, 2, Result).addImm(0).addReg(Tmp1); | 
| Andrew Lenharth | 304d0f3 | 2005-01-22 23:41:55 +0000 | [diff] [blame] | 392 | break; | 
|  | 393 | case MVT::i8: | 
| Andrew Lenharth | 2f8fb77 | 2005-01-25 00:35:34 +0000 | [diff] [blame] | 394 | BuildMI(BB, Alpha::LDBU, 2, Result).addImm(0).addReg(Tmp1); | 
| Andrew Lenharth | 304d0f3 | 2005-01-22 23:41:55 +0000 | [diff] [blame] | 395 | break; | 
|  | 396 | } | 
|  | 397 | break; | 
|  | 398 | } | 
|  | 399 | return Result; | 
|  | 400 |  | 
| Andrew Lenharth | 2f8fb77 | 2005-01-25 00:35:34 +0000 | [diff] [blame] | 401 |  | 
| Andrew Lenharth | 304d0f3 | 2005-01-22 23:41:55 +0000 | [diff] [blame] | 402 | case ISD::GlobalAddress: | 
|  | 403 | AlphaLowering.restoreGP(BB); | 
|  | 404 | BuildMI(BB, Alpha::LOAD_ADDR, 1, Result) | 
|  | 405 | .addGlobalAddress(cast<GlobalAddressSDNode>(N)->getGlobal()); | 
|  | 406 | return Result; | 
|  | 407 |  | 
|  | 408 | case ISD::CALL: | 
|  | 409 | { | 
|  | 410 | Select(N.getOperand(0)); | 
|  | 411 |  | 
|  | 412 | // The chain for this call is now lowered. | 
|  | 413 | ExprMap.insert(std::make_pair(N.getValue(Node->getNumValues()-1), 1)); | 
|  | 414 |  | 
|  | 415 | //grab the arguments | 
|  | 416 | std::vector<unsigned> argvregs; | 
|  | 417 | assert(Node->getNumOperands() < 8 && "Only 6 args supported"); | 
|  | 418 | for(int i = 2, e = Node->getNumOperands(); i < e; ++i) | 
|  | 419 | { | 
|  | 420 | argvregs.push_back(SelectExpr(N.getOperand(i))); | 
|  | 421 | } | 
|  | 422 | for(int i = 0, e = argvregs.size(); i < e; ++i) | 
|  | 423 | { | 
|  | 424 | unsigned args[] = {Alpha::R16, Alpha::R17, Alpha::R18, | 
|  | 425 | Alpha::R19, Alpha::R20, Alpha::R21}; | 
|  | 426 |  | 
|  | 427 | BuildMI(BB, Alpha::BIS, 2, args[i]).addReg(argvregs[i]).addReg(argvregs[i]); | 
|  | 428 | } | 
|  | 429 |  | 
|  | 430 | //build the right kind of call | 
|  | 431 | if (GlobalAddressSDNode *GASD = | 
|  | 432 | dyn_cast<GlobalAddressSDNode>(N.getOperand(1))) | 
|  | 433 | { | 
|  | 434 | Select(N.getOperand(0)); | 
|  | 435 | AlphaLowering.restoreGP(BB); | 
|  | 436 | BuildMI(BB, Alpha::CALL, 1).addGlobalAddress(GASD->getGlobal(),true); | 
|  | 437 | } | 
|  | 438 | else if (ExternalSymbolSDNode *ESSDN = | 
|  | 439 | dyn_cast<ExternalSymbolSDNode>(N.getOperand(1))) | 
|  | 440 | { | 
|  | 441 | Select(N.getOperand(0)); | 
|  | 442 | AlphaLowering.restoreGP(BB); | 
|  | 443 | BuildMI(BB, Alpha::CALL, 0).addExternalSymbol(ESSDN->getSymbol(), true); | 
|  | 444 | } | 
|  | 445 | else { | 
|  | 446 | Select(N.getOperand(0)); | 
|  | 447 | Tmp1 = SelectExpr(N.getOperand(1)); | 
|  | 448 | BuildMI(BB, Alpha::CALL, 1).addReg(Tmp1); | 
|  | 449 | AlphaLowering.restoreGP(BB); | 
|  | 450 | } | 
|  | 451 |  | 
|  | 452 | //push the result into a virtual register | 
|  | 453 | //    if (Result != 1) | 
|  | 454 | //      BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R0).addReg(Alpha::R0); | 
|  | 455 |  | 
|  | 456 | switch (Node->getValueType(0)) { | 
|  | 457 | default: assert(0 && "Unknown value type for call result!"); | 
|  | 458 | case MVT::Other: return 1; | 
|  | 459 | case MVT::i1: | 
|  | 460 | case MVT::i8: | 
|  | 461 | case MVT::i16: | 
|  | 462 | case MVT::i32: | 
|  | 463 | case MVT::i64: | 
|  | 464 | BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R0).addReg(Alpha::R0); | 
|  | 465 | break; | 
|  | 466 | } | 
|  | 467 | return Result+N.ResNo; | 
|  | 468 | } | 
|  | 469 |  | 
|  | 470 | case ISD::SIGN_EXTEND: | 
| Andrew Lenharth | 304d0f3 | 2005-01-22 23:41:55 +0000 | [diff] [blame] | 471 | case ISD::SIGN_EXTEND_INREG: | 
|  | 472 | { | 
|  | 473 | Tmp1 = SelectExpr(N.getOperand(0)); | 
|  | 474 | MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node); | 
|  | 475 | std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n"; | 
|  | 476 | switch(MVN->getExtraValueType()) | 
|  | 477 | { | 
|  | 478 | default: | 
|  | 479 | assert(0 && "Sign Extend InReg not there yet"); | 
|  | 480 | break; | 
|  | 481 | case MVT::i32: | 
|  | 482 | { | 
| Andrew Lenharth | 2f8fb77 | 2005-01-25 00:35:34 +0000 | [diff] [blame] | 483 | BuildMI(BB, Alpha::ADDLi, 2, Result).addReg(Tmp1).addImm(0); | 
| Andrew Lenharth | 304d0f3 | 2005-01-22 23:41:55 +0000 | [diff] [blame] | 484 | break; | 
|  | 485 | } | 
|  | 486 | case MVT::i16: | 
|  | 487 | BuildMI(BB, Alpha::SEXTW, 1, Result).addReg(Tmp1); | 
|  | 488 | break; | 
|  | 489 | case MVT::i8: | 
|  | 490 | BuildMI(BB, Alpha::SEXTB, 1, Result).addReg(Tmp1); | 
|  | 491 | break; | 
|  | 492 | } | 
|  | 493 | return Result; | 
|  | 494 | } | 
|  | 495 | case ISD::ZERO_EXTEND_INREG: | 
|  | 496 | { | 
|  | 497 | Tmp1 = SelectExpr(N.getOperand(0)); | 
|  | 498 | MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node); | 
|  | 499 | std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n"; | 
|  | 500 | switch(MVN->getExtraValueType()) | 
|  | 501 | { | 
|  | 502 | default: | 
|  | 503 | assert(0 && "Zero Extend InReg not there yet"); | 
|  | 504 | break; | 
| Andrew Lenharth | 2f8fb77 | 2005-01-25 00:35:34 +0000 | [diff] [blame] | 505 | case MVT::i32: Tmp2 = 0xf0; break; | 
|  | 506 | case MVT::i16: Tmp2 = 0xfc; break; | 
|  | 507 | case MVT::i8: Tmp2 = 0xfe; break; | 
| Andrew Lenharth | 304d0f3 | 2005-01-22 23:41:55 +0000 | [diff] [blame] | 508 | } | 
| Andrew Lenharth | 2f8fb77 | 2005-01-25 00:35:34 +0000 | [diff] [blame] | 509 | BuildMI(BB, Alpha::ZAPi, 2, Result).addReg(Tmp1).addImm(Tmp2); | 
|  | 510 | return Result; | 
| Andrew Lenharth | 304d0f3 | 2005-01-22 23:41:55 +0000 | [diff] [blame] | 511 | } | 
|  | 512 |  | 
|  | 513 | case ISD::SETCC: | 
|  | 514 | Tmp1 = SelectExpr(N.getOperand(0)); | 
|  | 515 | Tmp2 = SelectExpr(N.getOperand(1)); | 
|  | 516 | if (SetCCSDNode *SetCC = dyn_cast<SetCCSDNode>(Node)) { | 
|  | 517 | if (MVT::isInteger(SetCC->getOperand(0).getValueType())) { | 
|  | 518 | switch (SetCC->getCondition()) { | 
|  | 519 | default: assert(0 && "Unknown integer comparison!"); | 
|  | 520 | case ISD::SETEQ: | 
|  | 521 | BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Tmp1).addReg(Tmp2); | 
|  | 522 | break; | 
|  | 523 | case ISD::SETGT: | 
|  | 524 | BuildMI(BB, Alpha::CMPLT, 2, Result).addReg(Tmp2).addReg(Tmp1); | 
|  | 525 | break; | 
|  | 526 | case ISD::SETGE: | 
|  | 527 | BuildMI(BB, Alpha::CMPLE, 2, Result).addReg(Tmp2).addReg(Tmp1); | 
|  | 528 | break; | 
|  | 529 | case ISD::SETLT: | 
|  | 530 | BuildMI(BB, Alpha::CMPLT, 2, Result).addReg(Tmp1).addReg(Tmp2); | 
|  | 531 | break; | 
|  | 532 | case ISD::SETLE: | 
|  | 533 | BuildMI(BB, Alpha::CMPLE, 2, Result).addReg(Tmp1).addReg(Tmp2); | 
|  | 534 | break; | 
|  | 535 | case ISD::SETNE: | 
|  | 536 | { | 
|  | 537 | unsigned Tmp3 = MakeReg(MVT::i64); | 
|  | 538 | BuildMI(BB, Alpha::CMPEQ, 2, Tmp3).addReg(Tmp1).addReg(Tmp2); | 
|  | 539 | BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Tmp3).addReg(Alpha::R31); | 
|  | 540 | break; | 
|  | 541 | } | 
|  | 542 | case ISD::SETULT: | 
|  | 543 | BuildMI(BB, Alpha::CMPULT, 2, Result).addReg(Tmp1).addReg(Tmp2); | 
|  | 544 | break; | 
|  | 545 | case ISD::SETUGT: | 
|  | 546 | BuildMI(BB, Alpha::CMPULT, 2, Result).addReg(Tmp2).addReg(Tmp1); | 
|  | 547 | break; | 
|  | 548 | case ISD::SETULE: | 
|  | 549 | BuildMI(BB, Alpha::CMPULE, 2, Result).addReg(Tmp1).addReg(Tmp2); | 
|  | 550 | break; | 
|  | 551 | case ISD::SETUGE: | 
|  | 552 | BuildMI(BB, Alpha::CMPULE, 2, Result).addReg(Tmp2).addReg(Tmp1); | 
|  | 553 | break; | 
|  | 554 | } | 
|  | 555 | } | 
|  | 556 | else | 
|  | 557 | assert(0 && "only integer"); | 
|  | 558 | } | 
|  | 559 | else | 
|  | 560 | assert(0 && "Not a setcc in setcc"); | 
|  | 561 |  | 
|  | 562 | return Result; | 
|  | 563 |  | 
|  | 564 | case ISD::CopyFromReg: | 
|  | 565 | { | 
|  | 566 | if (Result == 1) | 
|  | 567 | Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType()); | 
|  | 568 |  | 
|  | 569 | SDOperand Chain   = N.getOperand(0); | 
|  | 570 |  | 
|  | 571 | Select(Chain); | 
|  | 572 | unsigned r = dyn_cast<RegSDNode>(Node)->getReg(); | 
|  | 573 | //std::cerr << "CopyFromReg " << Result << " = " << r << "\n"; | 
|  | 574 | BuildMI(BB, Alpha::BIS, 2, Result).addReg(r).addReg(r); | 
|  | 575 | return Result; | 
|  | 576 | } | 
|  | 577 |  | 
| Andrew Lenharth | 2d6f022 | 2005-01-24 19:44:07 +0000 | [diff] [blame] | 578 | //Most of the plain arithmetic and logic share the same form, and the same | 
|  | 579 | //constant immediate test | 
|  | 580 | case ISD::AND: | 
|  | 581 | case ISD::OR: | 
|  | 582 | case ISD::XOR: | 
|  | 583 | case ISD::SHL: | 
|  | 584 | case ISD::SRL: | 
|  | 585 | case ISD::MUL: | 
|  | 586 | if(N.getOperand(1).getOpcode() == ISD::Constant && | 
|  | 587 | cast<ConstantSDNode>(N.getOperand(1))->getValue() >= 0 && | 
|  | 588 | cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255) | 
|  | 589 | { | 
|  | 590 | switch(N.getOpcode()) { | 
|  | 591 | case ISD::AND: Opc = Alpha::ANDi; break; | 
|  | 592 | case ISD::OR:  Opc = Alpha::BISi; break; | 
|  | 593 | case ISD::XOR: Opc = Alpha::XORi; break; | 
|  | 594 | case ISD::SHL: Opc = Alpha::SLi; break; | 
|  | 595 | case ISD::SRL: Opc = Alpha::SRLi; break; | 
|  | 596 | case ISD::SRA: Opc = Alpha::SRAi; break; | 
|  | 597 | case ISD::MUL: Opc = Alpha::MULQi; break; | 
|  | 598 | }; | 
|  | 599 | Tmp1 = SelectExpr(N.getOperand(0)); | 
|  | 600 | Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue(); | 
|  | 601 | BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2); | 
|  | 602 | } | 
|  | 603 | else | 
|  | 604 | { | 
|  | 605 | switch(N.getOpcode()) { | 
|  | 606 | case ISD::AND: Opc = Alpha::AND; break; | 
|  | 607 | case ISD::OR:  Opc = Alpha::BIS; break; | 
|  | 608 | case ISD::XOR: Opc = Alpha::XOR; break; | 
|  | 609 | case ISD::SHL: Opc = Alpha::SL; break; | 
|  | 610 | case ISD::SRL: Opc = Alpha::SRL; break; | 
|  | 611 | case ISD::SRA: Opc = Alpha::SRA; break; | 
|  | 612 | case ISD::MUL: Opc = Alpha::MULQ; break; | 
|  | 613 | }; | 
|  | 614 | Tmp1 = SelectExpr(N.getOperand(0)); | 
|  | 615 | Tmp2 = SelectExpr(N.getOperand(1)); | 
|  | 616 | BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2); | 
|  | 617 | } | 
|  | 618 | return Result; | 
|  | 619 |  | 
| Andrew Lenharth | 304d0f3 | 2005-01-22 23:41:55 +0000 | [diff] [blame] | 620 | case ISD::ADD: | 
| Andrew Lenharth | 304d0f3 | 2005-01-22 23:41:55 +0000 | [diff] [blame] | 621 | case ISD::SUB: | 
| Andrew Lenharth | 2f8fb77 | 2005-01-25 00:35:34 +0000 | [diff] [blame] | 622 | { | 
|  | 623 | bool isAdd = N.getOpcode() == ISD::ADD; | 
|  | 624 |  | 
|  | 625 | //FIXME: first check for Scaled Adds and Subs! | 
|  | 626 | if(N.getOperand(1).getOpcode() == ISD::Constant && | 
|  | 627 | cast<ConstantSDNode>(N.getOperand(1))->getValue() >= 0 && | 
|  | 628 | cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255) | 
|  | 629 | { //Normal imm add/sub | 
|  | 630 | Opc = isAdd ? Alpha::ADDQi : Alpha::SUBQi; | 
|  | 631 | Tmp1 = SelectExpr(N.getOperand(0)); | 
|  | 632 | Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue(); | 
|  | 633 | BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2); | 
|  | 634 | } | 
|  | 635 | else if(N.getOperand(1).getOpcode() == ISD::Constant && | 
|  | 636 | cast<ConstantSDNode>(N.getOperand(1))->getValue() >= 0 && | 
|  | 637 | cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 32767) | 
|  | 638 | { //LDA  //FIXME: expand the above condition a bit | 
|  | 639 | Tmp1 = SelectExpr(N.getOperand(0)); | 
|  | 640 | Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue(); | 
|  | 641 | if (!isAdd) | 
|  | 642 | Tmp2 = -Tmp2; | 
|  | 643 | BuildMI(BB, Alpha::LDA, 2, Result).addImm(Tmp2).addReg(Tmp1); | 
|  | 644 | } | 
|  | 645 | else | 
|  | 646 | { //Normal add/sub | 
|  | 647 | Opc = isAdd ? Alpha::ADDQ : Alpha::SUBQ; | 
|  | 648 | Tmp1 = SelectExpr(N.getOperand(0)); | 
|  | 649 | Tmp2 = SelectExpr(N.getOperand(1)); | 
|  | 650 | BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2); | 
|  | 651 |  | 
|  | 652 | } | 
|  | 653 | return Result; | 
|  | 654 | } | 
| Andrew Lenharth | 304d0f3 | 2005-01-22 23:41:55 +0000 | [diff] [blame] | 655 |  | 
| Andrew Lenharth | 304d0f3 | 2005-01-22 23:41:55 +0000 | [diff] [blame] | 656 | case ISD::UREM: | 
|  | 657 | Tmp1 = SelectExpr(N.getOperand(0)); | 
|  | 658 | Tmp2 = SelectExpr(N.getOperand(1)); | 
|  | 659 | BuildMI(BB, Alpha::REMQU, 2, Result).addReg(Tmp1).addReg(Tmp2); | 
|  | 660 | return Result; | 
|  | 661 |  | 
|  | 662 | case ISD::SELECT: | 
|  | 663 | { | 
|  | 664 | Tmp2 = SelectExpr(N.getOperand(1)); //Use if TRUE | 
|  | 665 | Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE | 
|  | 666 | Tmp1 = SelectExpr(N.getOperand(0)); //Cond | 
|  | 667 | // Get the condition into the zero flag. | 
|  | 668 | unsigned dummy = MakeReg(MVT::i64); | 
|  | 669 | BuildMI(BB, Alpha::BIS, 2, dummy).addReg(Tmp3).addReg(Tmp3); | 
|  | 670 | BuildMI(BB, Alpha::CMOVEQ, 2, Result).addReg(Tmp2).addReg(Tmp1); | 
|  | 671 | return Result; | 
|  | 672 | } | 
|  | 673 |  | 
| Andrew Lenharth | 304d0f3 | 2005-01-22 23:41:55 +0000 | [diff] [blame] | 674 | case ISD::Constant: | 
|  | 675 | { | 
|  | 676 | long val = cast<ConstantSDNode>(N)->getValue(); | 
|  | 677 | BuildMI(BB, Alpha::LOAD_IMM, 1, Result).addImm(val); | 
|  | 678 | return Result; | 
|  | 679 | } | 
|  | 680 |  | 
| Andrew Lenharth | 304d0f3 | 2005-01-22 23:41:55 +0000 | [diff] [blame] | 681 | case ISD::LOAD: | 
|  | 682 | { | 
|  | 683 | // Make sure we generate both values. | 
|  | 684 | if (Result != 1) | 
|  | 685 | ExprMap[N.getValue(1)] = 1;   // Generate the token | 
|  | 686 | else | 
|  | 687 | Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType()); | 
|  | 688 |  | 
|  | 689 | SDOperand Chain   = N.getOperand(0); | 
|  | 690 | SDOperand Address = N.getOperand(1); | 
|  | 691 |  | 
|  | 692 | if (Address.getOpcode() == ISD::GlobalAddress) | 
|  | 693 | { | 
|  | 694 | Select(Chain); | 
|  | 695 | AlphaLowering.restoreGP(BB); | 
|  | 696 | BuildMI(BB, Alpha::LOAD, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal()); | 
|  | 697 | } | 
|  | 698 | else | 
|  | 699 | { | 
|  | 700 | Select(Chain); | 
|  | 701 | Tmp2 = SelectExpr(Address); | 
|  | 702 | BuildMI(BB, Alpha::LDQ, 2, Result).addImm(0).addReg(Tmp2); | 
|  | 703 | } | 
|  | 704 | return Result; | 
|  | 705 | } | 
|  | 706 | } | 
|  | 707 |  | 
|  | 708 | return 0; | 
|  | 709 | } | 
|  | 710 |  | 
|  | 711 | void ISel::Select(SDOperand N) { | 
|  | 712 | unsigned Tmp1, Tmp2, Opc; | 
|  | 713 |  | 
|  | 714 | // FIXME: Disable for our current expansion model! | 
|  | 715 | if (/*!N->hasOneUse() &&*/ !LoweredTokens.insert(N).second) | 
|  | 716 | return;  // Already selected. | 
|  | 717 |  | 
|  | 718 | SDNode *Node = N.Val; | 
|  | 719 |  | 
|  | 720 | switch (N.getOpcode()) { | 
|  | 721 |  | 
|  | 722 | default: | 
|  | 723 | Node->dump(); std::cerr << "\n"; | 
|  | 724 | assert(0 && "Node not handled yet!"); | 
|  | 725 |  | 
|  | 726 | case ISD::BRCOND: { | 
|  | 727 | MachineBasicBlock *Dest = | 
|  | 728 | cast<BasicBlockSDNode>(N.getOperand(2))->getBasicBlock(); | 
|  | 729 |  | 
|  | 730 | Select(N.getOperand(0)); | 
|  | 731 | Tmp1 = SelectExpr(N.getOperand(1)); | 
|  | 732 | BuildMI(BB, Alpha::BNE, 2).addReg(Tmp1).addMBB(Dest); | 
|  | 733 | return; | 
|  | 734 | } | 
|  | 735 |  | 
|  | 736 | case ISD::BR: { | 
|  | 737 | MachineBasicBlock *Dest = | 
|  | 738 | cast<BasicBlockSDNode>(N.getOperand(1))->getBasicBlock(); | 
|  | 739 |  | 
|  | 740 | Select(N.getOperand(0)); | 
|  | 741 | BuildMI(BB, Alpha::BR, 1, Alpha::R31).addMBB(Dest); | 
|  | 742 | return; | 
|  | 743 | } | 
|  | 744 |  | 
|  | 745 | case ISD::ImplicitDef: | 
|  | 746 | Select(N.getOperand(0)); | 
|  | 747 | BuildMI(BB, Alpha::IDEF, 0, cast<RegSDNode>(N)->getReg()); | 
|  | 748 | return; | 
|  | 749 |  | 
|  | 750 | case ISD::EntryToken: return;  // Noop | 
|  | 751 |  | 
|  | 752 | case ISD::TokenFactor: | 
|  | 753 | for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i) | 
|  | 754 | Select(Node->getOperand(i)); | 
|  | 755 |  | 
|  | 756 | //N.Val->dump(); std::cerr << "\n"; | 
|  | 757 | //assert(0 && "Node not handled yet!"); | 
|  | 758 |  | 
|  | 759 | return; | 
|  | 760 |  | 
|  | 761 | case ISD::CopyToReg: | 
|  | 762 | Select(N.getOperand(0)); | 
|  | 763 | Tmp1 = SelectExpr(N.getOperand(1)); | 
|  | 764 | Tmp2 = cast<RegSDNode>(N)->getReg(); | 
|  | 765 |  | 
|  | 766 | if (Tmp1 != Tmp2) { | 
|  | 767 | BuildMI(BB, Alpha::BIS, 2, Tmp2).addReg(Tmp1).addReg(Tmp1); | 
|  | 768 | } | 
|  | 769 | return; | 
|  | 770 |  | 
|  | 771 | case ISD::RET: | 
|  | 772 | switch (N.getNumOperands()) { | 
|  | 773 | default: | 
|  | 774 | std::cerr << N.getNumOperands() << "\n"; | 
|  | 775 | for (unsigned i = 0; i < N.getNumOperands(); ++i) | 
|  | 776 | std::cerr << N.getOperand(i).getValueType() << "\n"; | 
|  | 777 | assert(0 && "Unknown return instruction!"); | 
|  | 778 | case 2: | 
|  | 779 | Select(N.getOperand(0)); | 
|  | 780 | Tmp1 = SelectExpr(N.getOperand(1)); | 
|  | 781 | switch (N.getOperand(1).getValueType()) { | 
|  | 782 | default: assert(0 && "All other types should have been promoted!!"); | 
| Andrew Lenharth | 2f8fb77 | 2005-01-25 00:35:34 +0000 | [diff] [blame] | 783 | case MVT::i32: | 
| Andrew Lenharth | 304d0f3 | 2005-01-22 23:41:55 +0000 | [diff] [blame] | 784 | case MVT::i64: | 
|  | 785 | BuildMI(BB, Alpha::BIS, 2, Alpha::R0).addReg(Tmp1).addReg(Tmp1); | 
|  | 786 | break; | 
|  | 787 | } | 
|  | 788 | break; | 
|  | 789 | case 1: | 
|  | 790 | Select(N.getOperand(0)); | 
|  | 791 | break; | 
|  | 792 | } | 
|  | 793 | //Tmp2 = AlphaLowering.getRetAddr(); | 
|  | 794 | //BuildMI(BB, Alpha::BIS, 2, Alpha::R26).addReg(Tmp2).addReg(Tmp2); | 
|  | 795 | BuildMI(BB, Alpha::RETURN, 0); // Just emit a 'ret' instruction | 
|  | 796 | return; | 
|  | 797 |  | 
|  | 798 | case ISD::STORE: | 
|  | 799 | Select(N.getOperand(0)); | 
|  | 800 | Tmp1 = SelectExpr(N.getOperand(1)); //value | 
|  | 801 | if (N.getOperand(2).getOpcode() == ISD::GlobalAddress) | 
|  | 802 | { | 
|  | 803 | AlphaLowering.restoreGP(BB); | 
|  | 804 | BuildMI(BB, Alpha::STORE, 2).addReg(Tmp1).addGlobalAddress(cast<GlobalAddressSDNode>(N.getOperand(2))->getGlobal()); | 
|  | 805 | } | 
|  | 806 | else | 
|  | 807 | { | 
|  | 808 | Tmp2 = SelectExpr(N.getOperand(2)); //address | 
|  | 809 | BuildMI(BB, Alpha::STQ, 3).addReg(Tmp1).addImm(0).addReg(Tmp2); | 
|  | 810 | } | 
|  | 811 | return; | 
|  | 812 |  | 
|  | 813 | case ISD::EXTLOAD: | 
|  | 814 | case ISD::SEXTLOAD: | 
|  | 815 | case ISD::ZEXTLOAD: | 
|  | 816 | case ISD::LOAD: | 
|  | 817 | case ISD::CopyFromReg: | 
|  | 818 | case ISD::CALL: | 
|  | 819 | //   case ISD::DYNAMIC_STACKALLOC: | 
|  | 820 | SelectExpr(N); | 
|  | 821 | return; | 
|  | 822 |  | 
|  | 823 |  | 
|  | 824 | case ISD::TRUNCSTORE: {  // truncstore chain, val, ptr :storety | 
|  | 825 | MVT::ValueType StoredTy = cast<MVTSDNode>(Node)->getExtraValueType(); | 
|  | 826 | assert(StoredTy != MVT::i64 && "Unsupported TRUNCSTORE for this target!"); | 
|  | 827 |  | 
|  | 828 | Select(N.getOperand(0)); | 
|  | 829 | Tmp1 = SelectExpr(N.getOperand(1)); | 
|  | 830 | Tmp2 = SelectExpr(N.getOperand(2)); | 
|  | 831 |  | 
|  | 832 | switch (StoredTy) { | 
|  | 833 | default: assert(0 && "Unhandled Type"); break; | 
| Andrew Lenharth | d279b41 | 2005-01-25 19:58:40 +0000 | [diff] [blame^] | 834 | case MVT::i1: //FIXME: DAG does not promote this load | 
| Andrew Lenharth | 304d0f3 | 2005-01-22 23:41:55 +0000 | [diff] [blame] | 835 | case MVT::i8: Opc = Alpha::STB; break; | 
|  | 836 | case MVT::i16: Opc = Alpha::STW; break; | 
|  | 837 | case MVT::i32: Opc = Alpha::STL; break; | 
|  | 838 | } | 
|  | 839 |  | 
|  | 840 | BuildMI(BB, Opc, 2).addReg(Tmp1).addImm(0).addReg(Tmp2); | 
|  | 841 | return; | 
|  | 842 | } | 
|  | 843 |  | 
|  | 844 | case ISD::ADJCALLSTACKDOWN: | 
|  | 845 | case ISD::ADJCALLSTACKUP: | 
|  | 846 | Select(N.getOperand(0)); | 
|  | 847 | Tmp1 = cast<ConstantSDNode>(N.getOperand(1))->getValue(); | 
|  | 848 |  | 
|  | 849 | Opc = N.getOpcode() == ISD::ADJCALLSTACKDOWN ? Alpha::ADJUSTSTACKDOWN : | 
|  | 850 | Alpha::ADJUSTSTACKUP; | 
|  | 851 | BuildMI(BB, Opc, 1).addImm(Tmp1); | 
|  | 852 | return; | 
|  | 853 | } | 
|  | 854 | assert(0 && "Should not be reached!"); | 
|  | 855 | } | 
|  | 856 |  | 
|  | 857 |  | 
|  | 858 | /// createAlphaPatternInstructionSelector - This pass converts an LLVM function | 
|  | 859 | /// into a machine code representation using pattern matching and a machine | 
|  | 860 | /// description file. | 
|  | 861 | /// | 
|  | 862 | FunctionPass *llvm::createAlphaPatternInstructionSelector(TargetMachine &TM) { | 
|  | 863 | return new ISel(TM); | 
|  | 864 | } |