XCoreISelLowering.cpp revision 239462
1234353Sdim//===-- 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" 39193323Sedusing namespace llvm; 40193323Sed 41193323Sedconst char *XCoreTargetLowering:: 42219077SdimgetTargetNodeName(unsigned Opcode) const 43193323Sed{ 44219077Sdim switch (Opcode) 45193323Sed { 46193323Sed case XCoreISD::BL : return "XCoreISD::BL"; 47193323Sed case XCoreISD::PCRelativeWrapper : return "XCoreISD::PCRelativeWrapper"; 48193323Sed case XCoreISD::DPRelativeWrapper : return "XCoreISD::DPRelativeWrapper"; 49193323Sed case XCoreISD::CPRelativeWrapper : return "XCoreISD::CPRelativeWrapper"; 50193323Sed case XCoreISD::STWSP : return "XCoreISD::STWSP"; 51193323Sed case XCoreISD::RETSP : return "XCoreISD::RETSP"; 52198090Srdivacky case XCoreISD::LADD : return "XCoreISD::LADD"; 53198090Srdivacky case XCoreISD::LSUB : return "XCoreISD::LSUB"; 54204961Srdivacky case XCoreISD::LMUL : return "XCoreISD::LMUL"; 55204961Srdivacky case XCoreISD::MACCU : return "XCoreISD::MACCU"; 56204961Srdivacky case XCoreISD::MACCS : return "XCoreISD::MACCS"; 57204642Srdivacky case XCoreISD::BR_JT : return "XCoreISD::BR_JT"; 58204642Srdivacky case XCoreISD::BR_JT32 : return "XCoreISD::BR_JT32"; 59204961Srdivacky default : return NULL; 60193323Sed } 61193323Sed} 62193323Sed 63193323SedXCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM) 64198090Srdivacky : TargetLowering(XTM, new XCoreTargetObjectFile()), 65193323Sed TM(XTM), 66193323Sed Subtarget(*XTM.getSubtargetImpl()) { 67193323Sed 68193323Sed // Set up the register classes. 69239462Sdim addRegisterClass(MVT::i32, &XCore::GRRegsRegClass); 70193323Sed 71193323Sed // Compute derived properties from the register classes 72193323Sed computeRegisterProperties(); 73193323Sed 74193323Sed // Division is expensive 75193323Sed setIntDivIsCheap(false); 76193323Sed 77193323Sed setStackPointerRegisterToSaveRestore(XCore::SP); 78193323Sed 79208599Srdivacky setSchedulingPreference(Sched::RegPressure); 80193323Sed 81193323Sed // Use i32 for setcc operations results (slt, sgt, ...). 82193323Sed setBooleanContents(ZeroOrOneBooleanContent); 83226633Sdim setBooleanVectorContents(ZeroOrOneBooleanContent); // FIXME: Is this correct? 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); 111234353Sdim setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i32, Expand); 112234353Sdim setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32, Expand); 113219077Sdim 114193323Sed setOperationAction(ISD::TRAP, MVT::Other, Legal); 115219077Sdim 116204642Srdivacky // Jump tables. 117204642Srdivacky setOperationAction(ISD::BR_JT, MVT::Other, Custom); 118193323Sed 119193323Sed setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); 120199511Srdivacky setOperationAction(ISD::BlockAddress, MVT::i32 , Custom); 121199511Srdivacky 122193323Sed // Thread Local Storage 123193323Sed setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom); 124219077Sdim 125193323Sed // Conversion of i64 -> double produces constantpool nodes 126193323Sed setOperationAction(ISD::ConstantPool, MVT::i32, Custom); 127193323Sed 128193323Sed // Loads 129193323Sed setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote); 130193323Sed setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote); 131193323Sed setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); 132193323Sed 133193323Sed setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Expand); 134193323Sed setLoadExtAction(ISD::ZEXTLOAD, MVT::i16, Expand); 135198090Srdivacky 136198090Srdivacky // Custom expand misaligned loads / stores. 137198090Srdivacky setOperationAction(ISD::LOAD, MVT::i32, Custom); 138198090Srdivacky setOperationAction(ISD::STORE, MVT::i32, Custom); 139198090Srdivacky 140193323Sed // Varargs 141193323Sed setOperationAction(ISD::VAEND, MVT::Other, Expand); 142193323Sed setOperationAction(ISD::VACOPY, MVT::Other, Expand); 143193323Sed setOperationAction(ISD::VAARG, MVT::Other, Custom); 144193323Sed setOperationAction(ISD::VASTART, MVT::Other, Custom); 145219077Sdim 146193323Sed // Dynamic stack 147193323Sed setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); 148193323Sed setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); 149193323Sed setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand); 150198090Srdivacky 151218893Sdim // TRAMPOLINE is custom lowered. 152226633Sdim setOperationAction(ISD::INIT_TRAMPOLINE, MVT::Other, Custom); 153226633Sdim setOperationAction(ISD::ADJUST_TRAMPOLINE, MVT::Other, Custom); 154218893Sdim 155218893Sdim maxStoresPerMemset = maxStoresPerMemsetOptSize = 4; 156218893Sdim maxStoresPerMemmove = maxStoresPerMemmoveOptSize 157218893Sdim = maxStoresPerMemcpy = maxStoresPerMemcpyOptSize = 2; 158218893Sdim 159198090Srdivacky // We have target-specific dag combine patterns for the following nodes: 160198090Srdivacky setTargetDAGCombine(ISD::STORE); 161204961Srdivacky setTargetDAGCombine(ISD::ADD); 162223017Sdim 163223017Sdim setMinFunctionAlignment(1); 164193323Sed} 165193323Sed 166193323SedSDValue XCoreTargetLowering:: 167207618SrdivackyLowerOperation(SDValue Op, SelectionDAG &DAG) const { 168219077Sdim switch (Op.getOpcode()) 169193323Sed { 170193323Sed case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); 171193323Sed case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG); 172199511Srdivacky case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); 173193323Sed case ISD::ConstantPool: return LowerConstantPool(Op, DAG); 174204642Srdivacky case ISD::BR_JT: return LowerBR_JT(Op, DAG); 175198090Srdivacky case ISD::LOAD: return LowerLOAD(Op, DAG); 176198090Srdivacky case ISD::STORE: return LowerSTORE(Op, DAG); 177193323Sed case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG); 178193323Sed case ISD::VAARG: return LowerVAARG(Op, DAG); 179193323Sed case ISD::VASTART: return LowerVASTART(Op, DAG); 180204961Srdivacky case ISD::SMUL_LOHI: return LowerSMUL_LOHI(Op, DAG); 181204961Srdivacky case ISD::UMUL_LOHI: return LowerUMUL_LOHI(Op, DAG); 182193323Sed // FIXME: Remove these when LegalizeDAGTypes lands. 183193323Sed case ISD::ADD: 184193323Sed case ISD::SUB: return ExpandADDSUB(Op.getNode(), DAG); 185193323Sed case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG); 186226633Sdim case ISD::INIT_TRAMPOLINE: return LowerINIT_TRAMPOLINE(Op, DAG); 187226633Sdim case ISD::ADJUST_TRAMPOLINE: return LowerADJUST_TRAMPOLINE(Op, DAG); 188193323Sed default: 189198090Srdivacky llvm_unreachable("unimplemented operand"); 190193323Sed } 191193323Sed} 192193323Sed 193193323Sed/// ReplaceNodeResults - Replace the results of node with an illegal result 194193323Sed/// type with new values built out of custom code. 195193323Sedvoid XCoreTargetLowering::ReplaceNodeResults(SDNode *N, 196193323Sed SmallVectorImpl<SDValue>&Results, 197207618Srdivacky SelectionDAG &DAG) const { 198193323Sed switch (N->getOpcode()) { 199193323Sed default: 200198090Srdivacky llvm_unreachable("Don't know how to custom expand this!"); 201193323Sed case ISD::ADD: 202193323Sed case ISD::SUB: 203193323Sed Results.push_back(ExpandADDSUB(N, DAG)); 204193323Sed return; 205193323Sed } 206193323Sed} 207193323Sed 208193323Sed//===----------------------------------------------------------------------===// 209193323Sed// Misc Lower Operation implementation 210193323Sed//===----------------------------------------------------------------------===// 211193323Sed 212193323SedSDValue XCoreTargetLowering:: 213207618SrdivackyLowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const 214193323Sed{ 215193323Sed DebugLoc dl = Op.getDebugLoc(); 216193323Sed SDValue Cond = DAG.getNode(ISD::SETCC, dl, MVT::i32, Op.getOperand(2), 217193323Sed Op.getOperand(3), Op.getOperand(4)); 218193323Sed return DAG.getNode(ISD::SELECT, dl, MVT::i32, Cond, Op.getOperand(0), 219193323Sed Op.getOperand(1)); 220193323Sed} 221193323Sed 222193323SedSDValue XCoreTargetLowering:: 223207618SrdivackygetGlobalAddressWrapper(SDValue GA, const GlobalValue *GV, 224207618Srdivacky SelectionDAG &DAG) const 225193323Sed{ 226193323Sed // FIXME there is no actual debug info here 227193323Sed DebugLoc dl = GA.getDebugLoc(); 228193323Sed if (isa<Function>(GV)) { 229193323Sed return DAG.getNode(XCoreISD::PCRelativeWrapper, dl, MVT::i32, GA); 230193323Sed } 231198090Srdivacky const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV); 232198090Srdivacky if (!GVar) { 233198090Srdivacky // If GV is an alias then use the aliasee to determine constness 234198090Srdivacky if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV)) 235198090Srdivacky GVar = dyn_cast_or_null<GlobalVariable>(GA->resolveAliasedGlobal()); 236198090Srdivacky } 237198090Srdivacky bool isConst = GVar && GVar->isConstant(); 238198090Srdivacky if (isConst) { 239198090Srdivacky return DAG.getNode(XCoreISD::CPRelativeWrapper, dl, MVT::i32, GA); 240198090Srdivacky } 241193323Sed return DAG.getNode(XCoreISD::DPRelativeWrapper, dl, MVT::i32, GA); 242193323Sed} 243193323Sed 244193323SedSDValue XCoreTargetLowering:: 245207618SrdivackyLowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const 246193323Sed{ 247207618Srdivacky const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); 248210299Sed SDValue GA = DAG.getTargetGlobalAddress(GV, Op.getDebugLoc(), MVT::i32); 249193323Sed return getGlobalAddressWrapper(GA, GV, DAG); 250193323Sed} 251193323Sed 252193323Sedstatic inline SDValue BuildGetId(SelectionDAG &DAG, DebugLoc dl) { 253193323Sed return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::i32, 254193323Sed DAG.getConstant(Intrinsic::xcore_getid, MVT::i32)); 255193323Sed} 256193323Sed 257226633Sdimstatic inline bool isZeroLengthArray(Type *Ty) { 258226633Sdim ArrayType *AT = dyn_cast_or_null<ArrayType>(Ty); 259193323Sed return AT && (AT->getNumElements() == 0); 260193323Sed} 261193323Sed 262193323SedSDValue XCoreTargetLowering:: 263207618SrdivackyLowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const 264193323Sed{ 265193323Sed // FIXME there isn't really debug info here 266193323Sed DebugLoc dl = Op.getDebugLoc(); 267193323Sed // transform to label + getid() * size 268207618Srdivacky const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); 269210299Sed SDValue GA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32); 270193323Sed const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV); 271193323Sed if (!GVar) { 272193323Sed // If GV is an alias then use the aliasee to determine size 273193323Sed if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV)) 274193323Sed GVar = dyn_cast_or_null<GlobalVariable>(GA->resolveAliasedGlobal()); 275193323Sed } 276234353Sdim if (!GVar) { 277198090Srdivacky llvm_unreachable("Thread local object not a GlobalVariable?"); 278193323Sed } 279226633Sdim Type *Ty = cast<PointerType>(GV->getType())->getElementType(); 280193323Sed if (!Ty->isSized() || isZeroLengthArray(Ty)) { 281198090Srdivacky#ifndef NDEBUG 282198090Srdivacky errs() << "Size of thread local object " << GVar->getName() 283198090Srdivacky << " is unknown\n"; 284198090Srdivacky#endif 285198090Srdivacky llvm_unreachable(0); 286193323Sed } 287193323Sed SDValue base = getGlobalAddressWrapper(GA, GV, DAG); 288193323Sed const TargetData *TD = TM.getTargetData(); 289193323Sed unsigned Size = TD->getTypeAllocSize(Ty); 290193323Sed SDValue offset = DAG.getNode(ISD::MUL, dl, MVT::i32, BuildGetId(DAG, dl), 291193323Sed DAG.getConstant(Size, MVT::i32)); 292193323Sed return DAG.getNode(ISD::ADD, dl, MVT::i32, base, offset); 293193323Sed} 294193323Sed 295193323SedSDValue XCoreTargetLowering:: 296207618SrdivackyLowerBlockAddress(SDValue Op, SelectionDAG &DAG) const 297199511Srdivacky{ 298199511Srdivacky DebugLoc DL = Op.getDebugLoc(); 299199511Srdivacky 300207618Srdivacky const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress(); 301199989Srdivacky SDValue Result = DAG.getBlockAddress(BA, getPointerTy(), /*isTarget=*/true); 302199511Srdivacky 303199511Srdivacky return DAG.getNode(XCoreISD::PCRelativeWrapper, DL, getPointerTy(), Result); 304199511Srdivacky} 305199511Srdivacky 306199511SrdivackySDValue XCoreTargetLowering:: 307207618SrdivackyLowerConstantPool(SDValue Op, SelectionDAG &DAG) const 308193323Sed{ 309193323Sed ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op); 310193323Sed // FIXME there isn't really debug info here 311193323Sed DebugLoc dl = CP->getDebugLoc(); 312198090Srdivacky EVT PtrVT = Op.getValueType(); 313198090Srdivacky SDValue Res; 314198090Srdivacky if (CP->isMachineConstantPoolEntry()) { 315198090Srdivacky Res = DAG.getTargetConstantPool(CP->getMachineCPVal(), PtrVT, 316198090Srdivacky CP->getAlignment()); 317193323Sed } else { 318198090Srdivacky Res = DAG.getTargetConstantPool(CP->getConstVal(), PtrVT, 319198090Srdivacky CP->getAlignment()); 320193323Sed } 321198090Srdivacky return DAG.getNode(XCoreISD::CPRelativeWrapper, dl, MVT::i32, Res); 322193323Sed} 323193323Sed 324205218Srdivackyunsigned XCoreTargetLowering::getJumpTableEncoding() const { 325205218Srdivacky return MachineJumpTableInfo::EK_Inline; 326205218Srdivacky} 327205218Srdivacky 328193323SedSDValue XCoreTargetLowering:: 329207618SrdivackyLowerBR_JT(SDValue Op, SelectionDAG &DAG) const 330193323Sed{ 331204642Srdivacky SDValue Chain = Op.getOperand(0); 332204642Srdivacky SDValue Table = Op.getOperand(1); 333204642Srdivacky SDValue Index = Op.getOperand(2); 334193323Sed DebugLoc dl = Op.getDebugLoc(); 335204642Srdivacky JumpTableSDNode *JT = cast<JumpTableSDNode>(Table); 336204642Srdivacky unsigned JTI = JT->getIndex(); 337204642Srdivacky MachineFunction &MF = DAG.getMachineFunction(); 338204642Srdivacky const MachineJumpTableInfo *MJTI = MF.getJumpTableInfo(); 339204642Srdivacky SDValue TargetJT = DAG.getTargetJumpTable(JT->getIndex(), MVT::i32); 340204642Srdivacky 341204642Srdivacky unsigned NumEntries = MJTI->getJumpTables()[JTI].MBBs.size(); 342204642Srdivacky if (NumEntries <= 32) { 343204642Srdivacky return DAG.getNode(XCoreISD::BR_JT, dl, MVT::Other, Chain, TargetJT, Index); 344204642Srdivacky } 345204642Srdivacky assert((NumEntries >> 31) == 0); 346204642Srdivacky SDValue ScaledIndex = DAG.getNode(ISD::SHL, dl, MVT::i32, Index, 347204642Srdivacky DAG.getConstant(1, MVT::i32)); 348204642Srdivacky return DAG.getNode(XCoreISD::BR_JT32, dl, MVT::Other, Chain, TargetJT, 349204642Srdivacky ScaledIndex); 350193323Sed} 351193323Sed 352198090Srdivackystatic bool 353198090SrdivackyIsWordAlignedBasePlusConstantOffset(SDValue Addr, SDValue &AlignedBase, 354198090Srdivacky int64_t &Offset) 355198090Srdivacky{ 356198090Srdivacky if (Addr.getOpcode() != ISD::ADD) { 357198090Srdivacky return false; 358198090Srdivacky } 359198090Srdivacky ConstantSDNode *CN = 0; 360198090Srdivacky if (!(CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))) { 361198090Srdivacky return false; 362198090Srdivacky } 363198090Srdivacky int64_t off = CN->getSExtValue(); 364198090Srdivacky const SDValue &Base = Addr.getOperand(0); 365198090Srdivacky const SDValue *Root = &Base; 366198090Srdivacky if (Base.getOpcode() == ISD::ADD && 367198090Srdivacky Base.getOperand(1).getOpcode() == ISD::SHL) { 368198090Srdivacky ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Base.getOperand(1) 369198090Srdivacky .getOperand(1)); 370198090Srdivacky if (CN && (CN->getSExtValue() >= 2)) { 371198090Srdivacky Root = &Base.getOperand(0); 372198090Srdivacky } 373198090Srdivacky } 374198090Srdivacky if (isa<FrameIndexSDNode>(*Root)) { 375198090Srdivacky // All frame indicies are word aligned 376198090Srdivacky AlignedBase = Base; 377198090Srdivacky Offset = off; 378198090Srdivacky return true; 379198090Srdivacky } 380198090Srdivacky if (Root->getOpcode() == XCoreISD::DPRelativeWrapper || 381198090Srdivacky Root->getOpcode() == XCoreISD::CPRelativeWrapper) { 382198090Srdivacky // All dp / cp relative addresses are word aligned 383198090Srdivacky AlignedBase = Base; 384198090Srdivacky Offset = off; 385198090Srdivacky return true; 386198090Srdivacky } 387234353Sdim // Check for an aligned global variable. 388234353Sdim if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(*Root)) { 389234353Sdim const GlobalValue *GV = GA->getGlobal(); 390234353Sdim if (GA->getOffset() == 0 && GV->getAlignment() >= 4) { 391234353Sdim AlignedBase = Base; 392234353Sdim Offset = off; 393234353Sdim return true; 394234353Sdim } 395234353Sdim } 396198090Srdivacky return false; 397198090Srdivacky} 398198090Srdivacky 399193323SedSDValue XCoreTargetLowering:: 400218893SdimLowerLOAD(SDValue Op, SelectionDAG &DAG) const { 401198090Srdivacky LoadSDNode *LD = cast<LoadSDNode>(Op); 402198090Srdivacky assert(LD->getExtensionType() == ISD::NON_EXTLOAD && 403198090Srdivacky "Unexpected extension type"); 404198090Srdivacky assert(LD->getMemoryVT() == MVT::i32 && "Unexpected load EVT"); 405218893Sdim if (allowsUnalignedMemoryAccesses(LD->getMemoryVT())) 406198090Srdivacky return SDValue(); 407218893Sdim 408198090Srdivacky unsigned ABIAlignment = getTargetData()-> 409198090Srdivacky getABITypeAlignment(LD->getMemoryVT().getTypeForEVT(*DAG.getContext())); 410198090Srdivacky // Leave aligned load alone. 411218893Sdim if (LD->getAlignment() >= ABIAlignment) 412198090Srdivacky return SDValue(); 413218893Sdim 414198090Srdivacky SDValue Chain = LD->getChain(); 415198090Srdivacky SDValue BasePtr = LD->getBasePtr(); 416218893Sdim DebugLoc DL = Op.getDebugLoc(); 417219077Sdim 418198090Srdivacky SDValue Base; 419198090Srdivacky int64_t Offset; 420198090Srdivacky if (!LD->isVolatile() && 421198090Srdivacky IsWordAlignedBasePlusConstantOffset(BasePtr, Base, Offset)) { 422198090Srdivacky if (Offset % 4 == 0) { 423198090Srdivacky // We've managed to infer better alignment information than the load 424198090Srdivacky // already has. Use an aligned load. 425203954Srdivacky // 426218893Sdim return DAG.getLoad(getPointerTy(), DL, Chain, BasePtr, 427218893Sdim MachinePointerInfo(), 428234353Sdim false, false, false, 0); 429198090Srdivacky } 430198090Srdivacky // Lower to 431198090Srdivacky // ldw low, base[offset >> 2] 432198090Srdivacky // ldw high, base[(offset >> 2) + 1] 433198090Srdivacky // shr low_shifted, low, (offset & 0x3) * 8 434198090Srdivacky // shl high_shifted, high, 32 - (offset & 0x3) * 8 435198090Srdivacky // or result, low_shifted, high_shifted 436198090Srdivacky SDValue LowOffset = DAG.getConstant(Offset & ~0x3, MVT::i32); 437198090Srdivacky SDValue HighOffset = DAG.getConstant((Offset & ~0x3) + 4, MVT::i32); 438198090Srdivacky SDValue LowShift = DAG.getConstant((Offset & 0x3) * 8, MVT::i32); 439198090Srdivacky SDValue HighShift = DAG.getConstant(32 - (Offset & 0x3) * 8, MVT::i32); 440219077Sdim 441218893Sdim SDValue LowAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, Base, LowOffset); 442218893Sdim SDValue HighAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, Base, HighOffset); 443219077Sdim 444218893Sdim SDValue Low = DAG.getLoad(getPointerTy(), DL, Chain, 445234353Sdim LowAddr, MachinePointerInfo(), 446234353Sdim false, false, false, 0); 447218893Sdim SDValue High = DAG.getLoad(getPointerTy(), DL, Chain, 448234353Sdim HighAddr, MachinePointerInfo(), 449234353Sdim false, false, false, 0); 450218893Sdim SDValue LowShifted = DAG.getNode(ISD::SRL, DL, MVT::i32, Low, LowShift); 451218893Sdim SDValue HighShifted = DAG.getNode(ISD::SHL, DL, MVT::i32, High, HighShift); 452218893Sdim SDValue Result = DAG.getNode(ISD::OR, DL, MVT::i32, LowShifted, HighShifted); 453218893Sdim Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Low.getValue(1), 454198090Srdivacky High.getValue(1)); 455198090Srdivacky SDValue Ops[] = { Result, Chain }; 456218893Sdim return DAG.getMergeValues(Ops, 2, DL); 457198090Srdivacky } 458219077Sdim 459198090Srdivacky if (LD->getAlignment() == 2) { 460218893Sdim SDValue Low = DAG.getExtLoad(ISD::ZEXTLOAD, DL, MVT::i32, Chain, 461218893Sdim BasePtr, LD->getPointerInfo(), MVT::i16, 462203954Srdivacky LD->isVolatile(), LD->isNonTemporal(), 2); 463218893Sdim SDValue HighAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, BasePtr, 464198090Srdivacky DAG.getConstant(2, MVT::i32)); 465218893Sdim SDValue High = DAG.getExtLoad(ISD::EXTLOAD, DL, MVT::i32, Chain, 466218893Sdim HighAddr, 467218893Sdim LD->getPointerInfo().getWithOffset(2), 468203954Srdivacky MVT::i16, LD->isVolatile(), 469203954Srdivacky LD->isNonTemporal(), 2); 470218893Sdim SDValue HighShifted = DAG.getNode(ISD::SHL, DL, MVT::i32, High, 471198090Srdivacky DAG.getConstant(16, MVT::i32)); 472218893Sdim SDValue Result = DAG.getNode(ISD::OR, DL, MVT::i32, Low, HighShifted); 473218893Sdim Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Low.getValue(1), 474198090Srdivacky High.getValue(1)); 475198090Srdivacky SDValue Ops[] = { Result, Chain }; 476218893Sdim return DAG.getMergeValues(Ops, 2, DL); 477198090Srdivacky } 478219077Sdim 479198090Srdivacky // Lower to a call to __misaligned_load(BasePtr). 480226633Sdim Type *IntPtrTy = getTargetData()->getIntPtrType(*DAG.getContext()); 481198090Srdivacky TargetLowering::ArgListTy Args; 482198090Srdivacky TargetLowering::ArgListEntry Entry; 483219077Sdim 484198090Srdivacky Entry.Ty = IntPtrTy; 485198090Srdivacky Entry.Node = BasePtr; 486198090Srdivacky Args.push_back(Entry); 487219077Sdim 488239462Sdim TargetLowering::CallLoweringInfo CLI(Chain, IntPtrTy, false, false, 489234353Sdim false, false, 0, CallingConv::C, /*isTailCall=*/false, 490234353Sdim /*doesNotRet=*/false, /*isReturnValueUsed=*/true, 491198090Srdivacky DAG.getExternalSymbol("__misaligned_load", getPointerTy()), 492218893Sdim Args, DAG, DL); 493239462Sdim std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI); 494198090Srdivacky 495198090Srdivacky SDValue Ops[] = 496198090Srdivacky { CallResult.first, CallResult.second }; 497198090Srdivacky 498218893Sdim return DAG.getMergeValues(Ops, 2, DL); 499198090Srdivacky} 500198090Srdivacky 501198090SrdivackySDValue XCoreTargetLowering:: 502207618SrdivackyLowerSTORE(SDValue Op, SelectionDAG &DAG) const 503198090Srdivacky{ 504198090Srdivacky StoreSDNode *ST = cast<StoreSDNode>(Op); 505198090Srdivacky assert(!ST->isTruncatingStore() && "Unexpected store type"); 506198090Srdivacky assert(ST->getMemoryVT() == MVT::i32 && "Unexpected store EVT"); 507198090Srdivacky if (allowsUnalignedMemoryAccesses(ST->getMemoryVT())) { 508198090Srdivacky return SDValue(); 509198090Srdivacky } 510198090Srdivacky unsigned ABIAlignment = getTargetData()-> 511198090Srdivacky getABITypeAlignment(ST->getMemoryVT().getTypeForEVT(*DAG.getContext())); 512198090Srdivacky // Leave aligned store alone. 513198090Srdivacky if (ST->getAlignment() >= ABIAlignment) { 514198090Srdivacky return SDValue(); 515198090Srdivacky } 516198090Srdivacky SDValue Chain = ST->getChain(); 517198090Srdivacky SDValue BasePtr = ST->getBasePtr(); 518198090Srdivacky SDValue Value = ST->getValue(); 519198090Srdivacky DebugLoc dl = Op.getDebugLoc(); 520219077Sdim 521198090Srdivacky if (ST->getAlignment() == 2) { 522198090Srdivacky SDValue Low = Value; 523198090Srdivacky SDValue High = DAG.getNode(ISD::SRL, dl, MVT::i32, Value, 524198090Srdivacky DAG.getConstant(16, MVT::i32)); 525198090Srdivacky SDValue StoreLow = DAG.getTruncStore(Chain, dl, Low, BasePtr, 526218893Sdim ST->getPointerInfo(), MVT::i16, 527203954Srdivacky ST->isVolatile(), ST->isNonTemporal(), 528203954Srdivacky 2); 529198090Srdivacky SDValue HighAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, BasePtr, 530198090Srdivacky DAG.getConstant(2, MVT::i32)); 531198090Srdivacky SDValue StoreHigh = DAG.getTruncStore(Chain, dl, High, HighAddr, 532218893Sdim ST->getPointerInfo().getWithOffset(2), 533203954Srdivacky MVT::i16, ST->isVolatile(), 534203954Srdivacky ST->isNonTemporal(), 2); 535198090Srdivacky return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, StoreLow, StoreHigh); 536198090Srdivacky } 537219077Sdim 538198090Srdivacky // Lower to a call to __misaligned_store(BasePtr, Value). 539226633Sdim Type *IntPtrTy = getTargetData()->getIntPtrType(*DAG.getContext()); 540198090Srdivacky TargetLowering::ArgListTy Args; 541198090Srdivacky TargetLowering::ArgListEntry Entry; 542219077Sdim 543198090Srdivacky Entry.Ty = IntPtrTy; 544198090Srdivacky Entry.Node = BasePtr; 545198090Srdivacky Args.push_back(Entry); 546219077Sdim 547198090Srdivacky Entry.Node = Value; 548198090Srdivacky Args.push_back(Entry); 549219077Sdim 550239462Sdim TargetLowering::CallLoweringInfo CLI(Chain, 551239462Sdim Type::getVoidTy(*DAG.getContext()), false, false, 552234353Sdim false, false, 0, CallingConv::C, /*isTailCall=*/false, 553234353Sdim /*doesNotRet=*/false, /*isReturnValueUsed=*/true, 554198090Srdivacky DAG.getExternalSymbol("__misaligned_store", getPointerTy()), 555204642Srdivacky Args, DAG, dl); 556239462Sdim std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI); 557198090Srdivacky 558198090Srdivacky return CallResult.second; 559198090Srdivacky} 560198090Srdivacky 561198090SrdivackySDValue XCoreTargetLowering:: 562207618SrdivackyLowerSMUL_LOHI(SDValue Op, SelectionDAG &DAG) const 563204961Srdivacky{ 564204961Srdivacky assert(Op.getValueType() == MVT::i32 && Op.getOpcode() == ISD::SMUL_LOHI && 565204961Srdivacky "Unexpected operand to lower!"); 566204961Srdivacky DebugLoc dl = Op.getDebugLoc(); 567204961Srdivacky SDValue LHS = Op.getOperand(0); 568204961Srdivacky SDValue RHS = Op.getOperand(1); 569204961Srdivacky SDValue Zero = DAG.getConstant(0, MVT::i32); 570204961Srdivacky SDValue Hi = DAG.getNode(XCoreISD::MACCS, dl, 571204961Srdivacky DAG.getVTList(MVT::i32, MVT::i32), Zero, Zero, 572204961Srdivacky LHS, RHS); 573204961Srdivacky SDValue Lo(Hi.getNode(), 1); 574204961Srdivacky SDValue Ops[] = { Lo, Hi }; 575204961Srdivacky return DAG.getMergeValues(Ops, 2, dl); 576204961Srdivacky} 577204961Srdivacky 578204961SrdivackySDValue XCoreTargetLowering:: 579207618SrdivackyLowerUMUL_LOHI(SDValue Op, SelectionDAG &DAG) const 580204961Srdivacky{ 581204961Srdivacky assert(Op.getValueType() == MVT::i32 && Op.getOpcode() == ISD::UMUL_LOHI && 582204961Srdivacky "Unexpected operand to lower!"); 583204961Srdivacky DebugLoc dl = Op.getDebugLoc(); 584204961Srdivacky SDValue LHS = Op.getOperand(0); 585204961Srdivacky SDValue RHS = Op.getOperand(1); 586204961Srdivacky SDValue Zero = DAG.getConstant(0, MVT::i32); 587204961Srdivacky SDValue Hi = DAG.getNode(XCoreISD::LMUL, dl, 588204961Srdivacky DAG.getVTList(MVT::i32, MVT::i32), LHS, RHS, 589204961Srdivacky Zero, Zero); 590204961Srdivacky SDValue Lo(Hi.getNode(), 1); 591204961Srdivacky SDValue Ops[] = { Lo, Hi }; 592204961Srdivacky return DAG.getMergeValues(Ops, 2, dl); 593204961Srdivacky} 594204961Srdivacky 595204961Srdivacky/// isADDADDMUL - Return whether Op is in a form that is equivalent to 596204961Srdivacky/// add(add(mul(x,y),a),b). If requireIntermediatesHaveOneUse is true then 597204961Srdivacky/// each intermediate result in the calculation must also have a single use. 598204961Srdivacky/// If the Op is in the correct form the constituent parts are written to Mul0, 599204961Srdivacky/// Mul1, Addend0 and Addend1. 600204961Srdivackystatic bool 601204961SrdivackyisADDADDMUL(SDValue Op, SDValue &Mul0, SDValue &Mul1, SDValue &Addend0, 602204961Srdivacky SDValue &Addend1, bool requireIntermediatesHaveOneUse) 603204961Srdivacky{ 604204961Srdivacky if (Op.getOpcode() != ISD::ADD) 605204961Srdivacky return false; 606204961Srdivacky SDValue N0 = Op.getOperand(0); 607204961Srdivacky SDValue N1 = Op.getOperand(1); 608204961Srdivacky SDValue AddOp; 609204961Srdivacky SDValue OtherOp; 610204961Srdivacky if (N0.getOpcode() == ISD::ADD) { 611204961Srdivacky AddOp = N0; 612204961Srdivacky OtherOp = N1; 613204961Srdivacky } else if (N1.getOpcode() == ISD::ADD) { 614204961Srdivacky AddOp = N1; 615204961Srdivacky OtherOp = N0; 616204961Srdivacky } else { 617204961Srdivacky return false; 618204961Srdivacky } 619204961Srdivacky if (requireIntermediatesHaveOneUse && !AddOp.hasOneUse()) 620204961Srdivacky return false; 621204961Srdivacky if (OtherOp.getOpcode() == ISD::MUL) { 622204961Srdivacky // add(add(a,b),mul(x,y)) 623204961Srdivacky if (requireIntermediatesHaveOneUse && !OtherOp.hasOneUse()) 624204961Srdivacky return false; 625204961Srdivacky Mul0 = OtherOp.getOperand(0); 626204961Srdivacky Mul1 = OtherOp.getOperand(1); 627204961Srdivacky Addend0 = AddOp.getOperand(0); 628204961Srdivacky Addend1 = AddOp.getOperand(1); 629204961Srdivacky return true; 630204961Srdivacky } 631204961Srdivacky if (AddOp.getOperand(0).getOpcode() == ISD::MUL) { 632204961Srdivacky // add(add(mul(x,y),a),b) 633204961Srdivacky if (requireIntermediatesHaveOneUse && !AddOp.getOperand(0).hasOneUse()) 634204961Srdivacky return false; 635204961Srdivacky Mul0 = AddOp.getOperand(0).getOperand(0); 636204961Srdivacky Mul1 = AddOp.getOperand(0).getOperand(1); 637204961Srdivacky Addend0 = AddOp.getOperand(1); 638204961Srdivacky Addend1 = OtherOp; 639204961Srdivacky return true; 640204961Srdivacky } 641204961Srdivacky if (AddOp.getOperand(1).getOpcode() == ISD::MUL) { 642204961Srdivacky // add(add(a,mul(x,y)),b) 643204961Srdivacky if (requireIntermediatesHaveOneUse && !AddOp.getOperand(1).hasOneUse()) 644204961Srdivacky return false; 645204961Srdivacky Mul0 = AddOp.getOperand(1).getOperand(0); 646204961Srdivacky Mul1 = AddOp.getOperand(1).getOperand(1); 647204961Srdivacky Addend0 = AddOp.getOperand(0); 648204961Srdivacky Addend1 = OtherOp; 649204961Srdivacky return true; 650204961Srdivacky } 651204961Srdivacky return false; 652204961Srdivacky} 653204961Srdivacky 654204961SrdivackySDValue XCoreTargetLowering:: 655207618SrdivackyTryExpandADDWithMul(SDNode *N, SelectionDAG &DAG) const 656204961Srdivacky{ 657204961Srdivacky SDValue Mul; 658204961Srdivacky SDValue Other; 659204961Srdivacky if (N->getOperand(0).getOpcode() == ISD::MUL) { 660204961Srdivacky Mul = N->getOperand(0); 661204961Srdivacky Other = N->getOperand(1); 662204961Srdivacky } else if (N->getOperand(1).getOpcode() == ISD::MUL) { 663204961Srdivacky Mul = N->getOperand(1); 664204961Srdivacky Other = N->getOperand(0); 665204961Srdivacky } else { 666204961Srdivacky return SDValue(); 667204961Srdivacky } 668204961Srdivacky DebugLoc dl = N->getDebugLoc(); 669204961Srdivacky SDValue LL, RL, AddendL, AddendH; 670204961Srdivacky LL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 671204961Srdivacky Mul.getOperand(0), DAG.getConstant(0, MVT::i32)); 672204961Srdivacky RL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 673204961Srdivacky Mul.getOperand(1), DAG.getConstant(0, MVT::i32)); 674204961Srdivacky AddendL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 675204961Srdivacky Other, DAG.getConstant(0, MVT::i32)); 676204961Srdivacky AddendH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 677204961Srdivacky Other, DAG.getConstant(1, MVT::i32)); 678204961Srdivacky APInt HighMask = APInt::getHighBitsSet(64, 32); 679204961Srdivacky unsigned LHSSB = DAG.ComputeNumSignBits(Mul.getOperand(0)); 680204961Srdivacky unsigned RHSSB = DAG.ComputeNumSignBits(Mul.getOperand(1)); 681204961Srdivacky if (DAG.MaskedValueIsZero(Mul.getOperand(0), HighMask) && 682204961Srdivacky DAG.MaskedValueIsZero(Mul.getOperand(1), HighMask)) { 683204961Srdivacky // The inputs are both zero-extended. 684204961Srdivacky SDValue Hi = DAG.getNode(XCoreISD::MACCU, dl, 685204961Srdivacky DAG.getVTList(MVT::i32, MVT::i32), AddendH, 686204961Srdivacky AddendL, LL, RL); 687204961Srdivacky SDValue Lo(Hi.getNode(), 1); 688204961Srdivacky return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi); 689204961Srdivacky } 690204961Srdivacky if (LHSSB > 32 && RHSSB > 32) { 691204961Srdivacky // The inputs are both sign-extended. 692204961Srdivacky SDValue Hi = DAG.getNode(XCoreISD::MACCS, dl, 693204961Srdivacky DAG.getVTList(MVT::i32, MVT::i32), AddendH, 694204961Srdivacky AddendL, LL, RL); 695204961Srdivacky SDValue Lo(Hi.getNode(), 1); 696204961Srdivacky return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi); 697204961Srdivacky } 698204961Srdivacky SDValue LH, RH; 699204961Srdivacky LH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 700204961Srdivacky Mul.getOperand(0), DAG.getConstant(1, MVT::i32)); 701204961Srdivacky RH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 702204961Srdivacky Mul.getOperand(1), DAG.getConstant(1, MVT::i32)); 703204961Srdivacky SDValue Hi = DAG.getNode(XCoreISD::MACCU, dl, 704204961Srdivacky DAG.getVTList(MVT::i32, MVT::i32), AddendH, 705204961Srdivacky AddendL, LL, RL); 706204961Srdivacky SDValue Lo(Hi.getNode(), 1); 707204961Srdivacky RH = DAG.getNode(ISD::MUL, dl, MVT::i32, LL, RH); 708204961Srdivacky LH = DAG.getNode(ISD::MUL, dl, MVT::i32, LH, RL); 709204961Srdivacky Hi = DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, RH); 710204961Srdivacky Hi = DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, LH); 711204961Srdivacky return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi); 712204961Srdivacky} 713204961Srdivacky 714204961SrdivackySDValue XCoreTargetLowering:: 715207618SrdivackyExpandADDSUB(SDNode *N, SelectionDAG &DAG) const 716193323Sed{ 717193323Sed assert(N->getValueType(0) == MVT::i64 && 718193323Sed (N->getOpcode() == ISD::ADD || N->getOpcode() == ISD::SUB) && 719193323Sed "Unknown operand to lower!"); 720204961Srdivacky 721204961Srdivacky if (N->getOpcode() == ISD::ADD) { 722204961Srdivacky SDValue Result = TryExpandADDWithMul(N, DAG); 723204961Srdivacky if (Result.getNode() != 0) 724204961Srdivacky return Result; 725204961Srdivacky } 726204961Srdivacky 727193323Sed DebugLoc dl = N->getDebugLoc(); 728219077Sdim 729193323Sed // Extract components 730193323Sed SDValue LHSL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 731193323Sed N->getOperand(0), DAG.getConstant(0, MVT::i32)); 732193323Sed SDValue LHSH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 733193323Sed N->getOperand(0), DAG.getConstant(1, MVT::i32)); 734193323Sed SDValue RHSL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 735193323Sed N->getOperand(1), DAG.getConstant(0, MVT::i32)); 736193323Sed SDValue RHSH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 737193323Sed N->getOperand(1), DAG.getConstant(1, MVT::i32)); 738219077Sdim 739193323Sed // Expand 740193323Sed unsigned Opcode = (N->getOpcode() == ISD::ADD) ? XCoreISD::LADD : 741193323Sed XCoreISD::LSUB; 742193323Sed SDValue Zero = DAG.getConstant(0, MVT::i32); 743193323Sed SDValue Carry = DAG.getNode(Opcode, dl, DAG.getVTList(MVT::i32, MVT::i32), 744193323Sed LHSL, RHSL, Zero); 745193323Sed SDValue Lo(Carry.getNode(), 1); 746219077Sdim 747193323Sed SDValue Ignored = DAG.getNode(Opcode, dl, DAG.getVTList(MVT::i32, MVT::i32), 748193323Sed LHSH, RHSH, Carry); 749193323Sed SDValue Hi(Ignored.getNode(), 1); 750193323Sed // Merge the pieces 751193323Sed return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi); 752193323Sed} 753193323Sed 754193323SedSDValue XCoreTargetLowering:: 755207618SrdivackyLowerVAARG(SDValue Op, SelectionDAG &DAG) const 756193323Sed{ 757198090Srdivacky llvm_unreachable("unimplemented"); 758234353Sdim // FIXME Arguments passed by reference need a extra dereference. 759193323Sed SDNode *Node = Op.getNode(); 760193323Sed DebugLoc dl = Node->getDebugLoc(); 761193323Sed const Value *V = cast<SrcValueSDNode>(Node->getOperand(2))->getValue(); 762198090Srdivacky EVT VT = Node->getValueType(0); 763193323Sed SDValue VAList = DAG.getLoad(getPointerTy(), dl, Node->getOperand(0), 764218893Sdim Node->getOperand(1), MachinePointerInfo(V), 765234353Sdim false, false, false, 0); 766193323Sed // Increment the pointer, VAList, to the next vararg 767219077Sdim SDValue Tmp3 = DAG.getNode(ISD::ADD, dl, getPointerTy(), VAList, 768219077Sdim DAG.getConstant(VT.getSizeInBits(), 769193323Sed getPointerTy())); 770193323Sed // Store the incremented VAList to the legalized pointer 771218893Sdim Tmp3 = DAG.getStore(VAList.getValue(1), dl, Tmp3, Node->getOperand(1), 772218893Sdim MachinePointerInfo(V), false, false, 0); 773193323Sed // Load the actual argument out of the pointer VAList 774218893Sdim return DAG.getLoad(VT, dl, Tmp3, VAList, MachinePointerInfo(), 775234353Sdim false, false, false, 0); 776193323Sed} 777193323Sed 778193323SedSDValue XCoreTargetLowering:: 779207618SrdivackyLowerVASTART(SDValue Op, SelectionDAG &DAG) const 780193323Sed{ 781193323Sed DebugLoc dl = Op.getDebugLoc(); 782193323Sed // vastart stores the address of the VarArgsFrameIndex slot into the 783193323Sed // memory location argument 784193323Sed MachineFunction &MF = DAG.getMachineFunction(); 785193323Sed XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); 786193323Sed SDValue Addr = DAG.getFrameIndex(XFI->getVarArgsFrameIndex(), MVT::i32); 787219077Sdim return DAG.getStore(Op.getOperand(0), dl, Addr, Op.getOperand(1), 788218893Sdim MachinePointerInfo(), false, false, 0); 789193323Sed} 790193323Sed 791207618SrdivackySDValue XCoreTargetLowering::LowerFRAMEADDR(SDValue Op, 792207618Srdivacky SelectionDAG &DAG) const { 793193323Sed DebugLoc dl = Op.getDebugLoc(); 794219077Sdim // Depths > 0 not supported yet! 795193323Sed if (cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() > 0) 796193323Sed return SDValue(); 797219077Sdim 798193323Sed MachineFunction &MF = DAG.getMachineFunction(); 799193323Sed const TargetRegisterInfo *RegInfo = getTargetMachine().getRegisterInfo(); 800219077Sdim return DAG.getCopyFromReg(DAG.getEntryNode(), dl, 801193323Sed RegInfo->getFrameRegister(MF), MVT::i32); 802193323Sed} 803193323Sed 804218893SdimSDValue XCoreTargetLowering:: 805226633SdimLowerADJUST_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const { 806226633Sdim return Op.getOperand(0); 807226633Sdim} 808226633Sdim 809226633SdimSDValue XCoreTargetLowering:: 810226633SdimLowerINIT_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const { 811218893Sdim SDValue Chain = Op.getOperand(0); 812218893Sdim SDValue Trmp = Op.getOperand(1); // trampoline 813218893Sdim SDValue FPtr = Op.getOperand(2); // nested function 814218893Sdim SDValue Nest = Op.getOperand(3); // 'nest' parameter value 815218893Sdim 816218893Sdim const Value *TrmpAddr = cast<SrcValueSDNode>(Op.getOperand(4))->getValue(); 817218893Sdim 818218893Sdim // .align 4 819218893Sdim // LDAPF_u10 r11, nest 820218893Sdim // LDW_2rus r11, r11[0] 821218893Sdim // STWSP_ru6 r11, sp[0] 822218893Sdim // LDAPF_u10 r11, fptr 823218893Sdim // LDW_2rus r11, r11[0] 824218893Sdim // BAU_1r r11 825218893Sdim // nest: 826218893Sdim // .word nest 827218893Sdim // fptr: 828218893Sdim // .word fptr 829218893Sdim SDValue OutChains[5]; 830218893Sdim 831218893Sdim SDValue Addr = Trmp; 832218893Sdim 833218893Sdim DebugLoc dl = Op.getDebugLoc(); 834218893Sdim OutChains[0] = DAG.getStore(Chain, dl, DAG.getConstant(0x0a3cd805, MVT::i32), 835218893Sdim Addr, MachinePointerInfo(TrmpAddr), false, false, 836218893Sdim 0); 837218893Sdim 838218893Sdim Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp, 839218893Sdim DAG.getConstant(4, MVT::i32)); 840218893Sdim OutChains[1] = DAG.getStore(Chain, dl, DAG.getConstant(0xd80456c0, MVT::i32), 841218893Sdim Addr, MachinePointerInfo(TrmpAddr, 4), false, 842218893Sdim false, 0); 843218893Sdim 844218893Sdim Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp, 845218893Sdim DAG.getConstant(8, MVT::i32)); 846218893Sdim OutChains[2] = DAG.getStore(Chain, dl, DAG.getConstant(0x27fb0a3c, MVT::i32), 847218893Sdim Addr, MachinePointerInfo(TrmpAddr, 8), false, 848218893Sdim false, 0); 849218893Sdim 850218893Sdim Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp, 851218893Sdim DAG.getConstant(12, MVT::i32)); 852218893Sdim OutChains[3] = DAG.getStore(Chain, dl, Nest, Addr, 853218893Sdim MachinePointerInfo(TrmpAddr, 12), false, false, 854218893Sdim 0); 855218893Sdim 856218893Sdim Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp, 857218893Sdim DAG.getConstant(16, MVT::i32)); 858218893Sdim OutChains[4] = DAG.getStore(Chain, dl, FPtr, Addr, 859218893Sdim MachinePointerInfo(TrmpAddr, 16), false, false, 860218893Sdim 0); 861218893Sdim 862226633Sdim return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains, 5); 863218893Sdim} 864218893Sdim 865193323Sed//===----------------------------------------------------------------------===// 866193323Sed// Calling Convention Implementation 867193323Sed//===----------------------------------------------------------------------===// 868193323Sed 869193323Sed#include "XCoreGenCallingConv.inc" 870193323Sed 871193323Sed//===----------------------------------------------------------------------===// 872198090Srdivacky// Call Calling Convention Implementation 873193323Sed//===----------------------------------------------------------------------===// 874193323Sed 875198090Srdivacky/// XCore call implementation 876198090SrdivackySDValue 877239462SdimXCoreTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, 878207618Srdivacky SmallVectorImpl<SDValue> &InVals) const { 879239462Sdim SelectionDAG &DAG = CLI.DAG; 880239462Sdim DebugLoc &dl = CLI.DL; 881239462Sdim SmallVector<ISD::OutputArg, 32> &Outs = CLI.Outs; 882239462Sdim SmallVector<SDValue, 32> &OutVals = CLI.OutVals; 883239462Sdim SmallVector<ISD::InputArg, 32> &Ins = CLI.Ins; 884239462Sdim SDValue Chain = CLI.Chain; 885239462Sdim SDValue Callee = CLI.Callee; 886239462Sdim bool &isTailCall = CLI.IsTailCall; 887239462Sdim CallingConv::ID CallConv = CLI.CallConv; 888239462Sdim bool isVarArg = CLI.IsVarArg; 889239462Sdim 890203954Srdivacky // XCore target does not yet support tail call optimization. 891203954Srdivacky isTailCall = false; 892198090Srdivacky 893193323Sed // For now, only CallingConv::C implemented 894198090Srdivacky switch (CallConv) 895193323Sed { 896193323Sed default: 897198090Srdivacky llvm_unreachable("Unsupported calling convention"); 898193323Sed case CallingConv::Fast: 899193323Sed case CallingConv::C: 900198090Srdivacky return LowerCCCCallTo(Chain, Callee, CallConv, isVarArg, isTailCall, 901210299Sed Outs, OutVals, Ins, dl, DAG, InVals); 902193323Sed } 903193323Sed} 904193323Sed 905193323Sed/// LowerCCCCallTo - functions arguments are copied from virtual 906193323Sed/// regs to (physical regs)/(stack frame), CALLSEQ_START and 907193323Sed/// CALLSEQ_END are emitted. 908193323Sed/// TODO: isTailCall, sret. 909198090SrdivackySDValue 910198090SrdivackyXCoreTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee, 911198090Srdivacky CallingConv::ID CallConv, bool isVarArg, 912198090Srdivacky bool isTailCall, 913198090Srdivacky const SmallVectorImpl<ISD::OutputArg> &Outs, 914210299Sed const SmallVectorImpl<SDValue> &OutVals, 915198090Srdivacky const SmallVectorImpl<ISD::InputArg> &Ins, 916198090Srdivacky DebugLoc dl, SelectionDAG &DAG, 917207618Srdivacky SmallVectorImpl<SDValue> &InVals) const { 918193323Sed 919193323Sed // Analyze operands of the call, assigning locations to each operand. 920193323Sed SmallVector<CCValAssign, 16> ArgLocs; 921223017Sdim CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), 922239462Sdim getTargetMachine(), ArgLocs, *DAG.getContext()); 923193323Sed 924193323Sed // The ABI dictates there should be one stack slot available to the callee 925193323Sed // on function entry (for saving lr). 926193323Sed CCInfo.AllocateStack(4, 4); 927193323Sed 928198090Srdivacky CCInfo.AnalyzeCallOperands(Outs, CC_XCore); 929193323Sed 930193323Sed // Get a count of how many bytes are to be pushed on the stack. 931193323Sed unsigned NumBytes = CCInfo.getNextStackOffset(); 932193323Sed 933219077Sdim Chain = DAG.getCALLSEQ_START(Chain,DAG.getConstant(NumBytes, 934193323Sed getPointerTy(), true)); 935193323Sed 936193323Sed SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass; 937193323Sed SmallVector<SDValue, 12> MemOpChains; 938193323Sed 939193323Sed // Walk the register/memloc assignments, inserting copies/loads. 940193323Sed for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 941193323Sed CCValAssign &VA = ArgLocs[i]; 942210299Sed SDValue Arg = OutVals[i]; 943193323Sed 944193323Sed // Promote the value if needed. 945193323Sed switch (VA.getLocInfo()) { 946198090Srdivacky default: llvm_unreachable("Unknown loc info!"); 947193323Sed case CCValAssign::Full: break; 948193323Sed case CCValAssign::SExt: 949193323Sed Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg); 950193323Sed break; 951193323Sed case CCValAssign::ZExt: 952193323Sed Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg); 953193323Sed break; 954193323Sed case CCValAssign::AExt: 955193323Sed Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg); 956193323Sed break; 957193323Sed } 958219077Sdim 959219077Sdim // Arguments that can be passed on register must be kept at 960193323Sed // RegsToPass vector 961193323Sed if (VA.isRegLoc()) { 962193323Sed RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); 963193323Sed } else { 964193323Sed assert(VA.isMemLoc()); 965193323Sed 966193323Sed int Offset = VA.getLocMemOffset(); 967193323Sed 968219077Sdim MemOpChains.push_back(DAG.getNode(XCoreISD::STWSP, dl, MVT::Other, 969193323Sed Chain, Arg, 970193323Sed DAG.getConstant(Offset/4, MVT::i32))); 971193323Sed } 972193323Sed } 973193323Sed 974193323Sed // Transform all store nodes into one single node because 975193323Sed // all store nodes are independent of each other. 976193323Sed if (!MemOpChains.empty()) 977219077Sdim Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, 978193323Sed &MemOpChains[0], MemOpChains.size()); 979193323Sed 980219077Sdim // Build a sequence of copy-to-reg nodes chained together with token 981193323Sed // chain and flag operands which copy the outgoing args into registers. 982221345Sdim // The InFlag in necessary since all emitted instructions must be 983193323Sed // stuck together. 984193323Sed SDValue InFlag; 985193323Sed for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { 986219077Sdim Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, 987193323Sed RegsToPass[i].second, InFlag); 988193323Sed InFlag = Chain.getValue(1); 989193323Sed } 990193323Sed 991193323Sed // If the callee is a GlobalAddress node (quite common, every direct call is) 992193323Sed // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. 993193323Sed // Likewise ExternalSymbol -> TargetExternalSymbol. 994193323Sed if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) 995210299Sed Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32); 996193323Sed else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee)) 997193323Sed Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32); 998193323Sed 999193323Sed // XCoreBranchLink = #chain, #target_address, #opt_in_flags... 1000219077Sdim // = Chain, Callee, Reg#1, Reg#2, ... 1001193323Sed // 1002193323Sed // Returns a chain & a flag for retval copy to use. 1003218893Sdim SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); 1004193323Sed SmallVector<SDValue, 8> Ops; 1005193323Sed Ops.push_back(Chain); 1006193323Sed Ops.push_back(Callee); 1007193323Sed 1008219077Sdim // Add argument registers to the end of the list so that they are 1009193323Sed // known live into the call. 1010193323Sed for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) 1011193323Sed Ops.push_back(DAG.getRegister(RegsToPass[i].first, 1012193323Sed RegsToPass[i].second.getValueType())); 1013193323Sed 1014193323Sed if (InFlag.getNode()) 1015193323Sed Ops.push_back(InFlag); 1016193323Sed 1017193323Sed Chain = DAG.getNode(XCoreISD::BL, dl, NodeTys, &Ops[0], Ops.size()); 1018193323Sed InFlag = Chain.getValue(1); 1019193323Sed 1020193323Sed // Create the CALLSEQ_END node. 1021193323Sed Chain = DAG.getCALLSEQ_END(Chain, 1022193323Sed DAG.getConstant(NumBytes, getPointerTy(), true), 1023193323Sed DAG.getConstant(0, getPointerTy(), true), 1024193323Sed InFlag); 1025193323Sed InFlag = Chain.getValue(1); 1026193323Sed 1027193323Sed // Handle result values, copying them out of physregs into vregs that we 1028193323Sed // return. 1029198090Srdivacky return LowerCallResult(Chain, InFlag, CallConv, isVarArg, 1030198090Srdivacky Ins, dl, DAG, InVals); 1031193323Sed} 1032193323Sed 1033198090Srdivacky/// LowerCallResult - Lower the result values of a call into the 1034198090Srdivacky/// appropriate copies out of appropriate physical registers. 1035198090SrdivackySDValue 1036198090SrdivackyXCoreTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, 1037198090Srdivacky CallingConv::ID CallConv, bool isVarArg, 1038198090Srdivacky const SmallVectorImpl<ISD::InputArg> &Ins, 1039198090Srdivacky DebugLoc dl, SelectionDAG &DAG, 1040207618Srdivacky SmallVectorImpl<SDValue> &InVals) const { 1041193323Sed 1042193323Sed // Assign locations to each value returned by this call. 1043193323Sed SmallVector<CCValAssign, 16> RVLocs; 1044223017Sdim CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), 1045239462Sdim getTargetMachine(), RVLocs, *DAG.getContext()); 1046193323Sed 1047198090Srdivacky CCInfo.AnalyzeCallResult(Ins, RetCC_XCore); 1048193323Sed 1049193323Sed // Copy all of the result registers out of their specified physreg. 1050193323Sed for (unsigned i = 0; i != RVLocs.size(); ++i) { 1051193323Sed Chain = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(), 1052193323Sed RVLocs[i].getValVT(), InFlag).getValue(1); 1053193323Sed InFlag = Chain.getValue(2); 1054198090Srdivacky InVals.push_back(Chain.getValue(0)); 1055193323Sed } 1056193323Sed 1057198090Srdivacky return Chain; 1058193323Sed} 1059193323Sed 1060193323Sed//===----------------------------------------------------------------------===// 1061198090Srdivacky// Formal Arguments Calling Convention Implementation 1062193323Sed//===----------------------------------------------------------------------===// 1063193323Sed 1064198090Srdivacky/// XCore formal arguments implementation 1065198090SrdivackySDValue 1066198090SrdivackyXCoreTargetLowering::LowerFormalArguments(SDValue Chain, 1067198090Srdivacky CallingConv::ID CallConv, 1068198090Srdivacky bool isVarArg, 1069198090Srdivacky const SmallVectorImpl<ISD::InputArg> &Ins, 1070198090Srdivacky DebugLoc dl, 1071198090Srdivacky SelectionDAG &DAG, 1072207618Srdivacky SmallVectorImpl<SDValue> &InVals) 1073207618Srdivacky const { 1074198090Srdivacky switch (CallConv) 1075193323Sed { 1076193323Sed default: 1077198090Srdivacky llvm_unreachable("Unsupported calling convention"); 1078193323Sed case CallingConv::C: 1079193323Sed case CallingConv::Fast: 1080198090Srdivacky return LowerCCCArguments(Chain, CallConv, isVarArg, 1081198090Srdivacky Ins, dl, DAG, InVals); 1082193323Sed } 1083193323Sed} 1084193323Sed 1085193323Sed/// LowerCCCArguments - transform physical registers into 1086193323Sed/// virtual registers and generate load operations for 1087193323Sed/// arguments places on the stack. 1088193323Sed/// TODO: sret 1089198090SrdivackySDValue 1090198090SrdivackyXCoreTargetLowering::LowerCCCArguments(SDValue Chain, 1091198090Srdivacky CallingConv::ID CallConv, 1092198090Srdivacky bool isVarArg, 1093198090Srdivacky const SmallVectorImpl<ISD::InputArg> 1094198090Srdivacky &Ins, 1095198090Srdivacky DebugLoc dl, 1096198090Srdivacky SelectionDAG &DAG, 1097207618Srdivacky SmallVectorImpl<SDValue> &InVals) const { 1098193323Sed MachineFunction &MF = DAG.getMachineFunction(); 1099193323Sed MachineFrameInfo *MFI = MF.getFrameInfo(); 1100193323Sed MachineRegisterInfo &RegInfo = MF.getRegInfo(); 1101193323Sed 1102193323Sed // Assign locations to all of the incoming arguments. 1103193323Sed SmallVector<CCValAssign, 16> ArgLocs; 1104223017Sdim CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), 1105239462Sdim getTargetMachine(), ArgLocs, *DAG.getContext()); 1106193323Sed 1107198090Srdivacky CCInfo.AnalyzeFormalArguments(Ins, CC_XCore); 1108193323Sed 1109218893Sdim unsigned StackSlotSize = XCoreFrameLowering::stackSlotSize(); 1110193323Sed 1111193323Sed unsigned LRSaveSize = StackSlotSize; 1112219077Sdim 1113193323Sed for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 1114193323Sed 1115193323Sed CCValAssign &VA = ArgLocs[i]; 1116219077Sdim 1117193323Sed if (VA.isRegLoc()) { 1118193323Sed // Arguments passed in registers 1119198090Srdivacky EVT RegVT = VA.getLocVT(); 1120198090Srdivacky switch (RegVT.getSimpleVT().SimpleTy) { 1121193323Sed default: 1122198090Srdivacky { 1123198090Srdivacky#ifndef NDEBUG 1124198090Srdivacky errs() << "LowerFormalArguments Unhandled argument type: " 1125198090Srdivacky << RegVT.getSimpleVT().SimpleTy << "\n"; 1126198090Srdivacky#endif 1127198090Srdivacky llvm_unreachable(0); 1128198090Srdivacky } 1129193323Sed case MVT::i32: 1130239462Sdim unsigned VReg = RegInfo.createVirtualRegister(&XCore::GRRegsRegClass); 1131193323Sed RegInfo.addLiveIn(VA.getLocReg(), VReg); 1132198090Srdivacky InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT)); 1133193323Sed } 1134193323Sed } else { 1135193323Sed // sanity check 1136193323Sed assert(VA.isMemLoc()); 1137193323Sed // Load the argument to a virtual register 1138193323Sed unsigned ObjSize = VA.getLocVT().getSizeInBits()/8; 1139193323Sed if (ObjSize > StackSlotSize) { 1140198090Srdivacky errs() << "LowerFormalArguments Unhandled argument type: " 1141218893Sdim << EVT(VA.getLocVT()).getEVTString() 1142198090Srdivacky << "\n"; 1143193323Sed } 1144193323Sed // Create the frame index object for this incoming parameter... 1145193323Sed int FI = MFI->CreateFixedObject(ObjSize, 1146199481Srdivacky LRSaveSize + VA.getLocMemOffset(), 1147210299Sed true); 1148193323Sed 1149193323Sed // Create the SelectionDAG nodes corresponding to a load 1150193323Sed //from this parameter 1151193323Sed SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); 1152219077Sdim InVals.push_back(DAG.getLoad(VA.getLocVT(), dl, Chain, FIN, 1153218893Sdim MachinePointerInfo::getFixedStack(FI), 1154234353Sdim false, false, false, 0)); 1155193323Sed } 1156193323Sed } 1157219077Sdim 1158193323Sed if (isVarArg) { 1159193323Sed /* Argument registers */ 1160234353Sdim static const uint16_t ArgRegs[] = { 1161193323Sed XCore::R0, XCore::R1, XCore::R2, XCore::R3 1162193323Sed }; 1163193323Sed XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); 1164193323Sed unsigned FirstVAReg = CCInfo.getFirstUnallocated(ArgRegs, 1165193323Sed array_lengthof(ArgRegs)); 1166193323Sed if (FirstVAReg < array_lengthof(ArgRegs)) { 1167193323Sed SmallVector<SDValue, 4> MemOps; 1168193323Sed int offset = 0; 1169193323Sed // Save remaining registers, storing higher register numbers at a higher 1170193323Sed // address 1171226633Sdim for (int i = array_lengthof(ArgRegs) - 1; i >= (int)FirstVAReg; --i) { 1172193323Sed // Create a stack slot 1173210299Sed int FI = MFI->CreateFixedObject(4, offset, true); 1174226633Sdim if (i == (int)FirstVAReg) { 1175193323Sed XFI->setVarArgsFrameIndex(FI); 1176193323Sed } 1177193323Sed offset -= StackSlotSize; 1178193323Sed SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); 1179193323Sed // Move argument from phys reg -> virt reg 1180239462Sdim unsigned VReg = RegInfo.createVirtualRegister(&XCore::GRRegsRegClass); 1181193323Sed RegInfo.addLiveIn(ArgRegs[i], VReg); 1182198090Srdivacky SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32); 1183193323Sed // Move argument from virt reg -> stack 1184218893Sdim SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, 1185218893Sdim MachinePointerInfo(), false, false, 0); 1186193323Sed MemOps.push_back(Store); 1187193323Sed } 1188193323Sed if (!MemOps.empty()) 1189198090Srdivacky Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, 1190198090Srdivacky &MemOps[0], MemOps.size()); 1191193323Sed } else { 1192193323Sed // This will point to the next argument passed via stack. 1193193323Sed XFI->setVarArgsFrameIndex( 1194199481Srdivacky MFI->CreateFixedObject(4, LRSaveSize + CCInfo.getNextStackOffset(), 1195210299Sed true)); 1196193323Sed } 1197193323Sed } 1198219077Sdim 1199198090Srdivacky return Chain; 1200193323Sed} 1201193323Sed 1202193323Sed//===----------------------------------------------------------------------===// 1203193323Sed// Return Value Calling Convention Implementation 1204193323Sed//===----------------------------------------------------------------------===// 1205193323Sed 1206199481Srdivackybool XCoreTargetLowering:: 1207223017SdimCanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, 1208239462Sdim bool isVarArg, 1209210299Sed const SmallVectorImpl<ISD::OutputArg> &Outs, 1210210299Sed LLVMContext &Context) const { 1211199481Srdivacky SmallVector<CCValAssign, 16> RVLocs; 1212223017Sdim CCState CCInfo(CallConv, isVarArg, MF, getTargetMachine(), RVLocs, Context); 1213210299Sed return CCInfo.CheckReturn(Outs, RetCC_XCore); 1214199481Srdivacky} 1215199481Srdivacky 1216198090SrdivackySDValue 1217198090SrdivackyXCoreTargetLowering::LowerReturn(SDValue Chain, 1218198090Srdivacky CallingConv::ID CallConv, bool isVarArg, 1219198090Srdivacky const SmallVectorImpl<ISD::OutputArg> &Outs, 1220210299Sed const SmallVectorImpl<SDValue> &OutVals, 1221207618Srdivacky DebugLoc dl, SelectionDAG &DAG) const { 1222198090Srdivacky 1223193323Sed // CCValAssign - represent the assignment of 1224193323Sed // the return value to a location 1225193323Sed SmallVector<CCValAssign, 16> RVLocs; 1226193323Sed 1227193323Sed // CCState - Info about the registers and stack slot. 1228223017Sdim CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), 1229239462Sdim getTargetMachine(), RVLocs, *DAG.getContext()); 1230193323Sed 1231223017Sdim // Analyze return values. 1232198090Srdivacky CCInfo.AnalyzeReturn(Outs, RetCC_XCore); 1233193323Sed 1234219077Sdim // If this is the first return lowered for this function, add 1235193323Sed // the regs to the liveout set for the function. 1236193323Sed if (DAG.getMachineFunction().getRegInfo().liveout_empty()) { 1237193323Sed for (unsigned i = 0; i != RVLocs.size(); ++i) 1238193323Sed if (RVLocs[i].isRegLoc()) 1239193323Sed DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg()); 1240193323Sed } 1241193323Sed 1242193323Sed SDValue Flag; 1243193323Sed 1244193323Sed // Copy the result values into the output registers. 1245193323Sed for (unsigned i = 0; i != RVLocs.size(); ++i) { 1246193323Sed CCValAssign &VA = RVLocs[i]; 1247193323Sed assert(VA.isRegLoc() && "Can only return in registers!"); 1248193323Sed 1249219077Sdim Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), 1250210299Sed OutVals[i], Flag); 1251193323Sed 1252193323Sed // guarantee that all emitted copies are 1253193323Sed // stuck together, avoiding something bad 1254193323Sed Flag = Chain.getValue(1); 1255193323Sed } 1256193323Sed 1257193323Sed // Return on XCore is always a "retsp 0" 1258193323Sed if (Flag.getNode()) 1259193323Sed return DAG.getNode(XCoreISD::RETSP, dl, MVT::Other, 1260193323Sed Chain, DAG.getConstant(0, MVT::i32), Flag); 1261193323Sed else // Return Void 1262193323Sed return DAG.getNode(XCoreISD::RETSP, dl, MVT::Other, 1263193323Sed Chain, DAG.getConstant(0, MVT::i32)); 1264193323Sed} 1265193323Sed 1266193323Sed//===----------------------------------------------------------------------===// 1267193323Sed// Other Lowering Code 1268193323Sed//===----------------------------------------------------------------------===// 1269193323Sed 1270193323SedMachineBasicBlock * 1271193323SedXCoreTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, 1272207618Srdivacky MachineBasicBlock *BB) const { 1273193323Sed const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo(); 1274193323Sed DebugLoc dl = MI->getDebugLoc(); 1275193323Sed assert((MI->getOpcode() == XCore::SELECT_CC) && 1276193323Sed "Unexpected instr type to insert"); 1277219077Sdim 1278193323Sed // To "insert" a SELECT_CC instruction, we actually have to insert the diamond 1279193323Sed // control-flow pattern. The incoming instruction knows the destination vreg 1280193323Sed // to set, the condition code register to branch on, the true/false values to 1281193323Sed // select between, and a branch opcode to use. 1282193323Sed const BasicBlock *LLVM_BB = BB->getBasicBlock(); 1283193323Sed MachineFunction::iterator It = BB; 1284193323Sed ++It; 1285219077Sdim 1286193323Sed // thisMBB: 1287193323Sed // ... 1288193323Sed // TrueVal = ... 1289193323Sed // cmpTY ccX, r1, r2 1290193323Sed // bCC copy1MBB 1291193323Sed // fallthrough --> copy0MBB 1292193323Sed MachineBasicBlock *thisMBB = BB; 1293193323Sed MachineFunction *F = BB->getParent(); 1294193323Sed MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); 1295193323Sed MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); 1296193323Sed F->insert(It, copy0MBB); 1297193323Sed F->insert(It, sinkMBB); 1298210299Sed 1299210299Sed // Transfer the remainder of BB and its successor edges to sinkMBB. 1300210299Sed sinkMBB->splice(sinkMBB->begin(), BB, 1301210299Sed llvm::next(MachineBasicBlock::iterator(MI)), 1302210299Sed BB->end()); 1303210299Sed sinkMBB->transferSuccessorsAndUpdatePHIs(BB); 1304210299Sed 1305193323Sed // Next, add the true and fallthrough blocks as its successors. 1306193323Sed BB->addSuccessor(copy0MBB); 1307193323Sed BB->addSuccessor(sinkMBB); 1308219077Sdim 1309210299Sed BuildMI(BB, dl, TII.get(XCore::BRFT_lru6)) 1310210299Sed .addReg(MI->getOperand(1).getReg()).addMBB(sinkMBB); 1311210299Sed 1312193323Sed // copy0MBB: 1313193323Sed // %FalseValue = ... 1314193323Sed // # fallthrough to sinkMBB 1315193323Sed BB = copy0MBB; 1316219077Sdim 1317193323Sed // Update machine-CFG edges 1318193323Sed BB->addSuccessor(sinkMBB); 1319219077Sdim 1320193323Sed // sinkMBB: 1321193323Sed // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] 1322193323Sed // ... 1323193323Sed BB = sinkMBB; 1324210299Sed BuildMI(*BB, BB->begin(), dl, 1325210299Sed TII.get(XCore::PHI), MI->getOperand(0).getReg()) 1326193323Sed .addReg(MI->getOperand(3).getReg()).addMBB(copy0MBB) 1327193323Sed .addReg(MI->getOperand(2).getReg()).addMBB(thisMBB); 1328219077Sdim 1329210299Sed MI->eraseFromParent(); // The pseudo instruction is gone now. 1330193323Sed return BB; 1331193323Sed} 1332193323Sed 1333193323Sed//===----------------------------------------------------------------------===// 1334198090Srdivacky// Target Optimization Hooks 1335198090Srdivacky//===----------------------------------------------------------------------===// 1336198090Srdivacky 1337198090SrdivackySDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N, 1338198090Srdivacky DAGCombinerInfo &DCI) const { 1339198090Srdivacky SelectionDAG &DAG = DCI.DAG; 1340198090Srdivacky DebugLoc dl = N->getDebugLoc(); 1341198090Srdivacky switch (N->getOpcode()) { 1342198090Srdivacky default: break; 1343204961Srdivacky case XCoreISD::LADD: { 1344204961Srdivacky SDValue N0 = N->getOperand(0); 1345204961Srdivacky SDValue N1 = N->getOperand(1); 1346204961Srdivacky SDValue N2 = N->getOperand(2); 1347204961Srdivacky ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0); 1348204961Srdivacky ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1); 1349204961Srdivacky EVT VT = N0.getValueType(); 1350204961Srdivacky 1351204961Srdivacky // canonicalize constant to RHS 1352204961Srdivacky if (N0C && !N1C) 1353204961Srdivacky return DAG.getNode(XCoreISD::LADD, dl, DAG.getVTList(VT, VT), N1, N0, N2); 1354204961Srdivacky 1355204961Srdivacky // fold (ladd 0, 0, x) -> 0, x & 1 1356204961Srdivacky if (N0C && N0C->isNullValue() && N1C && N1C->isNullValue()) { 1357204961Srdivacky SDValue Carry = DAG.getConstant(0, VT); 1358204961Srdivacky SDValue Result = DAG.getNode(ISD::AND, dl, VT, N2, 1359204961Srdivacky DAG.getConstant(1, VT)); 1360204961Srdivacky SDValue Ops [] = { Carry, Result }; 1361204961Srdivacky return DAG.getMergeValues(Ops, 2, dl); 1362204961Srdivacky } 1363204961Srdivacky 1364204961Srdivacky // fold (ladd x, 0, y) -> 0, add x, y iff carry is unused and y has only the 1365204961Srdivacky // low bit set 1366219077Sdim if (N1C && N1C->isNullValue() && N->hasNUsesOfValue(0, 0)) { 1367204961Srdivacky APInt KnownZero, KnownOne; 1368204961Srdivacky APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(), 1369204961Srdivacky VT.getSizeInBits() - 1); 1370234353Sdim DAG.ComputeMaskedBits(N2, KnownZero, KnownOne); 1371234353Sdim if ((KnownZero & Mask) == Mask) { 1372204961Srdivacky SDValue Carry = DAG.getConstant(0, VT); 1373204961Srdivacky SDValue Result = DAG.getNode(ISD::ADD, dl, VT, N0, N2); 1374204961Srdivacky SDValue Ops [] = { Carry, Result }; 1375204961Srdivacky return DAG.getMergeValues(Ops, 2, dl); 1376204961Srdivacky } 1377204961Srdivacky } 1378204961Srdivacky } 1379204961Srdivacky break; 1380204961Srdivacky case XCoreISD::LSUB: { 1381204961Srdivacky SDValue N0 = N->getOperand(0); 1382204961Srdivacky SDValue N1 = N->getOperand(1); 1383204961Srdivacky SDValue N2 = N->getOperand(2); 1384204961Srdivacky ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0); 1385204961Srdivacky ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1); 1386204961Srdivacky EVT VT = N0.getValueType(); 1387204961Srdivacky 1388204961Srdivacky // fold (lsub 0, 0, x) -> x, -x iff x has only the low bit set 1389219077Sdim if (N0C && N0C->isNullValue() && N1C && N1C->isNullValue()) { 1390204961Srdivacky APInt KnownZero, KnownOne; 1391204961Srdivacky APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(), 1392204961Srdivacky VT.getSizeInBits() - 1); 1393234353Sdim DAG.ComputeMaskedBits(N2, KnownZero, KnownOne); 1394234353Sdim if ((KnownZero & Mask) == Mask) { 1395204961Srdivacky SDValue Borrow = N2; 1396204961Srdivacky SDValue Result = DAG.getNode(ISD::SUB, dl, VT, 1397204961Srdivacky DAG.getConstant(0, VT), N2); 1398204961Srdivacky SDValue Ops [] = { Borrow, Result }; 1399204961Srdivacky return DAG.getMergeValues(Ops, 2, dl); 1400204961Srdivacky } 1401204961Srdivacky } 1402204961Srdivacky 1403204961Srdivacky // fold (lsub x, 0, y) -> 0, sub x, y iff borrow is unused and y has only the 1404204961Srdivacky // low bit set 1405219077Sdim if (N1C && N1C->isNullValue() && N->hasNUsesOfValue(0, 0)) { 1406204961Srdivacky APInt KnownZero, KnownOne; 1407204961Srdivacky APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(), 1408204961Srdivacky VT.getSizeInBits() - 1); 1409234353Sdim DAG.ComputeMaskedBits(N2, KnownZero, KnownOne); 1410234353Sdim if ((KnownZero & Mask) == Mask) { 1411204961Srdivacky SDValue Borrow = DAG.getConstant(0, VT); 1412204961Srdivacky SDValue Result = DAG.getNode(ISD::SUB, dl, VT, N0, N2); 1413204961Srdivacky SDValue Ops [] = { Borrow, Result }; 1414204961Srdivacky return DAG.getMergeValues(Ops, 2, dl); 1415204961Srdivacky } 1416204961Srdivacky } 1417204961Srdivacky } 1418204961Srdivacky break; 1419205218Srdivacky case XCoreISD::LMUL: { 1420205218Srdivacky SDValue N0 = N->getOperand(0); 1421205218Srdivacky SDValue N1 = N->getOperand(1); 1422205218Srdivacky SDValue N2 = N->getOperand(2); 1423205218Srdivacky SDValue N3 = N->getOperand(3); 1424205218Srdivacky ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0); 1425205218Srdivacky ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1); 1426205218Srdivacky EVT VT = N0.getValueType(); 1427205218Srdivacky // Canonicalize multiplicative constant to RHS. If both multiplicative 1428205218Srdivacky // operands are constant canonicalize smallest to RHS. 1429205218Srdivacky if ((N0C && !N1C) || 1430205218Srdivacky (N0C && N1C && N0C->getZExtValue() < N1C->getZExtValue())) 1431226633Sdim return DAG.getNode(XCoreISD::LMUL, dl, DAG.getVTList(VT, VT), 1432226633Sdim N1, N0, N2, N3); 1433205218Srdivacky 1434205218Srdivacky // lmul(x, 0, a, b) 1435205218Srdivacky if (N1C && N1C->isNullValue()) { 1436205218Srdivacky // If the high result is unused fold to add(a, b) 1437205218Srdivacky if (N->hasNUsesOfValue(0, 0)) { 1438205218Srdivacky SDValue Lo = DAG.getNode(ISD::ADD, dl, VT, N2, N3); 1439205218Srdivacky SDValue Ops [] = { Lo, Lo }; 1440205218Srdivacky return DAG.getMergeValues(Ops, 2, dl); 1441205218Srdivacky } 1442205218Srdivacky // Otherwise fold to ladd(a, b, 0) 1443205218Srdivacky return DAG.getNode(XCoreISD::LADD, dl, DAG.getVTList(VT, VT), N2, N3, N1); 1444205218Srdivacky } 1445205218Srdivacky } 1446205218Srdivacky break; 1447204961Srdivacky case ISD::ADD: { 1448205218Srdivacky // Fold 32 bit expressions such as add(add(mul(x,y),a),b) -> 1449205218Srdivacky // lmul(x, y, a, b). The high result of lmul will be ignored. 1450204961Srdivacky // This is only profitable if the intermediate results are unused 1451204961Srdivacky // elsewhere. 1452204961Srdivacky SDValue Mul0, Mul1, Addend0, Addend1; 1453205218Srdivacky if (N->getValueType(0) == MVT::i32 && 1454205218Srdivacky isADDADDMUL(SDValue(N, 0), Mul0, Mul1, Addend0, Addend1, true)) { 1455204961Srdivacky SDValue Ignored = DAG.getNode(XCoreISD::LMUL, dl, 1456204961Srdivacky DAG.getVTList(MVT::i32, MVT::i32), Mul0, 1457204961Srdivacky Mul1, Addend0, Addend1); 1458204961Srdivacky SDValue Result(Ignored.getNode(), 1); 1459204961Srdivacky return Result; 1460204961Srdivacky } 1461205218Srdivacky APInt HighMask = APInt::getHighBitsSet(64, 32); 1462205218Srdivacky // Fold 64 bit expression such as add(add(mul(x,y),a),b) -> 1463205218Srdivacky // lmul(x, y, a, b) if all operands are zero-extended. We do this 1464205218Srdivacky // before type legalization as it is messy to match the operands after 1465205218Srdivacky // that. 1466205218Srdivacky if (N->getValueType(0) == MVT::i64 && 1467205218Srdivacky isADDADDMUL(SDValue(N, 0), Mul0, Mul1, Addend0, Addend1, false) && 1468205218Srdivacky DAG.MaskedValueIsZero(Mul0, HighMask) && 1469205218Srdivacky DAG.MaskedValueIsZero(Mul1, HighMask) && 1470205218Srdivacky DAG.MaskedValueIsZero(Addend0, HighMask) && 1471205218Srdivacky DAG.MaskedValueIsZero(Addend1, HighMask)) { 1472205218Srdivacky SDValue Mul0L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 1473205218Srdivacky Mul0, DAG.getConstant(0, MVT::i32)); 1474205218Srdivacky SDValue Mul1L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 1475205218Srdivacky Mul1, DAG.getConstant(0, MVT::i32)); 1476205218Srdivacky SDValue Addend0L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 1477205218Srdivacky Addend0, DAG.getConstant(0, MVT::i32)); 1478205218Srdivacky SDValue Addend1L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 1479205218Srdivacky Addend1, DAG.getConstant(0, MVT::i32)); 1480205218Srdivacky SDValue Hi = DAG.getNode(XCoreISD::LMUL, dl, 1481205218Srdivacky DAG.getVTList(MVT::i32, MVT::i32), Mul0L, Mul1L, 1482205218Srdivacky Addend0L, Addend1L); 1483205218Srdivacky SDValue Lo(Hi.getNode(), 1); 1484205218Srdivacky return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi); 1485205218Srdivacky } 1486204961Srdivacky } 1487204961Srdivacky break; 1488198090Srdivacky case ISD::STORE: { 1489198090Srdivacky // Replace unaligned store of unaligned load with memmove. 1490198090Srdivacky StoreSDNode *ST = cast<StoreSDNode>(N); 1491198090Srdivacky if (!DCI.isBeforeLegalize() || 1492198090Srdivacky allowsUnalignedMemoryAccesses(ST->getMemoryVT()) || 1493198090Srdivacky ST->isVolatile() || ST->isIndexed()) { 1494198090Srdivacky break; 1495198090Srdivacky } 1496198090Srdivacky SDValue Chain = ST->getChain(); 1497198090Srdivacky 1498198090Srdivacky unsigned StoreBits = ST->getMemoryVT().getStoreSizeInBits(); 1499198090Srdivacky if (StoreBits % 8) { 1500198090Srdivacky break; 1501198090Srdivacky } 1502198090Srdivacky unsigned ABIAlignment = getTargetData()->getABITypeAlignment( 1503198090Srdivacky ST->getMemoryVT().getTypeForEVT(*DCI.DAG.getContext())); 1504198090Srdivacky unsigned Alignment = ST->getAlignment(); 1505198090Srdivacky if (Alignment >= ABIAlignment) { 1506198090Srdivacky break; 1507198090Srdivacky } 1508198090Srdivacky 1509198090Srdivacky if (LoadSDNode *LD = dyn_cast<LoadSDNode>(ST->getValue())) { 1510198090Srdivacky if (LD->hasNUsesOfValue(1, 0) && ST->getMemoryVT() == LD->getMemoryVT() && 1511198090Srdivacky LD->getAlignment() == Alignment && 1512198090Srdivacky !LD->isVolatile() && !LD->isIndexed() && 1513198090Srdivacky Chain.reachesChainWithoutSideEffects(SDValue(LD, 1))) { 1514198090Srdivacky return DAG.getMemmove(Chain, dl, ST->getBasePtr(), 1515198090Srdivacky LD->getBasePtr(), 1516198090Srdivacky DAG.getConstant(StoreBits/8, MVT::i32), 1517218893Sdim Alignment, false, ST->getPointerInfo(), 1518218893Sdim LD->getPointerInfo()); 1519198090Srdivacky } 1520198090Srdivacky } 1521198090Srdivacky break; 1522198090Srdivacky } 1523198090Srdivacky } 1524198090Srdivacky return SDValue(); 1525198090Srdivacky} 1526198090Srdivacky 1527204961Srdivackyvoid XCoreTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op, 1528204961Srdivacky APInt &KnownZero, 1529204961Srdivacky APInt &KnownOne, 1530204961Srdivacky const SelectionDAG &DAG, 1531204961Srdivacky unsigned Depth) const { 1532234353Sdim KnownZero = KnownOne = APInt(KnownZero.getBitWidth(), 0); 1533204961Srdivacky switch (Op.getOpcode()) { 1534204961Srdivacky default: break; 1535204961Srdivacky case XCoreISD::LADD: 1536204961Srdivacky case XCoreISD::LSUB: 1537204961Srdivacky if (Op.getResNo() == 0) { 1538204961Srdivacky // Top bits of carry / borrow are clear. 1539234353Sdim KnownZero = APInt::getHighBitsSet(KnownZero.getBitWidth(), 1540234353Sdim KnownZero.getBitWidth() - 1); 1541204961Srdivacky } 1542204961Srdivacky break; 1543204961Srdivacky } 1544204961Srdivacky} 1545204961Srdivacky 1546198090Srdivacky//===----------------------------------------------------------------------===// 1547193323Sed// Addressing mode description hooks 1548193323Sed//===----------------------------------------------------------------------===// 1549193323Sed 1550193323Sedstatic inline bool isImmUs(int64_t val) 1551193323Sed{ 1552193323Sed return (val >= 0 && val <= 11); 1553193323Sed} 1554193323Sed 1555193323Sedstatic inline bool isImmUs2(int64_t val) 1556193323Sed{ 1557193323Sed return (val%2 == 0 && isImmUs(val/2)); 1558193323Sed} 1559193323Sed 1560193323Sedstatic inline bool isImmUs4(int64_t val) 1561193323Sed{ 1562193323Sed return (val%4 == 0 && isImmUs(val/4)); 1563193323Sed} 1564193323Sed 1565193323Sed/// isLegalAddressingMode - Return true if the addressing mode represented 1566193323Sed/// by AM is legal for this target, for a load/store of the specified type. 1567193323Sedbool 1568219077SdimXCoreTargetLowering::isLegalAddressingMode(const AddrMode &AM, 1569226633Sdim Type *Ty) const { 1570198090Srdivacky if (Ty->getTypeID() == Type::VoidTyID) 1571204642Srdivacky return AM.Scale == 0 && isImmUs(AM.BaseOffs) && isImmUs4(AM.BaseOffs); 1572198090Srdivacky 1573198090Srdivacky const TargetData *TD = TM.getTargetData(); 1574198090Srdivacky unsigned Size = TD->getTypeAllocSize(Ty); 1575193323Sed if (AM.BaseGV) { 1576198090Srdivacky return Size >= 4 && !AM.HasBaseReg && AM.Scale == 0 && 1577193323Sed AM.BaseOffs%4 == 0; 1578193323Sed } 1579219077Sdim 1580198090Srdivacky switch (Size) { 1581198090Srdivacky case 1: 1582193323Sed // reg + imm 1583193323Sed if (AM.Scale == 0) { 1584193323Sed return isImmUs(AM.BaseOffs); 1585193323Sed } 1586198090Srdivacky // reg + reg 1587193323Sed return AM.Scale == 1 && AM.BaseOffs == 0; 1588198090Srdivacky case 2: 1589198090Srdivacky case 3: 1590193323Sed // reg + imm 1591193323Sed if (AM.Scale == 0) { 1592193323Sed return isImmUs2(AM.BaseOffs); 1593193323Sed } 1594198090Srdivacky // reg + reg<<1 1595193323Sed return AM.Scale == 2 && AM.BaseOffs == 0; 1596198090Srdivacky default: 1597193323Sed // reg + imm 1598193323Sed if (AM.Scale == 0) { 1599193323Sed return isImmUs4(AM.BaseOffs); 1600193323Sed } 1601193323Sed // reg + reg<<2 1602193323Sed return AM.Scale == 4 && AM.BaseOffs == 0; 1603193323Sed } 1604193323Sed} 1605193323Sed 1606193323Sed//===----------------------------------------------------------------------===// 1607193323Sed// XCore Inline Assembly Support 1608193323Sed//===----------------------------------------------------------------------===// 1609193323Sed 1610224145Sdimstd::pair<unsigned, const TargetRegisterClass*> 1611224145SdimXCoreTargetLowering:: 1612224145SdimgetRegForInlineAsmConstraint(const std::string &Constraint, 1613239462Sdim EVT VT) const { 1614224145Sdim if (Constraint.size() == 1) { 1615224145Sdim switch (Constraint[0]) { 1616193323Sed default : break; 1617193323Sed case 'r': 1618239462Sdim return std::make_pair(0U, &XCore::GRRegsRegClass); 1619224145Sdim } 1620193323Sed } 1621224145Sdim // Use the default implementation in TargetLowering to convert the register 1622224145Sdim // constraint into a member of a register class. 1623224145Sdim return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); 1624193323Sed} 1625