XCoreISelLowering.cpp revision 223017
1193323Sed//===-- XCoreISelLowering.cpp - XCore DAG Lowering Implementation ------===// 2193323Sed// 3193323Sed// The LLVM Compiler Infrastructure 4193323Sed// 5193323Sed// This file is distributed under the University of Illinois Open Source 6193323Sed// License. See LICENSE.TXT for details. 7193323Sed// 8193323Sed//===----------------------------------------------------------------------===// 9193323Sed// 10193323Sed// This file implements the XCoreTargetLowering class. 11193323Sed// 12193323Sed//===----------------------------------------------------------------------===// 13193323Sed 14193323Sed#define DEBUG_TYPE "xcore-lower" 15193323Sed 16193323Sed#include "XCoreISelLowering.h" 17193323Sed#include "XCoreMachineFunctionInfo.h" 18193323Sed#include "XCore.h" 19198090Srdivacky#include "XCoreTargetObjectFile.h" 20193323Sed#include "XCoreTargetMachine.h" 21193323Sed#include "XCoreSubtarget.h" 22193323Sed#include "llvm/DerivedTypes.h" 23193323Sed#include "llvm/Function.h" 24193323Sed#include "llvm/Intrinsics.h" 25193323Sed#include "llvm/CallingConv.h" 26193323Sed#include "llvm/GlobalVariable.h" 27193323Sed#include "llvm/GlobalAlias.h" 28193323Sed#include "llvm/CodeGen/CallingConvLower.h" 29193323Sed#include "llvm/CodeGen/MachineFrameInfo.h" 30193323Sed#include "llvm/CodeGen/MachineFunction.h" 31193323Sed#include "llvm/CodeGen/MachineInstrBuilder.h" 32204642Srdivacky#include "llvm/CodeGen/MachineJumpTableInfo.h" 33193323Sed#include "llvm/CodeGen/MachineRegisterInfo.h" 34193323Sed#include "llvm/CodeGen/SelectionDAGISel.h" 35193323Sed#include "llvm/CodeGen/ValueTypes.h" 36193323Sed#include "llvm/Support/Debug.h" 37198090Srdivacky#include "llvm/Support/ErrorHandling.h" 38198090Srdivacky#include "llvm/Support/raw_ostream.h" 39193323Sed#include "llvm/ADT/VectorExtras.h" 40193323Sedusing namespace llvm; 41193323Sed 42193323Sedconst char *XCoreTargetLowering:: 43219077SdimgetTargetNodeName(unsigned Opcode) const 44193323Sed{ 45219077Sdim switch (Opcode) 46193323Sed { 47193323Sed case XCoreISD::BL : return "XCoreISD::BL"; 48193323Sed case XCoreISD::PCRelativeWrapper : return "XCoreISD::PCRelativeWrapper"; 49193323Sed case XCoreISD::DPRelativeWrapper : return "XCoreISD::DPRelativeWrapper"; 50193323Sed case XCoreISD::CPRelativeWrapper : return "XCoreISD::CPRelativeWrapper"; 51193323Sed case XCoreISD::STWSP : return "XCoreISD::STWSP"; 52193323Sed case XCoreISD::RETSP : return "XCoreISD::RETSP"; 53198090Srdivacky case XCoreISD::LADD : return "XCoreISD::LADD"; 54198090Srdivacky case XCoreISD::LSUB : return "XCoreISD::LSUB"; 55204961Srdivacky case XCoreISD::LMUL : return "XCoreISD::LMUL"; 56204961Srdivacky case XCoreISD::MACCU : return "XCoreISD::MACCU"; 57204961Srdivacky case XCoreISD::MACCS : return "XCoreISD::MACCS"; 58204642Srdivacky case XCoreISD::BR_JT : return "XCoreISD::BR_JT"; 59204642Srdivacky case XCoreISD::BR_JT32 : return "XCoreISD::BR_JT32"; 60204961Srdivacky default : return NULL; 61193323Sed } 62193323Sed} 63193323Sed 64193323SedXCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM) 65198090Srdivacky : TargetLowering(XTM, new XCoreTargetObjectFile()), 66193323Sed TM(XTM), 67193323Sed Subtarget(*XTM.getSubtargetImpl()) { 68193323Sed 69193323Sed // Set up the register classes. 70193323Sed addRegisterClass(MVT::i32, XCore::GRRegsRegisterClass); 71193323Sed 72193323Sed // Compute derived properties from the register classes 73193323Sed computeRegisterProperties(); 74193323Sed 75193323Sed // Division is expensive 76193323Sed setIntDivIsCheap(false); 77193323Sed 78193323Sed setStackPointerRegisterToSaveRestore(XCore::SP); 79193323Sed 80208599Srdivacky setSchedulingPreference(Sched::RegPressure); 81193323Sed 82193323Sed // Use i32 for setcc operations results (slt, sgt, ...). 83193323Sed setBooleanContents(ZeroOrOneBooleanContent); 84193323Sed 85193323Sed // XCore does not have the NodeTypes below. 86193323Sed setOperationAction(ISD::BR_CC, MVT::Other, Expand); 87193323Sed setOperationAction(ISD::SELECT_CC, MVT::i32, Custom); 88193323Sed setOperationAction(ISD::ADDC, MVT::i32, Expand); 89193323Sed setOperationAction(ISD::ADDE, MVT::i32, Expand); 90193323Sed setOperationAction(ISD::SUBC, MVT::i32, Expand); 91193323Sed setOperationAction(ISD::SUBE, MVT::i32, Expand); 92193323Sed 93193323Sed // Stop the combiner recombining select and set_cc 94193323Sed setOperationAction(ISD::SELECT_CC, MVT::Other, Expand); 95219077Sdim 96193323Sed // 64bit 97198090Srdivacky setOperationAction(ISD::ADD, MVT::i64, Custom); 98198090Srdivacky setOperationAction(ISD::SUB, MVT::i64, Custom); 99204961Srdivacky setOperationAction(ISD::SMUL_LOHI, MVT::i32, Custom); 100204961Srdivacky setOperationAction(ISD::UMUL_LOHI, MVT::i32, Custom); 101193323Sed setOperationAction(ISD::MULHS, MVT::i32, Expand); 102193323Sed setOperationAction(ISD::MULHU, MVT::i32, Expand); 103193323Sed setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); 104193323Sed setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); 105193323Sed setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); 106219077Sdim 107193323Sed // Bit Manipulation 108193323Sed setOperationAction(ISD::CTPOP, MVT::i32, Expand); 109193323Sed setOperationAction(ISD::ROTL , MVT::i32, Expand); 110193323Sed setOperationAction(ISD::ROTR , MVT::i32, Expand); 111219077Sdim 112193323Sed setOperationAction(ISD::TRAP, MVT::Other, Legal); 113219077Sdim 114204642Srdivacky // Jump tables. 115204642Srdivacky setOperationAction(ISD::BR_JT, MVT::Other, Custom); 116193323Sed 117193323Sed setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); 118199511Srdivacky setOperationAction(ISD::BlockAddress, MVT::i32 , Custom); 119199511Srdivacky 120193323Sed // Thread Local Storage 121193323Sed setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom); 122219077Sdim 123193323Sed // Conversion of i64 -> double produces constantpool nodes 124193323Sed setOperationAction(ISD::ConstantPool, MVT::i32, Custom); 125193323Sed 126193323Sed // Loads 127193323Sed setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote); 128193323Sed setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote); 129193323Sed setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); 130193323Sed 131193323Sed setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Expand); 132193323Sed setLoadExtAction(ISD::ZEXTLOAD, MVT::i16, Expand); 133198090Srdivacky 134198090Srdivacky // Custom expand misaligned loads / stores. 135198090Srdivacky setOperationAction(ISD::LOAD, MVT::i32, Custom); 136198090Srdivacky setOperationAction(ISD::STORE, MVT::i32, Custom); 137198090Srdivacky 138193323Sed // Varargs 139193323Sed setOperationAction(ISD::VAEND, MVT::Other, Expand); 140193323Sed setOperationAction(ISD::VACOPY, MVT::Other, Expand); 141193323Sed setOperationAction(ISD::VAARG, MVT::Other, Custom); 142193323Sed setOperationAction(ISD::VASTART, MVT::Other, Custom); 143219077Sdim 144193323Sed // Dynamic stack 145193323Sed setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); 146193323Sed setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); 147193323Sed setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand); 148198090Srdivacky 149218893Sdim // TRAMPOLINE is custom lowered. 150218893Sdim setOperationAction(ISD::TRAMPOLINE, MVT::Other, Custom); 151218893Sdim 152218893Sdim maxStoresPerMemset = maxStoresPerMemsetOptSize = 4; 153218893Sdim maxStoresPerMemmove = maxStoresPerMemmoveOptSize 154218893Sdim = maxStoresPerMemcpy = maxStoresPerMemcpyOptSize = 2; 155218893Sdim 156198090Srdivacky // We have target-specific dag combine patterns for the following nodes: 157198090Srdivacky setTargetDAGCombine(ISD::STORE); 158204961Srdivacky setTargetDAGCombine(ISD::ADD); 159223017Sdim 160223017Sdim setMinFunctionAlignment(1); 161193323Sed} 162193323Sed 163193323SedSDValue XCoreTargetLowering:: 164207618SrdivackyLowerOperation(SDValue Op, SelectionDAG &DAG) const { 165219077Sdim switch (Op.getOpcode()) 166193323Sed { 167193323Sed case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); 168193323Sed case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG); 169199511Srdivacky case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); 170193323Sed case ISD::ConstantPool: return LowerConstantPool(Op, DAG); 171204642Srdivacky case ISD::BR_JT: return LowerBR_JT(Op, DAG); 172198090Srdivacky case ISD::LOAD: return LowerLOAD(Op, DAG); 173198090Srdivacky case ISD::STORE: return LowerSTORE(Op, DAG); 174193323Sed case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG); 175193323Sed case ISD::VAARG: return LowerVAARG(Op, DAG); 176193323Sed case ISD::VASTART: return LowerVASTART(Op, DAG); 177204961Srdivacky case ISD::SMUL_LOHI: return LowerSMUL_LOHI(Op, DAG); 178204961Srdivacky case ISD::UMUL_LOHI: return LowerUMUL_LOHI(Op, DAG); 179193323Sed // FIXME: Remove these when LegalizeDAGTypes lands. 180193323Sed case ISD::ADD: 181193323Sed case ISD::SUB: return ExpandADDSUB(Op.getNode(), DAG); 182193323Sed case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG); 183218893Sdim case ISD::TRAMPOLINE: return LowerTRAMPOLINE(Op, DAG); 184193323Sed default: 185198090Srdivacky llvm_unreachable("unimplemented operand"); 186193323Sed return SDValue(); 187193323Sed } 188193323Sed} 189193323Sed 190193323Sed/// ReplaceNodeResults - Replace the results of node with an illegal result 191193323Sed/// type with new values built out of custom code. 192193323Sedvoid XCoreTargetLowering::ReplaceNodeResults(SDNode *N, 193193323Sed SmallVectorImpl<SDValue>&Results, 194207618Srdivacky SelectionDAG &DAG) const { 195193323Sed switch (N->getOpcode()) { 196193323Sed default: 197198090Srdivacky llvm_unreachable("Don't know how to custom expand this!"); 198193323Sed return; 199193323Sed case ISD::ADD: 200193323Sed case ISD::SUB: 201193323Sed Results.push_back(ExpandADDSUB(N, DAG)); 202193323Sed return; 203193323Sed } 204193323Sed} 205193323Sed 206193323Sed//===----------------------------------------------------------------------===// 207193323Sed// Misc Lower Operation implementation 208193323Sed//===----------------------------------------------------------------------===// 209193323Sed 210193323SedSDValue XCoreTargetLowering:: 211207618SrdivackyLowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const 212193323Sed{ 213193323Sed DebugLoc dl = Op.getDebugLoc(); 214193323Sed SDValue Cond = DAG.getNode(ISD::SETCC, dl, MVT::i32, Op.getOperand(2), 215193323Sed Op.getOperand(3), Op.getOperand(4)); 216193323Sed return DAG.getNode(ISD::SELECT, dl, MVT::i32, Cond, Op.getOperand(0), 217193323Sed Op.getOperand(1)); 218193323Sed} 219193323Sed 220193323SedSDValue XCoreTargetLowering:: 221207618SrdivackygetGlobalAddressWrapper(SDValue GA, const GlobalValue *GV, 222207618Srdivacky SelectionDAG &DAG) const 223193323Sed{ 224193323Sed // FIXME there is no actual debug info here 225193323Sed DebugLoc dl = GA.getDebugLoc(); 226193323Sed if (isa<Function>(GV)) { 227193323Sed return DAG.getNode(XCoreISD::PCRelativeWrapper, dl, MVT::i32, GA); 228193323Sed } 229198090Srdivacky const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV); 230198090Srdivacky if (!GVar) { 231198090Srdivacky // If GV is an alias then use the aliasee to determine constness 232198090Srdivacky if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV)) 233198090Srdivacky GVar = dyn_cast_or_null<GlobalVariable>(GA->resolveAliasedGlobal()); 234198090Srdivacky } 235198090Srdivacky bool isConst = GVar && GVar->isConstant(); 236198090Srdivacky if (isConst) { 237198090Srdivacky return DAG.getNode(XCoreISD::CPRelativeWrapper, dl, MVT::i32, GA); 238198090Srdivacky } 239193323Sed return DAG.getNode(XCoreISD::DPRelativeWrapper, dl, MVT::i32, GA); 240193323Sed} 241193323Sed 242193323SedSDValue XCoreTargetLowering:: 243207618SrdivackyLowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const 244193323Sed{ 245207618Srdivacky const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); 246210299Sed SDValue GA = DAG.getTargetGlobalAddress(GV, Op.getDebugLoc(), MVT::i32); 247193323Sed return getGlobalAddressWrapper(GA, GV, DAG); 248193323Sed} 249193323Sed 250193323Sedstatic inline SDValue BuildGetId(SelectionDAG &DAG, DebugLoc dl) { 251193323Sed return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::i32, 252193323Sed DAG.getConstant(Intrinsic::xcore_getid, MVT::i32)); 253193323Sed} 254193323Sed 255193323Sedstatic inline bool isZeroLengthArray(const Type *Ty) { 256193323Sed const ArrayType *AT = dyn_cast_or_null<ArrayType>(Ty); 257193323Sed return AT && (AT->getNumElements() == 0); 258193323Sed} 259193323Sed 260193323SedSDValue XCoreTargetLowering:: 261207618SrdivackyLowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const 262193323Sed{ 263193323Sed // FIXME there isn't really debug info here 264193323Sed DebugLoc dl = Op.getDebugLoc(); 265193323Sed // transform to label + getid() * size 266207618Srdivacky const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); 267210299Sed SDValue GA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32); 268193323Sed const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV); 269193323Sed if (!GVar) { 270193323Sed // If GV is an alias then use the aliasee to determine size 271193323Sed if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV)) 272193323Sed GVar = dyn_cast_or_null<GlobalVariable>(GA->resolveAliasedGlobal()); 273193323Sed } 274193323Sed if (! GVar) { 275198090Srdivacky llvm_unreachable("Thread local object not a GlobalVariable?"); 276193323Sed return SDValue(); 277193323Sed } 278193323Sed const Type *Ty = cast<PointerType>(GV->getType())->getElementType(); 279193323Sed if (!Ty->isSized() || isZeroLengthArray(Ty)) { 280198090Srdivacky#ifndef NDEBUG 281198090Srdivacky errs() << "Size of thread local object " << GVar->getName() 282198090Srdivacky << " is unknown\n"; 283198090Srdivacky#endif 284198090Srdivacky llvm_unreachable(0); 285193323Sed } 286193323Sed SDValue base = getGlobalAddressWrapper(GA, GV, DAG); 287193323Sed const TargetData *TD = TM.getTargetData(); 288193323Sed unsigned Size = TD->getTypeAllocSize(Ty); 289193323Sed SDValue offset = DAG.getNode(ISD::MUL, dl, MVT::i32, BuildGetId(DAG, dl), 290193323Sed DAG.getConstant(Size, MVT::i32)); 291193323Sed return DAG.getNode(ISD::ADD, dl, MVT::i32, base, offset); 292193323Sed} 293193323Sed 294193323SedSDValue XCoreTargetLowering:: 295207618SrdivackyLowerBlockAddress(SDValue Op, SelectionDAG &DAG) const 296199511Srdivacky{ 297199511Srdivacky DebugLoc DL = Op.getDebugLoc(); 298199511Srdivacky 299207618Srdivacky const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress(); 300199989Srdivacky SDValue Result = DAG.getBlockAddress(BA, getPointerTy(), /*isTarget=*/true); 301199511Srdivacky 302199511Srdivacky return DAG.getNode(XCoreISD::PCRelativeWrapper, DL, getPointerTy(), Result); 303199511Srdivacky} 304199511Srdivacky 305199511SrdivackySDValue XCoreTargetLowering:: 306207618SrdivackyLowerConstantPool(SDValue Op, SelectionDAG &DAG) const 307193323Sed{ 308193323Sed ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op); 309193323Sed // FIXME there isn't really debug info here 310193323Sed DebugLoc dl = CP->getDebugLoc(); 311198090Srdivacky EVT PtrVT = Op.getValueType(); 312198090Srdivacky SDValue Res; 313198090Srdivacky if (CP->isMachineConstantPoolEntry()) { 314198090Srdivacky Res = DAG.getTargetConstantPool(CP->getMachineCPVal(), PtrVT, 315198090Srdivacky CP->getAlignment()); 316193323Sed } else { 317198090Srdivacky Res = DAG.getTargetConstantPool(CP->getConstVal(), PtrVT, 318198090Srdivacky CP->getAlignment()); 319193323Sed } 320198090Srdivacky return DAG.getNode(XCoreISD::CPRelativeWrapper, dl, MVT::i32, Res); 321193323Sed} 322193323Sed 323205218Srdivackyunsigned XCoreTargetLowering::getJumpTableEncoding() const { 324205218Srdivacky return MachineJumpTableInfo::EK_Inline; 325205218Srdivacky} 326205218Srdivacky 327193323SedSDValue XCoreTargetLowering:: 328207618SrdivackyLowerBR_JT(SDValue Op, SelectionDAG &DAG) const 329193323Sed{ 330204642Srdivacky SDValue Chain = Op.getOperand(0); 331204642Srdivacky SDValue Table = Op.getOperand(1); 332204642Srdivacky SDValue Index = Op.getOperand(2); 333193323Sed DebugLoc dl = Op.getDebugLoc(); 334204642Srdivacky JumpTableSDNode *JT = cast<JumpTableSDNode>(Table); 335204642Srdivacky unsigned JTI = JT->getIndex(); 336204642Srdivacky MachineFunction &MF = DAG.getMachineFunction(); 337204642Srdivacky const MachineJumpTableInfo *MJTI = MF.getJumpTableInfo(); 338204642Srdivacky SDValue TargetJT = DAG.getTargetJumpTable(JT->getIndex(), MVT::i32); 339204642Srdivacky 340204642Srdivacky unsigned NumEntries = MJTI->getJumpTables()[JTI].MBBs.size(); 341204642Srdivacky if (NumEntries <= 32) { 342204642Srdivacky return DAG.getNode(XCoreISD::BR_JT, dl, MVT::Other, Chain, TargetJT, Index); 343204642Srdivacky } 344204642Srdivacky assert((NumEntries >> 31) == 0); 345204642Srdivacky SDValue ScaledIndex = DAG.getNode(ISD::SHL, dl, MVT::i32, Index, 346204642Srdivacky DAG.getConstant(1, MVT::i32)); 347204642Srdivacky return DAG.getNode(XCoreISD::BR_JT32, dl, MVT::Other, Chain, TargetJT, 348204642Srdivacky ScaledIndex); 349193323Sed} 350193323Sed 351198090Srdivackystatic bool 352198090SrdivackyIsWordAlignedBasePlusConstantOffset(SDValue Addr, SDValue &AlignedBase, 353198090Srdivacky int64_t &Offset) 354198090Srdivacky{ 355198090Srdivacky if (Addr.getOpcode() != ISD::ADD) { 356198090Srdivacky return false; 357198090Srdivacky } 358198090Srdivacky ConstantSDNode *CN = 0; 359198090Srdivacky if (!(CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))) { 360198090Srdivacky return false; 361198090Srdivacky } 362198090Srdivacky int64_t off = CN->getSExtValue(); 363198090Srdivacky const SDValue &Base = Addr.getOperand(0); 364198090Srdivacky const SDValue *Root = &Base; 365198090Srdivacky if (Base.getOpcode() == ISD::ADD && 366198090Srdivacky Base.getOperand(1).getOpcode() == ISD::SHL) { 367198090Srdivacky ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Base.getOperand(1) 368198090Srdivacky .getOperand(1)); 369198090Srdivacky if (CN && (CN->getSExtValue() >= 2)) { 370198090Srdivacky Root = &Base.getOperand(0); 371198090Srdivacky } 372198090Srdivacky } 373198090Srdivacky if (isa<FrameIndexSDNode>(*Root)) { 374198090Srdivacky // All frame indicies are word aligned 375198090Srdivacky AlignedBase = Base; 376198090Srdivacky Offset = off; 377198090Srdivacky return true; 378198090Srdivacky } 379198090Srdivacky if (Root->getOpcode() == XCoreISD::DPRelativeWrapper || 380198090Srdivacky Root->getOpcode() == XCoreISD::CPRelativeWrapper) { 381198090Srdivacky // All dp / cp relative addresses are word aligned 382198090Srdivacky AlignedBase = Base; 383198090Srdivacky Offset = off; 384198090Srdivacky return true; 385198090Srdivacky } 386198090Srdivacky return false; 387198090Srdivacky} 388198090Srdivacky 389193323SedSDValue XCoreTargetLowering:: 390218893SdimLowerLOAD(SDValue Op, SelectionDAG &DAG) const { 391198090Srdivacky LoadSDNode *LD = cast<LoadSDNode>(Op); 392198090Srdivacky assert(LD->getExtensionType() == ISD::NON_EXTLOAD && 393198090Srdivacky "Unexpected extension type"); 394198090Srdivacky assert(LD->getMemoryVT() == MVT::i32 && "Unexpected load EVT"); 395218893Sdim if (allowsUnalignedMemoryAccesses(LD->getMemoryVT())) 396198090Srdivacky return SDValue(); 397218893Sdim 398198090Srdivacky unsigned ABIAlignment = getTargetData()-> 399198090Srdivacky getABITypeAlignment(LD->getMemoryVT().getTypeForEVT(*DAG.getContext())); 400198090Srdivacky // Leave aligned load alone. 401218893Sdim if (LD->getAlignment() >= ABIAlignment) 402198090Srdivacky return SDValue(); 403218893Sdim 404198090Srdivacky SDValue Chain = LD->getChain(); 405198090Srdivacky SDValue BasePtr = LD->getBasePtr(); 406218893Sdim DebugLoc DL = Op.getDebugLoc(); 407219077Sdim 408198090Srdivacky SDValue Base; 409198090Srdivacky int64_t Offset; 410198090Srdivacky if (!LD->isVolatile() && 411198090Srdivacky IsWordAlignedBasePlusConstantOffset(BasePtr, Base, Offset)) { 412198090Srdivacky if (Offset % 4 == 0) { 413198090Srdivacky // We've managed to infer better alignment information than the load 414198090Srdivacky // already has. Use an aligned load. 415203954Srdivacky // 416218893Sdim return DAG.getLoad(getPointerTy(), DL, Chain, BasePtr, 417218893Sdim MachinePointerInfo(), 418203954Srdivacky false, false, 0); 419198090Srdivacky } 420198090Srdivacky // Lower to 421198090Srdivacky // ldw low, base[offset >> 2] 422198090Srdivacky // ldw high, base[(offset >> 2) + 1] 423198090Srdivacky // shr low_shifted, low, (offset & 0x3) * 8 424198090Srdivacky // shl high_shifted, high, 32 - (offset & 0x3) * 8 425198090Srdivacky // or result, low_shifted, high_shifted 426198090Srdivacky SDValue LowOffset = DAG.getConstant(Offset & ~0x3, MVT::i32); 427198090Srdivacky SDValue HighOffset = DAG.getConstant((Offset & ~0x3) + 4, MVT::i32); 428198090Srdivacky SDValue LowShift = DAG.getConstant((Offset & 0x3) * 8, MVT::i32); 429198090Srdivacky SDValue HighShift = DAG.getConstant(32 - (Offset & 0x3) * 8, MVT::i32); 430219077Sdim 431218893Sdim SDValue LowAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, Base, LowOffset); 432218893Sdim SDValue HighAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, Base, HighOffset); 433219077Sdim 434218893Sdim SDValue Low = DAG.getLoad(getPointerTy(), DL, Chain, 435218893Sdim LowAddr, MachinePointerInfo(), false, false, 0); 436218893Sdim SDValue High = DAG.getLoad(getPointerTy(), DL, Chain, 437218893Sdim HighAddr, MachinePointerInfo(), false, false, 0); 438218893Sdim SDValue LowShifted = DAG.getNode(ISD::SRL, DL, MVT::i32, Low, LowShift); 439218893Sdim SDValue HighShifted = DAG.getNode(ISD::SHL, DL, MVT::i32, High, HighShift); 440218893Sdim SDValue Result = DAG.getNode(ISD::OR, DL, MVT::i32, LowShifted, HighShifted); 441218893Sdim Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Low.getValue(1), 442198090Srdivacky High.getValue(1)); 443198090Srdivacky SDValue Ops[] = { Result, Chain }; 444218893Sdim return DAG.getMergeValues(Ops, 2, DL); 445198090Srdivacky } 446219077Sdim 447198090Srdivacky if (LD->getAlignment() == 2) { 448218893Sdim SDValue Low = DAG.getExtLoad(ISD::ZEXTLOAD, DL, MVT::i32, Chain, 449218893Sdim BasePtr, LD->getPointerInfo(), MVT::i16, 450203954Srdivacky LD->isVolatile(), LD->isNonTemporal(), 2); 451218893Sdim SDValue HighAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, BasePtr, 452198090Srdivacky DAG.getConstant(2, MVT::i32)); 453218893Sdim SDValue High = DAG.getExtLoad(ISD::EXTLOAD, DL, MVT::i32, Chain, 454218893Sdim HighAddr, 455218893Sdim LD->getPointerInfo().getWithOffset(2), 456203954Srdivacky MVT::i16, LD->isVolatile(), 457203954Srdivacky LD->isNonTemporal(), 2); 458218893Sdim SDValue HighShifted = DAG.getNode(ISD::SHL, DL, MVT::i32, High, 459198090Srdivacky DAG.getConstant(16, MVT::i32)); 460218893Sdim SDValue Result = DAG.getNode(ISD::OR, DL, MVT::i32, Low, HighShifted); 461218893Sdim Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Low.getValue(1), 462198090Srdivacky High.getValue(1)); 463198090Srdivacky SDValue Ops[] = { Result, Chain }; 464218893Sdim return DAG.getMergeValues(Ops, 2, DL); 465198090Srdivacky } 466219077Sdim 467198090Srdivacky // Lower to a call to __misaligned_load(BasePtr). 468198090Srdivacky const Type *IntPtrTy = getTargetData()->getIntPtrType(*DAG.getContext()); 469198090Srdivacky TargetLowering::ArgListTy Args; 470198090Srdivacky TargetLowering::ArgListEntry Entry; 471219077Sdim 472198090Srdivacky Entry.Ty = IntPtrTy; 473198090Srdivacky Entry.Node = BasePtr; 474198090Srdivacky Args.push_back(Entry); 475219077Sdim 476198090Srdivacky std::pair<SDValue, SDValue> CallResult = 477198090Srdivacky LowerCallTo(Chain, IntPtrTy, false, false, 478198090Srdivacky false, false, 0, CallingConv::C, false, 479198090Srdivacky /*isReturnValueUsed=*/true, 480198090Srdivacky DAG.getExternalSymbol("__misaligned_load", getPointerTy()), 481218893Sdim Args, DAG, DL); 482198090Srdivacky 483198090Srdivacky SDValue Ops[] = 484198090Srdivacky { CallResult.first, CallResult.second }; 485198090Srdivacky 486218893Sdim return DAG.getMergeValues(Ops, 2, DL); 487198090Srdivacky} 488198090Srdivacky 489198090SrdivackySDValue XCoreTargetLowering:: 490207618SrdivackyLowerSTORE(SDValue Op, SelectionDAG &DAG) const 491198090Srdivacky{ 492198090Srdivacky StoreSDNode *ST = cast<StoreSDNode>(Op); 493198090Srdivacky assert(!ST->isTruncatingStore() && "Unexpected store type"); 494198090Srdivacky assert(ST->getMemoryVT() == MVT::i32 && "Unexpected store EVT"); 495198090Srdivacky if (allowsUnalignedMemoryAccesses(ST->getMemoryVT())) { 496198090Srdivacky return SDValue(); 497198090Srdivacky } 498198090Srdivacky unsigned ABIAlignment = getTargetData()-> 499198090Srdivacky getABITypeAlignment(ST->getMemoryVT().getTypeForEVT(*DAG.getContext())); 500198090Srdivacky // Leave aligned store alone. 501198090Srdivacky if (ST->getAlignment() >= ABIAlignment) { 502198090Srdivacky return SDValue(); 503198090Srdivacky } 504198090Srdivacky SDValue Chain = ST->getChain(); 505198090Srdivacky SDValue BasePtr = ST->getBasePtr(); 506198090Srdivacky SDValue Value = ST->getValue(); 507198090Srdivacky DebugLoc dl = Op.getDebugLoc(); 508219077Sdim 509198090Srdivacky if (ST->getAlignment() == 2) { 510198090Srdivacky SDValue Low = Value; 511198090Srdivacky SDValue High = DAG.getNode(ISD::SRL, dl, MVT::i32, Value, 512198090Srdivacky DAG.getConstant(16, MVT::i32)); 513198090Srdivacky SDValue StoreLow = DAG.getTruncStore(Chain, dl, Low, BasePtr, 514218893Sdim ST->getPointerInfo(), MVT::i16, 515203954Srdivacky ST->isVolatile(), ST->isNonTemporal(), 516203954Srdivacky 2); 517198090Srdivacky SDValue HighAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, BasePtr, 518198090Srdivacky DAG.getConstant(2, MVT::i32)); 519198090Srdivacky SDValue StoreHigh = DAG.getTruncStore(Chain, dl, High, HighAddr, 520218893Sdim ST->getPointerInfo().getWithOffset(2), 521203954Srdivacky MVT::i16, ST->isVolatile(), 522203954Srdivacky ST->isNonTemporal(), 2); 523198090Srdivacky return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, StoreLow, StoreHigh); 524198090Srdivacky } 525219077Sdim 526198090Srdivacky // Lower to a call to __misaligned_store(BasePtr, Value). 527198090Srdivacky const Type *IntPtrTy = getTargetData()->getIntPtrType(*DAG.getContext()); 528198090Srdivacky TargetLowering::ArgListTy Args; 529198090Srdivacky TargetLowering::ArgListEntry Entry; 530219077Sdim 531198090Srdivacky Entry.Ty = IntPtrTy; 532198090Srdivacky Entry.Node = BasePtr; 533198090Srdivacky Args.push_back(Entry); 534219077Sdim 535198090Srdivacky Entry.Node = Value; 536198090Srdivacky Args.push_back(Entry); 537219077Sdim 538198090Srdivacky std::pair<SDValue, SDValue> CallResult = 539198090Srdivacky LowerCallTo(Chain, Type::getVoidTy(*DAG.getContext()), false, false, 540198090Srdivacky false, false, 0, CallingConv::C, false, 541198090Srdivacky /*isReturnValueUsed=*/true, 542198090Srdivacky DAG.getExternalSymbol("__misaligned_store", getPointerTy()), 543204642Srdivacky Args, DAG, dl); 544198090Srdivacky 545198090Srdivacky return CallResult.second; 546198090Srdivacky} 547198090Srdivacky 548198090SrdivackySDValue XCoreTargetLowering:: 549207618SrdivackyLowerSMUL_LOHI(SDValue Op, SelectionDAG &DAG) const 550204961Srdivacky{ 551204961Srdivacky assert(Op.getValueType() == MVT::i32 && Op.getOpcode() == ISD::SMUL_LOHI && 552204961Srdivacky "Unexpected operand to lower!"); 553204961Srdivacky DebugLoc dl = Op.getDebugLoc(); 554204961Srdivacky SDValue LHS = Op.getOperand(0); 555204961Srdivacky SDValue RHS = Op.getOperand(1); 556204961Srdivacky SDValue Zero = DAG.getConstant(0, MVT::i32); 557204961Srdivacky SDValue Hi = DAG.getNode(XCoreISD::MACCS, dl, 558204961Srdivacky DAG.getVTList(MVT::i32, MVT::i32), Zero, Zero, 559204961Srdivacky LHS, RHS); 560204961Srdivacky SDValue Lo(Hi.getNode(), 1); 561204961Srdivacky SDValue Ops[] = { Lo, Hi }; 562204961Srdivacky return DAG.getMergeValues(Ops, 2, dl); 563204961Srdivacky} 564204961Srdivacky 565204961SrdivackySDValue XCoreTargetLowering:: 566207618SrdivackyLowerUMUL_LOHI(SDValue Op, SelectionDAG &DAG) const 567204961Srdivacky{ 568204961Srdivacky assert(Op.getValueType() == MVT::i32 && Op.getOpcode() == ISD::UMUL_LOHI && 569204961Srdivacky "Unexpected operand to lower!"); 570204961Srdivacky DebugLoc dl = Op.getDebugLoc(); 571204961Srdivacky SDValue LHS = Op.getOperand(0); 572204961Srdivacky SDValue RHS = Op.getOperand(1); 573204961Srdivacky SDValue Zero = DAG.getConstant(0, MVT::i32); 574204961Srdivacky SDValue Hi = DAG.getNode(XCoreISD::LMUL, dl, 575204961Srdivacky DAG.getVTList(MVT::i32, MVT::i32), LHS, RHS, 576204961Srdivacky Zero, Zero); 577204961Srdivacky SDValue Lo(Hi.getNode(), 1); 578204961Srdivacky SDValue Ops[] = { Lo, Hi }; 579204961Srdivacky return DAG.getMergeValues(Ops, 2, dl); 580204961Srdivacky} 581204961Srdivacky 582204961Srdivacky/// isADDADDMUL - Return whether Op is in a form that is equivalent to 583204961Srdivacky/// add(add(mul(x,y),a),b). If requireIntermediatesHaveOneUse is true then 584204961Srdivacky/// each intermediate result in the calculation must also have a single use. 585204961Srdivacky/// If the Op is in the correct form the constituent parts are written to Mul0, 586204961Srdivacky/// Mul1, Addend0 and Addend1. 587204961Srdivackystatic bool 588204961SrdivackyisADDADDMUL(SDValue Op, SDValue &Mul0, SDValue &Mul1, SDValue &Addend0, 589204961Srdivacky SDValue &Addend1, bool requireIntermediatesHaveOneUse) 590204961Srdivacky{ 591204961Srdivacky if (Op.getOpcode() != ISD::ADD) 592204961Srdivacky return false; 593204961Srdivacky SDValue N0 = Op.getOperand(0); 594204961Srdivacky SDValue N1 = Op.getOperand(1); 595204961Srdivacky SDValue AddOp; 596204961Srdivacky SDValue OtherOp; 597204961Srdivacky if (N0.getOpcode() == ISD::ADD) { 598204961Srdivacky AddOp = N0; 599204961Srdivacky OtherOp = N1; 600204961Srdivacky } else if (N1.getOpcode() == ISD::ADD) { 601204961Srdivacky AddOp = N1; 602204961Srdivacky OtherOp = N0; 603204961Srdivacky } else { 604204961Srdivacky return false; 605204961Srdivacky } 606204961Srdivacky if (requireIntermediatesHaveOneUse && !AddOp.hasOneUse()) 607204961Srdivacky return false; 608204961Srdivacky if (OtherOp.getOpcode() == ISD::MUL) { 609204961Srdivacky // add(add(a,b),mul(x,y)) 610204961Srdivacky if (requireIntermediatesHaveOneUse && !OtherOp.hasOneUse()) 611204961Srdivacky return false; 612204961Srdivacky Mul0 = OtherOp.getOperand(0); 613204961Srdivacky Mul1 = OtherOp.getOperand(1); 614204961Srdivacky Addend0 = AddOp.getOperand(0); 615204961Srdivacky Addend1 = AddOp.getOperand(1); 616204961Srdivacky return true; 617204961Srdivacky } 618204961Srdivacky if (AddOp.getOperand(0).getOpcode() == ISD::MUL) { 619204961Srdivacky // add(add(mul(x,y),a),b) 620204961Srdivacky if (requireIntermediatesHaveOneUse && !AddOp.getOperand(0).hasOneUse()) 621204961Srdivacky return false; 622204961Srdivacky Mul0 = AddOp.getOperand(0).getOperand(0); 623204961Srdivacky Mul1 = AddOp.getOperand(0).getOperand(1); 624204961Srdivacky Addend0 = AddOp.getOperand(1); 625204961Srdivacky Addend1 = OtherOp; 626204961Srdivacky return true; 627204961Srdivacky } 628204961Srdivacky if (AddOp.getOperand(1).getOpcode() == ISD::MUL) { 629204961Srdivacky // add(add(a,mul(x,y)),b) 630204961Srdivacky if (requireIntermediatesHaveOneUse && !AddOp.getOperand(1).hasOneUse()) 631204961Srdivacky return false; 632204961Srdivacky Mul0 = AddOp.getOperand(1).getOperand(0); 633204961Srdivacky Mul1 = AddOp.getOperand(1).getOperand(1); 634204961Srdivacky Addend0 = AddOp.getOperand(0); 635204961Srdivacky Addend1 = OtherOp; 636204961Srdivacky return true; 637204961Srdivacky } 638204961Srdivacky return false; 639204961Srdivacky} 640204961Srdivacky 641204961SrdivackySDValue XCoreTargetLowering:: 642207618SrdivackyTryExpandADDWithMul(SDNode *N, SelectionDAG &DAG) const 643204961Srdivacky{ 644204961Srdivacky SDValue Mul; 645204961Srdivacky SDValue Other; 646204961Srdivacky if (N->getOperand(0).getOpcode() == ISD::MUL) { 647204961Srdivacky Mul = N->getOperand(0); 648204961Srdivacky Other = N->getOperand(1); 649204961Srdivacky } else if (N->getOperand(1).getOpcode() == ISD::MUL) { 650204961Srdivacky Mul = N->getOperand(1); 651204961Srdivacky Other = N->getOperand(0); 652204961Srdivacky } else { 653204961Srdivacky return SDValue(); 654204961Srdivacky } 655204961Srdivacky DebugLoc dl = N->getDebugLoc(); 656204961Srdivacky SDValue LL, RL, AddendL, AddendH; 657204961Srdivacky LL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 658204961Srdivacky Mul.getOperand(0), DAG.getConstant(0, MVT::i32)); 659204961Srdivacky RL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 660204961Srdivacky Mul.getOperand(1), DAG.getConstant(0, MVT::i32)); 661204961Srdivacky AddendL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 662204961Srdivacky Other, DAG.getConstant(0, MVT::i32)); 663204961Srdivacky AddendH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 664204961Srdivacky Other, DAG.getConstant(1, MVT::i32)); 665204961Srdivacky APInt HighMask = APInt::getHighBitsSet(64, 32); 666204961Srdivacky unsigned LHSSB = DAG.ComputeNumSignBits(Mul.getOperand(0)); 667204961Srdivacky unsigned RHSSB = DAG.ComputeNumSignBits(Mul.getOperand(1)); 668204961Srdivacky if (DAG.MaskedValueIsZero(Mul.getOperand(0), HighMask) && 669204961Srdivacky DAG.MaskedValueIsZero(Mul.getOperand(1), HighMask)) { 670204961Srdivacky // The inputs are both zero-extended. 671204961Srdivacky SDValue Hi = DAG.getNode(XCoreISD::MACCU, dl, 672204961Srdivacky DAG.getVTList(MVT::i32, MVT::i32), AddendH, 673204961Srdivacky AddendL, LL, RL); 674204961Srdivacky SDValue Lo(Hi.getNode(), 1); 675204961Srdivacky return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi); 676204961Srdivacky } 677204961Srdivacky if (LHSSB > 32 && RHSSB > 32) { 678204961Srdivacky // The inputs are both sign-extended. 679204961Srdivacky SDValue Hi = DAG.getNode(XCoreISD::MACCS, dl, 680204961Srdivacky DAG.getVTList(MVT::i32, MVT::i32), AddendH, 681204961Srdivacky AddendL, LL, RL); 682204961Srdivacky SDValue Lo(Hi.getNode(), 1); 683204961Srdivacky return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi); 684204961Srdivacky } 685204961Srdivacky SDValue LH, RH; 686204961Srdivacky LH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 687204961Srdivacky Mul.getOperand(0), DAG.getConstant(1, MVT::i32)); 688204961Srdivacky RH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 689204961Srdivacky Mul.getOperand(1), DAG.getConstant(1, MVT::i32)); 690204961Srdivacky SDValue Hi = DAG.getNode(XCoreISD::MACCU, dl, 691204961Srdivacky DAG.getVTList(MVT::i32, MVT::i32), AddendH, 692204961Srdivacky AddendL, LL, RL); 693204961Srdivacky SDValue Lo(Hi.getNode(), 1); 694204961Srdivacky RH = DAG.getNode(ISD::MUL, dl, MVT::i32, LL, RH); 695204961Srdivacky LH = DAG.getNode(ISD::MUL, dl, MVT::i32, LH, RL); 696204961Srdivacky Hi = DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, RH); 697204961Srdivacky Hi = DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, LH); 698204961Srdivacky return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi); 699204961Srdivacky} 700204961Srdivacky 701204961SrdivackySDValue XCoreTargetLowering:: 702207618SrdivackyExpandADDSUB(SDNode *N, SelectionDAG &DAG) const 703193323Sed{ 704193323Sed assert(N->getValueType(0) == MVT::i64 && 705193323Sed (N->getOpcode() == ISD::ADD || N->getOpcode() == ISD::SUB) && 706193323Sed "Unknown operand to lower!"); 707204961Srdivacky 708204961Srdivacky if (N->getOpcode() == ISD::ADD) { 709204961Srdivacky SDValue Result = TryExpandADDWithMul(N, DAG); 710204961Srdivacky if (Result.getNode() != 0) 711204961Srdivacky return Result; 712204961Srdivacky } 713204961Srdivacky 714193323Sed DebugLoc dl = N->getDebugLoc(); 715219077Sdim 716193323Sed // Extract components 717193323Sed SDValue LHSL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 718193323Sed N->getOperand(0), DAG.getConstant(0, MVT::i32)); 719193323Sed SDValue LHSH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 720193323Sed N->getOperand(0), DAG.getConstant(1, MVT::i32)); 721193323Sed SDValue RHSL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 722193323Sed N->getOperand(1), DAG.getConstant(0, MVT::i32)); 723193323Sed SDValue RHSH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 724193323Sed N->getOperand(1), DAG.getConstant(1, MVT::i32)); 725219077Sdim 726193323Sed // Expand 727193323Sed unsigned Opcode = (N->getOpcode() == ISD::ADD) ? XCoreISD::LADD : 728193323Sed XCoreISD::LSUB; 729193323Sed SDValue Zero = DAG.getConstant(0, MVT::i32); 730193323Sed SDValue Carry = DAG.getNode(Opcode, dl, DAG.getVTList(MVT::i32, MVT::i32), 731193323Sed LHSL, RHSL, Zero); 732193323Sed SDValue Lo(Carry.getNode(), 1); 733219077Sdim 734193323Sed SDValue Ignored = DAG.getNode(Opcode, dl, DAG.getVTList(MVT::i32, MVT::i32), 735193323Sed LHSH, RHSH, Carry); 736193323Sed SDValue Hi(Ignored.getNode(), 1); 737193323Sed // Merge the pieces 738193323Sed return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi); 739193323Sed} 740193323Sed 741193323SedSDValue XCoreTargetLowering:: 742207618SrdivackyLowerVAARG(SDValue Op, SelectionDAG &DAG) const 743193323Sed{ 744198090Srdivacky llvm_unreachable("unimplemented"); 745193323Sed // FIX Arguments passed by reference need a extra dereference. 746193323Sed SDNode *Node = Op.getNode(); 747193323Sed DebugLoc dl = Node->getDebugLoc(); 748193323Sed const Value *V = cast<SrcValueSDNode>(Node->getOperand(2))->getValue(); 749198090Srdivacky EVT VT = Node->getValueType(0); 750193323Sed SDValue VAList = DAG.getLoad(getPointerTy(), dl, Node->getOperand(0), 751218893Sdim Node->getOperand(1), MachinePointerInfo(V), 752218893Sdim false, false, 0); 753193323Sed // Increment the pointer, VAList, to the next vararg 754219077Sdim SDValue Tmp3 = DAG.getNode(ISD::ADD, dl, getPointerTy(), VAList, 755219077Sdim DAG.getConstant(VT.getSizeInBits(), 756193323Sed getPointerTy())); 757193323Sed // Store the incremented VAList to the legalized pointer 758218893Sdim Tmp3 = DAG.getStore(VAList.getValue(1), dl, Tmp3, Node->getOperand(1), 759218893Sdim MachinePointerInfo(V), false, false, 0); 760193323Sed // Load the actual argument out of the pointer VAList 761218893Sdim return DAG.getLoad(VT, dl, Tmp3, VAList, MachinePointerInfo(), 762218893Sdim false, false, 0); 763193323Sed} 764193323Sed 765193323SedSDValue XCoreTargetLowering:: 766207618SrdivackyLowerVASTART(SDValue Op, SelectionDAG &DAG) const 767193323Sed{ 768193323Sed DebugLoc dl = Op.getDebugLoc(); 769193323Sed // vastart stores the address of the VarArgsFrameIndex slot into the 770193323Sed // memory location argument 771193323Sed MachineFunction &MF = DAG.getMachineFunction(); 772193323Sed XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); 773193323Sed SDValue Addr = DAG.getFrameIndex(XFI->getVarArgsFrameIndex(), MVT::i32); 774219077Sdim return DAG.getStore(Op.getOperand(0), dl, Addr, Op.getOperand(1), 775218893Sdim MachinePointerInfo(), false, false, 0); 776193323Sed} 777193323Sed 778207618SrdivackySDValue XCoreTargetLowering::LowerFRAMEADDR(SDValue Op, 779207618Srdivacky SelectionDAG &DAG) const { 780193323Sed DebugLoc dl = Op.getDebugLoc(); 781219077Sdim // Depths > 0 not supported yet! 782193323Sed if (cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() > 0) 783193323Sed return SDValue(); 784219077Sdim 785193323Sed MachineFunction &MF = DAG.getMachineFunction(); 786193323Sed const TargetRegisterInfo *RegInfo = getTargetMachine().getRegisterInfo(); 787219077Sdim return DAG.getCopyFromReg(DAG.getEntryNode(), dl, 788193323Sed RegInfo->getFrameRegister(MF), MVT::i32); 789193323Sed} 790193323Sed 791218893SdimSDValue XCoreTargetLowering:: 792218893SdimLowerTRAMPOLINE(SDValue Op, SelectionDAG &DAG) const { 793218893Sdim SDValue Chain = Op.getOperand(0); 794218893Sdim SDValue Trmp = Op.getOperand(1); // trampoline 795218893Sdim SDValue FPtr = Op.getOperand(2); // nested function 796218893Sdim SDValue Nest = Op.getOperand(3); // 'nest' parameter value 797218893Sdim 798218893Sdim const Value *TrmpAddr = cast<SrcValueSDNode>(Op.getOperand(4))->getValue(); 799218893Sdim 800218893Sdim // .align 4 801218893Sdim // LDAPF_u10 r11, nest 802218893Sdim // LDW_2rus r11, r11[0] 803218893Sdim // STWSP_ru6 r11, sp[0] 804218893Sdim // LDAPF_u10 r11, fptr 805218893Sdim // LDW_2rus r11, r11[0] 806218893Sdim // BAU_1r r11 807218893Sdim // nest: 808218893Sdim // .word nest 809218893Sdim // fptr: 810218893Sdim // .word fptr 811218893Sdim SDValue OutChains[5]; 812218893Sdim 813218893Sdim SDValue Addr = Trmp; 814218893Sdim 815218893Sdim DebugLoc dl = Op.getDebugLoc(); 816218893Sdim OutChains[0] = DAG.getStore(Chain, dl, DAG.getConstant(0x0a3cd805, MVT::i32), 817218893Sdim Addr, MachinePointerInfo(TrmpAddr), false, false, 818218893Sdim 0); 819218893Sdim 820218893Sdim Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp, 821218893Sdim DAG.getConstant(4, MVT::i32)); 822218893Sdim OutChains[1] = DAG.getStore(Chain, dl, DAG.getConstant(0xd80456c0, MVT::i32), 823218893Sdim Addr, MachinePointerInfo(TrmpAddr, 4), false, 824218893Sdim false, 0); 825218893Sdim 826218893Sdim Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp, 827218893Sdim DAG.getConstant(8, MVT::i32)); 828218893Sdim OutChains[2] = DAG.getStore(Chain, dl, DAG.getConstant(0x27fb0a3c, MVT::i32), 829218893Sdim Addr, MachinePointerInfo(TrmpAddr, 8), false, 830218893Sdim false, 0); 831218893Sdim 832218893Sdim Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp, 833218893Sdim DAG.getConstant(12, MVT::i32)); 834218893Sdim OutChains[3] = DAG.getStore(Chain, dl, Nest, Addr, 835218893Sdim MachinePointerInfo(TrmpAddr, 12), false, false, 836218893Sdim 0); 837218893Sdim 838218893Sdim Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp, 839218893Sdim DAG.getConstant(16, MVT::i32)); 840218893Sdim OutChains[4] = DAG.getStore(Chain, dl, FPtr, Addr, 841218893Sdim MachinePointerInfo(TrmpAddr, 16), false, false, 842218893Sdim 0); 843218893Sdim 844218893Sdim SDValue Ops[] = 845218893Sdim { Trmp, DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains, 5) }; 846218893Sdim return DAG.getMergeValues(Ops, 2, dl); 847218893Sdim} 848218893Sdim 849193323Sed//===----------------------------------------------------------------------===// 850193323Sed// Calling Convention Implementation 851193323Sed//===----------------------------------------------------------------------===// 852193323Sed 853193323Sed#include "XCoreGenCallingConv.inc" 854193323Sed 855193323Sed//===----------------------------------------------------------------------===// 856198090Srdivacky// Call Calling Convention Implementation 857193323Sed//===----------------------------------------------------------------------===// 858193323Sed 859198090Srdivacky/// XCore call implementation 860198090SrdivackySDValue 861198090SrdivackyXCoreTargetLowering::LowerCall(SDValue Chain, SDValue Callee, 862198090Srdivacky CallingConv::ID CallConv, bool isVarArg, 863203954Srdivacky bool &isTailCall, 864198090Srdivacky const SmallVectorImpl<ISD::OutputArg> &Outs, 865210299Sed const SmallVectorImpl<SDValue> &OutVals, 866198090Srdivacky const SmallVectorImpl<ISD::InputArg> &Ins, 867198090Srdivacky DebugLoc dl, SelectionDAG &DAG, 868207618Srdivacky SmallVectorImpl<SDValue> &InVals) const { 869203954Srdivacky // XCore target does not yet support tail call optimization. 870203954Srdivacky isTailCall = false; 871198090Srdivacky 872193323Sed // For now, only CallingConv::C implemented 873198090Srdivacky switch (CallConv) 874193323Sed { 875193323Sed default: 876198090Srdivacky llvm_unreachable("Unsupported calling convention"); 877193323Sed case CallingConv::Fast: 878193323Sed case CallingConv::C: 879198090Srdivacky return LowerCCCCallTo(Chain, Callee, CallConv, isVarArg, isTailCall, 880210299Sed Outs, OutVals, Ins, dl, DAG, InVals); 881193323Sed } 882193323Sed} 883193323Sed 884193323Sed/// LowerCCCCallTo - functions arguments are copied from virtual 885193323Sed/// regs to (physical regs)/(stack frame), CALLSEQ_START and 886193323Sed/// CALLSEQ_END are emitted. 887193323Sed/// TODO: isTailCall, sret. 888198090SrdivackySDValue 889198090SrdivackyXCoreTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee, 890198090Srdivacky CallingConv::ID CallConv, bool isVarArg, 891198090Srdivacky bool isTailCall, 892198090Srdivacky const SmallVectorImpl<ISD::OutputArg> &Outs, 893210299Sed const SmallVectorImpl<SDValue> &OutVals, 894198090Srdivacky const SmallVectorImpl<ISD::InputArg> &Ins, 895198090Srdivacky DebugLoc dl, SelectionDAG &DAG, 896207618Srdivacky SmallVectorImpl<SDValue> &InVals) const { 897193323Sed 898193323Sed // Analyze operands of the call, assigning locations to each operand. 899193323Sed SmallVector<CCValAssign, 16> ArgLocs; 900223017Sdim CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), 901223017Sdim getTargetMachine(), ArgLocs, *DAG.getContext()); 902193323Sed 903193323Sed // The ABI dictates there should be one stack slot available to the callee 904193323Sed // on function entry (for saving lr). 905193323Sed CCInfo.AllocateStack(4, 4); 906193323Sed 907198090Srdivacky CCInfo.AnalyzeCallOperands(Outs, CC_XCore); 908193323Sed 909193323Sed // Get a count of how many bytes are to be pushed on the stack. 910193323Sed unsigned NumBytes = CCInfo.getNextStackOffset(); 911193323Sed 912219077Sdim Chain = DAG.getCALLSEQ_START(Chain,DAG.getConstant(NumBytes, 913193323Sed getPointerTy(), true)); 914193323Sed 915193323Sed SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass; 916193323Sed SmallVector<SDValue, 12> MemOpChains; 917193323Sed 918193323Sed // Walk the register/memloc assignments, inserting copies/loads. 919193323Sed for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 920193323Sed CCValAssign &VA = ArgLocs[i]; 921210299Sed SDValue Arg = OutVals[i]; 922193323Sed 923193323Sed // Promote the value if needed. 924193323Sed switch (VA.getLocInfo()) { 925198090Srdivacky default: llvm_unreachable("Unknown loc info!"); 926193323Sed case CCValAssign::Full: break; 927193323Sed case CCValAssign::SExt: 928193323Sed Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg); 929193323Sed break; 930193323Sed case CCValAssign::ZExt: 931193323Sed Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg); 932193323Sed break; 933193323Sed case CCValAssign::AExt: 934193323Sed Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg); 935193323Sed break; 936193323Sed } 937219077Sdim 938219077Sdim // Arguments that can be passed on register must be kept at 939193323Sed // RegsToPass vector 940193323Sed if (VA.isRegLoc()) { 941193323Sed RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); 942193323Sed } else { 943193323Sed assert(VA.isMemLoc()); 944193323Sed 945193323Sed int Offset = VA.getLocMemOffset(); 946193323Sed 947219077Sdim MemOpChains.push_back(DAG.getNode(XCoreISD::STWSP, dl, MVT::Other, 948193323Sed Chain, Arg, 949193323Sed DAG.getConstant(Offset/4, MVT::i32))); 950193323Sed } 951193323Sed } 952193323Sed 953193323Sed // Transform all store nodes into one single node because 954193323Sed // all store nodes are independent of each other. 955193323Sed if (!MemOpChains.empty()) 956219077Sdim Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, 957193323Sed &MemOpChains[0], MemOpChains.size()); 958193323Sed 959219077Sdim // Build a sequence of copy-to-reg nodes chained together with token 960193323Sed // chain and flag operands which copy the outgoing args into registers. 961221345Sdim // The InFlag in necessary since all emitted instructions must be 962193323Sed // stuck together. 963193323Sed SDValue InFlag; 964193323Sed for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { 965219077Sdim Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, 966193323Sed RegsToPass[i].second, InFlag); 967193323Sed InFlag = Chain.getValue(1); 968193323Sed } 969193323Sed 970193323Sed // If the callee is a GlobalAddress node (quite common, every direct call is) 971193323Sed // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. 972193323Sed // Likewise ExternalSymbol -> TargetExternalSymbol. 973193323Sed if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) 974210299Sed Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32); 975193323Sed else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee)) 976193323Sed Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32); 977193323Sed 978193323Sed // XCoreBranchLink = #chain, #target_address, #opt_in_flags... 979219077Sdim // = Chain, Callee, Reg#1, Reg#2, ... 980193323Sed // 981193323Sed // Returns a chain & a flag for retval copy to use. 982218893Sdim SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); 983193323Sed SmallVector<SDValue, 8> Ops; 984193323Sed Ops.push_back(Chain); 985193323Sed Ops.push_back(Callee); 986193323Sed 987219077Sdim // Add argument registers to the end of the list so that they are 988193323Sed // known live into the call. 989193323Sed for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) 990193323Sed Ops.push_back(DAG.getRegister(RegsToPass[i].first, 991193323Sed RegsToPass[i].second.getValueType())); 992193323Sed 993193323Sed if (InFlag.getNode()) 994193323Sed Ops.push_back(InFlag); 995193323Sed 996193323Sed Chain = DAG.getNode(XCoreISD::BL, dl, NodeTys, &Ops[0], Ops.size()); 997193323Sed InFlag = Chain.getValue(1); 998193323Sed 999193323Sed // Create the CALLSEQ_END node. 1000193323Sed Chain = DAG.getCALLSEQ_END(Chain, 1001193323Sed DAG.getConstant(NumBytes, getPointerTy(), true), 1002193323Sed DAG.getConstant(0, getPointerTy(), true), 1003193323Sed InFlag); 1004193323Sed InFlag = Chain.getValue(1); 1005193323Sed 1006193323Sed // Handle result values, copying them out of physregs into vregs that we 1007193323Sed // return. 1008198090Srdivacky return LowerCallResult(Chain, InFlag, CallConv, isVarArg, 1009198090Srdivacky Ins, dl, DAG, InVals); 1010193323Sed} 1011193323Sed 1012198090Srdivacky/// LowerCallResult - Lower the result values of a call into the 1013198090Srdivacky/// appropriate copies out of appropriate physical registers. 1014198090SrdivackySDValue 1015198090SrdivackyXCoreTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, 1016198090Srdivacky CallingConv::ID CallConv, bool isVarArg, 1017198090Srdivacky const SmallVectorImpl<ISD::InputArg> &Ins, 1018198090Srdivacky DebugLoc dl, SelectionDAG &DAG, 1019207618Srdivacky SmallVectorImpl<SDValue> &InVals) const { 1020193323Sed 1021193323Sed // Assign locations to each value returned by this call. 1022193323Sed SmallVector<CCValAssign, 16> RVLocs; 1023223017Sdim CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), 1024223017Sdim getTargetMachine(), RVLocs, *DAG.getContext()); 1025193323Sed 1026198090Srdivacky CCInfo.AnalyzeCallResult(Ins, RetCC_XCore); 1027193323Sed 1028193323Sed // Copy all of the result registers out of their specified physreg. 1029193323Sed for (unsigned i = 0; i != RVLocs.size(); ++i) { 1030193323Sed Chain = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(), 1031193323Sed RVLocs[i].getValVT(), InFlag).getValue(1); 1032193323Sed InFlag = Chain.getValue(2); 1033198090Srdivacky InVals.push_back(Chain.getValue(0)); 1034193323Sed } 1035193323Sed 1036198090Srdivacky return Chain; 1037193323Sed} 1038193323Sed 1039193323Sed//===----------------------------------------------------------------------===// 1040198090Srdivacky// Formal Arguments Calling Convention Implementation 1041193323Sed//===----------------------------------------------------------------------===// 1042193323Sed 1043198090Srdivacky/// XCore formal arguments implementation 1044198090SrdivackySDValue 1045198090SrdivackyXCoreTargetLowering::LowerFormalArguments(SDValue Chain, 1046198090Srdivacky CallingConv::ID CallConv, 1047198090Srdivacky bool isVarArg, 1048198090Srdivacky const SmallVectorImpl<ISD::InputArg> &Ins, 1049198090Srdivacky DebugLoc dl, 1050198090Srdivacky SelectionDAG &DAG, 1051207618Srdivacky SmallVectorImpl<SDValue> &InVals) 1052207618Srdivacky const { 1053198090Srdivacky switch (CallConv) 1054193323Sed { 1055193323Sed default: 1056198090Srdivacky llvm_unreachable("Unsupported calling convention"); 1057193323Sed case CallingConv::C: 1058193323Sed case CallingConv::Fast: 1059198090Srdivacky return LowerCCCArguments(Chain, CallConv, isVarArg, 1060198090Srdivacky Ins, dl, DAG, InVals); 1061193323Sed } 1062193323Sed} 1063193323Sed 1064193323Sed/// LowerCCCArguments - transform physical registers into 1065193323Sed/// virtual registers and generate load operations for 1066193323Sed/// arguments places on the stack. 1067193323Sed/// TODO: sret 1068198090SrdivackySDValue 1069198090SrdivackyXCoreTargetLowering::LowerCCCArguments(SDValue Chain, 1070198090Srdivacky CallingConv::ID CallConv, 1071198090Srdivacky bool isVarArg, 1072198090Srdivacky const SmallVectorImpl<ISD::InputArg> 1073198090Srdivacky &Ins, 1074198090Srdivacky DebugLoc dl, 1075198090Srdivacky SelectionDAG &DAG, 1076207618Srdivacky SmallVectorImpl<SDValue> &InVals) const { 1077193323Sed MachineFunction &MF = DAG.getMachineFunction(); 1078193323Sed MachineFrameInfo *MFI = MF.getFrameInfo(); 1079193323Sed MachineRegisterInfo &RegInfo = MF.getRegInfo(); 1080193323Sed 1081193323Sed // Assign locations to all of the incoming arguments. 1082193323Sed SmallVector<CCValAssign, 16> ArgLocs; 1083223017Sdim CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), 1084223017Sdim getTargetMachine(), ArgLocs, *DAG.getContext()); 1085193323Sed 1086198090Srdivacky CCInfo.AnalyzeFormalArguments(Ins, CC_XCore); 1087193323Sed 1088218893Sdim unsigned StackSlotSize = XCoreFrameLowering::stackSlotSize(); 1089193323Sed 1090193323Sed unsigned LRSaveSize = StackSlotSize; 1091219077Sdim 1092193323Sed for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 1093193323Sed 1094193323Sed CCValAssign &VA = ArgLocs[i]; 1095219077Sdim 1096193323Sed if (VA.isRegLoc()) { 1097193323Sed // Arguments passed in registers 1098198090Srdivacky EVT RegVT = VA.getLocVT(); 1099198090Srdivacky switch (RegVT.getSimpleVT().SimpleTy) { 1100193323Sed default: 1101198090Srdivacky { 1102198090Srdivacky#ifndef NDEBUG 1103198090Srdivacky errs() << "LowerFormalArguments Unhandled argument type: " 1104198090Srdivacky << RegVT.getSimpleVT().SimpleTy << "\n"; 1105198090Srdivacky#endif 1106198090Srdivacky llvm_unreachable(0); 1107198090Srdivacky } 1108193323Sed case MVT::i32: 1109193323Sed unsigned VReg = RegInfo.createVirtualRegister( 1110193323Sed XCore::GRRegsRegisterClass); 1111193323Sed RegInfo.addLiveIn(VA.getLocReg(), VReg); 1112198090Srdivacky InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT)); 1113193323Sed } 1114193323Sed } else { 1115193323Sed // sanity check 1116193323Sed assert(VA.isMemLoc()); 1117193323Sed // Load the argument to a virtual register 1118193323Sed unsigned ObjSize = VA.getLocVT().getSizeInBits()/8; 1119193323Sed if (ObjSize > StackSlotSize) { 1120198090Srdivacky errs() << "LowerFormalArguments Unhandled argument type: " 1121218893Sdim << EVT(VA.getLocVT()).getEVTString() 1122198090Srdivacky << "\n"; 1123193323Sed } 1124193323Sed // Create the frame index object for this incoming parameter... 1125193323Sed int FI = MFI->CreateFixedObject(ObjSize, 1126199481Srdivacky LRSaveSize + VA.getLocMemOffset(), 1127210299Sed true); 1128193323Sed 1129193323Sed // Create the SelectionDAG nodes corresponding to a load 1130193323Sed //from this parameter 1131193323Sed SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); 1132219077Sdim InVals.push_back(DAG.getLoad(VA.getLocVT(), dl, Chain, FIN, 1133218893Sdim MachinePointerInfo::getFixedStack(FI), 1134203954Srdivacky false, false, 0)); 1135193323Sed } 1136193323Sed } 1137219077Sdim 1138193323Sed if (isVarArg) { 1139193323Sed /* Argument registers */ 1140193323Sed static const unsigned ArgRegs[] = { 1141193323Sed XCore::R0, XCore::R1, XCore::R2, XCore::R3 1142193323Sed }; 1143193323Sed XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); 1144193323Sed unsigned FirstVAReg = CCInfo.getFirstUnallocated(ArgRegs, 1145193323Sed array_lengthof(ArgRegs)); 1146193323Sed if (FirstVAReg < array_lengthof(ArgRegs)) { 1147193323Sed SmallVector<SDValue, 4> MemOps; 1148193323Sed int offset = 0; 1149193323Sed // Save remaining registers, storing higher register numbers at a higher 1150193323Sed // address 1151193323Sed for (unsigned i = array_lengthof(ArgRegs) - 1; i >= FirstVAReg; --i) { 1152193323Sed // Create a stack slot 1153210299Sed int FI = MFI->CreateFixedObject(4, offset, true); 1154193323Sed if (i == FirstVAReg) { 1155193323Sed XFI->setVarArgsFrameIndex(FI); 1156193323Sed } 1157193323Sed offset -= StackSlotSize; 1158193323Sed SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); 1159193323Sed // Move argument from phys reg -> virt reg 1160193323Sed unsigned VReg = RegInfo.createVirtualRegister( 1161193323Sed XCore::GRRegsRegisterClass); 1162193323Sed RegInfo.addLiveIn(ArgRegs[i], VReg); 1163198090Srdivacky SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32); 1164193323Sed // Move argument from virt reg -> stack 1165218893Sdim SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, 1166218893Sdim MachinePointerInfo(), false, false, 0); 1167193323Sed MemOps.push_back(Store); 1168193323Sed } 1169193323Sed if (!MemOps.empty()) 1170198090Srdivacky Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, 1171198090Srdivacky &MemOps[0], MemOps.size()); 1172193323Sed } else { 1173193323Sed // This will point to the next argument passed via stack. 1174193323Sed XFI->setVarArgsFrameIndex( 1175199481Srdivacky MFI->CreateFixedObject(4, LRSaveSize + CCInfo.getNextStackOffset(), 1176210299Sed true)); 1177193323Sed } 1178193323Sed } 1179219077Sdim 1180198090Srdivacky return Chain; 1181193323Sed} 1182193323Sed 1183193323Sed//===----------------------------------------------------------------------===// 1184193323Sed// Return Value Calling Convention Implementation 1185193323Sed//===----------------------------------------------------------------------===// 1186193323Sed 1187199481Srdivackybool XCoreTargetLowering:: 1188223017SdimCanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, 1189223017Sdim bool isVarArg, 1190210299Sed const SmallVectorImpl<ISD::OutputArg> &Outs, 1191210299Sed LLVMContext &Context) const { 1192199481Srdivacky SmallVector<CCValAssign, 16> RVLocs; 1193223017Sdim CCState CCInfo(CallConv, isVarArg, MF, getTargetMachine(), RVLocs, Context); 1194210299Sed return CCInfo.CheckReturn(Outs, RetCC_XCore); 1195199481Srdivacky} 1196199481Srdivacky 1197198090SrdivackySDValue 1198198090SrdivackyXCoreTargetLowering::LowerReturn(SDValue Chain, 1199198090Srdivacky CallingConv::ID CallConv, bool isVarArg, 1200198090Srdivacky const SmallVectorImpl<ISD::OutputArg> &Outs, 1201210299Sed const SmallVectorImpl<SDValue> &OutVals, 1202207618Srdivacky DebugLoc dl, SelectionDAG &DAG) const { 1203198090Srdivacky 1204193323Sed // CCValAssign - represent the assignment of 1205193323Sed // the return value to a location 1206193323Sed SmallVector<CCValAssign, 16> RVLocs; 1207193323Sed 1208193323Sed // CCState - Info about the registers and stack slot. 1209223017Sdim CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), 1210223017Sdim getTargetMachine(), RVLocs, *DAG.getContext()); 1211193323Sed 1212223017Sdim // Analyze return values. 1213198090Srdivacky CCInfo.AnalyzeReturn(Outs, RetCC_XCore); 1214193323Sed 1215219077Sdim // If this is the first return lowered for this function, add 1216193323Sed // the regs to the liveout set for the function. 1217193323Sed if (DAG.getMachineFunction().getRegInfo().liveout_empty()) { 1218193323Sed for (unsigned i = 0; i != RVLocs.size(); ++i) 1219193323Sed if (RVLocs[i].isRegLoc()) 1220193323Sed DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg()); 1221193323Sed } 1222193323Sed 1223193323Sed SDValue Flag; 1224193323Sed 1225193323Sed // Copy the result values into the output registers. 1226193323Sed for (unsigned i = 0; i != RVLocs.size(); ++i) { 1227193323Sed CCValAssign &VA = RVLocs[i]; 1228193323Sed assert(VA.isRegLoc() && "Can only return in registers!"); 1229193323Sed 1230219077Sdim Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), 1231210299Sed OutVals[i], Flag); 1232193323Sed 1233193323Sed // guarantee that all emitted copies are 1234193323Sed // stuck together, avoiding something bad 1235193323Sed Flag = Chain.getValue(1); 1236193323Sed } 1237193323Sed 1238193323Sed // Return on XCore is always a "retsp 0" 1239193323Sed if (Flag.getNode()) 1240193323Sed return DAG.getNode(XCoreISD::RETSP, dl, MVT::Other, 1241193323Sed Chain, DAG.getConstant(0, MVT::i32), Flag); 1242193323Sed else // Return Void 1243193323Sed return DAG.getNode(XCoreISD::RETSP, dl, MVT::Other, 1244193323Sed Chain, DAG.getConstant(0, MVT::i32)); 1245193323Sed} 1246193323Sed 1247193323Sed//===----------------------------------------------------------------------===// 1248193323Sed// Other Lowering Code 1249193323Sed//===----------------------------------------------------------------------===// 1250193323Sed 1251193323SedMachineBasicBlock * 1252193323SedXCoreTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, 1253207618Srdivacky MachineBasicBlock *BB) const { 1254193323Sed const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo(); 1255193323Sed DebugLoc dl = MI->getDebugLoc(); 1256193323Sed assert((MI->getOpcode() == XCore::SELECT_CC) && 1257193323Sed "Unexpected instr type to insert"); 1258219077Sdim 1259193323Sed // To "insert" a SELECT_CC instruction, we actually have to insert the diamond 1260193323Sed // control-flow pattern. The incoming instruction knows the destination vreg 1261193323Sed // to set, the condition code register to branch on, the true/false values to 1262193323Sed // select between, and a branch opcode to use. 1263193323Sed const BasicBlock *LLVM_BB = BB->getBasicBlock(); 1264193323Sed MachineFunction::iterator It = BB; 1265193323Sed ++It; 1266219077Sdim 1267193323Sed // thisMBB: 1268193323Sed // ... 1269193323Sed // TrueVal = ... 1270193323Sed // cmpTY ccX, r1, r2 1271193323Sed // bCC copy1MBB 1272193323Sed // fallthrough --> copy0MBB 1273193323Sed MachineBasicBlock *thisMBB = BB; 1274193323Sed MachineFunction *F = BB->getParent(); 1275193323Sed MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); 1276193323Sed MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); 1277193323Sed F->insert(It, copy0MBB); 1278193323Sed F->insert(It, sinkMBB); 1279210299Sed 1280210299Sed // Transfer the remainder of BB and its successor edges to sinkMBB. 1281210299Sed sinkMBB->splice(sinkMBB->begin(), BB, 1282210299Sed llvm::next(MachineBasicBlock::iterator(MI)), 1283210299Sed BB->end()); 1284210299Sed sinkMBB->transferSuccessorsAndUpdatePHIs(BB); 1285210299Sed 1286193323Sed // Next, add the true and fallthrough blocks as its successors. 1287193323Sed BB->addSuccessor(copy0MBB); 1288193323Sed BB->addSuccessor(sinkMBB); 1289219077Sdim 1290210299Sed BuildMI(BB, dl, TII.get(XCore::BRFT_lru6)) 1291210299Sed .addReg(MI->getOperand(1).getReg()).addMBB(sinkMBB); 1292210299Sed 1293193323Sed // copy0MBB: 1294193323Sed // %FalseValue = ... 1295193323Sed // # fallthrough to sinkMBB 1296193323Sed BB = copy0MBB; 1297219077Sdim 1298193323Sed // Update machine-CFG edges 1299193323Sed BB->addSuccessor(sinkMBB); 1300219077Sdim 1301193323Sed // sinkMBB: 1302193323Sed // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] 1303193323Sed // ... 1304193323Sed BB = sinkMBB; 1305210299Sed BuildMI(*BB, BB->begin(), dl, 1306210299Sed TII.get(XCore::PHI), MI->getOperand(0).getReg()) 1307193323Sed .addReg(MI->getOperand(3).getReg()).addMBB(copy0MBB) 1308193323Sed .addReg(MI->getOperand(2).getReg()).addMBB(thisMBB); 1309219077Sdim 1310210299Sed MI->eraseFromParent(); // The pseudo instruction is gone now. 1311193323Sed return BB; 1312193323Sed} 1313193323Sed 1314193323Sed//===----------------------------------------------------------------------===// 1315198090Srdivacky// Target Optimization Hooks 1316198090Srdivacky//===----------------------------------------------------------------------===// 1317198090Srdivacky 1318198090SrdivackySDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N, 1319198090Srdivacky DAGCombinerInfo &DCI) const { 1320198090Srdivacky SelectionDAG &DAG = DCI.DAG; 1321198090Srdivacky DebugLoc dl = N->getDebugLoc(); 1322198090Srdivacky switch (N->getOpcode()) { 1323198090Srdivacky default: break; 1324204961Srdivacky case XCoreISD::LADD: { 1325204961Srdivacky SDValue N0 = N->getOperand(0); 1326204961Srdivacky SDValue N1 = N->getOperand(1); 1327204961Srdivacky SDValue N2 = N->getOperand(2); 1328204961Srdivacky ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0); 1329204961Srdivacky ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1); 1330204961Srdivacky EVT VT = N0.getValueType(); 1331204961Srdivacky 1332204961Srdivacky // canonicalize constant to RHS 1333204961Srdivacky if (N0C && !N1C) 1334204961Srdivacky return DAG.getNode(XCoreISD::LADD, dl, DAG.getVTList(VT, VT), N1, N0, N2); 1335204961Srdivacky 1336204961Srdivacky // fold (ladd 0, 0, x) -> 0, x & 1 1337204961Srdivacky if (N0C && N0C->isNullValue() && N1C && N1C->isNullValue()) { 1338204961Srdivacky SDValue Carry = DAG.getConstant(0, VT); 1339204961Srdivacky SDValue Result = DAG.getNode(ISD::AND, dl, VT, N2, 1340204961Srdivacky DAG.getConstant(1, VT)); 1341204961Srdivacky SDValue Ops [] = { Carry, Result }; 1342204961Srdivacky return DAG.getMergeValues(Ops, 2, dl); 1343204961Srdivacky } 1344204961Srdivacky 1345204961Srdivacky // fold (ladd x, 0, y) -> 0, add x, y iff carry is unused and y has only the 1346204961Srdivacky // low bit set 1347219077Sdim if (N1C && N1C->isNullValue() && N->hasNUsesOfValue(0, 0)) { 1348204961Srdivacky APInt KnownZero, KnownOne; 1349204961Srdivacky APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(), 1350204961Srdivacky VT.getSizeInBits() - 1); 1351204961Srdivacky DAG.ComputeMaskedBits(N2, Mask, KnownZero, KnownOne); 1352204961Srdivacky if (KnownZero == Mask) { 1353204961Srdivacky SDValue Carry = DAG.getConstant(0, VT); 1354204961Srdivacky SDValue Result = DAG.getNode(ISD::ADD, dl, VT, N0, N2); 1355204961Srdivacky SDValue Ops [] = { Carry, Result }; 1356204961Srdivacky return DAG.getMergeValues(Ops, 2, dl); 1357204961Srdivacky } 1358204961Srdivacky } 1359204961Srdivacky } 1360204961Srdivacky break; 1361204961Srdivacky case XCoreISD::LSUB: { 1362204961Srdivacky SDValue N0 = N->getOperand(0); 1363204961Srdivacky SDValue N1 = N->getOperand(1); 1364204961Srdivacky SDValue N2 = N->getOperand(2); 1365204961Srdivacky ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0); 1366204961Srdivacky ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1); 1367204961Srdivacky EVT VT = N0.getValueType(); 1368204961Srdivacky 1369204961Srdivacky // fold (lsub 0, 0, x) -> x, -x iff x has only the low bit set 1370219077Sdim if (N0C && N0C->isNullValue() && N1C && N1C->isNullValue()) { 1371204961Srdivacky APInt KnownZero, KnownOne; 1372204961Srdivacky APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(), 1373204961Srdivacky VT.getSizeInBits() - 1); 1374204961Srdivacky DAG.ComputeMaskedBits(N2, Mask, KnownZero, KnownOne); 1375204961Srdivacky if (KnownZero == Mask) { 1376204961Srdivacky SDValue Borrow = N2; 1377204961Srdivacky SDValue Result = DAG.getNode(ISD::SUB, dl, VT, 1378204961Srdivacky DAG.getConstant(0, VT), N2); 1379204961Srdivacky SDValue Ops [] = { Borrow, Result }; 1380204961Srdivacky return DAG.getMergeValues(Ops, 2, dl); 1381204961Srdivacky } 1382204961Srdivacky } 1383204961Srdivacky 1384204961Srdivacky // fold (lsub x, 0, y) -> 0, sub x, y iff borrow is unused and y has only the 1385204961Srdivacky // low bit set 1386219077Sdim if (N1C && N1C->isNullValue() && N->hasNUsesOfValue(0, 0)) { 1387204961Srdivacky APInt KnownZero, KnownOne; 1388204961Srdivacky APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(), 1389204961Srdivacky VT.getSizeInBits() - 1); 1390204961Srdivacky DAG.ComputeMaskedBits(N2, Mask, KnownZero, KnownOne); 1391204961Srdivacky if (KnownZero == Mask) { 1392204961Srdivacky SDValue Borrow = DAG.getConstant(0, VT); 1393204961Srdivacky SDValue Result = DAG.getNode(ISD::SUB, dl, VT, N0, N2); 1394204961Srdivacky SDValue Ops [] = { Borrow, Result }; 1395204961Srdivacky return DAG.getMergeValues(Ops, 2, dl); 1396204961Srdivacky } 1397204961Srdivacky } 1398204961Srdivacky } 1399204961Srdivacky break; 1400205218Srdivacky case XCoreISD::LMUL: { 1401205218Srdivacky SDValue N0 = N->getOperand(0); 1402205218Srdivacky SDValue N1 = N->getOperand(1); 1403205218Srdivacky SDValue N2 = N->getOperand(2); 1404205218Srdivacky SDValue N3 = N->getOperand(3); 1405205218Srdivacky ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0); 1406205218Srdivacky ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1); 1407205218Srdivacky EVT VT = N0.getValueType(); 1408205218Srdivacky // Canonicalize multiplicative constant to RHS. If both multiplicative 1409205218Srdivacky // operands are constant canonicalize smallest to RHS. 1410205218Srdivacky if ((N0C && !N1C) || 1411205218Srdivacky (N0C && N1C && N0C->getZExtValue() < N1C->getZExtValue())) 1412205218Srdivacky return DAG.getNode(XCoreISD::LMUL, dl, DAG.getVTList(VT, VT), N1, N0, N2, N3); 1413205218Srdivacky 1414205218Srdivacky // lmul(x, 0, a, b) 1415205218Srdivacky if (N1C && N1C->isNullValue()) { 1416205218Srdivacky // If the high result is unused fold to add(a, b) 1417205218Srdivacky if (N->hasNUsesOfValue(0, 0)) { 1418205218Srdivacky SDValue Lo = DAG.getNode(ISD::ADD, dl, VT, N2, N3); 1419205218Srdivacky SDValue Ops [] = { Lo, Lo }; 1420205218Srdivacky return DAG.getMergeValues(Ops, 2, dl); 1421205218Srdivacky } 1422205218Srdivacky // Otherwise fold to ladd(a, b, 0) 1423205218Srdivacky return DAG.getNode(XCoreISD::LADD, dl, DAG.getVTList(VT, VT), N2, N3, N1); 1424205218Srdivacky } 1425205218Srdivacky } 1426205218Srdivacky break; 1427204961Srdivacky case ISD::ADD: { 1428205218Srdivacky // Fold 32 bit expressions such as add(add(mul(x,y),a),b) -> 1429205218Srdivacky // lmul(x, y, a, b). The high result of lmul will be ignored. 1430204961Srdivacky // This is only profitable if the intermediate results are unused 1431204961Srdivacky // elsewhere. 1432204961Srdivacky SDValue Mul0, Mul1, Addend0, Addend1; 1433205218Srdivacky if (N->getValueType(0) == MVT::i32 && 1434205218Srdivacky isADDADDMUL(SDValue(N, 0), Mul0, Mul1, Addend0, Addend1, true)) { 1435204961Srdivacky SDValue Ignored = DAG.getNode(XCoreISD::LMUL, dl, 1436204961Srdivacky DAG.getVTList(MVT::i32, MVT::i32), Mul0, 1437204961Srdivacky Mul1, Addend0, Addend1); 1438204961Srdivacky SDValue Result(Ignored.getNode(), 1); 1439204961Srdivacky return Result; 1440204961Srdivacky } 1441205218Srdivacky APInt HighMask = APInt::getHighBitsSet(64, 32); 1442205218Srdivacky // Fold 64 bit expression such as add(add(mul(x,y),a),b) -> 1443205218Srdivacky // lmul(x, y, a, b) if all operands are zero-extended. We do this 1444205218Srdivacky // before type legalization as it is messy to match the operands after 1445205218Srdivacky // that. 1446205218Srdivacky if (N->getValueType(0) == MVT::i64 && 1447205218Srdivacky isADDADDMUL(SDValue(N, 0), Mul0, Mul1, Addend0, Addend1, false) && 1448205218Srdivacky DAG.MaskedValueIsZero(Mul0, HighMask) && 1449205218Srdivacky DAG.MaskedValueIsZero(Mul1, HighMask) && 1450205218Srdivacky DAG.MaskedValueIsZero(Addend0, HighMask) && 1451205218Srdivacky DAG.MaskedValueIsZero(Addend1, HighMask)) { 1452205218Srdivacky SDValue Mul0L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 1453205218Srdivacky Mul0, DAG.getConstant(0, MVT::i32)); 1454205218Srdivacky SDValue Mul1L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 1455205218Srdivacky Mul1, DAG.getConstant(0, MVT::i32)); 1456205218Srdivacky SDValue Addend0L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 1457205218Srdivacky Addend0, DAG.getConstant(0, MVT::i32)); 1458205218Srdivacky SDValue Addend1L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 1459205218Srdivacky Addend1, DAG.getConstant(0, MVT::i32)); 1460205218Srdivacky SDValue Hi = DAG.getNode(XCoreISD::LMUL, dl, 1461205218Srdivacky DAG.getVTList(MVT::i32, MVT::i32), Mul0L, Mul1L, 1462205218Srdivacky Addend0L, Addend1L); 1463205218Srdivacky SDValue Lo(Hi.getNode(), 1); 1464205218Srdivacky return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi); 1465205218Srdivacky } 1466204961Srdivacky } 1467204961Srdivacky break; 1468198090Srdivacky case ISD::STORE: { 1469198090Srdivacky // Replace unaligned store of unaligned load with memmove. 1470198090Srdivacky StoreSDNode *ST = cast<StoreSDNode>(N); 1471198090Srdivacky if (!DCI.isBeforeLegalize() || 1472198090Srdivacky allowsUnalignedMemoryAccesses(ST->getMemoryVT()) || 1473198090Srdivacky ST->isVolatile() || ST->isIndexed()) { 1474198090Srdivacky break; 1475198090Srdivacky } 1476198090Srdivacky SDValue Chain = ST->getChain(); 1477198090Srdivacky 1478198090Srdivacky unsigned StoreBits = ST->getMemoryVT().getStoreSizeInBits(); 1479198090Srdivacky if (StoreBits % 8) { 1480198090Srdivacky break; 1481198090Srdivacky } 1482198090Srdivacky unsigned ABIAlignment = getTargetData()->getABITypeAlignment( 1483198090Srdivacky ST->getMemoryVT().getTypeForEVT(*DCI.DAG.getContext())); 1484198090Srdivacky unsigned Alignment = ST->getAlignment(); 1485198090Srdivacky if (Alignment >= ABIAlignment) { 1486198090Srdivacky break; 1487198090Srdivacky } 1488198090Srdivacky 1489198090Srdivacky if (LoadSDNode *LD = dyn_cast<LoadSDNode>(ST->getValue())) { 1490198090Srdivacky if (LD->hasNUsesOfValue(1, 0) && ST->getMemoryVT() == LD->getMemoryVT() && 1491198090Srdivacky LD->getAlignment() == Alignment && 1492198090Srdivacky !LD->isVolatile() && !LD->isIndexed() && 1493198090Srdivacky Chain.reachesChainWithoutSideEffects(SDValue(LD, 1))) { 1494198090Srdivacky return DAG.getMemmove(Chain, dl, ST->getBasePtr(), 1495198090Srdivacky LD->getBasePtr(), 1496198090Srdivacky DAG.getConstant(StoreBits/8, MVT::i32), 1497218893Sdim Alignment, false, ST->getPointerInfo(), 1498218893Sdim LD->getPointerInfo()); 1499198090Srdivacky } 1500198090Srdivacky } 1501198090Srdivacky break; 1502198090Srdivacky } 1503198090Srdivacky } 1504198090Srdivacky return SDValue(); 1505198090Srdivacky} 1506198090Srdivacky 1507204961Srdivackyvoid XCoreTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op, 1508204961Srdivacky const APInt &Mask, 1509204961Srdivacky APInt &KnownZero, 1510204961Srdivacky APInt &KnownOne, 1511204961Srdivacky const SelectionDAG &DAG, 1512204961Srdivacky unsigned Depth) const { 1513204961Srdivacky KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0); 1514204961Srdivacky switch (Op.getOpcode()) { 1515204961Srdivacky default: break; 1516204961Srdivacky case XCoreISD::LADD: 1517204961Srdivacky case XCoreISD::LSUB: 1518204961Srdivacky if (Op.getResNo() == 0) { 1519204961Srdivacky // Top bits of carry / borrow are clear. 1520204961Srdivacky KnownZero = APInt::getHighBitsSet(Mask.getBitWidth(), 1521204961Srdivacky Mask.getBitWidth() - 1); 1522204961Srdivacky KnownZero &= Mask; 1523204961Srdivacky } 1524204961Srdivacky break; 1525204961Srdivacky } 1526204961Srdivacky} 1527204961Srdivacky 1528198090Srdivacky//===----------------------------------------------------------------------===// 1529193323Sed// Addressing mode description hooks 1530193323Sed//===----------------------------------------------------------------------===// 1531193323Sed 1532193323Sedstatic inline bool isImmUs(int64_t val) 1533193323Sed{ 1534193323Sed return (val >= 0 && val <= 11); 1535193323Sed} 1536193323Sed 1537193323Sedstatic inline bool isImmUs2(int64_t val) 1538193323Sed{ 1539193323Sed return (val%2 == 0 && isImmUs(val/2)); 1540193323Sed} 1541193323Sed 1542193323Sedstatic inline bool isImmUs4(int64_t val) 1543193323Sed{ 1544193323Sed return (val%4 == 0 && isImmUs(val/4)); 1545193323Sed} 1546193323Sed 1547193323Sed/// isLegalAddressingMode - Return true if the addressing mode represented 1548193323Sed/// by AM is legal for this target, for a load/store of the specified type. 1549193323Sedbool 1550219077SdimXCoreTargetLowering::isLegalAddressingMode(const AddrMode &AM, 1551193323Sed const Type *Ty) const { 1552198090Srdivacky if (Ty->getTypeID() == Type::VoidTyID) 1553204642Srdivacky return AM.Scale == 0 && isImmUs(AM.BaseOffs) && isImmUs4(AM.BaseOffs); 1554198090Srdivacky 1555198090Srdivacky const TargetData *TD = TM.getTargetData(); 1556198090Srdivacky unsigned Size = TD->getTypeAllocSize(Ty); 1557193323Sed if (AM.BaseGV) { 1558198090Srdivacky return Size >= 4 && !AM.HasBaseReg && AM.Scale == 0 && 1559193323Sed AM.BaseOffs%4 == 0; 1560193323Sed } 1561219077Sdim 1562198090Srdivacky switch (Size) { 1563198090Srdivacky case 1: 1564193323Sed // reg + imm 1565193323Sed if (AM.Scale == 0) { 1566193323Sed return isImmUs(AM.BaseOffs); 1567193323Sed } 1568198090Srdivacky // reg + reg 1569193323Sed return AM.Scale == 1 && AM.BaseOffs == 0; 1570198090Srdivacky case 2: 1571198090Srdivacky case 3: 1572193323Sed // reg + imm 1573193323Sed if (AM.Scale == 0) { 1574193323Sed return isImmUs2(AM.BaseOffs); 1575193323Sed } 1576198090Srdivacky // reg + reg<<1 1577193323Sed return AM.Scale == 2 && AM.BaseOffs == 0; 1578198090Srdivacky default: 1579193323Sed // reg + imm 1580193323Sed if (AM.Scale == 0) { 1581193323Sed return isImmUs4(AM.BaseOffs); 1582193323Sed } 1583193323Sed // reg + reg<<2 1584193323Sed return AM.Scale == 4 && AM.BaseOffs == 0; 1585193323Sed } 1586219077Sdim 1587193323Sed return false; 1588193323Sed} 1589193323Sed 1590193323Sed//===----------------------------------------------------------------------===// 1591193323Sed// XCore Inline Assembly Support 1592193323Sed//===----------------------------------------------------------------------===// 1593193323Sed 1594193323Sedstd::vector<unsigned> XCoreTargetLowering:: 1595193323SedgetRegClassForInlineAsmConstraint(const std::string &Constraint, 1596219077Sdim EVT VT) const 1597193323Sed{ 1598193323Sed if (Constraint.size() != 1) 1599193323Sed return std::vector<unsigned>(); 1600193323Sed 1601193323Sed switch (Constraint[0]) { 1602193323Sed default : break; 1603193323Sed case 'r': 1604219077Sdim return make_vector<unsigned>(XCore::R0, XCore::R1, XCore::R2, 1605219077Sdim XCore::R3, XCore::R4, XCore::R5, 1606219077Sdim XCore::R6, XCore::R7, XCore::R8, 1607193323Sed XCore::R9, XCore::R10, XCore::R11, 0); 1608193323Sed break; 1609193323Sed } 1610193323Sed return std::vector<unsigned>(); 1611193323Sed} 1612