| Andrew Lenharth | 72b16d8 | 2005-06-17 16:52:12 +0000 | [diff] [blame^] | 1 | #if 0 | 
|  | 2 | //===- SparcV8ISelPattern.cpp - A pattern matching isel for SparcV8 -------===// | 
|  | 3 | // | 
|  | 4 | //                     The LLVM Compiler Infrastructure | 
|  | 5 | // | 
|  | 6 | // This file was developed by the LLVM research group and is distributed under | 
|  | 7 | // the University of Illinois Open Source License. See LICENSE.TXT for details. | 
|  | 8 | // | 
|  | 9 | //===----------------------------------------------------------------------===// | 
|  | 10 | // | 
|  | 11 | // This file defines a pattern matching instruction selector for SparcV8. | 
|  | 12 | // | 
|  | 13 | //===----------------------------------------------------------------------===// | 
|  | 14 |  | 
|  | 15 | //Please note that this file is a work in progress, and not a high | 
|  | 16 | //priority for anyone. | 
|  | 17 |  | 
|  | 18 | #include "SparcV8.h" | 
|  | 19 | #include "SparcV8RegisterInfo.h" | 
|  | 20 | #include "llvm/Constants.h"                   // FIXME: REMOVE | 
|  | 21 | #include "llvm/Function.h" | 
|  | 22 | #include "llvm/CodeGen/MachineInstrBuilder.h" | 
|  | 23 | #include "llvm/CodeGen/MachineConstantPool.h" // FIXME: REMOVE | 
|  | 24 | #include "llvm/CodeGen/MachineFunction.h" | 
|  | 25 | #include "llvm/CodeGen/MachineFrameInfo.h" | 
|  | 26 | #include "llvm/CodeGen/SelectionDAG.h" | 
|  | 27 | #include "llvm/CodeGen/SelectionDAGISel.h" | 
|  | 28 | #include "llvm/CodeGen/SSARegMap.h" | 
|  | 29 | #include "llvm/Target/TargetData.h" | 
|  | 30 | #include "llvm/Target/TargetLowering.h" | 
|  | 31 | #include "llvm/Support/MathExtras.h" | 
|  | 32 | #include "llvm/ADT/Statistic.h" | 
|  | 33 | #include "llvm/Support/Debug.h" | 
|  | 34 | #include "llvm/Support/CommandLine.h" | 
|  | 35 | #include <set> | 
|  | 36 | #include <algorithm> | 
|  | 37 | using namespace llvm; | 
|  | 38 |  | 
|  | 39 | //===----------------------------------------------------------------------===// | 
|  | 40 | //  V8TargetLowering - SparcV8 Implementation of the TargetLowering interface | 
|  | 41 | namespace { | 
|  | 42 | class V8TargetLowering : public TargetLowering { | 
|  | 43 | int VarArgsFrameIndex;            // FrameIndex for start of varargs area. | 
|  | 44 | public: | 
|  | 45 | V8TargetLowering(TargetMachine &TM) : TargetLowering(TM) { | 
|  | 46 | // Set up the TargetLowering object. | 
|  | 47 | //I am having problems with shr n ubyte 1 | 
|  | 48 | setShiftAmountType(MVT::i32); | 
|  | 49 | setSetCCResultType(MVT::i32); | 
|  | 50 | setSetCCResultContents(ZeroOrOneSetCCResult); | 
|  | 51 |  | 
|  | 52 | //FIXME: get these right | 
|  | 53 | addRegisterClass(MVT::i64, V8::GPRCRegisterClass); | 
|  | 54 | addRegisterClass(MVT::f64, V8::FPRCRegisterClass); | 
|  | 55 | addRegisterClass(MVT::f32, V8::FPRCRegisterClass); | 
|  | 56 |  | 
|  | 57 | setOperationAction(ISD::BRCONDTWOWAY, MVT::Other, Expand); | 
|  | 58 | setOperationAction(ISD::EXTLOAD, MVT::i1,  Promote); | 
|  | 59 | setOperationAction(ISD::EXTLOAD, MVT::f32, Promote); | 
|  | 60 |  | 
|  | 61 | setOperationAction(ISD::ZEXTLOAD, MVT::i1, Expand); | 
|  | 62 | setOperationAction(ISD::SEXTLOAD, MVT::i1, Expand); | 
|  | 63 |  | 
|  | 64 | setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1,  Expand); | 
|  | 65 | setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8,  Expand); | 
|  | 66 | setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand); | 
|  | 67 | setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i32, Expand); | 
|  | 68 |  | 
|  | 69 | setOperationAction(ISD::UREM, MVT::i32, Expand); | 
|  | 70 | setOperationAction(ISD::SREM, MVT::i32, Expand); | 
|  | 71 |  | 
|  | 72 | setOperationAction(ISD::CTPOP, MVT::i32, Expand); | 
|  | 73 | setOperationAction(ISD::CTTZ, MVT::i32, Expand); | 
|  | 74 | setOperationAction(ISD::CTLZ, MVT::i32, Expand); | 
|  | 75 |  | 
|  | 76 | setOperationAction(ISD::MEMMOVE, MVT::Other, Expand); | 
|  | 77 | setOperationAction(ISD::MEMSET,  MVT::Other, Expand); | 
|  | 78 | setOperationAction(ISD::MEMCPY,  MVT::Other, Expand); | 
|  | 79 |  | 
|  | 80 | // We don't support sin/cos/sqrt | 
|  | 81 | setOperationAction(ISD::FSIN , MVT::f64, Expand); | 
|  | 82 | setOperationAction(ISD::FCOS , MVT::f64, Expand); | 
|  | 83 | setOperationAction(ISD::FSQRT, MVT::f64, Expand); | 
|  | 84 | setOperationAction(ISD::FSIN , MVT::f32, Expand); | 
|  | 85 | setOperationAction(ISD::FCOS , MVT::f32, Expand); | 
|  | 86 | setOperationAction(ISD::FSQRT, MVT::f32, Expand); | 
|  | 87 |  | 
|  | 88 | computeRegisterProperties(); | 
|  | 89 |  | 
|  | 90 | addLegalFPImmediate(+0.0); //F31 | 
|  | 91 | addLegalFPImmediate(-0.0); //-F31 | 
|  | 92 | } | 
|  | 93 |  | 
|  | 94 | /// LowerArguments - This hook must be implemented to indicate how we should | 
|  | 95 | /// lower the arguments for the specified function, into the specified DAG. | 
|  | 96 | virtual std::vector<SDOperand> | 
|  | 97 | LowerArguments(Function &F, SelectionDAG &DAG); | 
|  | 98 |  | 
|  | 99 | /// LowerCallTo - This hook lowers an abstract call to a function into an | 
|  | 100 | /// actual call. | 
|  | 101 | virtual std::pair<SDOperand, SDOperand> | 
|  | 102 | LowerCallTo(SDOperand Chain, const Type *RetTy, bool isVarArg, unsigned CC, | 
|  | 103 | bool isTailCall, SDOperand Callee, ArgListTy &Args, | 
|  | 104 | SelectionDAG &DAG); | 
|  | 105 | }; | 
|  | 106 | } | 
|  | 107 |  | 
|  | 108 | /// AddLiveIn - This helper function adds the specified physical register to the | 
|  | 109 | /// MachineFunction as a live in value.  It also creates a corresponding virtual | 
|  | 110 | /// register for it. | 
|  | 111 | static unsigned AddLiveIn(MachineFunction &MF, unsigned PReg, | 
|  | 112 | TargetRegisterClass *RC) { | 
|  | 113 | assert(RC->contains(PReg) && "Not the correct regclass!"); | 
|  | 114 | unsigned VReg = MF.getSSARegMap()->createVirtualRegister(RC); | 
|  | 115 | MF.addLiveIn(PReg, VReg); | 
|  | 116 | return VReg; | 
|  | 117 | } | 
|  | 118 |  | 
|  | 119 | std::vector<SDOperand> | 
|  | 120 | V8TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) | 
|  | 121 | { | 
|  | 122 | //FIXME | 
|  | 123 | std::vector<SDOperand> ArgValues; | 
|  | 124 |  | 
|  | 125 | MachineFunction &MF = DAG.getMachineFunction(); | 
|  | 126 | MachineFrameInfo*MFI = MF.getFrameInfo(); | 
|  | 127 |  | 
|  | 128 | MachineBasicBlock& BB = MF.front(); | 
|  | 129 |  | 
|  | 130 | //return the arguments | 
|  | 131 | return ArgValues; | 
|  | 132 | } | 
|  | 133 |  | 
|  | 134 | std::pair<SDOperand, SDOperand> | 
|  | 135 | V8TargetLowering::LowerCallTo(SDOperand Chain, | 
|  | 136 | const Type *RetTy, bool isVarArg, | 
|  | 137 | unsigned CallingConv, bool isTailCall, | 
|  | 138 | SDOperand Callee, ArgListTy &Args, | 
|  | 139 | SelectionDAG &DAG) { | 
|  | 140 | //FIXME | 
|  | 141 | return std::make_pair(Chain, Chain); | 
|  | 142 | } | 
|  | 143 |  | 
|  | 144 | namespace { | 
|  | 145 |  | 
|  | 146 | //===--------------------------------------------------------------------===// | 
|  | 147 | /// ISel - V8 specific code to select V8 machine instructions for | 
|  | 148 | /// SelectionDAG operations. | 
|  | 149 | //===--------------------------------------------------------------------===// | 
|  | 150 | class ISel : public SelectionDAGISel { | 
|  | 151 |  | 
|  | 152 | /// V8Lowering - This object fully describes how to lower LLVM code to an | 
|  | 153 | /// V8-specific SelectionDAG. | 
|  | 154 | V8TargetLowering V8Lowering; | 
|  | 155 |  | 
|  | 156 | SelectionDAG *ISelDAG;  // Hack to support us having a dag->dag transform | 
|  | 157 | // for sdiv and udiv until it is put into the future | 
|  | 158 | // dag combiner. | 
|  | 159 |  | 
|  | 160 | /// ExprMap - As shared expressions are codegen'd, we keep track of which | 
|  | 161 | /// vreg the value is produced in, so we only emit one copy of each compiled | 
|  | 162 | /// tree. | 
|  | 163 | static const unsigned notIn = (unsigned)(-1); | 
|  | 164 | std::map<SDOperand, unsigned> ExprMap; | 
|  | 165 |  | 
|  | 166 | public: | 
|  | 167 | ISel(TargetMachine &TM) : SelectionDAGISel(V8Lowering), V8Lowering(TM) | 
|  | 168 | {} | 
|  | 169 |  | 
|  | 170 | /// InstructionSelectBasicBlock - This callback is invoked by | 
|  | 171 | /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. | 
|  | 172 | virtual void InstructionSelectBasicBlock(SelectionDAG &DAG) { | 
|  | 173 | DEBUG(BB->dump()); | 
|  | 174 |  | 
|  | 175 | // Codegen the basic block. | 
|  | 176 | ISelDAG = &DAG; | 
|  | 177 | max_depth = DAG.getRoot().getNodeDepth(); | 
|  | 178 | Select(DAG.getRoot()); | 
|  | 179 |  | 
|  | 180 | // Clear state used for selection. | 
|  | 181 | ExprMap.clear(); | 
|  | 182 | } | 
|  | 183 |  | 
|  | 184 | virtual void EmitFunctionEntryCode(Function &Fn, MachineFunction &MF); | 
|  | 185 |  | 
|  | 186 | unsigned SelectExpr(SDOperand N); | 
|  | 187 | void Select(SDOperand N); | 
|  | 188 |  | 
|  | 189 | }; | 
|  | 190 | } | 
|  | 191 |  | 
|  | 192 | void ISel::EmitFunctionEntryCode(Function &Fn, MachineFunction &MF) { | 
|  | 193 | // If this function has live-in values, emit the copies from pregs to vregs at | 
|  | 194 | // the top of the function, before anything else. | 
|  | 195 | MachineBasicBlock *BB = MF.begin(); | 
|  | 196 | if (MF.livein_begin() != MF.livein_end()) { | 
|  | 197 | SSARegMap *RegMap = MF.getSSARegMap(); | 
|  | 198 | for (MachineFunction::livein_iterator LI = MF.livein_begin(), | 
|  | 199 | E = MF.livein_end(); LI != E; ++LI) { | 
|  | 200 | const TargetRegisterClass *RC = RegMap->getRegClass(LI->second); | 
|  | 201 | if (RC == V8::GPRCRegisterClass) { | 
|  | 202 | BuildMI(BB, V8::ORrr, 2, LI->second).addReg(LI->first).addReg(V8::G0); | 
|  | 203 | } else if (RC == V8::FPRCRegisterClass) { | 
|  | 204 | BuildMI(BB, V8::FMOVSrr, 2, LI->second).addReg(LI->first); | 
|  | 205 | } else { | 
|  | 206 | assert(0 && "Unknown regclass!"); | 
|  | 207 | } | 
|  | 208 | } | 
|  | 209 | } | 
|  | 210 | } | 
|  | 211 |  | 
|  | 212 | //These describe LDAx | 
|  | 213 | static const int IMM_LOW  = -32768; | 
|  | 214 | static const int IMM_HIGH = 32767; | 
|  | 215 | static const int IMM_MULT = 65536; | 
|  | 216 |  | 
|  | 217 | static long getUpper16(long l) | 
|  | 218 | { | 
|  | 219 | long y = l / IMM_MULT; | 
|  | 220 | if (l % IMM_MULT > IMM_HIGH) | 
|  | 221 | ++y; | 
|  | 222 | return y; | 
|  | 223 | } | 
|  | 224 |  | 
|  | 225 | static long getLower16(long l) | 
|  | 226 | { | 
|  | 227 | long h = getUpper16(l); | 
|  | 228 | return l - h * IMM_MULT; | 
|  | 229 | } | 
|  | 230 |  | 
|  | 231 | unsigned ISel::SelectExpr(SDOperand N) { | 
|  | 232 | unsigned Result; | 
|  | 233 | unsigned Tmp1, Tmp2 = 0, Tmp3; | 
|  | 234 | unsigned Opc = 0; | 
|  | 235 | unsigned opcode = N.getOpcode(); | 
|  | 236 |  | 
|  | 237 | SDNode *Node = N.Val; | 
|  | 238 | MVT::ValueType DestType = N.getValueType(); | 
|  | 239 |  | 
|  | 240 | unsigned &Reg = ExprMap[N]; | 
|  | 241 | if (Reg) return Reg; | 
|  | 242 |  | 
|  | 243 | if (N.getOpcode() != ISD::CALL && N.getOpcode() != ISD::TAILCALL) | 
|  | 244 | Reg = Result = (N.getValueType() != MVT::Other) ? | 
|  | 245 | MakeReg(N.getValueType()) : notIn; | 
|  | 246 | else { | 
|  | 247 | // If this is a call instruction, make sure to prepare ALL of the result | 
|  | 248 | // values as well as the chain. | 
|  | 249 | if (Node->getNumValues() == 1) | 
|  | 250 | Reg = Result = notIn;  // Void call, just a chain. | 
|  | 251 | else { | 
|  | 252 | Result = MakeReg(Node->getValueType(0)); | 
|  | 253 | ExprMap[N.getValue(0)] = Result; | 
|  | 254 | for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i) | 
|  | 255 | ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i)); | 
|  | 256 | ExprMap[SDOperand(Node, Node->getNumValues()-1)] = notIn; | 
|  | 257 | } | 
|  | 258 | } | 
|  | 259 |  | 
|  | 260 | switch (opcode) { | 
|  | 261 | default: | 
|  | 262 | Node->dump(); | 
|  | 263 | assert(0 && "Node not handled!\n"); | 
|  | 264 |  | 
|  | 265 | case ISD::EXTLOAD: | 
|  | 266 | case ISD::ZEXTLOAD: | 
|  | 267 | case ISD::SEXTLOAD: | 
|  | 268 | case ISD::LOAD: | 
|  | 269 | { | 
|  | 270 | // Make sure we generate both values. | 
|  | 271 | if (Result != notIn) | 
|  | 272 | ExprMap[N.getValue(1)] = notIn;   // Generate the token | 
|  | 273 | else | 
|  | 274 | Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType()); | 
|  | 275 |  | 
|  | 276 | SDOperand Chain   = N.getOperand(0); | 
|  | 277 | SDOperand Address = N.getOperand(1); | 
|  | 278 | Select(Chain); | 
|  | 279 | unsigned Adr = SelectExpr(Address); | 
|  | 280 | switch(cast<MVTSDNode>(Node)->getExtraValueType()) { | 
|  | 281 | case MVT::i32: Opc = V8::LD; | 
|  | 282 | case MVT::i16: Opc = opcode == ISD::ZEXTLOAD ? V8::LDUH : V8::LDSH; break; | 
|  | 283 | case MVT::i8:  Opc = opcode == ISD::ZEXTLOAD ? V8::LDUB : V8::LDSB; break; | 
|  | 284 | case MVT::f64: Opc = V8::LDFSRrr; | 
|  | 285 | case MVT::f32: Opc = V8::LDDFrr; | 
|  | 286 | default: | 
|  | 287 | Node->dump(); | 
|  | 288 | assert(0 && "Bad type!"); | 
|  | 289 | break; | 
|  | 290 | } | 
|  | 291 | BuildMI(BB, Opc, 1, Result).addReg(Adr); | 
|  | 292 | return Result; | 
|  | 293 | } | 
|  | 294 |  | 
|  | 295 | case ISD::TAILCALL: | 
|  | 296 | case ISD::CALL: | 
|  | 297 | { | 
|  | 298 | //FIXME: | 
|  | 299 | abort(); | 
|  | 300 | return Result; | 
|  | 301 | } | 
|  | 302 |  | 
|  | 303 | case ISD::CopyFromReg: | 
|  | 304 | { | 
|  | 305 | // Make sure we generate both values. | 
|  | 306 | if (Result != notIn) | 
|  | 307 | ExprMap[N.getValue(1)] = notIn;   // Generate the token | 
|  | 308 | else | 
|  | 309 | Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType()); | 
|  | 310 |  | 
|  | 311 | SDOperand Chain   = N.getOperand(0); | 
|  | 312 | Select(Chain); | 
|  | 313 | unsigned r = dyn_cast<RegSDNode>(Node)->getReg(); | 
|  | 314 |  | 
|  | 315 | BuildMI(BB, V8::ORrr, 2, Result).addReg(r).addReg(V8::G0); | 
|  | 316 | return Result; | 
|  | 317 | } | 
|  | 318 |  | 
|  | 319 | //Most of the plain arithmetic and logic share the same form, and the same | 
|  | 320 | //constant immediate test | 
|  | 321 | case ISD::XOR: | 
|  | 322 | case ISD::AND: | 
|  | 323 | case ISD::OR: | 
|  | 324 | case ISD::SHL: | 
|  | 325 | case ISD::SRL: | 
|  | 326 | case ISD::SRA: | 
|  | 327 | case ISD::ADD: | 
|  | 328 | case ISD::SUB: | 
|  | 329 | case ISD::SDIV: | 
|  | 330 | case ISD::UDIV: | 
|  | 331 | case ISD::SMUL: | 
|  | 332 | case ISD::UMUL: | 
|  | 333 | switch(opcode) { | 
|  | 334 | case ISD::XOR:  Opc = V8::XORrr; break; | 
|  | 335 | case ISD::AND:  Opc = V8::ANDrr; break; | 
|  | 336 | case ISD::OR:   Opc = V8::ORrr; break; | 
|  | 337 | case ISD::SHL:  Opc = V8::SLLrr; break; | 
|  | 338 | case ISD::SRL:  Opc = V8::SRLrr; break; | 
|  | 339 | case ISD::SRA:  Opc = V8::SRArr; break; | 
|  | 340 | case ISD::ADD:  Opc = V8::ADDrr; break; | 
|  | 341 | case ISD::SUB:  Opc = V8::SUBrr; break; | 
|  | 342 | case ISD::SDIV: Opc = V8::SDIVrr; break; | 
|  | 343 | case ISD::UDIV: Opc = V8::UDIVrr; break; | 
|  | 344 | case ISD::SMUL: Opc = V8::SMULrr; break; | 
|  | 345 | case ISD::UMUL: Opc = V8::UMULrr; break; | 
|  | 346 | } | 
|  | 347 | Tmp1 = SelectExpr(N.getOperand(0)); | 
|  | 348 | Tmp2 = SelectExpr(N.getOperand(1)); | 
|  | 349 | BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2); | 
|  | 350 | return Result; | 
|  | 351 |  | 
|  | 352 | } | 
|  | 353 | return 0; | 
|  | 354 | } | 
|  | 355 |  | 
|  | 356 | void ISel::Select(SDOperand N) { | 
|  | 357 | unsigned Tmp1, Tmp2, Opc; | 
|  | 358 | unsigned opcode = N.getOpcode(); | 
|  | 359 |  | 
|  | 360 | if (!ExprMap.insert(std::make_pair(N, notIn)).second) | 
|  | 361 | return;  // Already selected. | 
|  | 362 |  | 
|  | 363 | SDNode *Node = N.Val; | 
|  | 364 |  | 
|  | 365 | switch (opcode) { | 
|  | 366 |  | 
|  | 367 | default: | 
|  | 368 | Node->dump(); std::cerr << "\n"; | 
|  | 369 | assert(0 && "Node not handled yet!"); | 
|  | 370 |  | 
|  | 371 | case ISD::BRCOND: { | 
|  | 372 | //FIXME | 
|  | 373 | abort(); | 
|  | 374 | return; | 
|  | 375 | } | 
|  | 376 |  | 
|  | 377 | case ISD::BR: { | 
|  | 378 | MachineBasicBlock *Dest = | 
|  | 379 | cast<BasicBlockSDNode>(N.getOperand(1))->getBasicBlock(); | 
|  | 380 |  | 
|  | 381 | Select(N.getOperand(0)); | 
|  | 382 | BuildMI(BB, V8::BA, 1).addMBB(Dest); | 
|  | 383 | return; | 
|  | 384 | } | 
|  | 385 |  | 
|  | 386 | case ISD::ImplicitDef: | 
|  | 387 | Select(N.getOperand(0)); | 
|  | 388 | BuildMI(BB, V8::IMPLICIT_DEF, 0, cast<RegSDNode>(N)->getReg()); | 
|  | 389 | return; | 
|  | 390 |  | 
|  | 391 | case ISD::EntryToken: return;  // Noop | 
|  | 392 |  | 
|  | 393 | case ISD::TokenFactor: | 
|  | 394 | for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i) | 
|  | 395 | Select(Node->getOperand(i)); | 
|  | 396 | return; | 
|  | 397 |  | 
|  | 398 | case ISD::CopyToReg: | 
|  | 399 | Select(N.getOperand(0)); | 
|  | 400 | Tmp1 = SelectExpr(N.getOperand(1)); | 
|  | 401 | Tmp2 = cast<RegSDNode>(N)->getReg(); | 
|  | 402 |  | 
|  | 403 | if (Tmp1 != Tmp2) { | 
|  | 404 | if (N.getOperand(1).getValueType() == MVT::f64 || | 
|  | 405 | N.getOperand(1).getValueType() == MVT::f32) | 
|  | 406 | BuildMI(BB, V8::FMOVS, 2, Tmp2).addReg(Tmp1); | 
|  | 407 | else | 
|  | 408 | BuildMI(BB, V8::ORrr, 2, Tmp2).addReg(Tmp1).addReg(V8::G0); | 
|  | 409 | } | 
|  | 410 | return; | 
|  | 411 |  | 
|  | 412 | case ISD::RET: | 
|  | 413 | //FIXME: | 
|  | 414 | abort(); | 
|  | 415 | return; | 
|  | 416 |  | 
|  | 417 | case ISD::TRUNCSTORE: | 
|  | 418 | case ISD::STORE: | 
|  | 419 | { | 
|  | 420 | SDOperand Chain   = N.getOperand(0); | 
|  | 421 | SDOperand Value = N.getOperand(1); | 
|  | 422 | SDOperand Address = N.getOperand(2); | 
|  | 423 | Select(Chain); | 
|  | 424 |  | 
|  | 425 | Tmp1 = SelectExpr(Value); | 
|  | 426 | Tmp2 = SelectExpr(Address); | 
|  | 427 |  | 
|  | 428 | unsigned VT = opcode == ISD::STORE ? | 
|  | 429 | Value.getValueType() : cast<MVTSDNode>(Node)->getExtraValueType(); | 
|  | 430 | switch(VT) { | 
|  | 431 | default: assert(0 && "unknown Type in store"); | 
|  | 432 | case MVT::f64: Opc = V8::STDFrr; break; | 
|  | 433 | case MVT::f32: Opc = V8::STFrr; break; | 
|  | 434 | case MVT::i1:  //FIXME: DAG does not promote this load | 
|  | 435 | case MVT::i8:  Opc = V8::STBrr; break; | 
|  | 436 | case MVT::i16: Opc = V8::STHrr; break; | 
|  | 437 | case MVT::i32: Opc = V8::STLrr; break; | 
|  | 438 | case MVT::i64: Opc = V8::STDrr; break; | 
|  | 439 | } | 
|  | 440 |  | 
|  | 441 | BuildMI(BB,Opc,2).addReg(Tmp1).addReg(Tmp2); | 
|  | 442 | return; | 
|  | 443 | } | 
|  | 444 |  | 
|  | 445 | case ISD::EXTLOAD: | 
|  | 446 | case ISD::SEXTLOAD: | 
|  | 447 | case ISD::ZEXTLOAD: | 
|  | 448 | case ISD::LOAD: | 
|  | 449 | case ISD::CopyFromReg: | 
|  | 450 | case ISD::TAILCALL: | 
|  | 451 | case ISD::CALL: | 
|  | 452 | case ISD::DYNAMIC_STACKALLOC: | 
|  | 453 | ExprMap.erase(N); | 
|  | 454 | SelectExpr(N); | 
|  | 455 | return; | 
|  | 456 |  | 
|  | 457 | case ISD::CALLSEQ_START: | 
|  | 458 | case ISD::CALLSEQ_END: | 
|  | 459 | Select(N.getOperand(0)); | 
|  | 460 | Tmp1 = cast<ConstantSDNode>(N.getOperand(1))->getValue(); | 
|  | 461 |  | 
|  | 462 | Opc = N.getOpcode() == ISD::CALLSEQ_START ? V8::ADJUSTCALLSTACKDOWN : | 
|  | 463 | V8::ADJUSTCALLSTACKUP; | 
|  | 464 | BuildMI(BB, Opc, 1).addImm(Tmp1); | 
|  | 465 | return; | 
|  | 466 | } | 
|  | 467 | assert(0 && "Should not be reached!"); | 
|  | 468 | } | 
|  | 469 |  | 
|  | 470 |  | 
|  | 471 | /// createV8PatternInstructionSelector - This pass converts an LLVM function | 
|  | 472 | /// into a machine code representation using pattern matching and a machine | 
|  | 473 | /// description file. | 
|  | 474 | /// | 
|  | 475 | FunctionPass *llvm::createV8PatternInstructionSelector(TargetMachine &TM) { | 
|  | 476 | return new ISel(TM); | 
|  | 477 | } | 
|  | 478 |  | 
|  | 479 | #endif |