2005-09-02 18:46:02 +00:00
|
|
|
//===-- AlphaISelLowering.cpp - Alpha DAG Lowering Implementation ---------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-29 20:36:04 +00:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2005-09-02 18:46:02 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements the AlphaISelLowering class.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "AlphaISelLowering.h"
|
|
|
|
#include "AlphaTargetMachine.h"
|
2009-07-19 01:11:32 +00:00
|
|
|
#include "llvm/CodeGen/CallingConvLower.h"
|
2005-09-02 18:46:02 +00:00
|
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
|
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
|
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
2007-12-31 04:13:23 +00:00
|
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
2005-09-02 18:46:02 +00:00
|
|
|
#include "llvm/CodeGen/SelectionDAG.h"
|
2007-12-31 04:13:23 +00:00
|
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
2009-07-19 01:11:32 +00:00
|
|
|
#include "llvm/CodeGen/PseudoSourceValue.h"
|
2009-07-28 03:13:23 +00:00
|
|
|
#include "llvm/Target/TargetLoweringObjectFile.h"
|
2005-09-02 18:46:02 +00:00
|
|
|
#include "llvm/Constants.h"
|
|
|
|
#include "llvm/Function.h"
|
2006-01-23 20:59:50 +00:00
|
|
|
#include "llvm/Module.h"
|
2008-10-07 02:10:26 +00:00
|
|
|
#include "llvm/Intrinsics.h"
|
2005-09-02 18:46:02 +00:00
|
|
|
#include "llvm/Support/CommandLine.h"
|
2009-07-08 19:04:27 +00:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2009-07-08 20:53:28 +00:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2005-09-02 18:46:02 +00:00
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
/// 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.
|
|
|
|
static unsigned AddLiveIn(MachineFunction &MF, unsigned PReg,
|
|
|
|
TargetRegisterClass *RC) {
|
|
|
|
assert(RC->contains(PReg) && "Not the correct regclass!");
|
2007-12-31 04:13:23 +00:00
|
|
|
unsigned VReg = MF.getRegInfo().createVirtualRegister(RC);
|
|
|
|
MF.getRegInfo().addLiveIn(PReg, VReg);
|
2005-09-02 18:46:02 +00:00
|
|
|
return VReg;
|
|
|
|
}
|
|
|
|
|
2009-07-28 03:13:23 +00:00
|
|
|
AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM)
|
2009-08-05 18:13:04 +00:00
|
|
|
: TargetLowering(TM, new TargetLoweringObjectFileELF()) {
|
2005-09-02 18:46:02 +00:00
|
|
|
// Set up the TargetLowering object.
|
2009-06-14 23:30:43 +00:00
|
|
|
//I am having problems with shr n i8 1
|
2009-08-11 20:47:22 +00:00
|
|
|
setShiftAmountType(MVT::i64);
|
2008-11-23 15:47:28 +00:00
|
|
|
setBooleanContents(ZeroOrOneBooleanContent);
|
2009-09-20 02:20:51 +00:00
|
|
|
|
2006-10-06 22:46:51 +00:00
|
|
|
setUsesGlobalOffsetTable(true);
|
2009-09-20 02:20:51 +00:00
|
|
|
|
2009-08-11 20:47:22 +00:00
|
|
|
addRegisterClass(MVT::i64, Alpha::GPRCRegisterClass);
|
|
|
|
addRegisterClass(MVT::f64, Alpha::F8RCRegisterClass);
|
|
|
|
addRegisterClass(MVT::f32, Alpha::F4RCRegisterClass);
|
2008-10-07 02:10:26 +00:00
|
|
|
|
|
|
|
// We want to custom lower some of our intrinsics.
|
2009-08-11 20:47:22 +00:00
|
|
|
setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
|
2008-10-07 02:10:26 +00:00
|
|
|
|
2009-08-11 20:47:22 +00:00
|
|
|
setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote);
|
|
|
|
setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand);
|
2009-09-20 02:20:51 +00:00
|
|
|
|
2009-08-11 20:47:22 +00:00
|
|
|
setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote);
|
|
|
|
setLoadExtAction(ISD::ZEXTLOAD, MVT::i32, Expand);
|
2009-09-20 02:20:51 +00:00
|
|
|
|
2009-08-11 20:47:22 +00:00
|
|
|
setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
|
|
|
|
setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Expand);
|
|
|
|
setLoadExtAction(ISD::SEXTLOAD, MVT::i16, Expand);
|
2006-10-13 21:14:26 +00:00
|
|
|
|
2009-08-11 20:47:22 +00:00
|
|
|
setTruncStoreAction(MVT::f64, MVT::f32, Expand);
|
2009-07-17 05:23:03 +00:00
|
|
|
|
2009-08-11 20:47:22 +00:00
|
|
|
// setOperationAction(ISD::BRIND, MVT::Other, Expand);
|
|
|
|
setOperationAction(ISD::BR_JT, MVT::Other, Expand);
|
|
|
|
setOperationAction(ISD::BR_CC, MVT::Other, Expand);
|
2009-09-20 02:20:51 +00:00
|
|
|
setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
|
2005-10-06 16:54:29 +00:00
|
|
|
|
2009-08-11 20:47:22 +00:00
|
|
|
setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
|
2006-06-27 23:19:14 +00:00
|
|
|
|
2009-08-11 20:47:22 +00:00
|
|
|
setOperationAction(ISD::FREM, MVT::f32, Expand);
|
|
|
|
setOperationAction(ISD::FREM, MVT::f64, Expand);
|
2009-09-20 02:20:51 +00:00
|
|
|
|
2009-08-11 20:47:22 +00:00
|
|
|
setOperationAction(ISD::UINT_TO_FP, MVT::i64, Expand);
|
|
|
|
setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
|
|
|
|
setOperationAction(ISD::FP_TO_UINT, MVT::i64, Expand);
|
|
|
|
setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
|
2005-11-30 16:10:29 +00:00
|
|
|
|
2005-09-29 22:54:56 +00:00
|
|
|
if (!TM.getSubtarget<AlphaSubtarget>().hasCT()) {
|
2009-08-11 20:47:22 +00:00
|
|
|
setOperationAction(ISD::CTPOP , MVT::i64 , Expand);
|
|
|
|
setOperationAction(ISD::CTTZ , MVT::i64 , Expand);
|
|
|
|
setOperationAction(ISD::CTLZ , MVT::i64 , Expand);
|
2005-09-02 18:46:02 +00:00
|
|
|
}
|
2009-08-11 20:47:22 +00:00
|
|
|
setOperationAction(ISD::BSWAP , MVT::i64, Expand);
|
|
|
|
setOperationAction(ISD::ROTL , MVT::i64, Expand);
|
|
|
|
setOperationAction(ISD::ROTR , MVT::i64, Expand);
|
2009-09-20 02:20:51 +00:00
|
|
|
|
2009-08-11 20:47:22 +00:00
|
|
|
setOperationAction(ISD::SREM , MVT::i64, Custom);
|
|
|
|
setOperationAction(ISD::UREM , MVT::i64, Custom);
|
|
|
|
setOperationAction(ISD::SDIV , MVT::i64, Custom);
|
|
|
|
setOperationAction(ISD::UDIV , MVT::i64, Custom);
|
2006-04-03 03:18:59 +00:00
|
|
|
|
2009-08-11 20:47:22 +00:00
|
|
|
setOperationAction(ISD::ADDC , MVT::i64, Expand);
|
|
|
|
setOperationAction(ISD::ADDE , MVT::i64, Expand);
|
|
|
|
setOperationAction(ISD::SUBC , MVT::i64, Expand);
|
|
|
|
setOperationAction(ISD::SUBE , MVT::i64, Expand);
|
2008-10-07 02:10:26 +00:00
|
|
|
|
2009-08-11 20:47:22 +00:00
|
|
|
setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand);
|
|
|
|
setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand);
|
2008-10-09 04:50:56 +00:00
|
|
|
|
2009-08-11 20:47:22 +00:00
|
|
|
setOperationAction(ISD::SRL_PARTS, MVT::i64, Custom);
|
|
|
|
setOperationAction(ISD::SRA_PARTS, MVT::i64, Expand);
|
|
|
|
setOperationAction(ISD::SHL_PARTS, MVT::i64, Expand);
|
2008-10-07 02:10:26 +00:00
|
|
|
|
2007-10-11 23:21:31 +00:00
|
|
|
// We don't support sin/cos/sqrt/pow
|
2009-08-11 20:47:22 +00:00
|
|
|
setOperationAction(ISD::FSIN , MVT::f64, Expand);
|
|
|
|
setOperationAction(ISD::FCOS , MVT::f64, Expand);
|
|
|
|
setOperationAction(ISD::FSIN , MVT::f32, Expand);
|
|
|
|
setOperationAction(ISD::FCOS , MVT::f32, Expand);
|
2006-01-19 21:10:38 +00:00
|
|
|
|
2009-08-11 20:47:22 +00:00
|
|
|
setOperationAction(ISD::FSQRT, MVT::f64, Expand);
|
|
|
|
setOperationAction(ISD::FSQRT, MVT::f32, Expand);
|
2007-10-11 23:21:31 +00:00
|
|
|
|
2009-08-11 20:47:22 +00:00
|
|
|
setOperationAction(ISD::FPOW , MVT::f32, Expand);
|
|
|
|
setOperationAction(ISD::FPOW , MVT::f64, Expand);
|
2008-09-04 00:47:13 +00:00
|
|
|
|
2009-08-11 20:47:22 +00:00
|
|
|
setOperationAction(ISD::SETCC, MVT::f32, Promote);
|
2005-11-29 06:16:21 +00:00
|
|
|
|
2009-08-11 20:47:22 +00:00
|
|
|
setOperationAction(ISD::BIT_CONVERT, MVT::f32, Promote);
|
2007-01-24 21:09:16 +00:00
|
|
|
|
2005-11-29 06:16:21 +00:00
|
|
|
// We don't have line number support yet.
|
2009-08-11 20:47:22 +00:00
|
|
|
setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
|
|
|
|
setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
|
|
|
|
setOperationAction(ISD::DBG_LABEL, MVT::Other, Expand);
|
|
|
|
setOperationAction(ISD::EH_LABEL, MVT::Other, Expand);
|
2006-01-13 02:42:53 +00:00
|
|
|
|
|
|
|
// Not implemented yet.
|
2009-09-20 02:20:51 +00:00
|
|
|
setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
|
2009-08-11 20:47:22 +00:00
|
|
|
setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
|
|
|
|
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Expand);
|
2006-01-16 21:22:38 +00:00
|
|
|
|
2008-09-16 21:48:12 +00:00
|
|
|
// We want to legalize GlobalAddress and ConstantPool and
|
|
|
|
// ExternalSymbols nodes into the appropriate instructions to
|
|
|
|
// materialize the address.
|
2009-08-11 20:47:22 +00:00
|
|
|
setOperationAction(ISD::GlobalAddress, MVT::i64, Custom);
|
|
|
|
setOperationAction(ISD::ConstantPool, MVT::i64, Custom);
|
|
|
|
setOperationAction(ISD::ExternalSymbol, MVT::i64, Custom);
|
|
|
|
setOperationAction(ISD::GlobalTLSAddress, MVT::i64, Custom);
|
2005-12-24 05:36:33 +00:00
|
|
|
|
2009-08-11 20:47:22 +00:00
|
|
|
setOperationAction(ISD::VASTART, MVT::Other, Custom);
|
|
|
|
setOperationAction(ISD::VAEND, MVT::Other, Expand);
|
|
|
|
setOperationAction(ISD::VACOPY, MVT::Other, Custom);
|
|
|
|
setOperationAction(ISD::VAARG, MVT::Other, Custom);
|
|
|
|
setOperationAction(ISD::VAARG, MVT::i32, Custom);
|
2006-01-25 21:54:38 +00:00
|
|
|
|
2009-08-11 20:47:22 +00:00
|
|
|
setOperationAction(ISD::JumpTable, MVT::i64, Custom);
|
|
|
|
setOperationAction(ISD::JumpTable, MVT::i32, Custom);
|
2006-09-18 18:01:03 +00:00
|
|
|
|
2006-01-16 21:22:38 +00:00
|
|
|
setStackPointerRegisterToSaveRestore(Alpha::R30);
|
|
|
|
|
2007-08-30 00:23:21 +00:00
|
|
|
addLegalFPImmediate(APFloat(+0.0)); //F31
|
2007-09-23 14:52:20 +00:00
|
|
|
addLegalFPImmediate(APFloat(+0.0f)); //F31
|
2007-08-30 00:23:21 +00:00
|
|
|
addLegalFPImmediate(APFloat(-0.0)); //-F31
|
2007-09-23 14:52:20 +00:00
|
|
|
addLegalFPImmediate(APFloat(-0.0f)); //-F31
|
2005-11-30 07:19:56 +00:00
|
|
|
|
2006-09-05 00:22:25 +00:00
|
|
|
setJumpBufSize(272);
|
|
|
|
setJumpBufAlignment(16);
|
|
|
|
|
2005-11-30 07:19:56 +00:00
|
|
|
computeRegisterProperties();
|
2005-09-02 18:46:02 +00:00
|
|
|
}
|
|
|
|
|
2009-08-11 20:47:22 +00:00
|
|
|
MVT::SimpleValueType AlphaTargetLowering::getSetCCResultType(EVT VT) const {
|
|
|
|
return MVT::i64;
|
2008-03-10 15:42:14 +00:00
|
|
|
}
|
|
|
|
|
2006-01-16 19:53:25 +00:00
|
|
|
const char *AlphaTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
|
|
|
switch (Opcode) {
|
|
|
|
default: return 0;
|
|
|
|
case AlphaISD::CVTQT_: return "Alpha::CVTQT_";
|
|
|
|
case AlphaISD::CVTQS_: return "Alpha::CVTQS_";
|
|
|
|
case AlphaISD::CVTTQ_: return "Alpha::CVTTQ_";
|
|
|
|
case AlphaISD::GPRelHi: return "Alpha::GPRelHi";
|
|
|
|
case AlphaISD::GPRelLo: return "Alpha::GPRelLo";
|
|
|
|
case AlphaISD::RelLit: return "Alpha::RelLit";
|
2006-06-13 18:27:39 +00:00
|
|
|
case AlphaISD::GlobalRetAddr: return "Alpha::GlobalRetAddr";
|
2006-01-27 23:39:00 +00:00
|
|
|
case AlphaISD::CALL: return "Alpha::CALL";
|
2006-01-16 19:53:25 +00:00
|
|
|
case AlphaISD::DivCall: return "Alpha::DivCall";
|
2006-06-12 18:09:24 +00:00
|
|
|
case AlphaISD::RET_FLAG: return "Alpha::RET_FLAG";
|
2006-10-31 16:49:55 +00:00
|
|
|
case AlphaISD::COND_BRANCH_I: return "Alpha::COND_BRANCH_I";
|
|
|
|
case AlphaISD::COND_BRANCH_F: return "Alpha::COND_BRANCH_F";
|
2006-01-16 19:53:25 +00:00
|
|
|
}
|
|
|
|
}
|
2005-09-02 18:46:02 +00:00
|
|
|
|
2009-07-01 18:50:55 +00:00
|
|
|
/// getFunctionAlignment - Return the Log2 alignment of this function.
|
2009-06-30 22:38:32 +00:00
|
|
|
unsigned AlphaTargetLowering::getFunctionAlignment(const Function *F) const {
|
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
static SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) {
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT PtrVT = Op.getValueType();
|
2006-09-18 18:01:03 +00:00
|
|
|
JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
|
|
|
|
SDValue Zero = DAG.getConstant(0, PtrVT);
|
2009-02-06 21:50:26 +00:00
|
|
|
// FIXME there isn't really any debug info here
|
|
|
|
DebugLoc dl = Op.getDebugLoc();
|
2009-09-20 02:20:51 +00:00
|
|
|
|
2009-08-11 20:47:22 +00:00
|
|
|
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);
|
2006-09-18 18:01:03 +00:00
|
|
|
return Lo;
|
|
|
|
}
|
|
|
|
|
2006-08-11 17:19:54 +00:00
|
|
|
//http://www.cs.arizona.edu/computer.help/policy/DIGITAL_unix/
|
|
|
|
//AA-PY8AC-TET1_html/callCH3.html#BLOCK21
|
2005-09-02 18:46:02 +00:00
|
|
|
|
|
|
|
//For now, just use variable size stack frame format
|
|
|
|
|
|
|
|
//In a standard call, the first six items are passed in registers $16
|
|
|
|
//- $21 and/or registers $f16 - $f21. (See Section 4.1.2 for details
|
|
|
|
//of argument-to-register correspondence.) The remaining items are
|
|
|
|
//collected in a memory argument list that is a naturally aligned
|
|
|
|
//array of quadwords. In a standard call, this list, if present, must
|
|
|
|
//be passed at 0(SP).
|
|
|
|
//7 ... n 0(SP) ... (n-7)*8(SP)
|
|
|
|
|
|
|
|
// //#define FP $15
|
|
|
|
// //#define RA $26
|
|
|
|
// //#define PV $27
|
|
|
|
// //#define GP $29
|
|
|
|
// //#define SP $30
|
|
|
|
|
2009-07-19 01:11:32 +00:00
|
|
|
#include "AlphaGenCallingConv.inc"
|
|
|
|
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-05 01:29:28 +00:00
|
|
|
SDValue
|
|
|
|
AlphaTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
|
2009-09-02 08:44:58 +00:00
|
|
|
CallingConv::ID CallConv, bool isVarArg,
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-05 01:29:28 +00:00
|
|
|
bool isTailCall,
|
|
|
|
const SmallVectorImpl<ISD::OutputArg> &Outs,
|
|
|
|
const SmallVectorImpl<ISD::InputArg> &Ins,
|
|
|
|
DebugLoc dl, SelectionDAG &DAG,
|
|
|
|
SmallVectorImpl<SDValue> &InVals) {
|
2009-07-19 01:11:32 +00:00
|
|
|
|
|
|
|
// Analyze operands of the call, assigning locations to each operand.
|
|
|
|
SmallVector<CCValAssign, 16> ArgLocs;
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-05 01:29:28 +00:00
|
|
|
CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
|
|
|
|
ArgLocs, *DAG.getContext());
|
2009-07-19 01:11:32 +00:00
|
|
|
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-05 01:29:28 +00:00
|
|
|
CCInfo.AnalyzeCallOperands(Outs, CC_Alpha);
|
2009-07-19 01:11:32 +00:00
|
|
|
|
|
|
|
// 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<std::pair<unsigned, SDValue>, 4> RegsToPass;
|
|
|
|
SmallVector<SDValue, 12> 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];
|
|
|
|
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-05 01:29:28 +00:00
|
|
|
SDValue Arg = Outs[i].Val;
|
2009-07-19 01:11:32 +00:00
|
|
|
|
|
|
|
// 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)
|
2009-08-11 20:47:22 +00:00
|
|
|
StackPtr = DAG.getCopyFromReg(Chain, dl, Alpha::R30, MVT::i64);
|
2009-07-19 01:11:32 +00:00
|
|
|
|
|
|
|
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())
|
2009-08-11 20:47:22 +00:00
|
|
|
Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
|
2009-07-19 01:11:32 +00:00
|
|
|
&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.
|
2009-08-11 20:47:22 +00:00
|
|
|
SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
|
2009-07-19 01:11:32 +00:00
|
|
|
SmallVector<SDValue, 8> 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.
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-05 01:29:28 +00:00
|
|
|
return LowerCallResult(Chain, InFlag, CallConv, isVarArg,
|
|
|
|
Ins, dl, DAG, InVals);
|
2009-07-19 01:11:32 +00:00
|
|
|
}
|
|
|
|
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-05 01:29:28 +00:00
|
|
|
/// LowerCallResult - Lower the result values of a call into the
|
|
|
|
/// appropriate copies out of appropriate physical registers.
|
|
|
|
///
|
|
|
|
SDValue
|
2009-07-19 01:11:32 +00:00
|
|
|
AlphaTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag,
|
2009-09-02 08:44:58 +00:00
|
|
|
CallingConv::ID CallConv, bool isVarArg,
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-05 01:29:28 +00:00
|
|
|
const SmallVectorImpl<ISD::InputArg> &Ins,
|
|
|
|
DebugLoc dl, SelectionDAG &DAG,
|
|
|
|
SmallVectorImpl<SDValue> &InVals) {
|
2009-07-19 01:11:32 +00:00
|
|
|
|
|
|
|
// Assign locations to each value returned by this call.
|
|
|
|
SmallVector<CCValAssign, 16> RVLocs;
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-05 01:29:28 +00:00
|
|
|
CCState CCInfo(CallConv, isVarArg, getTargetMachine(), RVLocs,
|
2009-07-22 00:24:57 +00:00
|
|
|
*DAG.getContext());
|
2009-07-19 01:11:32 +00:00
|
|
|
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-05 01:29:28 +00:00
|
|
|
CCInfo.AnalyzeCallResult(Ins, RetCC_Alpha);
|
2009-07-19 01:11:32 +00:00
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-05 01:29:28 +00:00
|
|
|
InVals.push_back(RetValue);
|
2009-07-19 01:11:32 +00:00
|
|
|
}
|
|
|
|
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-05 01:29:28 +00:00
|
|
|
return Chain;
|
2009-07-19 01:11:32 +00:00
|
|
|
}
|
|
|
|
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-05 01:29:28 +00:00
|
|
|
SDValue
|
|
|
|
AlphaTargetLowering::LowerFormalArguments(SDValue Chain,
|
2009-09-02 08:44:58 +00:00
|
|
|
CallingConv::ID CallConv, bool isVarArg,
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-05 01:29:28 +00:00
|
|
|
const SmallVectorImpl<ISD::InputArg>
|
|
|
|
&Ins,
|
|
|
|
DebugLoc dl, SelectionDAG &DAG,
|
|
|
|
SmallVectorImpl<SDValue> &InVals) {
|
|
|
|
|
2005-09-02 18:46:02 +00:00
|
|
|
MachineFunction &MF = DAG.getMachineFunction();
|
|
|
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
2006-06-12 18:09:24 +00:00
|
|
|
|
2005-09-04 06:12:19 +00:00
|
|
|
unsigned args_int[] = {
|
2005-09-02 18:46:02 +00:00
|
|
|
Alpha::R16, Alpha::R17, Alpha::R18, Alpha::R19, Alpha::R20, Alpha::R21};
|
2005-09-04 06:12:19 +00:00
|
|
|
unsigned args_float[] = {
|
2005-09-02 18:46:02 +00:00
|
|
|
Alpha::F16, Alpha::F17, Alpha::F18, Alpha::F19, Alpha::F20, Alpha::F21};
|
2009-09-20 02:20:51 +00:00
|
|
|
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-05 01:29:28 +00:00
|
|
|
for (unsigned ArgNo = 0, e = Ins.size(); ArgNo != e; ++ArgNo) {
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue argt;
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT ObjectVT = Ins[ArgNo].VT;
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue ArgVal;
|
2006-06-12 18:09:24 +00:00
|
|
|
|
|
|
|
if (ArgNo < 6) {
|
2009-08-11 20:47:22 +00:00
|
|
|
switch (ObjectVT.getSimpleVT().SimpleTy) {
|
2005-09-02 18:46:02 +00:00
|
|
|
default:
|
2008-06-06 12:08:01 +00:00
|
|
|
assert(false && "Invalid value type!");
|
2009-08-11 20:47:22 +00:00
|
|
|
case MVT::f64:
|
2009-09-20 02:20:51 +00:00
|
|
|
args_float[ArgNo] = AddLiveIn(MF, args_float[ArgNo],
|
2007-04-16 18:10:23 +00:00
|
|
|
&Alpha::F8RCRegClass);
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-05 01:29:28 +00:00
|
|
|
ArgVal = DAG.getCopyFromReg(Chain, dl, args_float[ArgNo], ObjectVT);
|
2005-09-02 18:46:02 +00:00
|
|
|
break;
|
2009-08-11 20:47:22 +00:00
|
|
|
case MVT::f32:
|
2009-09-20 02:20:51 +00:00
|
|
|
args_float[ArgNo] = AddLiveIn(MF, args_float[ArgNo],
|
2007-04-16 18:10:23 +00:00
|
|
|
&Alpha::F4RCRegClass);
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-05 01:29:28 +00:00
|
|
|
ArgVal = DAG.getCopyFromReg(Chain, dl, args_float[ArgNo], ObjectVT);
|
2006-06-21 01:00:43 +00:00
|
|
|
break;
|
2009-08-11 20:47:22 +00:00
|
|
|
case MVT::i64:
|
2009-09-20 02:20:51 +00:00
|
|
|
args_int[ArgNo] = AddLiveIn(MF, args_int[ArgNo],
|
2007-04-16 18:10:23 +00:00
|
|
|
&Alpha::GPRCRegClass);
|
2009-08-11 20:47:22 +00:00
|
|
|
ArgVal = DAG.getCopyFromReg(Chain, dl, args_int[ArgNo], MVT::i64);
|
2005-09-02 18:46:02 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else { //more args
|
|
|
|
// Create the frame index object for this incoming parameter...
|
2006-06-12 18:09:24 +00:00
|
|
|
int FI = MFI->CreateFixedObject(8, 8 * (ArgNo - 6));
|
2005-09-02 18:46:02 +00:00
|
|
|
|
|
|
|
// Create the SelectionDAG nodes corresponding to a load
|
|
|
|
//from this parameter
|
2009-08-11 20:47:22 +00:00
|
|
|
SDValue FIN = DAG.getFrameIndex(FI, MVT::i64);
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-05 01:29:28 +00:00
|
|
|
ArgVal = DAG.getLoad(ObjectVT, dl, Chain, FIN, NULL, 0);
|
2005-09-02 18:46:02 +00:00
|
|
|
}
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-05 01:29:28 +00:00
|
|
|
InVals.push_back(ArgVal);
|
2005-09-02 18:46:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// If the functions takes variable number of arguments, copy all regs to stack
|
2006-06-12 18:09:24 +00:00
|
|
|
if (isVarArg) {
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-05 01:29:28 +00:00
|
|
|
VarArgsOffset = Ins.size() * 8;
|
2008-07-27 21:46:04 +00:00
|
|
|
std::vector<SDValue> LS;
|
2005-09-02 18:46:02 +00:00
|
|
|
for (int i = 0; i < 6; ++i) {
|
2008-02-10 18:45:23 +00:00
|
|
|
if (TargetRegisterInfo::isPhysicalRegister(args_int[i]))
|
2006-06-12 18:09:24 +00:00
|
|
|
args_int[i] = AddLiveIn(MF, args_int[i], &Alpha::GPRCRegClass);
|
2009-08-11 20:47:22 +00:00
|
|
|
SDValue argt = DAG.getCopyFromReg(Chain, dl, args_int[i], MVT::i64);
|
2005-09-02 18:46:02 +00:00
|
|
|
int FI = MFI->CreateFixedObject(8, -8 * (6 - i));
|
|
|
|
if (i == 0) VarArgsBase = FI;
|
2009-08-11 20:47:22 +00:00
|
|
|
SDValue SDFI = DAG.getFrameIndex(FI, MVT::i64);
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-05 01:29:28 +00:00
|
|
|
LS.push_back(DAG.getStore(Chain, dl, argt, SDFI, NULL, 0));
|
2005-09-02 18:46:02 +00:00
|
|
|
|
2008-02-10 18:45:23 +00:00
|
|
|
if (TargetRegisterInfo::isPhysicalRegister(args_float[i]))
|
2006-06-12 18:09:24 +00:00
|
|
|
args_float[i] = AddLiveIn(MF, args_float[i], &Alpha::F8RCRegClass);
|
2009-08-11 20:47:22 +00:00
|
|
|
argt = DAG.getCopyFromReg(Chain, dl, args_float[i], MVT::f64);
|
2005-09-02 18:46:02 +00:00
|
|
|
FI = MFI->CreateFixedObject(8, - 8 * (12 - i));
|
2009-08-11 20:47:22 +00:00
|
|
|
SDFI = DAG.getFrameIndex(FI, MVT::i64);
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-05 01:29:28 +00:00
|
|
|
LS.push_back(DAG.getStore(Chain, dl, argt, SDFI, NULL, 0));
|
2005-09-02 18:46:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//Set up a token factor with all the stack traffic
|
2009-08-11 20:47:22 +00:00
|
|
|
Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &LS[0], LS.size());
|
2005-09-02 18:46:02 +00:00
|
|
|
}
|
|
|
|
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-05 01:29:28 +00:00
|
|
|
return Chain;
|
2006-06-12 18:09:24 +00:00
|
|
|
}
|
|
|
|
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-05 01:29:28 +00:00
|
|
|
SDValue
|
|
|
|
AlphaTargetLowering::LowerReturn(SDValue Chain,
|
2009-09-02 08:44:58 +00:00
|
|
|
CallingConv::ID CallConv, bool isVarArg,
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-05 01:29:28 +00:00
|
|
|
const SmallVectorImpl<ISD::OutputArg> &Outs,
|
|
|
|
DebugLoc dl, SelectionDAG &DAG) {
|
|
|
|
|
|
|
|
SDValue Copy = DAG.getCopyToReg(Chain, dl, Alpha::R26,
|
|
|
|
DAG.getNode(AlphaISD::GlobalRetAddr,
|
|
|
|
DebugLoc::getUnknownLoc(),
|
2009-08-11 20:47:22 +00:00
|
|
|
MVT::i64),
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-05 01:29:28 +00:00
|
|
|
SDValue());
|
|
|
|
switch (Outs.size()) {
|
2006-06-12 18:09:24 +00:00
|
|
|
default:
|
2009-07-14 16:55:14 +00:00
|
|
|
llvm_unreachable("Do not know how to return this many arguments!");
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-05 01:29:28 +00:00
|
|
|
case 0:
|
2006-06-13 18:27:39 +00:00
|
|
|
break;
|
2008-07-27 21:46:04 +00:00
|
|
|
//return SDValue(); // ret void is legal
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-05 01:29:28 +00:00
|
|
|
case 1: {
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT ArgVT = Outs[0].Val.getValueType();
|
2006-06-12 18:09:24 +00:00
|
|
|
unsigned ArgReg;
|
2008-06-06 12:08:01 +00:00
|
|
|
if (ArgVT.isInteger())
|
2006-06-12 18:09:24 +00:00
|
|
|
ArgReg = Alpha::R0;
|
|
|
|
else {
|
2008-06-06 12:08:01 +00:00
|
|
|
assert(ArgVT.isFloatingPoint());
|
2006-06-12 18:09:24 +00:00
|
|
|
ArgReg = Alpha::F0;
|
|
|
|
}
|
2009-09-20 02:20:51 +00:00
|
|
|
Copy = DAG.getCopyToReg(Copy, dl, ArgReg,
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-05 01:29:28 +00:00
|
|
|
Outs[0].Val, Copy.getValue(1));
|
2007-12-31 04:13:23 +00:00
|
|
|
if (DAG.getMachineFunction().getRegInfo().liveout_empty())
|
|
|
|
DAG.getMachineFunction().getRegInfo().addLiveOut(ArgReg);
|
2005-09-02 18:46:02 +00:00
|
|
|
break;
|
|
|
|
}
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-05 01:29:28 +00:00
|
|
|
case 2: {
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT ArgVT = Outs[0].Val.getValueType();
|
2008-10-07 02:10:26 +00:00
|
|
|
unsigned ArgReg1, ArgReg2;
|
|
|
|
if (ArgVT.isInteger()) {
|
|
|
|
ArgReg1 = Alpha::R0;
|
|
|
|
ArgReg2 = Alpha::R1;
|
|
|
|
} else {
|
|
|
|
assert(ArgVT.isFloatingPoint());
|
|
|
|
ArgReg1 = Alpha::F0;
|
|
|
|
ArgReg2 = Alpha::F1;
|
|
|
|
}
|
2009-09-20 02:20:51 +00:00
|
|
|
Copy = DAG.getCopyToReg(Copy, dl, ArgReg1,
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-05 01:29:28 +00:00
|
|
|
Outs[0].Val, Copy.getValue(1));
|
2009-09-20 02:20:51 +00:00
|
|
|
if (std::find(DAG.getMachineFunction().getRegInfo().liveout_begin(),
|
2008-10-07 02:10:26 +00:00
|
|
|
DAG.getMachineFunction().getRegInfo().liveout_end(), ArgReg1)
|
|
|
|
== DAG.getMachineFunction().getRegInfo().liveout_end())
|
|
|
|
DAG.getMachineFunction().getRegInfo().addLiveOut(ArgReg1);
|
2009-09-20 02:20:51 +00:00
|
|
|
Copy = DAG.getCopyToReg(Copy, dl, ArgReg2,
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-05 01:29:28 +00:00
|
|
|
Outs[1].Val, Copy.getValue(1));
|
2009-09-20 02:20:51 +00:00
|
|
|
if (std::find(DAG.getMachineFunction().getRegInfo().liveout_begin(),
|
2008-10-07 02:10:26 +00:00
|
|
|
DAG.getMachineFunction().getRegInfo().liveout_end(), ArgReg2)
|
|
|
|
== DAG.getMachineFunction().getRegInfo().liveout_end())
|
|
|
|
DAG.getMachineFunction().getRegInfo().addLiveOut(ArgReg2);
|
|
|
|
break;
|
|
|
|
}
|
2006-06-12 18:09:24 +00:00
|
|
|
}
|
2009-09-20 02:20:51 +00:00
|
|
|
return DAG.getNode(AlphaISD::RET_FLAG, dl,
|
2009-08-11 20:47:22 +00:00
|
|
|
MVT::Other, Copy, Copy.getValue(1));
|
2005-09-02 18:46:02 +00:00
|
|
|
}
|
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
void AlphaTargetLowering::LowerVAARG(SDNode *N, SDValue &Chain,
|
|
|
|
SDValue &DataPtr, SelectionDAG &DAG) {
|
2008-07-04 11:47:58 +00:00
|
|
|
Chain = N->getOperand(0);
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue VAListP = N->getOperand(1);
|
2008-07-04 11:47:58 +00:00
|
|
|
const Value *VAListS = cast<SrcValueSDNode>(N->getOperand(2))->getValue();
|
2009-02-04 01:48:28 +00:00
|
|
|
DebugLoc dl = N->getDebugLoc();
|
2008-07-04 11:47:58 +00:00
|
|
|
|
2009-08-11 20:47:22 +00:00
|
|
|
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);
|
2008-07-04 11:47:58 +00:00
|
|
|
if (N->getValueType(0).isFloatingPoint())
|
|
|
|
{
|
|
|
|
//if fp && Offset < 6*8, then subtract 6*8 from DataPtr
|
2009-08-11 20:47:22 +00:00
|
|
|
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);
|
2008-07-04 11:47:58 +00:00
|
|
|
}
|
|
|
|
|
2009-08-11 20:47:22 +00:00
|
|
|
SDValue NewOffset = DAG.getNode(ISD::ADD, dl, MVT::i64, Offset,
|
|
|
|
DAG.getConstant(8, MVT::i64));
|
2009-02-04 01:48:28 +00:00
|
|
|
Chain = DAG.getTruncStore(Offset.getValue(1), dl, NewOffset, Tmp, NULL, 0,
|
2009-08-11 20:47:22 +00:00
|
|
|
MVT::i32);
|
2008-07-04 11:47:58 +00:00
|
|
|
}
|
|
|
|
|
2005-11-30 07:19:56 +00:00
|
|
|
/// LowerOperation - Provide custom lowering hooks for some operations.
|
|
|
|
///
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue AlphaTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
|
2009-02-07 19:59:05 +00:00
|
|
|
DebugLoc dl = Op.getDebugLoc();
|
2005-11-30 07:19:56 +00:00
|
|
|
switch (Op.getOpcode()) {
|
2009-07-14 16:55:14 +00:00
|
|
|
default: llvm_unreachable("Wasn't expecting to be able to lower this!");
|
2006-09-18 18:01:03 +00:00
|
|
|
case ISD::JumpTable: return LowerJumpTable(Op, DAG);
|
|
|
|
|
2008-10-07 02:10:26 +00:00
|
|
|
case ISD::INTRINSIC_WO_CHAIN: {
|
|
|
|
unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
|
|
|
|
switch (IntNo) {
|
|
|
|
default: break; // Don't custom lower most intrinsics.
|
|
|
|
case Intrinsic::alpha_umulh:
|
2009-09-20 02:20:51 +00:00
|
|
|
return DAG.getNode(ISD::MULHU, dl, MVT::i64,
|
2009-02-06 21:50:26 +00:00
|
|
|
Op.getOperand(1), Op.getOperand(2));
|
2008-10-07 02:10:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-07 22:37:20 +00:00
|
|
|
case ISD::SRL_PARTS: {
|
|
|
|
SDValue ShOpLo = Op.getOperand(0);
|
|
|
|
SDValue ShOpHi = Op.getOperand(1);
|
|
|
|
SDValue ShAmt = Op.getOperand(2);
|
2009-09-20 02:20:51 +00:00
|
|
|
SDValue bm = DAG.getNode(ISD::SUB, dl, MVT::i64,
|
|
|
|
DAG.getConstant(64, MVT::i64), ShAmt);
|
2009-08-11 20:47:22 +00:00
|
|
|
SDValue BMCC = DAG.getSetCC(dl, MVT::i64, bm,
|
|
|
|
DAG.getConstant(0, MVT::i64), ISD::SETLE);
|
2009-08-07 22:37:20 +00:00
|
|
|
// if 64 - shAmt <= 0
|
2009-08-11 20:47:22 +00:00
|
|
|
SDValue Hi_Neg = DAG.getConstant(0, MVT::i64);
|
|
|
|
SDValue ShAmt_Neg = DAG.getNode(ISD::SUB, dl, MVT::i64,
|
2009-09-20 02:20:51 +00:00
|
|
|
DAG.getConstant(0, MVT::i64), bm);
|
2009-08-11 20:47:22 +00:00
|
|
|
SDValue Lo_Neg = DAG.getNode(ISD::SRL, dl, MVT::i64, ShOpHi, ShAmt_Neg);
|
2009-08-07 22:37:20 +00:00
|
|
|
// else
|
2009-08-11 20:47:22 +00:00
|
|
|
SDValue carries = DAG.getNode(ISD::SHL, dl, MVT::i64, ShOpHi, bm);
|
|
|
|
SDValue Hi_Pos = DAG.getNode(ISD::SRL, dl, MVT::i64, ShOpHi, ShAmt);
|
|
|
|
SDValue Lo_Pos = DAG.getNode(ISD::SRL, dl, MVT::i64, ShOpLo, ShAmt);
|
|
|
|
Lo_Pos = DAG.getNode(ISD::OR, dl, MVT::i64, Lo_Pos, carries);
|
2009-08-07 22:37:20 +00:00
|
|
|
// Merge
|
2009-08-11 20:47:22 +00:00
|
|
|
SDValue Hi = DAG.getNode(ISD::SELECT, dl, MVT::i64, BMCC, Hi_Neg, Hi_Pos);
|
|
|
|
SDValue Lo = DAG.getNode(ISD::SELECT, dl, MVT::i64, BMCC, Lo_Neg, Lo_Pos);
|
2009-08-07 22:37:20 +00:00
|
|
|
SDValue Ops[2] = { Lo, Hi };
|
|
|
|
return DAG.getMergeValues(Ops, 2, dl);
|
2009-09-20 02:20:51 +00:00
|
|
|
}
|
2009-08-07 22:37:20 +00:00
|
|
|
// case ISD::SRA_PARTS:
|
|
|
|
|
|
|
|
// case ISD::SHL_PARTS:
|
|
|
|
|
|
|
|
|
2005-11-30 07:19:56 +00:00
|
|
|
case ISD::SINT_TO_FP: {
|
2009-08-11 20:47:22 +00:00
|
|
|
assert(Op.getOperand(0).getValueType() == MVT::i64 &&
|
2005-11-30 07:19:56 +00:00
|
|
|
"Unhandled SINT_TO_FP type in custom expander!");
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue LD;
|
2009-08-11 20:47:22 +00:00
|
|
|
bool isDouble = Op.getValueType() == MVT::f64;
|
|
|
|
LD = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f64, Op.getOperand(0));
|
2009-02-06 21:50:26 +00:00
|
|
|
SDValue FP = DAG.getNode(isDouble?AlphaISD::CVTQT_:AlphaISD::CVTQS_, dl,
|
2009-08-11 20:47:22 +00:00
|
|
|
isDouble?MVT::f64:MVT::f32, LD);
|
2005-11-30 07:19:56 +00:00
|
|
|
return FP;
|
|
|
|
}
|
2005-11-30 16:10:29 +00:00
|
|
|
case ISD::FP_TO_SINT: {
|
2009-08-11 20:47:22 +00:00
|
|
|
bool isDouble = Op.getOperand(0).getValueType() == MVT::f64;
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue src = Op.getOperand(0);
|
2005-11-30 16:10:29 +00:00
|
|
|
|
|
|
|
if (!isDouble) //Promote
|
2009-08-11 20:47:22 +00:00
|
|
|
src = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, src);
|
2009-09-20 02:20:51 +00:00
|
|
|
|
2009-08-11 20:47:22 +00:00
|
|
|
src = DAG.getNode(AlphaISD::CVTTQ_, dl, MVT::f64, src);
|
2005-11-30 16:10:29 +00:00
|
|
|
|
2009-08-11 20:47:22 +00:00
|
|
|
return DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i64, src);
|
2005-11-30 07:19:56 +00:00
|
|
|
}
|
2005-12-24 05:36:33 +00:00
|
|
|
case ISD::ConstantPool: {
|
2006-01-31 22:23:14 +00:00
|
|
|
ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
|
2006-09-12 21:04:05 +00:00
|
|
|
Constant *C = CP->getConstVal();
|
2009-08-11 20:47:22 +00:00
|
|
|
SDValue CPI = DAG.getTargetConstantPool(C, MVT::i64, CP->getAlignment());
|
2009-02-06 21:50:26 +00:00
|
|
|
// FIXME there isn't really any debug info here
|
2009-09-20 02:20:51 +00:00
|
|
|
|
2009-08-11 20:47:22 +00:00
|
|
|
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);
|
2005-12-24 05:36:33 +00:00
|
|
|
return Lo;
|
|
|
|
}
|
2007-07-11 17:19:51 +00:00
|
|
|
case ISD::GlobalTLSAddress:
|
2009-07-14 16:55:14 +00:00
|
|
|
llvm_unreachable("TLS not implemented for Alpha.");
|
2005-12-24 05:36:33 +00:00
|
|
|
case ISD::GlobalAddress: {
|
|
|
|
GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
|
|
|
|
GlobalValue *GV = GSDN->getGlobal();
|
2009-08-11 20:47:22 +00:00
|
|
|
SDValue GA = DAG.getTargetGlobalAddress(GV, MVT::i64, GSDN->getOffset());
|
2009-02-06 21:50:26 +00:00
|
|
|
// FIXME there isn't really any debug info here
|
2005-12-24 05:36:33 +00:00
|
|
|
|
2007-01-30 20:08:39 +00:00
|
|
|
// if (!GV->hasWeakLinkage() && !GV->isDeclaration() && !GV->hasLinkOnceLinkage()) {
|
2009-01-15 20:18:42 +00:00
|
|
|
if (GV->hasLocalLinkage()) {
|
2009-08-11 20:47:22 +00:00
|
|
|
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);
|
2005-12-24 05:36:33 +00:00
|
|
|
return Lo;
|
|
|
|
} else
|
2009-09-20 02:20:51 +00:00
|
|
|
return DAG.getNode(AlphaISD::RelLit, dl, MVT::i64, GA,
|
2009-08-11 20:47:22 +00:00
|
|
|
DAG.getGLOBAL_OFFSET_TABLE(MVT::i64));
|
2005-12-24 05:36:33 +00:00
|
|
|
}
|
2008-09-16 21:48:12 +00:00
|
|
|
case ISD::ExternalSymbol: {
|
2009-09-20 02:20:51 +00:00
|
|
|
return DAG.getNode(AlphaISD::RelLit, dl, MVT::i64,
|
2008-09-16 21:48:12 +00:00
|
|
|
DAG.getTargetExternalSymbol(cast<ExternalSymbolSDNode>(Op)
|
2009-08-11 20:47:22 +00:00
|
|
|
->getSymbol(), MVT::i64),
|
|
|
|
DAG.getGLOBAL_OFFSET_TABLE(MVT::i64));
|
2005-12-25 01:34:27 +00:00
|
|
|
}
|
2008-09-16 21:48:12 +00:00
|
|
|
|
2005-12-25 01:34:27 +00:00
|
|
|
case ISD::UREM:
|
|
|
|
case ISD::SREM:
|
2006-04-02 21:08:39 +00:00
|
|
|
//Expand only on constant case
|
|
|
|
if (Op.getOperand(1).getOpcode() == ISD::Constant) {
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT VT = Op.getNode()->getValueType(0);
|
2008-08-28 21:40:38 +00:00
|
|
|
SDValue Tmp1 = Op.getNode()->getOpcode() == ISD::UREM ?
|
|
|
|
BuildUDIV(Op.getNode(), DAG, NULL) :
|
|
|
|
BuildSDIV(Op.getNode(), DAG, NULL);
|
2009-02-06 21:50:26 +00:00
|
|
|
Tmp1 = DAG.getNode(ISD::MUL, dl, VT, Tmp1, Op.getOperand(1));
|
|
|
|
Tmp1 = DAG.getNode(ISD::SUB, dl, VT, Op.getOperand(0), Tmp1);
|
2006-04-02 21:08:39 +00:00
|
|
|
return Tmp1;
|
|
|
|
}
|
|
|
|
//fall through
|
|
|
|
case ISD::SDIV:
|
|
|
|
case ISD::UDIV:
|
2008-06-06 12:08:01 +00:00
|
|
|
if (Op.getValueType().isInteger()) {
|
2006-04-06 21:26:32 +00:00
|
|
|
if (Op.getOperand(1).getOpcode() == ISD::Constant)
|
2009-09-20 02:20:51 +00:00
|
|
|
return Op.getOpcode() == ISD::SDIV ? BuildSDIV(Op.getNode(), DAG, NULL)
|
2008-08-28 21:40:38 +00:00
|
|
|
: BuildUDIV(Op.getNode(), DAG, NULL);
|
2005-12-25 01:34:27 +00:00
|
|
|
const char* opstr = 0;
|
2007-04-16 18:10:23 +00:00
|
|
|
switch (Op.getOpcode()) {
|
2005-12-25 01:34:27 +00:00
|
|
|
case ISD::UREM: opstr = "__remqu"; break;
|
|
|
|
case ISD::SREM: opstr = "__remq"; break;
|
|
|
|
case ISD::UDIV: opstr = "__divqu"; break;
|
|
|
|
case ISD::SDIV: opstr = "__divq"; break;
|
|
|
|
}
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue Tmp1 = Op.getOperand(0),
|
2005-12-25 01:34:27 +00:00
|
|
|
Tmp2 = Op.getOperand(1),
|
2009-08-11 20:47:22 +00:00
|
|
|
Addr = DAG.getExternalSymbol(opstr, MVT::i64);
|
|
|
|
return DAG.getNode(AlphaISD::DivCall, dl, MVT::i64, Addr, Tmp1, Tmp2);
|
2005-12-25 01:34:27 +00:00
|
|
|
}
|
|
|
|
break;
|
2005-11-30 16:10:29 +00:00
|
|
|
|
2006-01-25 18:21:52 +00:00
|
|
|
case ISD::VAARG: {
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue Chain, DataPtr;
|
2008-08-28 21:40:38 +00:00
|
|
|
LowerVAARG(Op.getNode(), Chain, DataPtr, DAG);
|
2006-01-23 21:51:33 +00:00
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue Result;
|
2009-08-11 20:47:22 +00:00
|
|
|
if (Op.getValueType() == MVT::i32)
|
|
|
|
Result = DAG.getExtLoad(ISD::SEXTLOAD, dl, MVT::i64, Chain, DataPtr,
|
|
|
|
NULL, 0, MVT::i32);
|
2006-01-25 18:21:52 +00:00
|
|
|
else
|
2009-02-04 02:34:38 +00:00
|
|
|
Result = DAG.getLoad(Op.getValueType(), dl, Chain, DataPtr, NULL, 0);
|
2006-01-25 18:21:52 +00:00
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
case ISD::VACOPY: {
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue Chain = Op.getOperand(0);
|
|
|
|
SDValue DestP = Op.getOperand(1);
|
|
|
|
SDValue SrcP = Op.getOperand(2);
|
2008-02-06 22:27:42 +00:00
|
|
|
const Value *DestS = cast<SrcValueSDNode>(Op.getOperand(3))->getValue();
|
|
|
|
const Value *SrcS = cast<SrcValueSDNode>(Op.getOperand(4))->getValue();
|
2009-09-20 02:20:51 +00:00
|
|
|
|
2009-02-04 02:34:38 +00:00
|
|
|
SDValue Val = DAG.getLoad(getPointerTy(), dl, Chain, SrcP, SrcS, 0);
|
|
|
|
SDValue Result = DAG.getStore(Val.getValue(1), dl, Val, DestP, DestS, 0);
|
2009-09-20 02:20:51 +00:00
|
|
|
SDValue NP = DAG.getNode(ISD::ADD, dl, MVT::i64, SrcP,
|
2009-08-11 20:47:22 +00:00
|
|
|
DAG.getConstant(8, MVT::i64));
|
2009-09-20 02:20:51 +00:00
|
|
|
Val = DAG.getExtLoad(ISD::SEXTLOAD, dl, MVT::i64, Result,
|
2009-08-11 20:47:22 +00:00
|
|
|
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), dl, Val, NPD, NULL, 0, MVT::i32);
|
2006-01-25 18:21:52 +00:00
|
|
|
}
|
|
|
|
case ISD::VASTART: {
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue Chain = Op.getOperand(0);
|
|
|
|
SDValue VAListP = Op.getOperand(1);
|
2008-02-06 22:27:42 +00:00
|
|
|
const Value *VAListS = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
|
2009-09-20 02:20:51 +00:00
|
|
|
|
2006-01-25 18:21:52 +00:00
|
|
|
// vastart stores the address of the VarArgsBase and VarArgsOffset
|
2009-08-11 20:47:22 +00:00
|
|
|
SDValue FR = DAG.getFrameIndex(VarArgsBase, MVT::i64);
|
2009-02-04 02:34:38 +00:00
|
|
|
SDValue S1 = DAG.getStore(Chain, dl, FR, VAListP, VAListS, 0);
|
2009-08-11 20:47:22 +00:00
|
|
|
SDValue SA2 = DAG.getNode(ISD::ADD, dl, MVT::i64, VAListP,
|
|
|
|
DAG.getConstant(8, MVT::i64));
|
|
|
|
return DAG.getTruncStore(S1, dl, DAG.getConstant(VarArgsOffset, MVT::i64),
|
|
|
|
SA2, NULL, 0, MVT::i32);
|
2006-01-25 18:21:52 +00:00
|
|
|
}
|
2009-09-20 02:20:51 +00:00
|
|
|
case ISD::RETURNADDR:
|
2009-02-07 00:55:49 +00:00
|
|
|
return DAG.getNode(AlphaISD::GlobalRetAddr, DebugLoc::getUnknownLoc(),
|
2009-08-11 20:47:22 +00:00
|
|
|
MVT::i64);
|
2007-02-08 17:37:41 +00:00
|
|
|
//FIXME: implement
|
2007-01-29 22:58:52 +00:00
|
|
|
case ISD::FRAMEADDR: break;
|
2005-11-30 16:10:29 +00:00
|
|
|
}
|
2009-09-20 02:20:51 +00:00
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
return SDValue();
|
2005-11-30 07:19:56 +00:00
|
|
|
}
|
2006-01-28 03:14:31 +00:00
|
|
|
|
2008-12-01 11:39:25 +00:00
|
|
|
void AlphaTargetLowering::ReplaceNodeResults(SDNode *N,
|
|
|
|
SmallVectorImpl<SDValue>&Results,
|
|
|
|
SelectionDAG &DAG) {
|
2009-02-04 20:06:27 +00:00
|
|
|
DebugLoc dl = N->getDebugLoc();
|
2009-08-11 20:47:22 +00:00
|
|
|
assert(N->getValueType(0) == MVT::i32 &&
|
2008-07-04 11:47:58 +00:00
|
|
|
N->getOpcode() == ISD::VAARG &&
|
2006-01-28 03:14:31 +00:00
|
|
|
"Unknown node to custom promote!");
|
2008-07-04 11:47:58 +00:00
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue Chain, DataPtr;
|
2008-07-04 11:47:58 +00:00
|
|
|
LowerVAARG(N, Chain, DataPtr, DAG);
|
2009-02-04 20:06:27 +00:00
|
|
|
SDValue Res = DAG.getLoad(N->getValueType(0), dl, Chain, DataPtr, NULL, 0);
|
2008-12-01 11:39:25 +00:00
|
|
|
Results.push_back(Res);
|
|
|
|
Results.push_back(SDValue(Res.getNode(), 1));
|
2006-01-28 03:14:31 +00:00
|
|
|
}
|
2006-06-21 13:37:27 +00:00
|
|
|
|
|
|
|
|
|
|
|
//Inline Asm
|
|
|
|
|
|
|
|
/// getConstraintType - Given a constraint letter, return the type of
|
|
|
|
/// constraint it is for this target.
|
2009-09-20 02:20:51 +00:00
|
|
|
AlphaTargetLowering::ConstraintType
|
2007-03-25 02:14:49 +00:00
|
|
|
AlphaTargetLowering::getConstraintType(const std::string &Constraint) const {
|
|
|
|
if (Constraint.size() == 1) {
|
|
|
|
switch (Constraint[0]) {
|
|
|
|
default: break;
|
|
|
|
case 'f':
|
|
|
|
case 'r':
|
|
|
|
return C_RegisterClass;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return TargetLowering::getConstraintType(Constraint);
|
2006-06-21 13:37:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<unsigned> AlphaTargetLowering::
|
|
|
|
getRegClassForInlineAsmConstraint(const std::string &Constraint,
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT VT) const {
|
2006-06-21 13:37:27 +00:00
|
|
|
if (Constraint.size() == 1) {
|
|
|
|
switch (Constraint[0]) {
|
|
|
|
default: break; // Unknown constriant letter
|
2009-09-20 02:20:51 +00:00
|
|
|
case 'f':
|
2006-06-21 13:37:27 +00:00
|
|
|
return make_vector<unsigned>(Alpha::F0 , Alpha::F1 , Alpha::F2 ,
|
2007-04-16 18:10:23 +00:00
|
|
|
Alpha::F3 , Alpha::F4 , Alpha::F5 ,
|
2009-09-20 02:20:51 +00:00
|
|
|
Alpha::F6 , Alpha::F7 , Alpha::F8 ,
|
|
|
|
Alpha::F9 , Alpha::F10, Alpha::F11,
|
|
|
|
Alpha::F12, Alpha::F13, Alpha::F14,
|
|
|
|
Alpha::F15, Alpha::F16, Alpha::F17,
|
|
|
|
Alpha::F18, Alpha::F19, Alpha::F20,
|
|
|
|
Alpha::F21, Alpha::F22, Alpha::F23,
|
|
|
|
Alpha::F24, Alpha::F25, Alpha::F26,
|
|
|
|
Alpha::F27, Alpha::F28, Alpha::F29,
|
2007-04-16 18:10:23 +00:00
|
|
|
Alpha::F30, Alpha::F31, 0);
|
2009-09-20 02:20:51 +00:00
|
|
|
case 'r':
|
|
|
|
return make_vector<unsigned>(Alpha::R0 , Alpha::R1 , Alpha::R2 ,
|
|
|
|
Alpha::R3 , Alpha::R4 , Alpha::R5 ,
|
|
|
|
Alpha::R6 , Alpha::R7 , Alpha::R8 ,
|
|
|
|
Alpha::R9 , Alpha::R10, Alpha::R11,
|
|
|
|
Alpha::R12, Alpha::R13, Alpha::R14,
|
|
|
|
Alpha::R15, Alpha::R16, Alpha::R17,
|
|
|
|
Alpha::R18, Alpha::R19, Alpha::R20,
|
|
|
|
Alpha::R21, Alpha::R22, Alpha::R23,
|
|
|
|
Alpha::R24, Alpha::R25, Alpha::R26,
|
|
|
|
Alpha::R27, Alpha::R28, Alpha::R29,
|
2007-04-16 18:10:23 +00:00
|
|
|
Alpha::R30, Alpha::R31, 0);
|
2006-06-21 13:37:27 +00:00
|
|
|
}
|
|
|
|
}
|
2009-09-20 02:20:51 +00:00
|
|
|
|
2006-06-21 13:37:27 +00:00
|
|
|
return std::vector<unsigned>();
|
|
|
|
}
|
2008-02-21 06:45:13 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Other Lowering Code
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
MachineBasicBlock *
|
|
|
|
AlphaTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
|
2009-09-18 21:02:19 +00:00
|
|
|
MachineBasicBlock *BB,
|
|
|
|
DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM) const {
|
2008-02-21 06:45:13 +00:00
|
|
|
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");
|
|
|
|
|
2009-09-20 02:20:51 +00:00
|
|
|
bool is32 = MI->getOpcode() == Alpha::CAS32 ||
|
2008-02-21 06:45:13 +00:00
|
|
|
MI->getOpcode() == Alpha::LAS32 ||
|
|
|
|
MI->getOpcode() == Alpha::SWAP32;
|
2009-09-20 02:20:51 +00:00
|
|
|
|
2008-02-21 06:45:13 +00:00
|
|
|
//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();
|
2009-02-13 02:30:42 +00:00
|
|
|
DebugLoc dl = MI->getDebugLoc();
|
2008-07-07 23:14:23 +00:00
|
|
|
MachineFunction::iterator It = BB;
|
2008-02-21 06:45:13 +00:00
|
|
|
++It;
|
2009-09-20 02:20:51 +00:00
|
|
|
|
2008-02-21 06:45:13 +00:00
|
|
|
MachineBasicBlock *thisMBB = BB;
|
2008-07-07 23:14:23 +00:00
|
|
|
MachineFunction *F = BB->getParent();
|
|
|
|
MachineBasicBlock *llscMBB = F->CreateMachineBasicBlock(LLVM_BB);
|
|
|
|
MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
|
2008-02-21 06:45:13 +00:00
|
|
|
|
2009-09-19 09:51:03 +00:00
|
|
|
// Inform sdisel of the edge changes.
|
2009-09-20 02:20:51 +00:00
|
|
|
for (MachineBasicBlock::succ_iterator I = BB->succ_begin(),
|
2009-09-19 09:51:03 +00:00
|
|
|
E = BB->succ_end(); I != E; ++I)
|
|
|
|
EM->insert(std::make_pair(*I, sinkMBB));
|
|
|
|
|
2008-06-21 20:21:19 +00:00
|
|
|
sinkMBB->transferSuccessors(thisMBB);
|
2008-02-21 06:45:13 +00:00
|
|
|
|
2008-07-07 23:14:23 +00:00
|
|
|
F->insert(It, llscMBB);
|
|
|
|
F->insert(It, sinkMBB);
|
2008-02-21 06:45:13 +00:00
|
|
|
|
2009-02-13 02:30:42 +00:00
|
|
|
BuildMI(thisMBB, dl, TII->get(Alpha::BR)).addMBB(llscMBB);
|
2009-09-20 02:20:51 +00:00
|
|
|
|
2008-02-21 06:45:13 +00:00
|
|
|
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);
|
|
|
|
|
2009-09-20 02:20:51 +00:00
|
|
|
BuildMI(llscMBB, dl, TII->get(is32 ? Alpha::LDL_L : Alpha::LDQ_L),
|
2008-02-21 06:45:13 +00:00
|
|
|
reg_res).addImm(0).addReg(reg_ptr);
|
|
|
|
switch (MI->getOpcode()) {
|
|
|
|
case Alpha::CAS32:
|
|
|
|
case Alpha::CAS64: {
|
2009-09-20 02:20:51 +00:00
|
|
|
unsigned reg_cmp
|
2008-02-21 06:45:13 +00:00
|
|
|
= F->getRegInfo().createVirtualRegister(&Alpha::GPRCRegClass);
|
2009-02-13 02:30:42 +00:00
|
|
|
BuildMI(llscMBB, dl, TII->get(Alpha::CMPEQ), reg_cmp)
|
2008-02-21 06:45:13 +00:00
|
|
|
.addReg(reg_v2).addReg(reg_res);
|
2009-02-13 02:30:42 +00:00
|
|
|
BuildMI(llscMBB, dl, TII->get(Alpha::BEQ))
|
2008-02-21 06:45:13 +00:00
|
|
|
.addImm(0).addReg(reg_cmp).addMBB(sinkMBB);
|
2009-02-13 02:30:42 +00:00
|
|
|
BuildMI(llscMBB, dl, TII->get(Alpha::BISr), reg_store)
|
2008-02-21 06:45:13 +00:00
|
|
|
.addReg(Alpha::R31).addReg(MI->getOperand(3).getReg());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Alpha::LAS32:
|
|
|
|
case Alpha::LAS64: {
|
2009-02-13 02:30:42 +00:00
|
|
|
BuildMI(llscMBB, dl,TII->get(is32 ? Alpha::ADDLr : Alpha::ADDQr), reg_store)
|
2008-02-21 06:45:13 +00:00
|
|
|
.addReg(reg_res).addReg(reg_v2);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Alpha::SWAP32:
|
|
|
|
case Alpha::SWAP64: {
|
2009-02-13 02:30:42 +00:00
|
|
|
BuildMI(llscMBB, dl, TII->get(Alpha::BISr), reg_store)
|
2008-02-21 06:45:13 +00:00
|
|
|
.addReg(reg_v2).addReg(reg_v2);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2009-02-13 02:30:42 +00:00
|
|
|
BuildMI(llscMBB, dl, TII->get(is32 ? Alpha::STL_C : Alpha::STQ_C), reg_store)
|
2008-02-21 06:45:13 +00:00
|
|
|
.addReg(reg_store).addImm(0).addReg(reg_ptr);
|
2009-02-13 02:30:42 +00:00
|
|
|
BuildMI(llscMBB, dl, TII->get(Alpha::BEQ))
|
2008-02-21 06:45:13 +00:00
|
|
|
.addImm(0).addReg(reg_store).addMBB(llscMBB);
|
2009-02-13 02:30:42 +00:00
|
|
|
BuildMI(llscMBB, dl, TII->get(Alpha::BR)).addMBB(sinkMBB);
|
2008-02-21 06:45:13 +00:00
|
|
|
|
|
|
|
thisMBB->addSuccessor(llscMBB);
|
|
|
|
llscMBB->addSuccessor(llscMBB);
|
|
|
|
llscMBB->addSuccessor(sinkMBB);
|
2008-07-07 23:14:23 +00:00
|
|
|
F->DeleteMachineInstr(MI); // The pseudo instruction is gone now.
|
2008-02-21 06:45:13 +00:00
|
|
|
|
|
|
|
return sinkMBB;
|
|
|
|
}
|
Teach DAGCombine to fold constant offsets into GlobalAddress nodes,
and add a TargetLowering hook for it to use to determine when this
is legal (i.e. not in PIC mode, etc.)
This allows instruction selection to emit folded constant offsets
in more cases, such as the included testcase, eliminating the need
for explicit arithmetic instructions.
This eliminates the need for the C++ code in X86ISelDAGToDAG.cpp
that attempted to achieve the same effect, but wasn't as effective.
Also, fix handling of offsets in GlobalAddressSDNodes in several
places, including changing GlobalAddressSDNode's offset from
int to int64_t.
The Mips, Alpha, Sparc, and CellSPU targets appear to be
unaware of GlobalAddress offsets currently, so set the hook to
false on those targets.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@57748 91177308-0d34-0410-b5e6-96231b3b80d8
2008-10-18 02:06:02 +00:00
|
|
|
|
|
|
|
bool
|
|
|
|
AlphaTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
|
|
|
|
// The Alpha target isn't yet aware of offsets.
|
|
|
|
return false;
|
|
|
|
}
|