LLVM API Documentation

Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

AlphaISelLowering.cpp

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



This web site is hosted by the Computer Science Department at the University of Illinois at Urbana-Champaign.