SparcISelDAGToDAG.cpp revision 8fa54dc70239dc08cc3c93cb7513e0625be50eb4
1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)//===-- SparcV8ISelDAGToDAG.cpp - A dag to dag inst selector for SparcV8 --===// 2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// 3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// The LLVM Compiler Infrastructure 4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// 5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// This file was developed by Chris Lattner and is distributed under 6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// the University of Illinois Open Source License. See LICENSE.TXT for details. 7116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// 8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)//===----------------------------------------------------------------------===// 9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// 10116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// This file defines an instruction selector for the V8 target 11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// 12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)//===----------------------------------------------------------------------===// 13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "SparcV8.h" 15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "SparcV8TargetMachine.h" 16116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "llvm/Function.h" 17116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "llvm/CodeGen/MachineFrameInfo.h" 18116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "llvm/CodeGen/MachineFunction.h" 19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "llvm/CodeGen/SelectionDAG.h" 20116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "llvm/CodeGen/SelectionDAGISel.h" 21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "llvm/CodeGen/SSARegMap.h" 22116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "llvm/Target/TargetLowering.h" 23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "llvm/Support/Debug.h" 24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <iostream> 25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)using namespace llvm; 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)//===----------------------------------------------------------------------===// 28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// TargetLowering Implementation 29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)//===----------------------------------------------------------------------===// 30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 31116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace V8ISD { 32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) enum { 33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FIRST_NUMBER = ISD::BUILTIN_OP_END+V8::INSTRUCTION_LIST_END, 34116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CMPICC, // Compare two GPR operands, set icc. 355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CMPFCC, // Compare two FP operands, set fcc. 365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) BRICC, // Branch to dest on icc condition 37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) BRFCC, // Branch to dest on fcc condition 38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Hi, Lo, // Hi/Lo operations, typically on a global address. 40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FTOI, // FP to Int within a FP register. 42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ITOF, // Int to FP within a FP register. 43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) }; 44116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 46116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace { 47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) class SparcV8TargetLowering : public TargetLowering { 48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public: 49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SparcV8TargetLowering(TargetMachine &TM); 50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG); 515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual std::vector<SDOperand> 52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) LowerArguments(Function &F, SelectionDAG &DAG); 535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual std::pair<SDOperand, SDOperand> 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LowerCallTo(SDOperand Chain, const Type *RetTy, bool isVarArg, 55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) unsigned CC, 56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool isTailCall, SDOperand Callee, ArgListTy &Args, 57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SelectionDAG &DAG); 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual SDOperand LowerReturnTo(SDOperand Chain, SDOperand Op, 60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SelectionDAG &DAG); 61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual SDOperand LowerVAStart(SDOperand Chain, SDOperand VAListP, 62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Value *VAListV, SelectionDAG &DAG); 63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual std::pair<SDOperand,SDOperand> 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LowerVAArg(SDOperand Chain, SDOperand VAListP, Value *VAListV, 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const Type *ArgTy, SelectionDAG &DAG); 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual std::pair<SDOperand, SDOperand> 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth, 68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SelectionDAG &DAG); 69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) }; 70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)SparcV8TargetLowering::SparcV8TargetLowering(TargetMachine &TM) 73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) : TargetLowering(TM) { 74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Set up the register classes. 76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) addRegisterClass(MVT::i32, V8::IntRegsRegisterClass); 77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) addRegisterClass(MVT::f32, V8::FPRegsRegisterClass); 78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) addRegisterClass(MVT::f64, V8::DFPRegsRegisterClass); 79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Custom legalize GlobalAddress nodes into LO/HI parts. 81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); 82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) setOperationAction(ISD::ConstantPool , MVT::i32, Custom); 83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Sparc doesn't have sext_inreg, replace them with shl/sra 85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16 , Expand); 86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8 , Expand); 87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1 , Expand); 88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Sparc has no REM operation. 905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) setOperationAction(ISD::UREM, MVT::i32, Expand); 91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) setOperationAction(ISD::SREM, MVT::i32, Expand); 92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Custom expand fp<->sint 94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); 95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom); 96116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Expand fp<->uint 98116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand); 99116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand); 100116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 101116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Sparc has no select or setcc: expand to SELECT_CC. 102116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch setOperationAction(ISD::SELECT, MVT::i32, Expand); 103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch setOperationAction(ISD::SELECT, MVT::f32, Expand); 104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch setOperationAction(ISD::SELECT, MVT::f64, Expand); 105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch setOperationAction(ISD::SETCC, MVT::i32, Expand); 106116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch setOperationAction(ISD::SETCC, MVT::f32, Expand); 107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch setOperationAction(ISD::SETCC, MVT::f64, Expand); 108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Sparc doesn't have BRCOND either, it has BR_CC. 110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) setOperationAction(ISD::BRCOND, MVT::Other, Expand); 111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) setOperationAction(ISD::BRCONDTWOWAY, MVT::Other, Expand); 112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) setOperationAction(ISD::BRTWOWAY_CC, MVT::Other, Expand); 113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) setOperationAction(ISD::BR_CC, MVT::i32, Custom); 114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch setOperationAction(ISD::BR_CC, MVT::f32, Custom); 115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) setOperationAction(ISD::BR_CC, MVT::f64, Custom); 116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch computeRegisterProperties(); 118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)std::vector<SDOperand> 121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)SparcV8TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) { 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MachineFunction &MF = DAG.getMachineFunction(); 123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SSARegMap *RegMap = MF.getSSARegMap(); 124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::vector<SDOperand> ArgValues; 125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) static const unsigned GPR[] = { 127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) V8::I0, V8::I1, V8::I2, V8::I3, V8::I4, V8::I5 128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) }; 129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) unsigned ArgNo = 0; 130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) { 1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MVT::ValueType ObjectVT = getValueType(I->getType()); 1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) assert(ArgNo < 6 && "Only args in regs for now"); 1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) switch (ObjectVT) { 135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) default: assert(0 && "Unhandled argument type!"); 136116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // TODO: MVT::i64 & FP 137116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case MVT::i1: 138116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case MVT::i8: 139116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case MVT::i16: 140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case MVT::i32: { 141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch unsigned VReg = RegMap->createVirtualRegister(&V8::IntRegsRegClass); 142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch MF.addLiveIn(GPR[ArgNo++], VReg); 143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SDOperand Arg = DAG.getCopyFromReg(DAG.getRoot(), VReg, MVT::i32); 144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DAG.setRoot(Arg.getValue(1)); 145116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (ObjectVT != MVT::i32) { 146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch unsigned AssertOp = I->getType()->isSigned() ? ISD::AssertSext 147116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch : ISD::AssertZext; 148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Arg = DAG.getNode(AssertOp, MVT::i32, Arg, 149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DAG.getValueType(ObjectVT)); 150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Arg = DAG.getNode(ISD::TRUNCATE, ObjectVT, Arg); 151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 152116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ArgValues.push_back(Arg); 153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch break; 154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 155116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case MVT::i64: { 156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch unsigned VRegHi = RegMap->createVirtualRegister(&V8::IntRegsRegClass); 157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch MF.addLiveIn(GPR[ArgNo++], VRegHi); 158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch unsigned VRegLo = RegMap->createVirtualRegister(&V8::IntRegsRegClass); 159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch MF.addLiveIn(GPR[ArgNo++], VRegLo); 160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SDOperand ArgLo = DAG.getCopyFromReg(DAG.getRoot(), VRegLo, MVT::i32); 161 SDOperand ArgHi = DAG.getCopyFromReg(ArgLo.getValue(1), VRegHi, MVT::i32); 162 DAG.setRoot(ArgHi.getValue(1)); 163 ArgValues.push_back(DAG.getNode(ISD::BUILD_PAIR, MVT::i64, ArgLo, ArgHi)); 164 break; 165 } 166 } 167 } 168 169 assert(!F.isVarArg() && "Unimp"); 170 171 // Finally, inform the code generator which regs we return values in. 172 switch (getValueType(F.getReturnType())) { 173 default: assert(0 && "Unknown type!"); 174 case MVT::isVoid: break; 175 case MVT::i1: 176 case MVT::i8: 177 case MVT::i16: 178 case MVT::i32: 179 MF.addLiveOut(V8::I0); 180 break; 181 case MVT::i64: 182 MF.addLiveOut(V8::I0); 183 MF.addLiveOut(V8::I1); 184 break; 185 case MVT::f32: 186 MF.addLiveOut(V8::F0); 187 break; 188 case MVT::f64: 189 MF.addLiveOut(V8::D0); 190 break; 191 } 192 193 return ArgValues; 194} 195 196std::pair<SDOperand, SDOperand> 197SparcV8TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy, 198 bool isVarArg, unsigned CC, 199 bool isTailCall, SDOperand Callee, 200 ArgListTy &Args, SelectionDAG &DAG) { 201 assert(0 && "Unimp"); 202 abort(); 203} 204 205SDOperand SparcV8TargetLowering::LowerReturnTo(SDOperand Chain, SDOperand Op, 206 SelectionDAG &DAG) { 207 if (Op.getValueType() == MVT::i64) { 208 SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op, 209 DAG.getConstant(1, MVT::i32)); 210 SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op, 211 DAG.getConstant(0, MVT::i32)); 212 return DAG.getNode(ISD::RET, MVT::Other, Chain, Lo, Hi); 213 } else { 214 return DAG.getNode(ISD::RET, MVT::Other, Chain, Op); 215 } 216} 217 218SDOperand SparcV8TargetLowering:: 219LowerVAStart(SDOperand Chain, SDOperand VAListP, Value *VAListV, 220 SelectionDAG &DAG) { 221 222 assert(0 && "Unimp"); 223 abort(); 224} 225 226std::pair<SDOperand,SDOperand> SparcV8TargetLowering:: 227LowerVAArg(SDOperand Chain, SDOperand VAListP, Value *VAListV, 228 const Type *ArgTy, SelectionDAG &DAG) { 229 assert(0 && "Unimp"); 230 abort(); 231} 232 233std::pair<SDOperand, SDOperand> SparcV8TargetLowering:: 234LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth, 235 SelectionDAG &DAG) { 236 assert(0 && "Unimp"); 237 abort(); 238} 239 240SDOperand SparcV8TargetLowering:: 241LowerOperation(SDOperand Op, SelectionDAG &DAG) { 242 switch (Op.getOpcode()) { 243 default: assert(0 && "Should not custom lower this!"); 244 case ISD::BR_CC: { 245 SDOperand Chain = Op.getOperand(0); 246 SDOperand CC = Op.getOperand(1); 247 SDOperand LHS = Op.getOperand(2); 248 SDOperand RHS = Op.getOperand(3); 249 SDOperand Dest = Op.getOperand(4); 250 251 // Get the condition flag. 252 if (LHS.getValueType() == MVT::i32) { 253 SDOperand Cond = DAG.getNode(V8ISD::CMPICC, MVT::Flag, LHS, RHS); 254 return DAG.getNode(V8ISD::BRICC, MVT::Other, Chain, Dest, CC, Cond); 255 } else { 256 SDOperand Cond = DAG.getNode(V8ISD::CMPFCC, MVT::Flag, LHS, RHS); 257 return DAG.getNode(V8ISD::BRFCC, MVT::Other, Chain, Dest, CC, Cond); 258 } 259 } 260 case ISD::GlobalAddress: { 261 GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); 262 SDOperand GA = DAG.getTargetGlobalAddress(GV, MVT::i32); 263 SDOperand Hi = DAG.getNode(V8ISD::Hi, MVT::i32, GA); 264 SDOperand Lo = DAG.getNode(V8ISD::Lo, MVT::i32, GA); 265 return DAG.getNode(ISD::ADD, MVT::i32, Lo, Hi); 266 } 267 case ISD::ConstantPool: { 268 Constant *C = cast<ConstantPoolSDNode>(Op)->get(); 269 SDOperand CP = DAG.getTargetConstantPool(C, MVT::i32); 270 SDOperand Hi = DAG.getNode(V8ISD::Hi, MVT::i32, CP); 271 SDOperand Lo = DAG.getNode(V8ISD::Lo, MVT::i32, CP); 272 return DAG.getNode(ISD::ADD, MVT::i32, Lo, Hi); 273 } 274 case ISD::FP_TO_SINT: { 275 // Convert the fp value to integer in an FP register. 276 Op = DAG.getNode(V8ISD::FTOI, Op.getOperand(0).getValueType(), 277 Op.getOperand(0)); 278 int Size = Op.getOperand(0).getValueType() == MVT::f32 ? 4 : 8; 279 int FrameIdx = 280 DAG.getMachineFunction().getFrameInfo()->CreateStackObject(Size, Size); 281 SDOperand FI = DAG.getFrameIndex(FrameIdx, MVT::i32); 282 SDOperand ST = DAG.getNode(ISD::STORE, MVT::Other, DAG.getEntryNode(), 283 Op, FI, DAG.getSrcValue(0)); 284 return DAG.getLoad(MVT::i32, ST, FI, DAG.getSrcValue(0)); 285 } 286 case ISD::SINT_TO_FP: { 287 int Size = Op.getOperand(0).getValueType() == MVT::f32 ? 4 : 8; 288 int FrameIdx = 289 DAG.getMachineFunction().getFrameInfo()->CreateStackObject(Size, Size); 290 SDOperand FI = DAG.getFrameIndex(FrameIdx, MVT::i32); 291 SDOperand ST = DAG.getNode(ISD::STORE, MVT::Other, DAG.getEntryNode(), 292 Op.getOperand(0), FI, DAG.getSrcValue(0)); 293 294 Op = DAG.getLoad(Op.getValueType(), ST, FI, DAG.getSrcValue(0)); 295 296 // Convert the int value to FP in an FP register. 297 return DAG.getNode(V8ISD::ITOF, Op.getValueType(), Op); 298 } 299 } 300} 301 302 303//===----------------------------------------------------------------------===// 304// Instruction Selector Implementation 305//===----------------------------------------------------------------------===// 306 307//===--------------------------------------------------------------------===// 308/// SparcV8DAGToDAGISel - PPC specific code to select Sparc V8 machine 309/// instructions for SelectionDAG operations. 310/// 311namespace { 312class SparcV8DAGToDAGISel : public SelectionDAGISel { 313 SparcV8TargetLowering V8Lowering; 314public: 315 SparcV8DAGToDAGISel(TargetMachine &TM) 316 : SelectionDAGISel(V8Lowering), V8Lowering(TM) {} 317 318 SDOperand Select(SDOperand Op); 319 320 // Complex Pattern Selectors. 321 bool SelectADDRrr(SDOperand N, SDOperand &R1, SDOperand &R2); 322 bool SelectADDRri(SDOperand N, SDOperand &Base, SDOperand &Offset); 323 324 /// InstructionSelectBasicBlock - This callback is invoked by 325 /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. 326 virtual void InstructionSelectBasicBlock(SelectionDAG &DAG); 327 328 virtual const char *getPassName() const { 329 return "PowerPC DAG->DAG Pattern Instruction Selection"; 330 } 331 332 // Include the pieces autogenerated from the target description. 333#include "SparcV8GenDAGISel.inc" 334}; 335} // end anonymous namespace 336 337/// InstructionSelectBasicBlock - This callback is invoked by 338/// SelectionDAGISel when it has created a SelectionDAG for us to codegen. 339void SparcV8DAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) { 340 DEBUG(BB->dump()); 341 342 // Select target instructions for the DAG. 343 DAG.setRoot(Select(DAG.getRoot())); 344 CodeGenMap.clear(); 345 DAG.RemoveDeadNodes(); 346 347 // Emit machine code to BB. 348 ScheduleAndEmitDAG(DAG); 349} 350 351bool SparcV8DAGToDAGISel::SelectADDRri(SDOperand Addr, SDOperand &Base, 352 SDOperand &Offset) { 353 if (Addr.getOpcode() == ISD::FrameIndex) { 354 int FI = cast<FrameIndexSDNode>(Addr)->getIndex(); 355 Base = CurDAG->getTargetFrameIndex(FI, MVT::i32); 356 Offset = CurDAG->getTargetConstant(0, MVT::i32); 357 return true; 358 } 359 360 if (Addr.getOpcode() == ISD::ADD) { 361 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) { 362 if (Predicate_simm13(CN)) { 363 if (Addr.getOperand(0).getOpcode() == ISD::FrameIndex) { 364 // Constant offset from frame ref. 365 int FI = cast<FrameIndexSDNode>(Addr)->getIndex(); 366 Base = CurDAG->getTargetFrameIndex(FI, MVT::i32); 367 } else { 368 Base = Select(Addr.getOperand(0)); 369 } 370 Offset = CurDAG->getTargetConstant(CN->getValue(), MVT::i32); 371 return true; 372 } 373 } 374 if (Addr.getOperand(0).getOpcode() == V8ISD::Lo) { 375 Base = Select(Addr.getOperand(1)); 376 Offset = Addr.getOperand(0).getOperand(0); 377 return true; 378 } 379 if (Addr.getOperand(1).getOpcode() == V8ISD::Lo) { 380 Base = Select(Addr.getOperand(0)); 381 Offset = Addr.getOperand(1).getOperand(0); 382 return true; 383 } 384 } 385 Base = Select(Addr); 386 Offset = CurDAG->getTargetConstant(0, MVT::i32); 387 return true; 388} 389 390bool SparcV8DAGToDAGISel::SelectADDRrr(SDOperand Addr, SDOperand &R1, 391 SDOperand &R2) { 392 if (Addr.getOpcode() == ISD::FrameIndex) return false; 393 if (Addr.getOpcode() == ISD::ADD) { 394 if (isa<ConstantSDNode>(Addr.getOperand(1)) && 395 Predicate_simm13(Addr.getOperand(1).Val)) 396 return false; // Let the reg+imm pattern catch this! 397 if (Addr.getOperand(0).getOpcode() == V8ISD::Lo || 398 Addr.getOperand(1).getOpcode() == V8ISD::Lo) 399 return false; // Let the reg+imm pattern catch this! 400 R1 = Select(Addr.getOperand(0)); 401 R2 = Select(Addr.getOperand(1)); 402 return true; 403 } 404 405 R1 = Select(Addr); 406 R2 = CurDAG->getRegister(V8::G0, MVT::i32); 407 return true; 408} 409 410SDOperand SparcV8DAGToDAGISel::Select(SDOperand Op) { 411 SDNode *N = Op.Val; 412 if (N->getOpcode() >= ISD::BUILTIN_OP_END && 413 N->getOpcode() < V8ISD::FIRST_NUMBER) 414 return Op; // Already selected. 415 // If this has already been converted, use it. 416 std::map<SDOperand, SDOperand>::iterator CGMI = CodeGenMap.find(Op); 417 if (CGMI != CodeGenMap.end()) return CGMI->second; 418 419 switch (N->getOpcode()) { 420 default: break; 421 case ISD::BasicBlock: return CodeGenMap[Op] = Op; 422 case ISD::FrameIndex: { 423 int FI = cast<FrameIndexSDNode>(N)->getIndex(); 424 if (N->hasOneUse()) 425 return CurDAG->SelectNodeTo(N, V8::ADDri, MVT::i32, 426 CurDAG->getTargetFrameIndex(FI, MVT::i32), 427 CurDAG->getTargetConstant(0, MVT::i32)); 428 return CodeGenMap[Op] = 429 CurDAG->getTargetNode(V8::ADDri, MVT::i32, 430 CurDAG->getTargetFrameIndex(FI, MVT::i32), 431 CurDAG->getTargetConstant(0, MVT::i32)); 432 } 433 case V8ISD::CMPICC: { 434 // FIXME: Handle compare with immediate. 435 SDOperand LHS = Select(N->getOperand(0)); 436 SDOperand RHS = Select(N->getOperand(1)); 437 SDOperand Result = CurDAG->getTargetNode(V8::SUBCCrr, MVT::i32, MVT::Flag, 438 LHS, RHS); 439 return CodeGenMap[Op] = Result.getValue(1); 440 } 441 case ISD::ADD_PARTS: { 442 SDOperand LHSL = Select(N->getOperand(0)); 443 SDOperand LHSH = Select(N->getOperand(1)); 444 SDOperand RHSL = Select(N->getOperand(2)); 445 SDOperand RHSH = Select(N->getOperand(3)); 446 // FIXME, handle immediate RHS. 447 SDOperand Low = CurDAG->getTargetNode(V8::ADDCCrr, MVT::i32, MVT::Flag, 448 LHSL, RHSL); 449 SDOperand Hi = CurDAG->getTargetNode(V8::ADDXrr, MVT::i32, LHSH, RHSH, 450 Low.getValue(1)); 451 CodeGenMap[SDOperand(N, 0)] = Low; 452 CodeGenMap[SDOperand(N, 1)] = Hi; 453 return Op.ResNo ? Hi : Low; 454 } 455 case ISD::SUB_PARTS: { 456 SDOperand LHSL = Select(N->getOperand(0)); 457 SDOperand LHSH = Select(N->getOperand(1)); 458 SDOperand RHSL = Select(N->getOperand(2)); 459 SDOperand RHSH = Select(N->getOperand(3)); 460 // FIXME, handle immediate RHS. 461 SDOperand Low = CurDAG->getTargetNode(V8::SUBCCrr, MVT::i32, MVT::Flag, 462 LHSL, RHSL); 463 SDOperand Hi = CurDAG->getTargetNode(V8::SUBXrr, MVT::i32, LHSH, RHSH, 464 Low.getValue(1)); 465 CodeGenMap[SDOperand(N, 0)] = Low; 466 CodeGenMap[SDOperand(N, 1)] = Hi; 467 return Op.ResNo ? Hi : Low; 468 } 469 case ISD::SDIV: 470 case ISD::UDIV: { 471 // FIXME: should use a custom expander to expose the SRA to the dag. 472 SDOperand DivLHS = Select(N->getOperand(0)); 473 SDOperand DivRHS = Select(N->getOperand(1)); 474 475 // Set the Y register to the high-part. 476 SDOperand TopPart; 477 if (N->getOpcode() == ISD::SDIV) { 478 TopPart = CurDAG->getTargetNode(V8::SRAri, MVT::i32, DivLHS, 479 CurDAG->getTargetConstant(31, MVT::i32)); 480 } else { 481 TopPart = CurDAG->getRegister(V8::G0, MVT::i32); 482 } 483 TopPart = CurDAG->getTargetNode(V8::WRYrr, MVT::Flag, TopPart, 484 CurDAG->getRegister(V8::G0, MVT::i32)); 485 486 // FIXME: Handle div by immediate. 487 unsigned Opcode = N->getOpcode() == ISD::SDIV ? V8::SDIVrr : V8::UDIVrr; 488 return CurDAG->SelectNodeTo(N, Opcode, MVT::i32, DivLHS, DivRHS, TopPart); 489 } 490 case ISD::MULHU: 491 case ISD::MULHS: { 492 // FIXME: Handle mul by immediate. 493 SDOperand MulLHS = Select(N->getOperand(0)); 494 SDOperand MulRHS = Select(N->getOperand(1)); 495 unsigned Opcode = N->getOpcode() == ISD::MULHU ? V8::UMULrr : V8::SMULrr; 496 SDOperand Mul = CurDAG->getTargetNode(Opcode, MVT::i32, MVT::Flag, 497 MulLHS, MulRHS); 498 // The high part is in the Y register. 499 return CurDAG->SelectNodeTo(N, V8::RDY, MVT::i32, Mul.getValue(1)); 500 } 501 502 case ISD::RET: { 503 if (N->getNumOperands() == 2) { 504 SDOperand Chain = Select(N->getOperand(0)); // Token chain. 505 SDOperand Val = Select(N->getOperand(1)); 506 if (N->getOperand(1).getValueType() == MVT::i32) { 507 Chain = CurDAG->getCopyToReg(Chain, V8::I0, Val); 508 } else if (N->getOperand(1).getValueType() == MVT::f32) { 509 Chain = CurDAG->getCopyToReg(Chain, V8::F0, Val); 510 } else { 511 assert(N->getOperand(1).getValueType() == MVT::f64); 512 Chain = CurDAG->getCopyToReg(Chain, V8::D0, Val); 513 } 514 return CurDAG->SelectNodeTo(N, V8::RETL, MVT::Other, Chain); 515 } else if (N->getNumOperands() > 1) { 516 SDOperand Chain = Select(N->getOperand(0)); // Token chain. 517 assert(N->getOperand(1).getValueType() == MVT::i32 && 518 N->getOperand(2).getValueType() == MVT::i32 && 519 N->getNumOperands() == 3 && "Unknown two-register ret value!"); 520 Chain = CurDAG->getCopyToReg(Chain, V8::I1, Select(N->getOperand(1))); 521 Chain = CurDAG->getCopyToReg(Chain, V8::I0, Select(N->getOperand(2))); 522 return CurDAG->SelectNodeTo(N, V8::RETL, MVT::Other, Chain); 523 } 524 break; // Generated code handles the void case. 525 } 526 } 527 528 return SelectCode(Op); 529} 530 531 532/// createPPCISelDag - This pass converts a legalized DAG into a 533/// PowerPC-specific DAG, ready for instruction scheduling. 534/// 535FunctionPass *llvm::createSparcV8ISelDag(TargetMachine &TM) { 536 return new SparcV8DAGToDAGISel(TM); 537} 538