LLVM API Documentation
00001 //===-- AlphaISelLowering.cpp - Alpha DAG Lowering Implementation ---------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the AlphaISelLowering class. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "AlphaISelLowering.h" 00015 #include "AlphaTargetMachine.h" 00016 #include "llvm/CodeGen/MachineFrameInfo.h" 00017 #include "llvm/CodeGen/MachineFunction.h" 00018 #include "llvm/CodeGen/MachineInstrBuilder.h" 00019 #include "llvm/CodeGen/MachineRegisterInfo.h" 00020 #include "llvm/CodeGen/SelectionDAG.h" 00021 #include "llvm/CodeGen/MachineRegisterInfo.h" 00022 #include "llvm/Constants.h" 00023 #include "llvm/Function.h" 00024 #include "llvm/Module.h" 00025 #include "llvm/Intrinsics.h" 00026 #include "llvm/Support/CommandLine.h" 00027 using namespace llvm; 00028 00029 /// AddLiveIn - This helper function adds the specified physical register to the 00030 /// MachineFunction as a live in value. It also creates a corresponding virtual 00031 /// register for it. 00032 static unsigned AddLiveIn(MachineFunction &MF, unsigned PReg, 00033 TargetRegisterClass *RC) { 00034 assert(RC->contains(PReg) && "Not the correct regclass!"); 00035 unsigned VReg = MF.getRegInfo().createVirtualRegister(RC); 00036 MF.getRegInfo().addLiveIn(PReg, VReg); 00037 return VReg; 00038 } 00039 00040 AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM) : TargetLowering(TM) { 00041 // Set up the TargetLowering object. 00042 //I am having problems with shr n ubyte 1 00043 setShiftAmountType(MVT::i64); 00044 setBooleanContents(ZeroOrOneBooleanContent); 00045 00046 setUsesGlobalOffsetTable(true); 00047 00048 addRegisterClass(MVT::i64, Alpha::GPRCRegisterClass); 00049 addRegisterClass(MVT::f64, Alpha::F8RCRegisterClass); 00050 addRegisterClass(MVT::f32, Alpha::F4RCRegisterClass); 00051 00052 // We want to custom lower some of our intrinsics. 00053 setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom); 00054 00055 setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote); 00056 setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand); 00057 00058 setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote); 00059 setLoadExtAction(ISD::ZEXTLOAD, MVT::i32, Expand); 00060 00061 setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); 00062 setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Expand); 00063 setLoadExtAction(ISD::SEXTLOAD, MVT::i16, Expand); 00064 00065 // setOperationAction(ISD::BRIND, MVT::Other, Expand); 00066 setOperationAction(ISD::BR_JT, MVT::Other, Expand); 00067 setOperationAction(ISD::BR_CC, MVT::Other, Expand); 00068 setOperationAction(ISD::SELECT_CC, MVT::Other, Expand); 00069 00070 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); 00071 00072 setOperationAction(ISD::FREM, MVT::f32, Expand); 00073 setOperationAction(ISD::FREM, MVT::f64, Expand); 00074 00075 setOperationAction(ISD::UINT_TO_FP, MVT::i64, Expand); 00076 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom); 00077 setOperationAction(ISD::FP_TO_UINT, MVT::i64, Expand); 00078 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom); 00079 00080 if (!TM.getSubtarget<AlphaSubtarget>().hasCT()) { 00081 setOperationAction(ISD::CTPOP , MVT::i64 , Expand); 00082 setOperationAction(ISD::CTTZ , MVT::i64 , Expand); 00083 setOperationAction(ISD::CTLZ , MVT::i64 , Expand); 00084 } 00085 setOperationAction(ISD::BSWAP , MVT::i64, Expand); 00086 setOperationAction(ISD::ROTL , MVT::i64, Expand); 00087 setOperationAction(ISD::ROTR , MVT::i64, Expand); 00088 00089 setOperationAction(ISD::SREM , MVT::i64, Custom); 00090 setOperationAction(ISD::UREM , MVT::i64, Custom); 00091 setOperationAction(ISD::SDIV , MVT::i64, Custom); 00092 setOperationAction(ISD::UDIV , MVT::i64, Custom); 00093 00094 setOperationAction(ISD::ADDC , MVT::i64, Expand); 00095 setOperationAction(ISD::ADDE , MVT::i64, Expand); 00096 setOperationAction(ISD::SUBC , MVT::i64, Expand); 00097 setOperationAction(ISD::SUBE , MVT::i64, Expand); 00098 00099 setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand); 00100 setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand); 00101 00102 00103 // We don't support sin/cos/sqrt/pow 00104 setOperationAction(ISD::FSIN , MVT::f64, Expand); 00105 setOperationAction(ISD::FCOS , MVT::f64, Expand); 00106 setOperationAction(ISD::FSIN , MVT::f32, Expand); 00107 setOperationAction(ISD::FCOS , MVT::f32, Expand); 00108 00109 setOperationAction(ISD::FSQRT, MVT::f64, Expand); 00110 setOperationAction(ISD::FSQRT, MVT::f32, Expand); 00111 00112 setOperationAction(ISD::FPOW , MVT::f32, Expand); 00113 setOperationAction(ISD::FPOW , MVT::f64, Expand); 00114 00115 setOperationAction(ISD::SETCC, MVT::f32, Promote); 00116 00117 setOperationAction(ISD::BIT_CONVERT, MVT::f32, Promote); 00118 00119 // We don't have line number support yet. 00120 setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand); 00121 setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand); 00122 setOperationAction(ISD::DBG_LABEL, MVT::Other, Expand); 00123 setOperationAction(ISD::EH_LABEL, MVT::Other, Expand); 00124 00125 // Not implemented yet. 00126 setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); 00127 setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); 00128 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Expand); 00129 00130 // We want to legalize GlobalAddress and ConstantPool and 00131 // ExternalSymbols nodes into the appropriate instructions to 00132 // materialize the address. 00133 setOperationAction(ISD::GlobalAddress, MVT::i64, Custom); 00134 setOperationAction(ISD::ConstantPool, MVT::i64, Custom); 00135 setOperationAction(ISD::ExternalSymbol, MVT::i64, Custom); 00136 setOperationAction(ISD::GlobalTLSAddress, MVT::i64, Custom); 00137 00138 setOperationAction(ISD::VASTART, MVT::Other, Custom); 00139 setOperationAction(ISD::VAEND, MVT::Other, Expand); 00140 setOperationAction(ISD::VACOPY, MVT::Other, Custom); 00141 setOperationAction(ISD::VAARG, MVT::Other, Custom); 00142 setOperationAction(ISD::VAARG, MVT::i32, Custom); 00143 00144 setOperationAction(ISD::RET, MVT::Other, Custom); 00145 00146 setOperationAction(ISD::JumpTable, MVT::i64, Custom); 00147 setOperationAction(ISD::JumpTable, MVT::i32, Custom); 00148 00149 setStackPointerRegisterToSaveRestore(Alpha::R30); 00150 00151 addLegalFPImmediate(APFloat(+0.0)); //F31 00152 addLegalFPImmediate(APFloat(+0.0f)); //F31 00153 addLegalFPImmediate(APFloat(-0.0)); //-F31 00154 addLegalFPImmediate(APFloat(-0.0f)); //-F31 00155 00156 setJumpBufSize(272); 00157 setJumpBufAlignment(16); 00158 00159 computeRegisterProperties(); 00160 } 00161 00162 MVT AlphaTargetLowering::getSetCCResultType(MVT VT) const { 00163 return MVT::i64; 00164 } 00165 00166 const char *AlphaTargetLowering::getTargetNodeName(unsigned Opcode) const { 00167 switch (Opcode) { 00168 default: return 0; 00169 case AlphaISD::CVTQT_: return "Alpha::CVTQT_"; 00170 case AlphaISD::CVTQS_: return "Alpha::CVTQS_"; 00171 case AlphaISD::CVTTQ_: return "Alpha::CVTTQ_"; 00172 case AlphaISD::GPRelHi: return "Alpha::GPRelHi"; 00173 case AlphaISD::GPRelLo: return "Alpha::GPRelLo"; 00174 case AlphaISD::RelLit: return "Alpha::RelLit"; 00175 case AlphaISD::GlobalRetAddr: return "Alpha::GlobalRetAddr"; 00176 case AlphaISD::CALL: return "Alpha::CALL"; 00177 case AlphaISD::DivCall: return "Alpha::DivCall"; 00178 case AlphaISD::RET_FLAG: return "Alpha::RET_FLAG"; 00179 case AlphaISD::COND_BRANCH_I: return "Alpha::COND_BRANCH_I"; 00180 case AlphaISD::COND_BRANCH_F: return "Alpha::COND_BRANCH_F"; 00181 } 00182 } 00183 00184 static SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) { 00185 MVT PtrVT = Op.getValueType(); 00186 JumpTableSDNode *JT = cast<JumpTableSDNode>(Op); 00187 SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT); 00188 SDValue Zero = DAG.getConstant(0, PtrVT); 00189 00190 SDValue Hi = DAG.getNode(AlphaISD::GPRelHi, MVT::i64, JTI, 00191 DAG.getNode(ISD::GLOBAL_OFFSET_TABLE, MVT::i64)); 00192 SDValue Lo = DAG.getNode(AlphaISD::GPRelLo, MVT::i64, JTI, Hi); 00193 return Lo; 00194 } 00195 00196 //http://www.cs.arizona.edu/computer.help/policy/DIGITAL_unix/ 00197 //AA-PY8AC-TET1_html/callCH3.html#BLOCK21 00198 00199 //For now, just use variable size stack frame format 00200 00201 //In a standard call, the first six items are passed in registers $16 00202 //- $21 and/or registers $f16 - $f21. (See Section 4.1.2 for details 00203 //of argument-to-register correspondence.) The remaining items are 00204 //collected in a memory argument list that is a naturally aligned 00205 //array of quadwords. In a standard call, this list, if present, must 00206 //be passed at 0(SP). 00207 //7 ... n 0(SP) ... (n-7)*8(SP) 00208 00209 // //#define FP $15 00210 // //#define RA $26 00211 // //#define PV $27 00212 // //#define GP $29 00213 // //#define SP $30 00214 00215 static SDValue LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, 00216 int &VarArgsBase, 00217 int &VarArgsOffset) { 00218 MachineFunction &MF = DAG.getMachineFunction(); 00219 MachineFrameInfo *MFI = MF.getFrameInfo(); 00220 std::vector<SDValue> ArgValues; 00221 SDValue Root = Op.getOperand(0); 00222 00223 AddLiveIn(MF, Alpha::R29, &Alpha::GPRCRegClass); //GP 00224 AddLiveIn(MF, Alpha::R26, &Alpha::GPRCRegClass); //RA 00225 00226 unsigned args_int[] = { 00227 Alpha::R16, Alpha::R17, Alpha::R18, Alpha::R19, Alpha::R20, Alpha::R21}; 00228 unsigned args_float[] = { 00229 Alpha::F16, Alpha::F17, Alpha::F18, Alpha::F19, Alpha::F20, Alpha::F21}; 00230 00231 for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues()-1; ArgNo != e; ++ArgNo) { 00232 SDValue argt; 00233 MVT ObjectVT = Op.getValue(ArgNo).getValueType(); 00234 SDValue ArgVal; 00235 00236 if (ArgNo < 6) { 00237 switch (ObjectVT.getSimpleVT()) { 00238 default: 00239 assert(false && "Invalid value type!"); 00240 case MVT::f64: 00241 args_float[ArgNo] = AddLiveIn(MF, args_float[ArgNo], 00242 &Alpha::F8RCRegClass); 00243 ArgVal = DAG.getCopyFromReg(Root, args_float[ArgNo], ObjectVT); 00244 break; 00245 case MVT::f32: 00246 args_float[ArgNo] = AddLiveIn(MF, args_float[ArgNo], 00247 &Alpha::F4RCRegClass); 00248 ArgVal = DAG.getCopyFromReg(Root, args_float[ArgNo], ObjectVT); 00249 break; 00250 case MVT::i64: 00251 args_int[ArgNo] = AddLiveIn(MF, args_int[ArgNo], 00252 &Alpha::GPRCRegClass); 00253 ArgVal = DAG.getCopyFromReg(Root, args_int[ArgNo], MVT::i64); 00254 break; 00255 } 00256 } else { //more args 00257 // Create the frame index object for this incoming parameter... 00258 int FI = MFI->CreateFixedObject(8, 8 * (ArgNo - 6)); 00259 00260 // Create the SelectionDAG nodes corresponding to a load 00261 //from this parameter 00262 SDValue FIN = DAG.getFrameIndex(FI, MVT::i64); 00263 ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0); 00264 } 00265 ArgValues.push_back(ArgVal); 00266 } 00267 00268 // If the functions takes variable number of arguments, copy all regs to stack 00269 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0; 00270 if (isVarArg) { 00271 VarArgsOffset = (Op.getNode()->getNumValues()-1) * 8; 00272 std::vector<SDValue> LS; 00273 for (int i = 0; i < 6; ++i) { 00274 if (TargetRegisterInfo::isPhysicalRegister(args_int[i])) 00275 args_int[i] = AddLiveIn(MF, args_int[i], &Alpha::GPRCRegClass); 00276 SDValue argt = DAG.getCopyFromReg(Root, args_int[i], MVT::i64); 00277 int FI = MFI->CreateFixedObject(8, -8 * (6 - i)); 00278 if (i == 0) VarArgsBase = FI; 00279 SDValue SDFI = DAG.getFrameIndex(FI, MVT::i64); 00280 LS.push_back(DAG.getStore(Root, argt, SDFI, NULL, 0)); 00281 00282 if (TargetRegisterInfo::isPhysicalRegister(args_float[i])) 00283 args_float[i] = AddLiveIn(MF, args_float[i], &Alpha::F8RCRegClass); 00284 argt = DAG.getCopyFromReg(Root, args_float[i], MVT::f64); 00285 FI = MFI->CreateFixedObject(8, - 8 * (12 - i)); 00286 SDFI = DAG.getFrameIndex(FI, MVT::i64); 00287 LS.push_back(DAG.getStore(Root, argt, SDFI, NULL, 0)); 00288 } 00289 00290 //Set up a token factor with all the stack traffic 00291 Root = DAG.getNode(ISD::TokenFactor, MVT::Other, &LS[0], LS.size()); 00292 } 00293 00294 ArgValues.push_back(Root); 00295 00296 // Return the new list of results. 00297 return DAG.getNode(ISD::MERGE_VALUES, Op.getNode()->getVTList(), 00298 &ArgValues[0], ArgValues.size()); 00299 } 00300 00301 static SDValue LowerRET(SDValue Op, SelectionDAG &DAG) { 00302 SDValue Copy = DAG.getCopyToReg(Op.getOperand(0), Alpha::R26, 00303 DAG.getNode(AlphaISD::GlobalRetAddr, 00304 MVT::i64), 00305 SDValue()); 00306 switch (Op.getNumOperands()) { 00307 default: 00308 assert(0 && "Do not know how to return this many arguments!"); 00309 abort(); 00310 case 1: 00311 break; 00312 //return SDValue(); // ret void is legal 00313 case 3: { 00314 MVT ArgVT = Op.getOperand(1).getValueType(); 00315 unsigned ArgReg; 00316 if (ArgVT.isInteger()) 00317 ArgReg = Alpha::R0; 00318 else { 00319 assert(ArgVT.isFloatingPoint()); 00320 ArgReg = Alpha::F0; 00321 } 00322 Copy = DAG.getCopyToReg(Copy, ArgReg, Op.getOperand(1), Copy.getValue(1)); 00323 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) 00324 DAG.getMachineFunction().getRegInfo().addLiveOut(ArgReg); 00325 break; 00326 } 00327 case 5: { 00328 MVT ArgVT = Op.getOperand(1).getValueType(); 00329 unsigned ArgReg1, ArgReg2; 00330 if (ArgVT.isInteger()) { 00331 ArgReg1 = Alpha::R0; 00332 ArgReg2 = Alpha::R1; 00333 } else { 00334 assert(ArgVT.isFloatingPoint()); 00335 ArgReg1 = Alpha::F0; 00336 ArgReg2 = Alpha::F1; 00337 } 00338 Copy = DAG.getCopyToReg(Copy, ArgReg1, Op.getOperand(1), Copy.getValue(1)); 00339 if (std::find(DAG.getMachineFunction().getRegInfo().liveout_begin(), 00340 DAG.getMachineFunction().getRegInfo().liveout_end(), ArgReg1) 00341 == DAG.getMachineFunction().getRegInfo().liveout_end()) 00342 DAG.getMachineFunction().getRegInfo().addLiveOut(ArgReg1); 00343 Copy = DAG.getCopyToReg(Copy, ArgReg2, Op.getOperand(3), Copy.getValue(1)); 00344 if (std::find(DAG.getMachineFunction().getRegInfo().liveout_begin(), 00345 DAG.getMachineFunction().getRegInfo().liveout_end(), ArgReg2) 00346 == DAG.getMachineFunction().getRegInfo().liveout_end()) 00347 DAG.getMachineFunction().getRegInfo().addLiveOut(ArgReg2); 00348 break; 00349 } 00350 } 00351 return DAG.getNode(AlphaISD::RET_FLAG, MVT::Other, Copy, Copy.getValue(1)); 00352 } 00353 00354 std::pair<SDValue, SDValue> 00355 AlphaTargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy, 00356 bool RetSExt, bool RetZExt, bool isVarArg, 00357 bool isInreg, unsigned CallingConv, 00358 bool isTailCall, SDValue Callee, 00359 ArgListTy &Args, SelectionDAG &DAG, 00360 DebugLoc dl) { 00361 int NumBytes = 0; 00362 if (Args.size() > 6) 00363 NumBytes = (Args.size() - 6) * 8; 00364 00365 Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumBytes, true)); 00366 std::vector<SDValue> args_to_use; 00367 for (unsigned i = 0, e = Args.size(); i != e; ++i) 00368 { 00369 switch (getValueType(Args[i].Ty).getSimpleVT()) { 00370 default: assert(0 && "Unexpected ValueType for argument!"); 00371 case MVT::i1: 00372 case MVT::i8: 00373 case MVT::i16: 00374 case MVT::i32: 00375 // Promote the integer to 64 bits. If the input type is signed use a 00376 // sign extend, otherwise use a zero extend. 00377 if (Args[i].isSExt) 00378 Args[i].Node = DAG.getNode(ISD::SIGN_EXTEND, dl, 00379 MVT::i64, Args[i].Node); 00380 else if (Args[i].isZExt) 00381 Args[i].Node = DAG.getNode(ISD::ZERO_EXTEND, dl, 00382 MVT::i64, Args[i].Node); 00383 else 00384 Args[i].Node = DAG.getNode(ISD::ANY_EXTEND, dl, MVT::i64, Args[i].Node); 00385 break; 00386 case MVT::i64: 00387 case MVT::f64: 00388 case MVT::f32: 00389 break; 00390 } 00391 args_to_use.push_back(Args[i].Node); 00392 } 00393 00394 std::vector<MVT> RetVals; 00395 MVT RetTyVT = getValueType(RetTy); 00396 MVT ActualRetTyVT = RetTyVT; 00397 if (RetTyVT.getSimpleVT() >= MVT::i1 && RetTyVT.getSimpleVT() <= MVT::i32) 00398 ActualRetTyVT = MVT::i64; 00399 00400 if (RetTyVT != MVT::isVoid) 00401 RetVals.push_back(ActualRetTyVT); 00402 RetVals.push_back(MVT::Other); 00403 00404 std::vector<SDValue> Ops; 00405 Ops.push_back(Chain); 00406 Ops.push_back(Callee); 00407 Ops.insert(Ops.end(), args_to_use.begin(), args_to_use.end()); 00408 SDValue TheCall = DAG.getNode(AlphaISD::CALL, dl, 00409 RetVals, &Ops[0], Ops.size()); 00410 Chain = TheCall.getValue(RetTyVT != MVT::isVoid); 00411 Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumBytes, true), 00412 DAG.getIntPtrConstant(0, true), SDValue()); 00413 SDValue RetVal = TheCall; 00414 00415 if (RetTyVT != ActualRetTyVT) { 00416 ISD::NodeType AssertKind = ISD::DELETED_NODE; 00417 if (RetSExt) 00418 AssertKind = ISD::AssertSext; 00419 else if (RetZExt) 00420 AssertKind = ISD::AssertZext; 00421 00422 if (AssertKind != ISD::DELETED_NODE) 00423 RetVal = DAG.getNode(AssertKind, dl, MVT::i64, RetVal, 00424 DAG.getValueType(RetTyVT)); 00425 00426 RetVal = DAG.getNode(ISD::TRUNCATE, dl, RetTyVT, RetVal); 00427 } 00428 00429 return std::make_pair(RetVal, Chain); 00430 } 00431 00432 void AlphaTargetLowering::LowerVAARG(SDNode *N, SDValue &Chain, 00433 SDValue &DataPtr, SelectionDAG &DAG) { 00434 Chain = N->getOperand(0); 00435 SDValue VAListP = N->getOperand(1); 00436 const Value *VAListS = cast<SrcValueSDNode>(N->getOperand(2))->getValue(); 00437 00438 SDValue Base = DAG.getLoad(MVT::i64, Chain, VAListP, VAListS, 0); 00439 SDValue Tmp = DAG.getNode(ISD::ADD, MVT::i64, VAListP, 00440 DAG.getConstant(8, MVT::i64)); 00441 SDValue Offset = DAG.getExtLoad(ISD::SEXTLOAD, MVT::i64, Base.getValue(1), 00442 Tmp, NULL, 0, MVT::i32); 00443 DataPtr = DAG.getNode(ISD::ADD, MVT::i64, Base, Offset); 00444 if (N->getValueType(0).isFloatingPoint()) 00445 { 00446 //if fp && Offset < 6*8, then subtract 6*8 from DataPtr 00447 SDValue FPDataPtr = DAG.getNode(ISD::SUB, MVT::i64, DataPtr, 00448 DAG.getConstant(8*6, MVT::i64)); 00449 SDValue CC = DAG.getSetCC(MVT::i64, Offset, 00450 DAG.getConstant(8*6, MVT::i64), ISD::SETLT); 00451 DataPtr = DAG.getNode(ISD::SELECT, MVT::i64, CC, FPDataPtr, DataPtr); 00452 } 00453 00454 SDValue NewOffset = DAG.getNode(ISD::ADD, MVT::i64, Offset, 00455 DAG.getConstant(8, MVT::i64)); 00456 Chain = DAG.getTruncStore(Offset.getValue(1), NewOffset, Tmp, NULL, 0, 00457 MVT::i32); 00458 } 00459 00460 /// LowerOperation - Provide custom lowering hooks for some operations. 00461 /// 00462 SDValue AlphaTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) { 00463 switch (Op.getOpcode()) { 00464 default: assert(0 && "Wasn't expecting to be able to lower this!"); 00465 case ISD::FORMAL_ARGUMENTS: return LowerFORMAL_ARGUMENTS(Op, DAG, 00466 VarArgsBase, 00467 VarArgsOffset); 00468 00469 case ISD::RET: return LowerRET(Op,DAG); 00470 case ISD::JumpTable: return LowerJumpTable(Op, DAG); 00471 00472 case ISD::INTRINSIC_WO_CHAIN: { 00473 unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); 00474 switch (IntNo) { 00475 default: break; // Don't custom lower most intrinsics. 00476 case Intrinsic::alpha_umulh: 00477 return DAG.getNode(ISD::MULHU, MVT::i64, Op.getOperand(1), Op.getOperand(2)); 00478 } 00479 } 00480 00481 case ISD::SINT_TO_FP: { 00482 assert(Op.getOperand(0).getValueType() == MVT::i64 && 00483 "Unhandled SINT_TO_FP type in custom expander!"); 00484 SDValue LD; 00485 bool isDouble = Op.getValueType() == MVT::f64; 00486 LD = DAG.getNode(ISD::BIT_CONVERT, MVT::f64, Op.getOperand(0)); 00487 SDValue FP = DAG.getNode(isDouble?AlphaISD::CVTQT_:AlphaISD::CVTQS_, 00488 isDouble?MVT::f64:MVT::f32, LD); 00489 return FP; 00490 } 00491 case ISD::FP_TO_SINT: { 00492 bool isDouble = Op.getOperand(0).getValueType() == MVT::f64; 00493 SDValue src = Op.getOperand(0); 00494 00495 if (!isDouble) //Promote 00496 src = DAG.getNode(ISD::FP_EXTEND, MVT::f64, src); 00497 00498 src = DAG.getNode(AlphaISD::CVTTQ_, MVT::f64, src); 00499 00500 return DAG.getNode(ISD::BIT_CONVERT, MVT::i64, src); 00501 } 00502 case ISD::ConstantPool: { 00503 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op); 00504 Constant *C = CP->getConstVal(); 00505 SDValue CPI = DAG.getTargetConstantPool(C, MVT::i64, CP->getAlignment()); 00506 00507 SDValue Hi = DAG.getNode(AlphaISD::GPRelHi, MVT::i64, CPI, 00508 DAG.getNode(ISD::GLOBAL_OFFSET_TABLE, MVT::i64)); 00509 SDValue Lo = DAG.getNode(AlphaISD::GPRelLo, MVT::i64, CPI, Hi); 00510 return Lo; 00511 } 00512 case ISD::GlobalTLSAddress: 00513 assert(0 && "TLS not implemented for Alpha."); 00514 case ISD::GlobalAddress: { 00515 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op); 00516 GlobalValue *GV = GSDN->getGlobal(); 00517 SDValue GA = DAG.getTargetGlobalAddress(GV, MVT::i64, GSDN->getOffset()); 00518 00519 // if (!GV->hasWeakLinkage() && !GV->isDeclaration() && !GV->hasLinkOnceLinkage()) { 00520 if (GV->hasLocalLinkage()) { 00521 SDValue Hi = DAG.getNode(AlphaISD::GPRelHi, MVT::i64, GA, 00522 DAG.getNode(ISD::GLOBAL_OFFSET_TABLE, MVT::i64)); 00523 SDValue Lo = DAG.getNode(AlphaISD::GPRelLo, MVT::i64, GA, Hi); 00524 return Lo; 00525 } else 00526 return DAG.getNode(AlphaISD::RelLit, MVT::i64, GA, 00527 DAG.getNode(ISD::GLOBAL_OFFSET_TABLE, MVT::i64)); 00528 } 00529 case ISD::ExternalSymbol: { 00530 return DAG.getNode(AlphaISD::RelLit, MVT::i64, 00531 DAG.getTargetExternalSymbol(cast<ExternalSymbolSDNode>(Op) 00532 ->getSymbol(), MVT::i64), 00533 DAG.getNode(ISD::GLOBAL_OFFSET_TABLE, MVT::i64)); 00534 } 00535 00536 case ISD::UREM: 00537 case ISD::SREM: 00538 //Expand only on constant case 00539 if (Op.getOperand(1).getOpcode() == ISD::Constant) { 00540 MVT VT = Op.getNode()->getValueType(0); 00541 SDValue Tmp1 = Op.getNode()->getOpcode() == ISD::UREM ? 00542 BuildUDIV(Op.getNode(), DAG, NULL) : 00543 BuildSDIV(Op.getNode(), DAG, NULL); 00544 Tmp1 = DAG.getNode(ISD::MUL, VT, Tmp1, Op.getOperand(1)); 00545 Tmp1 = DAG.getNode(ISD::SUB, VT, Op.getOperand(0), Tmp1); 00546 return Tmp1; 00547 } 00548 //fall through 00549 case ISD::SDIV: 00550 case ISD::UDIV: 00551 if (Op.getValueType().isInteger()) { 00552 if (Op.getOperand(1).getOpcode() == ISD::Constant) 00553 return Op.getOpcode() == ISD::SDIV ? BuildSDIV(Op.getNode(), DAG, NULL) 00554 : BuildUDIV(Op.getNode(), DAG, NULL); 00555 const char* opstr = 0; 00556 switch (Op.getOpcode()) { 00557 case ISD::UREM: opstr = "__remqu"; break; 00558 case ISD::SREM: opstr = "__remq"; break; 00559 case ISD::UDIV: opstr = "__divqu"; break; 00560 case ISD::SDIV: opstr = "__divq"; break; 00561 } 00562 SDValue Tmp1 = Op.getOperand(0), 00563 Tmp2 = Op.getOperand(1), 00564 Addr = DAG.getExternalSymbol(opstr, MVT::i64); 00565 return DAG.getNode(AlphaISD::DivCall, MVT::i64, Addr, Tmp1, Tmp2); 00566 } 00567 break; 00568 00569 case ISD::VAARG: { 00570 SDValue Chain, DataPtr; 00571 LowerVAARG(Op.getNode(), Chain, DataPtr, DAG); 00572 00573 SDValue Result; 00574 if (Op.getValueType() == MVT::i32) 00575 Result = DAG.getExtLoad(ISD::SEXTLOAD, MVT::i64, Chain, DataPtr, 00576 NULL, 0, MVT::i32); 00577 else 00578 Result = DAG.getLoad(Op.getValueType(), Chain, DataPtr, NULL, 0); 00579 return Result; 00580 } 00581 case ISD::VACOPY: { 00582 SDValue Chain = Op.getOperand(0); 00583 SDValue DestP = Op.getOperand(1); 00584 SDValue SrcP = Op.getOperand(2); 00585 const Value *DestS = cast<SrcValueSDNode>(Op.getOperand(3))->getValue(); 00586 const Value *SrcS = cast<SrcValueSDNode>(Op.getOperand(4))->getValue(); 00587 00588 SDValue Val = DAG.getLoad(getPointerTy(), Chain, SrcP, SrcS, 0); 00589 SDValue Result = DAG.getStore(Val.getValue(1), Val, DestP, DestS, 0); 00590 SDValue NP = DAG.getNode(ISD::ADD, MVT::i64, SrcP, 00591 DAG.getConstant(8, MVT::i64)); 00592 Val = DAG.getExtLoad(ISD::SEXTLOAD, MVT::i64, Result, NP, NULL,0, MVT::i32); 00593 SDValue NPD = DAG.getNode(ISD::ADD, MVT::i64, DestP, 00594 DAG.getConstant(8, MVT::i64)); 00595 return DAG.getTruncStore(Val.getValue(1), Val, NPD, NULL, 0, MVT::i32); 00596 } 00597 case ISD::VASTART: { 00598 SDValue Chain = Op.getOperand(0); 00599 SDValue VAListP = Op.getOperand(1); 00600 const Value *VAListS = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); 00601 00602 // vastart stores the address of the VarArgsBase and VarArgsOffset 00603 SDValue FR = DAG.getFrameIndex(VarArgsBase, MVT::i64); 00604 SDValue S1 = DAG.getStore(Chain, FR, VAListP, VAListS, 0); 00605 SDValue SA2 = DAG.getNode(ISD::ADD, MVT::i64, VAListP, 00606 DAG.getConstant(8, MVT::i64)); 00607 return DAG.getTruncStore(S1, DAG.getConstant(VarArgsOffset, MVT::i64), 00608 SA2, NULL, 0, MVT::i32); 00609 } 00610 case ISD::RETURNADDR: 00611 return DAG.getNode(AlphaISD::GlobalRetAddr, MVT::i64); 00612 //FIXME: implement 00613 case ISD::FRAMEADDR: break; 00614 } 00615 00616 return SDValue(); 00617 } 00618 00619 void AlphaTargetLowering::ReplaceNodeResults(SDNode *N, 00620 SmallVectorImpl<SDValue>&Results, 00621 SelectionDAG &DAG) { 00622 assert(N->getValueType(0) == MVT::i32 && 00623 N->getOpcode() == ISD::VAARG && 00624 "Unknown node to custom promote!"); 00625 00626 SDValue Chain, DataPtr; 00627 LowerVAARG(N, Chain, DataPtr, DAG); 00628 SDValue Res = DAG.getLoad(N->getValueType(0), Chain, DataPtr, NULL, 0); 00629 Results.push_back(Res); 00630 Results.push_back(SDValue(Res.getNode(), 1)); 00631 } 00632 00633 00634 //Inline Asm 00635 00636 /// getConstraintType - Given a constraint letter, return the type of 00637 /// constraint it is for this target. 00638 AlphaTargetLowering::ConstraintType 00639 AlphaTargetLowering::getConstraintType(const std::string &Constraint) const { 00640 if (Constraint.size() == 1) { 00641 switch (Constraint[0]) { 00642 default: break; 00643 case 'f': 00644 case 'r': 00645 return C_RegisterClass; 00646 } 00647 } 00648 return TargetLowering::getConstraintType(Constraint); 00649 } 00650 00651 std::vector<unsigned> AlphaTargetLowering:: 00652 getRegClassForInlineAsmConstraint(const std::string &Constraint, 00653 MVT VT) const { 00654 if (Constraint.size() == 1) { 00655 switch (Constraint[0]) { 00656 default: break; // Unknown constriant letter 00657 case 'f': 00658 return make_vector<unsigned>(Alpha::F0 , Alpha::F1 , Alpha::F2 , 00659 Alpha::F3 , Alpha::F4 , Alpha::F5 , 00660 Alpha::F6 , Alpha::F7 , Alpha::F8 , 00661 Alpha::F9 , Alpha::F10, Alpha::F11, 00662 Alpha::F12, Alpha::F13, Alpha::F14, 00663 Alpha::F15, Alpha::F16, Alpha::F17, 00664 Alpha::F18, Alpha::F19, Alpha::F20, 00665 Alpha::F21, Alpha::F22, Alpha::F23, 00666 Alpha::F24, Alpha::F25, Alpha::F26, 00667 Alpha::F27, Alpha::F28, Alpha::F29, 00668 Alpha::F30, Alpha::F31, 0); 00669 case 'r': 00670 return make_vector<unsigned>(Alpha::R0 , Alpha::R1 , Alpha::R2 , 00671 Alpha::R3 , Alpha::R4 , Alpha::R5 , 00672 Alpha::R6 , Alpha::R7 , Alpha::R8 , 00673 Alpha::R9 , Alpha::R10, Alpha::R11, 00674 Alpha::R12, Alpha::R13, Alpha::R14, 00675 Alpha::R15, Alpha::R16, Alpha::R17, 00676 Alpha::R18, Alpha::R19, Alpha::R20, 00677 Alpha::R21, Alpha::R22, Alpha::R23, 00678 Alpha::R24, Alpha::R25, Alpha::R26, 00679 Alpha::R27, Alpha::R28, Alpha::R29, 00680 Alpha::R30, Alpha::R31, 0); 00681 } 00682 } 00683 00684 return std::vector<unsigned>(); 00685 } 00686 //===----------------------------------------------------------------------===// 00687 // Other Lowering Code 00688 //===----------------------------------------------------------------------===// 00689 00690 MachineBasicBlock * 00691 AlphaTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, 00692 MachineBasicBlock *BB) { 00693 const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); 00694 assert((MI->getOpcode() == Alpha::CAS32 || 00695 MI->getOpcode() == Alpha::CAS64 || 00696 MI->getOpcode() == Alpha::LAS32 || 00697 MI->getOpcode() == Alpha::LAS64 || 00698 MI->getOpcode() == Alpha::SWAP32 || 00699 MI->getOpcode() == Alpha::SWAP64) && 00700 "Unexpected instr type to insert"); 00701 00702 bool is32 = MI->getOpcode() == Alpha::CAS32 || 00703 MI->getOpcode() == Alpha::LAS32 || 00704 MI->getOpcode() == Alpha::SWAP32; 00705 00706 //Load locked store conditional for atomic ops take on the same form 00707 //start: 00708 //ll 00709 //do stuff (maybe branch to exit) 00710 //sc 00711 //test sc and maybe branck to start 00712 //exit: 00713 const BasicBlock *LLVM_BB = BB->getBasicBlock(); 00714 MachineFunction::iterator It = BB; 00715 ++It; 00716 00717 MachineBasicBlock *thisMBB = BB; 00718 MachineFunction *F = BB->getParent(); 00719 MachineBasicBlock *llscMBB = F->CreateMachineBasicBlock(LLVM_BB); 00720 MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); 00721 00722 sinkMBB->transferSuccessors(thisMBB); 00723 00724 F->insert(It, llscMBB); 00725 F->insert(It, sinkMBB); 00726 00727 BuildMI(thisMBB, TII->get(Alpha::BR)).addMBB(llscMBB); 00728 00729 unsigned reg_res = MI->getOperand(0).getReg(), 00730 reg_ptr = MI->getOperand(1).getReg(), 00731 reg_v2 = MI->getOperand(2).getReg(), 00732 reg_store = F->getRegInfo().createVirtualRegister(&Alpha::GPRCRegClass); 00733 00734 BuildMI(llscMBB, TII->get(is32 ? Alpha::LDL_L : Alpha::LDQ_L), 00735 reg_res).addImm(0).addReg(reg_ptr); 00736 switch (MI->getOpcode()) { 00737 case Alpha::CAS32: 00738 case Alpha::CAS64: { 00739 unsigned reg_cmp 00740 = F->getRegInfo().createVirtualRegister(&Alpha::GPRCRegClass); 00741 BuildMI(llscMBB, TII->get(Alpha::CMPEQ), reg_cmp) 00742 .addReg(reg_v2).addReg(reg_res); 00743 BuildMI(llscMBB, TII->get(Alpha::BEQ)) 00744 .addImm(0).addReg(reg_cmp).addMBB(sinkMBB); 00745 BuildMI(llscMBB, TII->get(Alpha::BISr), reg_store) 00746 .addReg(Alpha::R31).addReg(MI->getOperand(3).getReg()); 00747 break; 00748 } 00749 case Alpha::LAS32: 00750 case Alpha::LAS64: { 00751 BuildMI(llscMBB, TII->get(is32 ? Alpha::ADDLr : Alpha::ADDQr), reg_store) 00752 .addReg(reg_res).addReg(reg_v2); 00753 break; 00754 } 00755 case Alpha::SWAP32: 00756 case Alpha::SWAP64: { 00757 BuildMI(llscMBB, TII->get(Alpha::BISr), reg_store) 00758 .addReg(reg_v2).addReg(reg_v2); 00759 break; 00760 } 00761 } 00762 BuildMI(llscMBB, TII->get(is32 ? Alpha::STL_C : Alpha::STQ_C), reg_store) 00763 .addReg(reg_store).addImm(0).addReg(reg_ptr); 00764 BuildMI(llscMBB, TII->get(Alpha::BEQ)) 00765 .addImm(0).addReg(reg_store).addMBB(llscMBB); 00766 BuildMI(llscMBB, TII->get(Alpha::BR)).addMBB(sinkMBB); 00767 00768 thisMBB->addSuccessor(llscMBB); 00769 llscMBB->addSuccessor(llscMBB); 00770 llscMBB->addSuccessor(sinkMBB); 00771 F->DeleteMachineInstr(MI); // The pseudo instruction is gone now. 00772 00773 return sinkMBB; 00774 } 00775 00776 bool 00777 AlphaTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { 00778 // The Alpha target isn't yet aware of offsets. 00779 return false; 00780 }