X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FAlpha%2FAlphaISelLowering.cpp;h=001723a2fa7a2eb29cf12f4f1bbd47918c832311;hb=968ff1196768c0b6dbcc5508025a2923bfa73fab;hp=028f8851038b266381b7d587c38169353e165aa6;hpb=00fee65fd21f9615d1a604b8b7d42cd16a3f6b47;p=oota-llvm.git diff --git a/lib/Target/Alpha/AlphaISelLowering.cpp b/lib/Target/Alpha/AlphaISelLowering.cpp index 028f8851038..001723a2fa7 100644 --- a/lib/Target/Alpha/AlphaISelLowering.cpp +++ b/lib/Target/Alpha/AlphaISelLowering.cpp @@ -13,18 +13,39 @@ #include "AlphaISelLowering.h" #include "AlphaTargetMachine.h" +#include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Constants.h" #include "llvm/Function.h" #include "llvm/Module.h" +#include "llvm/Intrinsics.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; +namespace { +class TargetLoweringObjectFileAlpha : public TargetLoweringObjectFile { +public: + void Initialize(MCContext &Ctx, const TargetMachine &TM) { + TargetLoweringObjectFile::Initialize(Ctx, TM); + TextSection = getOrCreateSection("_text", true, + SectionKind::get(SectionKind::Text)); + DataSection = getOrCreateSection("_data", true, + SectionKind::get(SectionKind::DataRel)); + } +}; +} + + + /// AddLiveIn - This helper function adds the specified physical register to the /// MachineFunction as a live in value. It also creates a corresponding virtual /// register for it. @@ -36,28 +57,33 @@ static unsigned AddLiveIn(MachineFunction &MF, unsigned PReg, return VReg; } -AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM) : TargetLowering(TM) { +AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM) + : TargetLowering(TM, new TargetLoweringObjectFileAlpha()) { // Set up the TargetLowering object. - //I am having problems with shr n ubyte 1 + //I am having problems with shr n i8 1 setShiftAmountType(MVT::i64); - setSetCCResultType(MVT::i64); - setSetCCResultContents(ZeroOrOneSetCCResult); + setBooleanContents(ZeroOrOneBooleanContent); setUsesGlobalOffsetTable(true); addRegisterClass(MVT::i64, Alpha::GPRCRegisterClass); addRegisterClass(MVT::f64, Alpha::F8RCRegisterClass); addRegisterClass(MVT::f32, Alpha::F4RCRegisterClass); + + // We want to custom lower some of our intrinsics. + setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom); + + setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote); + setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand); - setLoadXAction(ISD::EXTLOAD, MVT::i1, Promote); - setLoadXAction(ISD::EXTLOAD, MVT::f32, Expand); - - setLoadXAction(ISD::ZEXTLOAD, MVT::i1, Promote); - setLoadXAction(ISD::ZEXTLOAD, MVT::i32, Expand); + setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote); + setLoadExtAction(ISD::ZEXTLOAD, MVT::i32, Expand); - setLoadXAction(ISD::SEXTLOAD, MVT::i1, Promote); - setLoadXAction(ISD::SEXTLOAD, MVT::i8, Expand); - setLoadXAction(ISD::SEXTLOAD, MVT::i16, Expand); + setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); + setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Expand); + setLoadExtAction(ISD::SEXTLOAD, MVT::i16, Expand); + + setTruncStoreAction(MVT::f64, MVT::f32, Expand); // setOperationAction(ISD::BRIND, MVT::Other, Expand); setOperationAction(ISD::BR_JT, MVT::Other, Expand); @@ -88,10 +114,15 @@ AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM) : TargetLowering(TM) setOperationAction(ISD::SDIV , MVT::i64, Custom); setOperationAction(ISD::UDIV , MVT::i64, Custom); - setOperationAction(ISD::MEMMOVE , MVT::Other, Expand); - setOperationAction(ISD::MEMSET , MVT::Other, Expand); - setOperationAction(ISD::MEMCPY , MVT::Other, Expand); - + setOperationAction(ISD::ADDC , MVT::i64, Expand); + setOperationAction(ISD::ADDE , MVT::i64, Expand); + setOperationAction(ISD::SUBC , MVT::i64, Expand); + setOperationAction(ISD::SUBE , MVT::i64, Expand); + + setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand); + setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand); + + // We don't support sin/cos/sqrt/pow setOperationAction(ISD::FSIN , MVT::f64, Expand); setOperationAction(ISD::FCOS , MVT::f64, Expand); @@ -103,15 +134,16 @@ AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM) : TargetLowering(TM) setOperationAction(ISD::FPOW , MVT::f32, Expand); setOperationAction(ISD::FPOW , MVT::f64, Expand); - + setOperationAction(ISD::SETCC, MVT::f32, Promote); setOperationAction(ISD::BIT_CONVERT, MVT::f32, Promote); // We don't have line number support yet. - setOperationAction(ISD::LOCATION, MVT::Other, Expand); + setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand); setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand); - setOperationAction(ISD::LABEL, MVT::Other, Expand); + setOperationAction(ISD::DBG_LABEL, MVT::Other, Expand); + setOperationAction(ISD::EH_LABEL, MVT::Other, Expand); // Not implemented yet. setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); @@ -150,6 +182,10 @@ AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM) : TargetLowering(TM) computeRegisterProperties(); } +MVT AlphaTargetLowering::getSetCCResultType(MVT VT) const { + return MVT::i64; +} + const char *AlphaTargetLowering::getTargetNodeName(unsigned Opcode) const { switch (Opcode) { default: return 0; @@ -168,15 +204,22 @@ const char *AlphaTargetLowering::getTargetNodeName(unsigned Opcode) const { } } -static SDOperand LowerJumpTable(SDOperand Op, SelectionDAG &DAG) { - MVT::ValueType PtrVT = Op.getValueType(); +/// getFunctionAlignment - Return the Log2 alignment of this function. +unsigned AlphaTargetLowering::getFunctionAlignment(const Function *F) const { + return 4; +} + +static SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) { + MVT PtrVT = Op.getValueType(); JumpTableSDNode *JT = cast(Op); - SDOperand JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT); - SDOperand Zero = DAG.getConstant(0, PtrVT); + SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT); + SDValue Zero = DAG.getConstant(0, PtrVT); + // FIXME there isn't really any debug info here + DebugLoc dl = Op.getDebugLoc(); - SDOperand Hi = DAG.getNode(AlphaISD::GPRelHi, MVT::i64, JTI, - DAG.getNode(ISD::GLOBAL_OFFSET_TABLE, MVT::i64)); - SDOperand Lo = DAG.getNode(AlphaISD::GPRelLo, MVT::i64, JTI, Hi); + SDValue Hi = DAG.getNode(AlphaISD::GPRelHi, dl, MVT::i64, JTI, + DAG.getGLOBAL_OFFSET_TABLE(MVT::i64)); + SDValue Lo = DAG.getNode(AlphaISD::GPRelLo, dl, MVT::i64, JTI, Hi); return Lo; } @@ -199,46 +242,211 @@ static SDOperand LowerJumpTable(SDOperand Op, SelectionDAG &DAG) { // //#define GP $29 // //#define SP $30 -static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG, +#include "AlphaGenCallingConv.inc" + +SDValue AlphaTargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) { + CallSDNode *TheCall = cast(Op.getNode()); + SDValue Chain = TheCall->getChain(); + SDValue Callee = TheCall->getCallee(); + bool isVarArg = TheCall->isVarArg(); + DebugLoc dl = Op.getDebugLoc(); + MachineFunction &MF = DAG.getMachineFunction(); + unsigned CC = MF.getFunction()->getCallingConv(); + + // Analyze operands of the call, assigning locations to each operand. + SmallVector ArgLocs; + CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext()); + + CCInfo.AnalyzeCallOperands(TheCall, CC_Alpha); + + // Get a count of how many bytes are to be pushed on the stack. + unsigned NumBytes = CCInfo.getNextStackOffset(); + + Chain = DAG.getCALLSEQ_START(Chain, DAG.getConstant(NumBytes, + getPointerTy(), true)); + + SmallVector, 4> RegsToPass; + SmallVector MemOpChains; + SDValue StackPtr; + + // Walk the register/memloc assignments, inserting copies/loads. + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + CCValAssign &VA = ArgLocs[i]; + + // Arguments start after the 5 first operands of ISD::CALL + SDValue Arg = TheCall->getArg(i); + + // Promote the value if needed. + switch (VA.getLocInfo()) { + default: assert(0 && "Unknown loc info!"); + case CCValAssign::Full: break; + case CCValAssign::SExt: + Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg); + break; + case CCValAssign::ZExt: + Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg); + break; + case CCValAssign::AExt: + Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg); + break; + } + + // Arguments that can be passed on register must be kept at RegsToPass + // vector + if (VA.isRegLoc()) { + RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); + } else { + assert(VA.isMemLoc()); + + if (StackPtr.getNode() == 0) + StackPtr = DAG.getCopyFromReg(Chain, dl, Alpha::R30, MVT::i64); + + SDValue PtrOff = DAG.getNode(ISD::ADD, dl, getPointerTy(), + StackPtr, + DAG.getIntPtrConstant(VA.getLocMemOffset())); + + MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, + PseudoSourceValue::getStack(), 0)); + } + } + + // Transform all store nodes into one single node because all store nodes are + // independent of each other. + if (!MemOpChains.empty()) + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + &MemOpChains[0], MemOpChains.size()); + + // Build a sequence of copy-to-reg nodes chained together with token chain and + // flag operands which copy the outgoing args into registers. The InFlag in + // necessary since all emited instructions must be stuck together. + SDValue InFlag; + for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { + Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, + RegsToPass[i].second, InFlag); + InFlag = Chain.getValue(1); + } + + // Returns a chain & a flag for retval copy to use. + SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); + SmallVector Ops; + Ops.push_back(Chain); + Ops.push_back(Callee); + + // Add argument registers to the end of the list so that they are + // known live into the call. + for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) + Ops.push_back(DAG.getRegister(RegsToPass[i].first, + RegsToPass[i].second.getValueType())); + + if (InFlag.getNode()) + Ops.push_back(InFlag); + + Chain = DAG.getNode(AlphaISD::CALL, dl, NodeTys, &Ops[0], Ops.size()); + InFlag = Chain.getValue(1); + + // Create the CALLSEQ_END node. + Chain = DAG.getCALLSEQ_END(Chain, + DAG.getConstant(NumBytes, getPointerTy(), true), + DAG.getConstant(0, getPointerTy(), true), + InFlag); + InFlag = Chain.getValue(1); + + // Handle result values, copying them out of physregs into vregs that we + // return. + return SDValue(LowerCallResult(Chain, InFlag, TheCall, CC, DAG), + Op.getResNo()); +} + +/// LowerCallResult - Lower the result values of an ISD::CALL into the +/// appropriate copies out of appropriate physical registers. This assumes that +/// Chain/InFlag are the input chain/flag to use, and that TheCall is the call +/// being lowered. Returns a SDNode with the same number of values as the +/// ISD::CALL. +SDNode* +AlphaTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, + CallSDNode *TheCall, + unsigned CallingConv, + SelectionDAG &DAG) { + bool isVarArg = TheCall->isVarArg(); + DebugLoc dl = TheCall->getDebugLoc(); + + // Assign locations to each value returned by this call. + SmallVector RVLocs; + CCState CCInfo(CallingConv, isVarArg, getTargetMachine(), RVLocs, + *DAG.getContext()); + + CCInfo.AnalyzeCallResult(TheCall, RetCC_Alpha); + SmallVector ResultVals; + + // Copy all of the result registers out of their specified physreg. + for (unsigned i = 0; i != RVLocs.size(); ++i) { + CCValAssign &VA = RVLocs[i]; + + Chain = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), + VA.getLocVT(), InFlag).getValue(1); + SDValue RetValue = Chain.getValue(0); + InFlag = Chain.getValue(2); + + // If this is an 8/16/32-bit value, it is really passed promoted to 64 + // bits. Insert an assert[sz]ext to capture this, then truncate to the + // right size. + if (VA.getLocInfo() == CCValAssign::SExt) + RetValue = DAG.getNode(ISD::AssertSext, dl, VA.getLocVT(), RetValue, + DAG.getValueType(VA.getValVT())); + else if (VA.getLocInfo() == CCValAssign::ZExt) + RetValue = DAG.getNode(ISD::AssertZext, dl, VA.getLocVT(), RetValue, + DAG.getValueType(VA.getValVT())); + + if (VA.getLocInfo() != CCValAssign::Full) + RetValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), RetValue); + + ResultVals.push_back(RetValue); + } + + ResultVals.push_back(Chain); + + // Merge everything together with a MERGE_VALUES node. + return DAG.getNode(ISD::MERGE_VALUES, dl, TheCall->getVTList(), + &ResultVals[0], ResultVals.size()).getNode(); +} + +static SDValue LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsBase, int &VarArgsOffset) { MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); - std::vector ArgValues; - SDOperand Root = Op.getOperand(0); - - AddLiveIn(MF, Alpha::R29, &Alpha::GPRCRegClass); //GP - AddLiveIn(MF, Alpha::R26, &Alpha::GPRCRegClass); //RA + std::vector ArgValues; + SDValue Root = Op.getOperand(0); + DebugLoc dl = Op.getDebugLoc(); unsigned args_int[] = { Alpha::R16, Alpha::R17, Alpha::R18, Alpha::R19, Alpha::R20, Alpha::R21}; unsigned args_float[] = { Alpha::F16, Alpha::F17, Alpha::F18, Alpha::F19, Alpha::F20, Alpha::F21}; - for (unsigned ArgNo = 0, e = Op.Val->getNumValues()-1; ArgNo != e; ++ArgNo) { - SDOperand argt; - MVT::ValueType ObjectVT = Op.getValue(ArgNo).getValueType(); - SDOperand ArgVal; + for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues()-1; ArgNo != e; ++ArgNo) { + SDValue argt; + MVT ObjectVT = Op.getValue(ArgNo).getValueType(); + SDValue ArgVal; if (ArgNo < 6) { - switch (ObjectVT) { + switch (ObjectVT.getSimpleVT()) { default: - cerr << "Unknown Type " << ObjectVT << "\n"; - abort(); + assert(false && "Invalid value type!"); case MVT::f64: args_float[ArgNo] = AddLiveIn(MF, args_float[ArgNo], &Alpha::F8RCRegClass); - ArgVal = DAG.getCopyFromReg(Root, args_float[ArgNo], ObjectVT); + ArgVal = DAG.getCopyFromReg(Root, dl, args_float[ArgNo], ObjectVT); break; case MVT::f32: args_float[ArgNo] = AddLiveIn(MF, args_float[ArgNo], &Alpha::F4RCRegClass); - ArgVal = DAG.getCopyFromReg(Root, args_float[ArgNo], ObjectVT); + ArgVal = DAG.getCopyFromReg(Root, dl, args_float[ArgNo], ObjectVT); break; case MVT::i64: args_int[ArgNo] = AddLiveIn(MF, args_int[ArgNo], &Alpha::GPRCRegClass); - ArgVal = DAG.getCopyFromReg(Root, args_int[ArgNo], MVT::i64); + ArgVal = DAG.getCopyFromReg(Root, dl, args_int[ArgNo], MVT::i64); break; } } else { //more args @@ -247,239 +455,231 @@ static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG, // Create the SelectionDAG nodes corresponding to a load //from this parameter - SDOperand FIN = DAG.getFrameIndex(FI, MVT::i64); - ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0); + SDValue FIN = DAG.getFrameIndex(FI, MVT::i64); + ArgVal = DAG.getLoad(ObjectVT, dl, Root, FIN, NULL, 0); } ArgValues.push_back(ArgVal); } // If the functions takes variable number of arguments, copy all regs to stack - bool isVarArg = cast(Op.getOperand(2))->getValue() != 0; + bool isVarArg = cast(Op.getOperand(2))->getZExtValue() != 0; if (isVarArg) { - VarArgsOffset = (Op.Val->getNumValues()-1) * 8; - std::vector LS; + VarArgsOffset = (Op.getNode()->getNumValues()-1) * 8; + std::vector LS; for (int i = 0; i < 6; ++i) { if (TargetRegisterInfo::isPhysicalRegister(args_int[i])) args_int[i] = AddLiveIn(MF, args_int[i], &Alpha::GPRCRegClass); - SDOperand argt = DAG.getCopyFromReg(Root, args_int[i], MVT::i64); + SDValue argt = DAG.getCopyFromReg(Root, dl, args_int[i], MVT::i64); int FI = MFI->CreateFixedObject(8, -8 * (6 - i)); if (i == 0) VarArgsBase = FI; - SDOperand SDFI = DAG.getFrameIndex(FI, MVT::i64); - LS.push_back(DAG.getStore(Root, argt, SDFI, NULL, 0)); + SDValue SDFI = DAG.getFrameIndex(FI, MVT::i64); + LS.push_back(DAG.getStore(Root, dl, argt, SDFI, NULL, 0)); if (TargetRegisterInfo::isPhysicalRegister(args_float[i])) args_float[i] = AddLiveIn(MF, args_float[i], &Alpha::F8RCRegClass); - argt = DAG.getCopyFromReg(Root, args_float[i], MVT::f64); + argt = DAG.getCopyFromReg(Root, dl, args_float[i], MVT::f64); FI = MFI->CreateFixedObject(8, - 8 * (12 - i)); SDFI = DAG.getFrameIndex(FI, MVT::i64); - LS.push_back(DAG.getStore(Root, argt, SDFI, NULL, 0)); + LS.push_back(DAG.getStore(Root, dl, argt, SDFI, NULL, 0)); } //Set up a token factor with all the stack traffic - Root = DAG.getNode(ISD::TokenFactor, MVT::Other, &LS[0], LS.size()); + Root = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &LS[0], LS.size()); } ArgValues.push_back(Root); // Return the new list of results. - std::vector RetVT(Op.Val->value_begin(), - Op.Val->value_end()); - return DAG.getNode(ISD::MERGE_VALUES, RetVT, &ArgValues[0], ArgValues.size()); + return DAG.getNode(ISD::MERGE_VALUES, dl, Op.getNode()->getVTList(), + &ArgValues[0], ArgValues.size()); } -static SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG) { - SDOperand Copy = DAG.getCopyToReg(Op.getOperand(0), Alpha::R26, +static SDValue LowerRET(SDValue Op, SelectionDAG &DAG) { + DebugLoc dl = Op.getDebugLoc(); + SDValue Copy = DAG.getCopyToReg(Op.getOperand(0), dl, Alpha::R26, DAG.getNode(AlphaISD::GlobalRetAddr, + DebugLoc::getUnknownLoc(), MVT::i64), - SDOperand()); + SDValue()); switch (Op.getNumOperands()) { default: - assert(0 && "Do not know how to return this many arguments!"); - abort(); + llvm_unreachable("Do not know how to return this many arguments!"); case 1: break; - //return SDOperand(); // ret void is legal + //return SDValue(); // ret void is legal case 3: { - MVT::ValueType ArgVT = Op.getOperand(1).getValueType(); + MVT ArgVT = Op.getOperand(1).getValueType(); unsigned ArgReg; - if (MVT::isInteger(ArgVT)) + if (ArgVT.isInteger()) ArgReg = Alpha::R0; else { - assert(MVT::isFloatingPoint(ArgVT)); + assert(ArgVT.isFloatingPoint()); ArgReg = Alpha::F0; } - Copy = DAG.getCopyToReg(Copy, ArgReg, Op.getOperand(1), Copy.getValue(1)); + Copy = DAG.getCopyToReg(Copy, dl, ArgReg, + Op.getOperand(1), Copy.getValue(1)); if (DAG.getMachineFunction().getRegInfo().liveout_empty()) DAG.getMachineFunction().getRegInfo().addLiveOut(ArgReg); break; } + case 5: { + MVT ArgVT = Op.getOperand(1).getValueType(); + unsigned ArgReg1, ArgReg2; + if (ArgVT.isInteger()) { + ArgReg1 = Alpha::R0; + ArgReg2 = Alpha::R1; + } else { + assert(ArgVT.isFloatingPoint()); + ArgReg1 = Alpha::F0; + ArgReg2 = Alpha::F1; + } + Copy = DAG.getCopyToReg(Copy, dl, ArgReg1, + Op.getOperand(1), Copy.getValue(1)); + if (std::find(DAG.getMachineFunction().getRegInfo().liveout_begin(), + DAG.getMachineFunction().getRegInfo().liveout_end(), ArgReg1) + == DAG.getMachineFunction().getRegInfo().liveout_end()) + DAG.getMachineFunction().getRegInfo().addLiveOut(ArgReg1); + Copy = DAG.getCopyToReg(Copy, dl, ArgReg2, + Op.getOperand(3), Copy.getValue(1)); + if (std::find(DAG.getMachineFunction().getRegInfo().liveout_begin(), + DAG.getMachineFunction().getRegInfo().liveout_end(), ArgReg2) + == DAG.getMachineFunction().getRegInfo().liveout_end()) + DAG.getMachineFunction().getRegInfo().addLiveOut(ArgReg2); + break; + } } - return DAG.getNode(AlphaISD::RET_FLAG, MVT::Other, Copy, Copy.getValue(1)); + return DAG.getNode(AlphaISD::RET_FLAG, dl, + MVT::Other, Copy, Copy.getValue(1)); } -std::pair -AlphaTargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy, - bool RetSExt, bool RetZExt, bool isVarArg, - unsigned CallingConv, bool isTailCall, - SDOperand Callee, ArgListTy &Args, - SelectionDAG &DAG) { - int NumBytes = 0; - if (Args.size() > 6) - NumBytes = (Args.size() - 6) * 8; - - Chain = DAG.getCALLSEQ_START(Chain, - DAG.getConstant(NumBytes, getPointerTy())); - std::vector args_to_use; - for (unsigned i = 0, e = Args.size(); i != e; ++i) +void AlphaTargetLowering::LowerVAARG(SDNode *N, SDValue &Chain, + SDValue &DataPtr, SelectionDAG &DAG) { + Chain = N->getOperand(0); + SDValue VAListP = N->getOperand(1); + const Value *VAListS = cast(N->getOperand(2))->getValue(); + DebugLoc dl = N->getDebugLoc(); + + SDValue Base = DAG.getLoad(MVT::i64, dl, Chain, VAListP, VAListS, 0); + SDValue Tmp = DAG.getNode(ISD::ADD, dl, MVT::i64, VAListP, + DAG.getConstant(8, MVT::i64)); + SDValue Offset = DAG.getExtLoad(ISD::SEXTLOAD, dl, MVT::i64, Base.getValue(1), + Tmp, NULL, 0, MVT::i32); + DataPtr = DAG.getNode(ISD::ADD, dl, MVT::i64, Base, Offset); + if (N->getValueType(0).isFloatingPoint()) { - switch (getValueType(Args[i].Ty)) { - default: assert(0 && "Unexpected ValueType for argument!"); - case MVT::i1: - case MVT::i8: - case MVT::i16: - case MVT::i32: - // Promote the integer to 64 bits. If the input type is signed use a - // sign extend, otherwise use a zero extend. - if (Args[i].isSExt) - Args[i].Node = DAG.getNode(ISD::SIGN_EXTEND, MVT::i64, Args[i].Node); - else if (Args[i].isZExt) - Args[i].Node = DAG.getNode(ISD::ZERO_EXTEND, MVT::i64, Args[i].Node); - else - Args[i].Node = DAG.getNode(ISD::ANY_EXTEND, MVT::i64, Args[i].Node); - break; - case MVT::i64: - case MVT::f64: - case MVT::f32: - break; - } - args_to_use.push_back(Args[i].Node); + //if fp && Offset < 6*8, then subtract 6*8 from DataPtr + SDValue FPDataPtr = DAG.getNode(ISD::SUB, dl, MVT::i64, DataPtr, + DAG.getConstant(8*6, MVT::i64)); + SDValue CC = DAG.getSetCC(dl, MVT::i64, Offset, + DAG.getConstant(8*6, MVT::i64), ISD::SETLT); + DataPtr = DAG.getNode(ISD::SELECT, dl, MVT::i64, CC, FPDataPtr, DataPtr); } - std::vector RetVals; - MVT::ValueType RetTyVT = getValueType(RetTy); - MVT::ValueType ActualRetTyVT = RetTyVT; - if (RetTyVT >= MVT::i1 && RetTyVT <= MVT::i32) - ActualRetTyVT = MVT::i64; - - if (RetTyVT != MVT::isVoid) - RetVals.push_back(ActualRetTyVT); - RetVals.push_back(MVT::Other); - - std::vector Ops; - Ops.push_back(Chain); - Ops.push_back(Callee); - Ops.insert(Ops.end(), args_to_use.begin(), args_to_use.end()); - SDOperand TheCall = DAG.getNode(AlphaISD::CALL, RetVals, &Ops[0], Ops.size()); - Chain = TheCall.getValue(RetTyVT != MVT::isVoid); - Chain = DAG.getCALLSEQ_END(Chain, - DAG.getConstant(NumBytes, getPointerTy()), - DAG.getConstant(0, getPointerTy()), - SDOperand()); - SDOperand RetVal = TheCall; - - if (RetTyVT != ActualRetTyVT) { - ISD::NodeType AssertKind = ISD::DELETED_NODE; - if (RetSExt) - AssertKind = ISD::AssertSext; - else if (RetZExt) - AssertKind = ISD::AssertZext; - - if (AssertKind != ISD::DELETED_NODE) - RetVal = DAG.getNode(AssertKind, MVT::i64, RetVal, - DAG.getValueType(RetTyVT)); - - RetVal = DAG.getNode(ISD::TRUNCATE, RetTyVT, RetVal); - } - - return std::make_pair(RetVal, Chain); + SDValue NewOffset = DAG.getNode(ISD::ADD, dl, MVT::i64, Offset, + DAG.getConstant(8, MVT::i64)); + Chain = DAG.getTruncStore(Offset.getValue(1), dl, NewOffset, Tmp, NULL, 0, + MVT::i32); } /// LowerOperation - Provide custom lowering hooks for some operations. /// -SDOperand AlphaTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { +SDValue AlphaTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) { + DebugLoc dl = Op.getDebugLoc(); switch (Op.getOpcode()) { - default: assert(0 && "Wasn't expecting to be able to lower this!"); + default: llvm_unreachable("Wasn't expecting to be able to lower this!"); case ISD::FORMAL_ARGUMENTS: return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsBase, VarArgsOffset); - + case ISD::CALL: return LowerCALL(Op, DAG); case ISD::RET: return LowerRET(Op,DAG); case ISD::JumpTable: return LowerJumpTable(Op, DAG); + case ISD::INTRINSIC_WO_CHAIN: { + unsigned IntNo = cast(Op.getOperand(0))->getZExtValue(); + switch (IntNo) { + default: break; // Don't custom lower most intrinsics. + case Intrinsic::alpha_umulh: + return DAG.getNode(ISD::MULHU, dl, MVT::i64, + Op.getOperand(1), Op.getOperand(2)); + } + } + case ISD::SINT_TO_FP: { - assert(MVT::i64 == Op.getOperand(0).getValueType() && + assert(Op.getOperand(0).getValueType() == MVT::i64 && "Unhandled SINT_TO_FP type in custom expander!"); - SDOperand LD; - bool isDouble = MVT::f64 == Op.getValueType(); - LD = DAG.getNode(ISD::BIT_CONVERT, MVT::f64, Op.getOperand(0)); - SDOperand FP = DAG.getNode(isDouble?AlphaISD::CVTQT_:AlphaISD::CVTQS_, + SDValue LD; + bool isDouble = Op.getValueType() == MVT::f64; + LD = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f64, Op.getOperand(0)); + SDValue FP = DAG.getNode(isDouble?AlphaISD::CVTQT_:AlphaISD::CVTQS_, dl, isDouble?MVT::f64:MVT::f32, LD); return FP; } case ISD::FP_TO_SINT: { - bool isDouble = MVT::f64 == Op.getOperand(0).getValueType(); - SDOperand src = Op.getOperand(0); + bool isDouble = Op.getOperand(0).getValueType() == MVT::f64; + SDValue src = Op.getOperand(0); if (!isDouble) //Promote - src = DAG.getNode(ISD::FP_EXTEND, MVT::f64, src); + src = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, src); - src = DAG.getNode(AlphaISD::CVTTQ_, MVT::f64, src); + src = DAG.getNode(AlphaISD::CVTTQ_, dl, MVT::f64, src); - return DAG.getNode(ISD::BIT_CONVERT, MVT::i64, src); + return DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i64, src); } case ISD::ConstantPool: { ConstantPoolSDNode *CP = cast(Op); Constant *C = CP->getConstVal(); - SDOperand CPI = DAG.getTargetConstantPool(C, MVT::i64, CP->getAlignment()); + SDValue CPI = DAG.getTargetConstantPool(C, MVT::i64, CP->getAlignment()); + // FIXME there isn't really any debug info here - SDOperand Hi = DAG.getNode(AlphaISD::GPRelHi, MVT::i64, CPI, - DAG.getNode(ISD::GLOBAL_OFFSET_TABLE, MVT::i64)); - SDOperand Lo = DAG.getNode(AlphaISD::GPRelLo, MVT::i64, CPI, Hi); + SDValue Hi = DAG.getNode(AlphaISD::GPRelHi, dl, MVT::i64, CPI, + DAG.getGLOBAL_OFFSET_TABLE(MVT::i64)); + SDValue Lo = DAG.getNode(AlphaISD::GPRelLo, dl, MVT::i64, CPI, Hi); return Lo; } case ISD::GlobalTLSAddress: - assert(0 && "TLS not implemented for Alpha."); + llvm_unreachable("TLS not implemented for Alpha."); case ISD::GlobalAddress: { GlobalAddressSDNode *GSDN = cast(Op); GlobalValue *GV = GSDN->getGlobal(); - SDOperand GA = DAG.getTargetGlobalAddress(GV, MVT::i64, GSDN->getOffset()); + SDValue GA = DAG.getTargetGlobalAddress(GV, MVT::i64, GSDN->getOffset()); + // FIXME there isn't really any debug info here // if (!GV->hasWeakLinkage() && !GV->isDeclaration() && !GV->hasLinkOnceLinkage()) { - if (GV->hasInternalLinkage()) { - SDOperand Hi = DAG.getNode(AlphaISD::GPRelHi, MVT::i64, GA, - DAG.getNode(ISD::GLOBAL_OFFSET_TABLE, MVT::i64)); - SDOperand Lo = DAG.getNode(AlphaISD::GPRelLo, MVT::i64, GA, Hi); + if (GV->hasLocalLinkage()) { + SDValue Hi = DAG.getNode(AlphaISD::GPRelHi, dl, MVT::i64, GA, + DAG.getGLOBAL_OFFSET_TABLE(MVT::i64)); + SDValue Lo = DAG.getNode(AlphaISD::GPRelLo, dl, MVT::i64, GA, Hi); return Lo; } else - return DAG.getNode(AlphaISD::RelLit, MVT::i64, GA, - DAG.getNode(ISD::GLOBAL_OFFSET_TABLE, MVT::i64)); + return DAG.getNode(AlphaISD::RelLit, dl, MVT::i64, GA, + DAG.getGLOBAL_OFFSET_TABLE(MVT::i64)); } case ISD::ExternalSymbol: { - return DAG.getNode(AlphaISD::RelLit, MVT::i64, + return DAG.getNode(AlphaISD::RelLit, dl, MVT::i64, DAG.getTargetExternalSymbol(cast(Op) ->getSymbol(), MVT::i64), - DAG.getNode(ISD::GLOBAL_OFFSET_TABLE, MVT::i64)); + DAG.getGLOBAL_OFFSET_TABLE(MVT::i64)); } case ISD::UREM: case ISD::SREM: //Expand only on constant case if (Op.getOperand(1).getOpcode() == ISD::Constant) { - MVT::ValueType VT = Op.Val->getValueType(0); - SDOperand Tmp1 = Op.Val->getOpcode() == ISD::UREM ? - BuildUDIV(Op.Val, DAG, NULL) : - BuildSDIV(Op.Val, DAG, NULL); - Tmp1 = DAG.getNode(ISD::MUL, VT, Tmp1, Op.getOperand(1)); - Tmp1 = DAG.getNode(ISD::SUB, VT, Op.getOperand(0), Tmp1); + MVT VT = Op.getNode()->getValueType(0); + SDValue Tmp1 = Op.getNode()->getOpcode() == ISD::UREM ? + BuildUDIV(Op.getNode(), DAG, NULL) : + BuildSDIV(Op.getNode(), DAG, NULL); + Tmp1 = DAG.getNode(ISD::MUL, dl, VT, Tmp1, Op.getOperand(1)); + Tmp1 = DAG.getNode(ISD::SUB, dl, VT, Op.getOperand(0), Tmp1); return Tmp1; } //fall through case ISD::SDIV: case ISD::UDIV: - if (MVT::isInteger(Op.getValueType())) { + if (Op.getValueType().isInteger()) { if (Op.getOperand(1).getOpcode() == ISD::Constant) - return Op.getOpcode() == ISD::SDIV ? BuildSDIV(Op.Val, DAG, NULL) - : BuildUDIV(Op.Val, DAG, NULL); + return Op.getOpcode() == ISD::SDIV ? BuildSDIV(Op.getNode(), DAG, NULL) + : BuildUDIV(Op.getNode(), DAG, NULL); const char* opstr = 0; switch (Op.getOpcode()) { case ISD::UREM: opstr = "__remqu"; break; @@ -487,93 +687,78 @@ SDOperand AlphaTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { case ISD::UDIV: opstr = "__divqu"; break; case ISD::SDIV: opstr = "__divq"; break; } - SDOperand Tmp1 = Op.getOperand(0), + SDValue Tmp1 = Op.getOperand(0), Tmp2 = Op.getOperand(1), Addr = DAG.getExternalSymbol(opstr, MVT::i64); - return DAG.getNode(AlphaISD::DivCall, MVT::i64, Addr, Tmp1, Tmp2); + return DAG.getNode(AlphaISD::DivCall, dl, MVT::i64, Addr, Tmp1, Tmp2); } break; case ISD::VAARG: { - SDOperand Chain = Op.getOperand(0); - SDOperand VAListP = Op.getOperand(1); - const Value *VAListS = cast(Op.getOperand(2))->getValue(); - - SDOperand Base = DAG.getLoad(MVT::i64, Chain, VAListP, VAListS, 0); - SDOperand Tmp = DAG.getNode(ISD::ADD, MVT::i64, VAListP, - DAG.getConstant(8, MVT::i64)); - SDOperand Offset = DAG.getExtLoad(ISD::SEXTLOAD, MVT::i64, Base.getValue(1), - Tmp, NULL, 0, MVT::i32); - SDOperand DataPtr = DAG.getNode(ISD::ADD, MVT::i64, Base, Offset); - if (MVT::isFloatingPoint(Op.getValueType())) - { - //if fp && Offset < 6*8, then subtract 6*8 from DataPtr - SDOperand FPDataPtr = DAG.getNode(ISD::SUB, MVT::i64, DataPtr, - DAG.getConstant(8*6, MVT::i64)); - SDOperand CC = DAG.getSetCC(MVT::i64, Offset, - DAG.getConstant(8*6, MVT::i64), ISD::SETLT); - DataPtr = DAG.getNode(ISD::SELECT, MVT::i64, CC, FPDataPtr, DataPtr); - } + SDValue Chain, DataPtr; + LowerVAARG(Op.getNode(), Chain, DataPtr, DAG); - SDOperand NewOffset = DAG.getNode(ISD::ADD, MVT::i64, Offset, - DAG.getConstant(8, MVT::i64)); - SDOperand Update = DAG.getTruncStore(Offset.getValue(1), NewOffset, - Tmp, NULL, 0, MVT::i32); - - SDOperand Result; + SDValue Result; if (Op.getValueType() == MVT::i32) - Result = DAG.getExtLoad(ISD::SEXTLOAD, MVT::i64, Update, DataPtr, + Result = DAG.getExtLoad(ISD::SEXTLOAD, dl, MVT::i64, Chain, DataPtr, NULL, 0, MVT::i32); else - Result = DAG.getLoad(Op.getValueType(), Update, DataPtr, NULL, 0); + Result = DAG.getLoad(Op.getValueType(), dl, Chain, DataPtr, NULL, 0); return Result; } case ISD::VACOPY: { - SDOperand Chain = Op.getOperand(0); - SDOperand DestP = Op.getOperand(1); - SDOperand SrcP = Op.getOperand(2); + SDValue Chain = Op.getOperand(0); + SDValue DestP = Op.getOperand(1); + SDValue SrcP = Op.getOperand(2); const Value *DestS = cast(Op.getOperand(3))->getValue(); const Value *SrcS = cast(Op.getOperand(4))->getValue(); - SDOperand Val = DAG.getLoad(getPointerTy(), Chain, SrcP, SrcS, 0); - SDOperand Result = DAG.getStore(Val.getValue(1), Val, DestP, DestS, 0); - SDOperand NP = DAG.getNode(ISD::ADD, MVT::i64, SrcP, + SDValue Val = DAG.getLoad(getPointerTy(), dl, Chain, SrcP, SrcS, 0); + SDValue Result = DAG.getStore(Val.getValue(1), dl, Val, DestP, DestS, 0); + SDValue NP = DAG.getNode(ISD::ADD, dl, MVT::i64, SrcP, DAG.getConstant(8, MVT::i64)); - Val = DAG.getExtLoad(ISD::SEXTLOAD, MVT::i64, Result, NP, NULL,0, MVT::i32); - SDOperand NPD = DAG.getNode(ISD::ADD, MVT::i64, DestP, + Val = DAG.getExtLoad(ISD::SEXTLOAD, dl, MVT::i64, Result, + NP, NULL,0, MVT::i32); + SDValue NPD = DAG.getNode(ISD::ADD, dl, MVT::i64, DestP, DAG.getConstant(8, MVT::i64)); - return DAG.getTruncStore(Val.getValue(1), Val, NPD, NULL, 0, MVT::i32); + return DAG.getTruncStore(Val.getValue(1), dl, Val, NPD, NULL, 0, MVT::i32); } case ISD::VASTART: { - SDOperand Chain = Op.getOperand(0); - SDOperand VAListP = Op.getOperand(1); + SDValue Chain = Op.getOperand(0); + SDValue VAListP = Op.getOperand(1); const Value *VAListS = cast(Op.getOperand(2))->getValue(); // vastart stores the address of the VarArgsBase and VarArgsOffset - SDOperand FR = DAG.getFrameIndex(VarArgsBase, MVT::i64); - SDOperand S1 = DAG.getStore(Chain, FR, VAListP, VAListS, 0); - SDOperand SA2 = DAG.getNode(ISD::ADD, MVT::i64, VAListP, + SDValue FR = DAG.getFrameIndex(VarArgsBase, MVT::i64); + SDValue S1 = DAG.getStore(Chain, dl, FR, VAListP, VAListS, 0); + SDValue SA2 = DAG.getNode(ISD::ADD, dl, MVT::i64, VAListP, DAG.getConstant(8, MVT::i64)); - return DAG.getTruncStore(S1, DAG.getConstant(VarArgsOffset, MVT::i64), + return DAG.getTruncStore(S1, dl, DAG.getConstant(VarArgsOffset, MVT::i64), SA2, NULL, 0, MVT::i32); } case ISD::RETURNADDR: - return DAG.getNode(AlphaISD::GlobalRetAddr, MVT::i64); + return DAG.getNode(AlphaISD::GlobalRetAddr, DebugLoc::getUnknownLoc(), + MVT::i64); //FIXME: implement case ISD::FRAMEADDR: break; } - return SDOperand(); + return SDValue(); } -SDOperand AlphaTargetLowering::CustomPromoteOperation(SDOperand Op, - SelectionDAG &DAG) { - assert(Op.getValueType() == MVT::i32 && - Op.getOpcode() == ISD::VAARG && +void AlphaTargetLowering::ReplaceNodeResults(SDNode *N, + SmallVectorImpl&Results, + SelectionDAG &DAG) { + DebugLoc dl = N->getDebugLoc(); + assert(N->getValueType(0) == MVT::i32 && + N->getOpcode() == ISD::VAARG && "Unknown node to custom promote!"); - - // The code in LowerOperation already handles i32 vaarg - return LowerOperation(Op, DAG); + + SDValue Chain, DataPtr; + LowerVAARG(N, Chain, DataPtr, DAG); + SDValue Res = DAG.getLoad(N->getValueType(0), dl, Chain, DataPtr, NULL, 0); + Results.push_back(Res); + Results.push_back(SDValue(Res.getNode(), 1)); } @@ -596,7 +781,7 @@ AlphaTargetLowering::getConstraintType(const std::string &Constraint) const { std::vector AlphaTargetLowering:: getRegClassForInlineAsmConstraint(const std::string &Constraint, - MVT::ValueType VT) const { + MVT VT) const { if (Constraint.size() == 1) { switch (Constraint[0]) { default: break; // Unknown constriant letter @@ -629,3 +814,99 @@ getRegClassForInlineAsmConstraint(const std::string &Constraint, return std::vector(); } +//===----------------------------------------------------------------------===// +// Other Lowering Code +//===----------------------------------------------------------------------===// + +MachineBasicBlock * +AlphaTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, + MachineBasicBlock *BB) const { + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + assert((MI->getOpcode() == Alpha::CAS32 || + MI->getOpcode() == Alpha::CAS64 || + MI->getOpcode() == Alpha::LAS32 || + MI->getOpcode() == Alpha::LAS64 || + MI->getOpcode() == Alpha::SWAP32 || + MI->getOpcode() == Alpha::SWAP64) && + "Unexpected instr type to insert"); + + bool is32 = MI->getOpcode() == Alpha::CAS32 || + MI->getOpcode() == Alpha::LAS32 || + MI->getOpcode() == Alpha::SWAP32; + + //Load locked store conditional for atomic ops take on the same form + //start: + //ll + //do stuff (maybe branch to exit) + //sc + //test sc and maybe branck to start + //exit: + const BasicBlock *LLVM_BB = BB->getBasicBlock(); + DebugLoc dl = MI->getDebugLoc(); + MachineFunction::iterator It = BB; + ++It; + + MachineBasicBlock *thisMBB = BB; + MachineFunction *F = BB->getParent(); + MachineBasicBlock *llscMBB = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); + + sinkMBB->transferSuccessors(thisMBB); + + F->insert(It, llscMBB); + F->insert(It, sinkMBB); + + BuildMI(thisMBB, dl, TII->get(Alpha::BR)).addMBB(llscMBB); + + unsigned reg_res = MI->getOperand(0).getReg(), + reg_ptr = MI->getOperand(1).getReg(), + reg_v2 = MI->getOperand(2).getReg(), + reg_store = F->getRegInfo().createVirtualRegister(&Alpha::GPRCRegClass); + + BuildMI(llscMBB, dl, TII->get(is32 ? Alpha::LDL_L : Alpha::LDQ_L), + reg_res).addImm(0).addReg(reg_ptr); + switch (MI->getOpcode()) { + case Alpha::CAS32: + case Alpha::CAS64: { + unsigned reg_cmp + = F->getRegInfo().createVirtualRegister(&Alpha::GPRCRegClass); + BuildMI(llscMBB, dl, TII->get(Alpha::CMPEQ), reg_cmp) + .addReg(reg_v2).addReg(reg_res); + BuildMI(llscMBB, dl, TII->get(Alpha::BEQ)) + .addImm(0).addReg(reg_cmp).addMBB(sinkMBB); + BuildMI(llscMBB, dl, TII->get(Alpha::BISr), reg_store) + .addReg(Alpha::R31).addReg(MI->getOperand(3).getReg()); + break; + } + case Alpha::LAS32: + case Alpha::LAS64: { + BuildMI(llscMBB, dl,TII->get(is32 ? Alpha::ADDLr : Alpha::ADDQr), reg_store) + .addReg(reg_res).addReg(reg_v2); + break; + } + case Alpha::SWAP32: + case Alpha::SWAP64: { + BuildMI(llscMBB, dl, TII->get(Alpha::BISr), reg_store) + .addReg(reg_v2).addReg(reg_v2); + break; + } + } + BuildMI(llscMBB, dl, TII->get(is32 ? Alpha::STL_C : Alpha::STQ_C), reg_store) + .addReg(reg_store).addImm(0).addReg(reg_ptr); + BuildMI(llscMBB, dl, TII->get(Alpha::BEQ)) + .addImm(0).addReg(reg_store).addMBB(llscMBB); + BuildMI(llscMBB, dl, TII->get(Alpha::BR)).addMBB(sinkMBB); + + thisMBB->addSuccessor(llscMBB); + llscMBB->addSuccessor(llscMBB); + llscMBB->addSuccessor(sinkMBB); + F->DeleteMachineInstr(MI); // The pseudo instruction is gone now. + + return sinkMBB; +} + +bool +AlphaTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { + // The Alpha target isn't yet aware of offsets. + return false; +}