1234353Sdim//===-- XCoreISelLowering.cpp - XCore DAG Lowering Implementation ---------===// 2193323Sed// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6193323Sed// 7193323Sed//===----------------------------------------------------------------------===// 8193323Sed// 9193323Sed// This file implements the XCoreTargetLowering class. 10193323Sed// 11193323Sed//===----------------------------------------------------------------------===// 12193323Sed 13193323Sed#include "XCoreISelLowering.h" 14249423Sdim#include "XCore.h" 15193323Sed#include "XCoreMachineFunctionInfo.h" 16249423Sdim#include "XCoreSubtarget.h" 17249423Sdim#include "XCoreTargetMachine.h" 18198090Srdivacky#include "XCoreTargetObjectFile.h" 19193323Sed#include "llvm/CodeGen/CallingConvLower.h" 20193323Sed#include "llvm/CodeGen/MachineFrameInfo.h" 21193323Sed#include "llvm/CodeGen/MachineFunction.h" 22193323Sed#include "llvm/CodeGen/MachineInstrBuilder.h" 23204642Srdivacky#include "llvm/CodeGen/MachineJumpTableInfo.h" 24193323Sed#include "llvm/CodeGen/MachineRegisterInfo.h" 25193323Sed#include "llvm/CodeGen/SelectionDAGISel.h" 26193323Sed#include "llvm/CodeGen/ValueTypes.h" 27249423Sdim#include "llvm/IR/CallingConv.h" 28276479Sdim#include "llvm/IR/Constants.h" 29249423Sdim#include "llvm/IR/DerivedTypes.h" 30249423Sdim#include "llvm/IR/Function.h" 31249423Sdim#include "llvm/IR/GlobalAlias.h" 32249423Sdim#include "llvm/IR/GlobalVariable.h" 33249423Sdim#include "llvm/IR/Intrinsics.h" 34360784Sdim#include "llvm/IR/IntrinsicsXCore.h" 35193323Sed#include "llvm/Support/Debug.h" 36198090Srdivacky#include "llvm/Support/ErrorHandling.h" 37321369Sdim#include "llvm/Support/KnownBits.h" 38198090Srdivacky#include "llvm/Support/raw_ostream.h" 39251662Sdim#include <algorithm> 40251662Sdim 41193323Sedusing namespace llvm; 42193323Sed 43276479Sdim#define DEBUG_TYPE "xcore-lower" 44276479Sdim 45193323Sedconst char *XCoreTargetLowering:: 46219077SdimgetTargetNodeName(unsigned Opcode) const 47193323Sed{ 48288943Sdim switch ((XCoreISD::NodeType)Opcode) 49193323Sed { 50288943Sdim case XCoreISD::FIRST_NUMBER : break; 51193323Sed case XCoreISD::BL : return "XCoreISD::BL"; 52193323Sed case XCoreISD::PCRelativeWrapper : return "XCoreISD::PCRelativeWrapper"; 53193323Sed case XCoreISD::DPRelativeWrapper : return "XCoreISD::DPRelativeWrapper"; 54193323Sed case XCoreISD::CPRelativeWrapper : return "XCoreISD::CPRelativeWrapper"; 55276479Sdim case XCoreISD::LDWSP : return "XCoreISD::LDWSP"; 56193323Sed case XCoreISD::STWSP : return "XCoreISD::STWSP"; 57193323Sed case XCoreISD::RETSP : return "XCoreISD::RETSP"; 58198090Srdivacky case XCoreISD::LADD : return "XCoreISD::LADD"; 59198090Srdivacky case XCoreISD::LSUB : return "XCoreISD::LSUB"; 60204961Srdivacky case XCoreISD::LMUL : return "XCoreISD::LMUL"; 61204961Srdivacky case XCoreISD::MACCU : return "XCoreISD::MACCU"; 62204961Srdivacky case XCoreISD::MACCS : return "XCoreISD::MACCS"; 63249423Sdim case XCoreISD::CRC8 : return "XCoreISD::CRC8"; 64204642Srdivacky case XCoreISD::BR_JT : return "XCoreISD::BR_JT"; 65204642Srdivacky case XCoreISD::BR_JT32 : return "XCoreISD::BR_JT32"; 66276479Sdim case XCoreISD::FRAME_TO_ARGS_OFFSET : return "XCoreISD::FRAME_TO_ARGS_OFFSET"; 67276479Sdim case XCoreISD::EH_RETURN : return "XCoreISD::EH_RETURN"; 68261991Sdim case XCoreISD::MEMBARRIER : return "XCoreISD::MEMBARRIER"; 69193323Sed } 70288943Sdim return nullptr; 71193323Sed} 72193323Sed 73288943SdimXCoreTargetLowering::XCoreTargetLowering(const TargetMachine &TM, 74288943Sdim const XCoreSubtarget &Subtarget) 75288943Sdim : TargetLowering(TM), TM(TM), Subtarget(Subtarget) { 76193323Sed 77193323Sed // Set up the register classes. 78239462Sdim addRegisterClass(MVT::i32, &XCore::GRRegsRegClass); 79193323Sed 80193323Sed // Compute derived properties from the register classes 81288943Sdim computeRegisterProperties(Subtarget.getRegisterInfo()); 82193323Sed 83193323Sed setStackPointerRegisterToSaveRestore(XCore::SP); 84193323Sed 85261991Sdim setSchedulingPreference(Sched::Source); 86193323Sed 87193323Sed // Use i32 for setcc operations results (slt, sgt, ...). 88193323Sed setBooleanContents(ZeroOrOneBooleanContent); 89226633Sdim setBooleanVectorContents(ZeroOrOneBooleanContent); // FIXME: Is this correct? 90193323Sed 91193323Sed // XCore does not have the NodeTypes below. 92249423Sdim setOperationAction(ISD::BR_CC, MVT::i32, Expand); 93276479Sdim setOperationAction(ISD::SELECT_CC, MVT::i32, Expand); 94193323Sed 95193323Sed // 64bit 96198090Srdivacky setOperationAction(ISD::ADD, MVT::i64, Custom); 97198090Srdivacky setOperationAction(ISD::SUB, MVT::i64, Custom); 98204961Srdivacky setOperationAction(ISD::SMUL_LOHI, MVT::i32, Custom); 99204961Srdivacky setOperationAction(ISD::UMUL_LOHI, MVT::i32, Custom); 100193323Sed setOperationAction(ISD::MULHS, MVT::i32, Expand); 101193323Sed setOperationAction(ISD::MULHU, MVT::i32, Expand); 102193323Sed setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); 103193323Sed setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); 104193323Sed setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); 105219077Sdim 106193323Sed // Bit Manipulation 107193323Sed setOperationAction(ISD::CTPOP, MVT::i32, Expand); 108193323Sed setOperationAction(ISD::ROTL , MVT::i32, Expand); 109193323Sed setOperationAction(ISD::ROTR , MVT::i32, Expand); 110219077Sdim 111193323Sed setOperationAction(ISD::TRAP, MVT::Other, Legal); 112219077Sdim 113204642Srdivacky // Jump tables. 114204642Srdivacky setOperationAction(ISD::BR_JT, MVT::Other, Custom); 115193323Sed 116193323Sed setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); 117199511Srdivacky setOperationAction(ISD::BlockAddress, MVT::i32 , Custom); 118199511Srdivacky 119193323Sed // Conversion of i64 -> double produces constantpool nodes 120193323Sed setOperationAction(ISD::ConstantPool, MVT::i32, Custom); 121193323Sed 122193323Sed // Loads 123280031Sdim for (MVT VT : MVT::integer_valuetypes()) { 124280031Sdim setLoadExtAction(ISD::EXTLOAD, VT, MVT::i1, Promote); 125280031Sdim setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i1, Promote); 126280031Sdim setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote); 127193323Sed 128280031Sdim setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i8, Expand); 129280031Sdim setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i16, Expand); 130280031Sdim } 131198090Srdivacky 132198090Srdivacky // Custom expand misaligned loads / stores. 133198090Srdivacky setOperationAction(ISD::LOAD, MVT::i32, Custom); 134198090Srdivacky setOperationAction(ISD::STORE, MVT::i32, Custom); 135198090Srdivacky 136193323Sed // Varargs 137193323Sed setOperationAction(ISD::VAEND, MVT::Other, Expand); 138193323Sed setOperationAction(ISD::VACOPY, MVT::Other, Expand); 139193323Sed setOperationAction(ISD::VAARG, MVT::Other, Custom); 140193323Sed setOperationAction(ISD::VASTART, MVT::Other, Custom); 141219077Sdim 142193323Sed // Dynamic stack 143193323Sed setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); 144193323Sed setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); 145193323Sed setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand); 146198090Srdivacky 147261991Sdim // Exception handling 148276479Sdim setOperationAction(ISD::EH_RETURN, MVT::Other, Custom); 149276479Sdim setOperationAction(ISD::FRAME_TO_ARGS_OFFSET, MVT::i32, Custom); 150261991Sdim 151261991Sdim // Atomic operations 152276479Sdim // We request a fence for ATOMIC_* instructions, to reduce them to Monotonic. 153276479Sdim // As we are always Sequential Consistent, an ATOMIC_FENCE becomes a no OP. 154261991Sdim setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom); 155276479Sdim setOperationAction(ISD::ATOMIC_LOAD, MVT::i32, Custom); 156276479Sdim setOperationAction(ISD::ATOMIC_STORE, MVT::i32, Custom); 157261991Sdim 158218893Sdim // TRAMPOLINE is custom lowered. 159226633Sdim setOperationAction(ISD::INIT_TRAMPOLINE, MVT::Other, Custom); 160226633Sdim setOperationAction(ISD::ADJUST_TRAMPOLINE, MVT::Other, Custom); 161218893Sdim 162249423Sdim // We want to custom lower some of our intrinsics. 163249423Sdim setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom); 164218893Sdim 165249423Sdim MaxStoresPerMemset = MaxStoresPerMemsetOptSize = 4; 166249423Sdim MaxStoresPerMemmove = MaxStoresPerMemmoveOptSize 167249423Sdim = MaxStoresPerMemcpy = MaxStoresPerMemcpyOptSize = 2; 168249423Sdim 169198090Srdivacky // We have target-specific dag combine patterns for the following nodes: 170198090Srdivacky setTargetDAGCombine(ISD::STORE); 171204961Srdivacky setTargetDAGCombine(ISD::ADD); 172276479Sdim setTargetDAGCombine(ISD::INTRINSIC_VOID); 173276479Sdim setTargetDAGCombine(ISD::INTRINSIC_W_CHAIN); 174223017Sdim 175360784Sdim setMinFunctionAlignment(Align(2)); 176360784Sdim setPrefFunctionAlignment(Align(4)); 177193323Sed} 178193323Sed 179261991Sdimbool XCoreTargetLowering::isZExtFree(SDValue Val, EVT VT2) const { 180261991Sdim if (Val.getOpcode() != ISD::LOAD) 181261991Sdim return false; 182261991Sdim 183261991Sdim EVT VT1 = Val.getValueType(); 184261991Sdim if (!VT1.isSimple() || !VT1.isInteger() || 185261991Sdim !VT2.isSimple() || !VT2.isInteger()) 186261991Sdim return false; 187261991Sdim 188261991Sdim switch (VT1.getSimpleVT().SimpleTy) { 189261991Sdim default: break; 190261991Sdim case MVT::i8: 191261991Sdim return true; 192261991Sdim } 193261991Sdim 194261991Sdim return false; 195261991Sdim} 196261991Sdim 197193323SedSDValue XCoreTargetLowering:: 198207618SrdivackyLowerOperation(SDValue Op, SelectionDAG &DAG) const { 199219077Sdim switch (Op.getOpcode()) 200193323Sed { 201276479Sdim case ISD::EH_RETURN: return LowerEH_RETURN(Op, DAG); 202249423Sdim case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); 203249423Sdim case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); 204249423Sdim case ISD::ConstantPool: return LowerConstantPool(Op, DAG); 205249423Sdim case ISD::BR_JT: return LowerBR_JT(Op, DAG); 206249423Sdim case ISD::LOAD: return LowerLOAD(Op, DAG); 207249423Sdim case ISD::STORE: return LowerSTORE(Op, DAG); 208249423Sdim case ISD::VAARG: return LowerVAARG(Op, DAG); 209249423Sdim case ISD::VASTART: return LowerVASTART(Op, DAG); 210249423Sdim case ISD::SMUL_LOHI: return LowerSMUL_LOHI(Op, DAG); 211249423Sdim case ISD::UMUL_LOHI: return LowerUMUL_LOHI(Op, DAG); 212193323Sed // FIXME: Remove these when LegalizeDAGTypes lands. 213193323Sed case ISD::ADD: 214249423Sdim case ISD::SUB: return ExpandADDSUB(Op.getNode(), DAG); 215249423Sdim case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG); 216276479Sdim case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG); 217276479Sdim case ISD::FRAME_TO_ARGS_OFFSET: return LowerFRAME_TO_ARGS_OFFSET(Op, DAG); 218249423Sdim case ISD::INIT_TRAMPOLINE: return LowerINIT_TRAMPOLINE(Op, DAG); 219249423Sdim case ISD::ADJUST_TRAMPOLINE: return LowerADJUST_TRAMPOLINE(Op, DAG); 220249423Sdim case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG); 221261991Sdim case ISD::ATOMIC_FENCE: return LowerATOMIC_FENCE(Op, DAG); 222276479Sdim case ISD::ATOMIC_LOAD: return LowerATOMIC_LOAD(Op, DAG); 223276479Sdim case ISD::ATOMIC_STORE: return LowerATOMIC_STORE(Op, DAG); 224193323Sed default: 225198090Srdivacky llvm_unreachable("unimplemented operand"); 226193323Sed } 227193323Sed} 228193323Sed 229193323Sed/// ReplaceNodeResults - Replace the results of node with an illegal result 230193323Sed/// type with new values built out of custom code. 231193323Sedvoid XCoreTargetLowering::ReplaceNodeResults(SDNode *N, 232193323Sed SmallVectorImpl<SDValue>&Results, 233207618Srdivacky SelectionDAG &DAG) const { 234193323Sed switch (N->getOpcode()) { 235193323Sed default: 236198090Srdivacky llvm_unreachable("Don't know how to custom expand this!"); 237193323Sed case ISD::ADD: 238193323Sed case ISD::SUB: 239193323Sed Results.push_back(ExpandADDSUB(N, DAG)); 240193323Sed return; 241193323Sed } 242193323Sed} 243193323Sed 244193323Sed//===----------------------------------------------------------------------===// 245193323Sed// Misc Lower Operation implementation 246193323Sed//===----------------------------------------------------------------------===// 247193323Sed 248276479SdimSDValue XCoreTargetLowering::getGlobalAddressWrapper(SDValue GA, 249276479Sdim const GlobalValue *GV, 250276479Sdim SelectionDAG &DAG) const { 251193323Sed // FIXME there is no actual debug info here 252261991Sdim SDLoc dl(GA); 253276479Sdim 254309124Sdim if (GV->getValueType()->isFunctionTy()) 255276479Sdim return DAG.getNode(XCoreISD::PCRelativeWrapper, dl, MVT::i32, GA); 256276479Sdim 257276479Sdim const auto *GVar = dyn_cast<GlobalVariable>(GV); 258309124Sdim if ((GV->hasSection() && GV->getSection().startswith(".cp.")) || 259276479Sdim (GVar && GVar->isConstant() && GV->hasLocalLinkage())) 260276479Sdim return DAG.getNode(XCoreISD::CPRelativeWrapper, dl, MVT::i32, GA); 261276479Sdim 262276479Sdim return DAG.getNode(XCoreISD::DPRelativeWrapper, dl, MVT::i32, GA); 263193323Sed} 264193323Sed 265276479Sdimstatic bool IsSmallObject(const GlobalValue *GV, const XCoreTargetLowering &XTL) { 266276479Sdim if (XTL.getTargetMachine().getCodeModel() == CodeModel::Small) 267276479Sdim return true; 268276479Sdim 269309124Sdim Type *ObjType = GV->getValueType(); 270276479Sdim if (!ObjType->isSized()) 271276479Sdim return false; 272276479Sdim 273288943Sdim auto &DL = GV->getParent()->getDataLayout(); 274288943Sdim unsigned ObjSize = DL.getTypeAllocSize(ObjType); 275276479Sdim return ObjSize < CodeModelLargeSize && ObjSize != 0; 276276479Sdim} 277276479Sdim 278193323SedSDValue XCoreTargetLowering:: 279207618SrdivackyLowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const 280193323Sed{ 281251662Sdim const GlobalAddressSDNode *GN = cast<GlobalAddressSDNode>(Op); 282251662Sdim const GlobalValue *GV = GN->getGlobal(); 283276479Sdim SDLoc DL(GN); 284251662Sdim int64_t Offset = GN->getOffset(); 285276479Sdim if (IsSmallObject(GV, *this)) { 286276479Sdim // We can only fold positive offsets that are a multiple of the word size. 287276479Sdim int64_t FoldedOffset = std::max(Offset & ~3, (int64_t)0); 288276479Sdim SDValue GA = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, FoldedOffset); 289276479Sdim GA = getGlobalAddressWrapper(GA, GV, DAG); 290276479Sdim // Handle the rest of the offset. 291276479Sdim if (Offset != FoldedOffset) { 292288943Sdim SDValue Remaining = DAG.getConstant(Offset - FoldedOffset, DL, MVT::i32); 293276479Sdim GA = DAG.getNode(ISD::ADD, DL, MVT::i32, GA, Remaining); 294276479Sdim } 295276479Sdim return GA; 296276479Sdim } else { 297276479Sdim // Ideally we would not fold in offset with an index <= 11. 298276479Sdim Type *Ty = Type::getInt8PtrTy(*DAG.getContext()); 299276479Sdim Constant *GA = ConstantExpr::getBitCast(const_cast<GlobalValue*>(GV), Ty); 300276479Sdim Ty = Type::getInt32Ty(*DAG.getContext()); 301276479Sdim Constant *Idx = ConstantInt::get(Ty, Offset); 302288943Sdim Constant *GAI = ConstantExpr::getGetElementPtr( 303288943Sdim Type::getInt8Ty(*DAG.getContext()), GA, Idx); 304276479Sdim SDValue CP = DAG.getConstantPool(GAI, MVT::i32); 305288943Sdim return DAG.getLoad(getPointerTy(DAG.getDataLayout()), DL, 306309124Sdim DAG.getEntryNode(), CP, MachinePointerInfo()); 307251662Sdim } 308193323Sed} 309193323Sed 310193323SedSDValue XCoreTargetLowering:: 311207618SrdivackyLowerBlockAddress(SDValue Op, SelectionDAG &DAG) const 312199511Srdivacky{ 313261991Sdim SDLoc DL(Op); 314288943Sdim auto PtrVT = getPointerTy(DAG.getDataLayout()); 315207618Srdivacky const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress(); 316288943Sdim SDValue Result = DAG.getTargetBlockAddress(BA, PtrVT); 317199511Srdivacky 318288943Sdim return DAG.getNode(XCoreISD::PCRelativeWrapper, DL, PtrVT, Result); 319199511Srdivacky} 320199511Srdivacky 321199511SrdivackySDValue XCoreTargetLowering:: 322207618SrdivackyLowerConstantPool(SDValue Op, SelectionDAG &DAG) const 323193323Sed{ 324193323Sed ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op); 325193323Sed // FIXME there isn't really debug info here 326261991Sdim SDLoc dl(CP); 327198090Srdivacky EVT PtrVT = Op.getValueType(); 328198090Srdivacky SDValue Res; 329198090Srdivacky if (CP->isMachineConstantPoolEntry()) { 330198090Srdivacky Res = DAG.getTargetConstantPool(CP->getMachineCPVal(), PtrVT, 331276479Sdim CP->getAlignment(), CP->getOffset()); 332193323Sed } else { 333198090Srdivacky Res = DAG.getTargetConstantPool(CP->getConstVal(), PtrVT, 334276479Sdim CP->getAlignment(), CP->getOffset()); 335193323Sed } 336198090Srdivacky return DAG.getNode(XCoreISD::CPRelativeWrapper, dl, MVT::i32, Res); 337193323Sed} 338193323Sed 339205218Srdivackyunsigned XCoreTargetLowering::getJumpTableEncoding() const { 340205218Srdivacky return MachineJumpTableInfo::EK_Inline; 341205218Srdivacky} 342205218Srdivacky 343193323SedSDValue XCoreTargetLowering:: 344207618SrdivackyLowerBR_JT(SDValue Op, SelectionDAG &DAG) const 345193323Sed{ 346204642Srdivacky SDValue Chain = Op.getOperand(0); 347204642Srdivacky SDValue Table = Op.getOperand(1); 348204642Srdivacky SDValue Index = Op.getOperand(2); 349261991Sdim SDLoc dl(Op); 350204642Srdivacky JumpTableSDNode *JT = cast<JumpTableSDNode>(Table); 351204642Srdivacky unsigned JTI = JT->getIndex(); 352204642Srdivacky MachineFunction &MF = DAG.getMachineFunction(); 353204642Srdivacky const MachineJumpTableInfo *MJTI = MF.getJumpTableInfo(); 354204642Srdivacky SDValue TargetJT = DAG.getTargetJumpTable(JT->getIndex(), MVT::i32); 355204642Srdivacky 356204642Srdivacky unsigned NumEntries = MJTI->getJumpTables()[JTI].MBBs.size(); 357204642Srdivacky if (NumEntries <= 32) { 358204642Srdivacky return DAG.getNode(XCoreISD::BR_JT, dl, MVT::Other, Chain, TargetJT, Index); 359204642Srdivacky } 360204642Srdivacky assert((NumEntries >> 31) == 0); 361204642Srdivacky SDValue ScaledIndex = DAG.getNode(ISD::SHL, dl, MVT::i32, Index, 362288943Sdim DAG.getConstant(1, dl, MVT::i32)); 363204642Srdivacky return DAG.getNode(XCoreISD::BR_JT32, dl, MVT::Other, Chain, TargetJT, 364204642Srdivacky ScaledIndex); 365193323Sed} 366193323Sed 367309124SdimSDValue XCoreTargetLowering::lowerLoadWordFromAlignedBasePlusOffset( 368309124Sdim const SDLoc &DL, SDValue Chain, SDValue Base, int64_t Offset, 369309124Sdim SelectionDAG &DAG) const { 370288943Sdim auto PtrVT = getPointerTy(DAG.getDataLayout()); 371251662Sdim if ((Offset & 0x3) == 0) { 372309124Sdim return DAG.getLoad(PtrVT, DL, Chain, Base, MachinePointerInfo()); 373198090Srdivacky } 374251662Sdim // Lower to pair of consecutive word aligned loads plus some bit shifting. 375309124Sdim int32_t HighOffset = alignTo(Offset, 4); 376251662Sdim int32_t LowOffset = HighOffset - 4; 377251662Sdim SDValue LowAddr, HighAddr; 378251662Sdim if (GlobalAddressSDNode *GASD = 379251662Sdim dyn_cast<GlobalAddressSDNode>(Base.getNode())) { 380251662Sdim LowAddr = DAG.getGlobalAddress(GASD->getGlobal(), DL, Base.getValueType(), 381251662Sdim LowOffset); 382251662Sdim HighAddr = DAG.getGlobalAddress(GASD->getGlobal(), DL, Base.getValueType(), 383251662Sdim HighOffset); 384251662Sdim } else { 385251662Sdim LowAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, Base, 386288943Sdim DAG.getConstant(LowOffset, DL, MVT::i32)); 387251662Sdim HighAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, Base, 388288943Sdim DAG.getConstant(HighOffset, DL, MVT::i32)); 389198090Srdivacky } 390288943Sdim SDValue LowShift = DAG.getConstant((Offset - LowOffset) * 8, DL, MVT::i32); 391288943Sdim SDValue HighShift = DAG.getConstant((HighOffset - Offset) * 8, DL, MVT::i32); 392251662Sdim 393309124Sdim SDValue Low = DAG.getLoad(PtrVT, DL, Chain, LowAddr, MachinePointerInfo()); 394309124Sdim SDValue High = DAG.getLoad(PtrVT, DL, Chain, HighAddr, MachinePointerInfo()); 395251662Sdim SDValue LowShifted = DAG.getNode(ISD::SRL, DL, MVT::i32, Low, LowShift); 396251662Sdim SDValue HighShifted = DAG.getNode(ISD::SHL, DL, MVT::i32, High, HighShift); 397251662Sdim SDValue Result = DAG.getNode(ISD::OR, DL, MVT::i32, LowShifted, HighShifted); 398251662Sdim Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Low.getValue(1), 399251662Sdim High.getValue(1)); 400251662Sdim SDValue Ops[] = { Result, Chain }; 401276479Sdim return DAG.getMergeValues(Ops, DL); 402198090Srdivacky} 403198090Srdivacky 404251662Sdimstatic bool isWordAligned(SDValue Value, SelectionDAG &DAG) 405251662Sdim{ 406344779Sdim KnownBits Known = DAG.computeKnownBits(Value); 407321369Sdim return Known.countMinTrailingZeros() >= 2; 408251662Sdim} 409251662Sdim 410353358SdimSDValue XCoreTargetLowering::LowerLOAD(SDValue Op, SelectionDAG &DAG) const { 411251662Sdim const TargetLowering &TLI = DAG.getTargetLoweringInfo(); 412353358Sdim LLVMContext &Context = *DAG.getContext(); 413198090Srdivacky LoadSDNode *LD = cast<LoadSDNode>(Op); 414198090Srdivacky assert(LD->getExtensionType() == ISD::NON_EXTLOAD && 415198090Srdivacky "Unexpected extension type"); 416198090Srdivacky assert(LD->getMemoryVT() == MVT::i32 && "Unexpected load EVT"); 417218893Sdim 418360784Sdim if (allowsMemoryAccessForAlignment(Context, DAG.getDataLayout(), 419360784Sdim LD->getMemoryVT(), *LD->getMemOperand())) 420198090Srdivacky return SDValue(); 421218893Sdim 422198090Srdivacky SDValue Chain = LD->getChain(); 423198090Srdivacky SDValue BasePtr = LD->getBasePtr(); 424261991Sdim SDLoc DL(Op); 425219077Sdim 426251662Sdim if (!LD->isVolatile()) { 427251662Sdim const GlobalValue *GV; 428251662Sdim int64_t Offset = 0; 429251662Sdim if (DAG.isBaseWithConstantOffset(BasePtr) && 430251662Sdim isWordAligned(BasePtr->getOperand(0), DAG)) { 431251662Sdim SDValue NewBasePtr = BasePtr->getOperand(0); 432251662Sdim Offset = cast<ConstantSDNode>(BasePtr->getOperand(1))->getSExtValue(); 433251662Sdim return lowerLoadWordFromAlignedBasePlusOffset(DL, Chain, NewBasePtr, 434251662Sdim Offset, DAG); 435198090Srdivacky } 436251662Sdim if (TLI.isGAPlusOffset(BasePtr.getNode(), GV, Offset) && 437251662Sdim MinAlign(GV->getAlignment(), 4) == 4) { 438251662Sdim SDValue NewBasePtr = DAG.getGlobalAddress(GV, DL, 439251662Sdim BasePtr->getValueType(0)); 440251662Sdim return lowerLoadWordFromAlignedBasePlusOffset(DL, Chain, NewBasePtr, 441251662Sdim Offset, DAG); 442251662Sdim } 443198090Srdivacky } 444219077Sdim 445198090Srdivacky if (LD->getAlignment() == 2) { 446309124Sdim SDValue Low = 447309124Sdim DAG.getExtLoad(ISD::ZEXTLOAD, DL, MVT::i32, Chain, BasePtr, 448309124Sdim LD->getPointerInfo(), MVT::i16, 449309124Sdim /* Alignment = */ 2, LD->getMemOperand()->getFlags()); 450218893Sdim SDValue HighAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, BasePtr, 451288943Sdim DAG.getConstant(2, DL, MVT::i32)); 452309124Sdim SDValue High = 453309124Sdim DAG.getExtLoad(ISD::EXTLOAD, DL, MVT::i32, Chain, HighAddr, 454309124Sdim LD->getPointerInfo().getWithOffset(2), MVT::i16, 455309124Sdim /* Alignment = */ 2, LD->getMemOperand()->getFlags()); 456218893Sdim SDValue HighShifted = DAG.getNode(ISD::SHL, DL, MVT::i32, High, 457288943Sdim DAG.getConstant(16, DL, MVT::i32)); 458218893Sdim SDValue Result = DAG.getNode(ISD::OR, DL, MVT::i32, Low, HighShifted); 459218893Sdim Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Low.getValue(1), 460198090Srdivacky High.getValue(1)); 461198090Srdivacky SDValue Ops[] = { Result, Chain }; 462276479Sdim return DAG.getMergeValues(Ops, DL); 463198090Srdivacky } 464219077Sdim 465198090Srdivacky // Lower to a call to __misaligned_load(BasePtr). 466353358Sdim Type *IntPtrTy = DAG.getDataLayout().getIntPtrType(Context); 467198090Srdivacky TargetLowering::ArgListTy Args; 468198090Srdivacky TargetLowering::ArgListEntry Entry; 469219077Sdim 470198090Srdivacky Entry.Ty = IntPtrTy; 471198090Srdivacky Entry.Node = BasePtr; 472198090Srdivacky Args.push_back(Entry); 473219077Sdim 474276479Sdim TargetLowering::CallLoweringInfo CLI(DAG); 475321369Sdim CLI.setDebugLoc(DL).setChain(Chain).setLibCallee( 476288943Sdim CallingConv::C, IntPtrTy, 477288943Sdim DAG.getExternalSymbol("__misaligned_load", 478288943Sdim getPointerTy(DAG.getDataLayout())), 479309124Sdim std::move(Args)); 480276479Sdim 481239462Sdim std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI); 482276479Sdim SDValue Ops[] = { CallResult.first, CallResult.second }; 483276479Sdim return DAG.getMergeValues(Ops, DL); 484198090Srdivacky} 485198090Srdivacky 486353358SdimSDValue XCoreTargetLowering::LowerSTORE(SDValue Op, SelectionDAG &DAG) const { 487353358Sdim LLVMContext &Context = *DAG.getContext(); 488198090Srdivacky StoreSDNode *ST = cast<StoreSDNode>(Op); 489198090Srdivacky assert(!ST->isTruncatingStore() && "Unexpected store type"); 490198090Srdivacky assert(ST->getMemoryVT() == MVT::i32 && "Unexpected store EVT"); 491353358Sdim 492360784Sdim if (allowsMemoryAccessForAlignment(Context, DAG.getDataLayout(), 493360784Sdim ST->getMemoryVT(), *ST->getMemOperand())) 494198090Srdivacky return SDValue(); 495353358Sdim 496198090Srdivacky SDValue Chain = ST->getChain(); 497198090Srdivacky SDValue BasePtr = ST->getBasePtr(); 498198090Srdivacky SDValue Value = ST->getValue(); 499261991Sdim SDLoc dl(Op); 500219077Sdim 501198090Srdivacky if (ST->getAlignment() == 2) { 502198090Srdivacky SDValue Low = Value; 503198090Srdivacky SDValue High = DAG.getNode(ISD::SRL, dl, MVT::i32, Value, 504353358Sdim DAG.getConstant(16, dl, MVT::i32)); 505309124Sdim SDValue StoreLow = DAG.getTruncStore( 506309124Sdim Chain, dl, Low, BasePtr, ST->getPointerInfo(), MVT::i16, 507309124Sdim /* Alignment = */ 2, ST->getMemOperand()->getFlags()); 508198090Srdivacky SDValue HighAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, BasePtr, 509288943Sdim DAG.getConstant(2, dl, MVT::i32)); 510309124Sdim SDValue StoreHigh = DAG.getTruncStore( 511309124Sdim Chain, dl, High, HighAddr, ST->getPointerInfo().getWithOffset(2), 512309124Sdim MVT::i16, /* Alignment = */ 2, ST->getMemOperand()->getFlags()); 513198090Srdivacky return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, StoreLow, StoreHigh); 514198090Srdivacky } 515219077Sdim 516198090Srdivacky // Lower to a call to __misaligned_store(BasePtr, Value). 517353358Sdim Type *IntPtrTy = DAG.getDataLayout().getIntPtrType(Context); 518198090Srdivacky TargetLowering::ArgListTy Args; 519198090Srdivacky TargetLowering::ArgListEntry Entry; 520219077Sdim 521198090Srdivacky Entry.Ty = IntPtrTy; 522198090Srdivacky Entry.Node = BasePtr; 523198090Srdivacky Args.push_back(Entry); 524219077Sdim 525198090Srdivacky Entry.Node = Value; 526198090Srdivacky Args.push_back(Entry); 527219077Sdim 528276479Sdim TargetLowering::CallLoweringInfo CLI(DAG); 529288943Sdim CLI.setDebugLoc(dl).setChain(Chain).setCallee( 530353358Sdim CallingConv::C, Type::getVoidTy(Context), 531288943Sdim DAG.getExternalSymbol("__misaligned_store", 532288943Sdim getPointerTy(DAG.getDataLayout())), 533309124Sdim std::move(Args)); 534276479Sdim 535239462Sdim std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI); 536198090Srdivacky return CallResult.second; 537198090Srdivacky} 538198090Srdivacky 539198090SrdivackySDValue XCoreTargetLowering:: 540207618SrdivackyLowerSMUL_LOHI(SDValue Op, SelectionDAG &DAG) const 541204961Srdivacky{ 542204961Srdivacky assert(Op.getValueType() == MVT::i32 && Op.getOpcode() == ISD::SMUL_LOHI && 543204961Srdivacky "Unexpected operand to lower!"); 544261991Sdim SDLoc dl(Op); 545204961Srdivacky SDValue LHS = Op.getOperand(0); 546204961Srdivacky SDValue RHS = Op.getOperand(1); 547288943Sdim SDValue Zero = DAG.getConstant(0, dl, MVT::i32); 548204961Srdivacky SDValue Hi = DAG.getNode(XCoreISD::MACCS, dl, 549204961Srdivacky DAG.getVTList(MVT::i32, MVT::i32), Zero, Zero, 550204961Srdivacky LHS, RHS); 551204961Srdivacky SDValue Lo(Hi.getNode(), 1); 552204961Srdivacky SDValue Ops[] = { Lo, Hi }; 553276479Sdim return DAG.getMergeValues(Ops, dl); 554204961Srdivacky} 555204961Srdivacky 556204961SrdivackySDValue XCoreTargetLowering:: 557207618SrdivackyLowerUMUL_LOHI(SDValue Op, SelectionDAG &DAG) const 558204961Srdivacky{ 559204961Srdivacky assert(Op.getValueType() == MVT::i32 && Op.getOpcode() == ISD::UMUL_LOHI && 560204961Srdivacky "Unexpected operand to lower!"); 561261991Sdim SDLoc dl(Op); 562204961Srdivacky SDValue LHS = Op.getOperand(0); 563204961Srdivacky SDValue RHS = Op.getOperand(1); 564288943Sdim SDValue Zero = DAG.getConstant(0, dl, MVT::i32); 565204961Srdivacky SDValue Hi = DAG.getNode(XCoreISD::LMUL, dl, 566204961Srdivacky DAG.getVTList(MVT::i32, MVT::i32), LHS, RHS, 567204961Srdivacky Zero, Zero); 568204961Srdivacky SDValue Lo(Hi.getNode(), 1); 569204961Srdivacky SDValue Ops[] = { Lo, Hi }; 570276479Sdim return DAG.getMergeValues(Ops, dl); 571204961Srdivacky} 572204961Srdivacky 573204961Srdivacky/// isADDADDMUL - Return whether Op is in a form that is equivalent to 574204961Srdivacky/// add(add(mul(x,y),a),b). If requireIntermediatesHaveOneUse is true then 575204961Srdivacky/// each intermediate result in the calculation must also have a single use. 576204961Srdivacky/// If the Op is in the correct form the constituent parts are written to Mul0, 577204961Srdivacky/// Mul1, Addend0 and Addend1. 578204961Srdivackystatic bool 579204961SrdivackyisADDADDMUL(SDValue Op, SDValue &Mul0, SDValue &Mul1, SDValue &Addend0, 580204961Srdivacky SDValue &Addend1, bool requireIntermediatesHaveOneUse) 581204961Srdivacky{ 582204961Srdivacky if (Op.getOpcode() != ISD::ADD) 583204961Srdivacky return false; 584204961Srdivacky SDValue N0 = Op.getOperand(0); 585204961Srdivacky SDValue N1 = Op.getOperand(1); 586204961Srdivacky SDValue AddOp; 587204961Srdivacky SDValue OtherOp; 588204961Srdivacky if (N0.getOpcode() == ISD::ADD) { 589204961Srdivacky AddOp = N0; 590204961Srdivacky OtherOp = N1; 591204961Srdivacky } else if (N1.getOpcode() == ISD::ADD) { 592204961Srdivacky AddOp = N1; 593204961Srdivacky OtherOp = N0; 594204961Srdivacky } else { 595204961Srdivacky return false; 596204961Srdivacky } 597204961Srdivacky if (requireIntermediatesHaveOneUse && !AddOp.hasOneUse()) 598204961Srdivacky return false; 599204961Srdivacky if (OtherOp.getOpcode() == ISD::MUL) { 600204961Srdivacky // add(add(a,b),mul(x,y)) 601204961Srdivacky if (requireIntermediatesHaveOneUse && !OtherOp.hasOneUse()) 602204961Srdivacky return false; 603204961Srdivacky Mul0 = OtherOp.getOperand(0); 604204961Srdivacky Mul1 = OtherOp.getOperand(1); 605204961Srdivacky Addend0 = AddOp.getOperand(0); 606204961Srdivacky Addend1 = AddOp.getOperand(1); 607204961Srdivacky return true; 608204961Srdivacky } 609204961Srdivacky if (AddOp.getOperand(0).getOpcode() == ISD::MUL) { 610204961Srdivacky // add(add(mul(x,y),a),b) 611204961Srdivacky if (requireIntermediatesHaveOneUse && !AddOp.getOperand(0).hasOneUse()) 612204961Srdivacky return false; 613204961Srdivacky Mul0 = AddOp.getOperand(0).getOperand(0); 614204961Srdivacky Mul1 = AddOp.getOperand(0).getOperand(1); 615204961Srdivacky Addend0 = AddOp.getOperand(1); 616204961Srdivacky Addend1 = OtherOp; 617204961Srdivacky return true; 618204961Srdivacky } 619204961Srdivacky if (AddOp.getOperand(1).getOpcode() == ISD::MUL) { 620204961Srdivacky // add(add(a,mul(x,y)),b) 621204961Srdivacky if (requireIntermediatesHaveOneUse && !AddOp.getOperand(1).hasOneUse()) 622204961Srdivacky return false; 623204961Srdivacky Mul0 = AddOp.getOperand(1).getOperand(0); 624204961Srdivacky Mul1 = AddOp.getOperand(1).getOperand(1); 625204961Srdivacky Addend0 = AddOp.getOperand(0); 626204961Srdivacky Addend1 = OtherOp; 627204961Srdivacky return true; 628204961Srdivacky } 629204961Srdivacky return false; 630204961Srdivacky} 631204961Srdivacky 632204961SrdivackySDValue XCoreTargetLowering:: 633207618SrdivackyTryExpandADDWithMul(SDNode *N, SelectionDAG &DAG) const 634204961Srdivacky{ 635204961Srdivacky SDValue Mul; 636204961Srdivacky SDValue Other; 637204961Srdivacky if (N->getOperand(0).getOpcode() == ISD::MUL) { 638204961Srdivacky Mul = N->getOperand(0); 639204961Srdivacky Other = N->getOperand(1); 640204961Srdivacky } else if (N->getOperand(1).getOpcode() == ISD::MUL) { 641204961Srdivacky Mul = N->getOperand(1); 642204961Srdivacky Other = N->getOperand(0); 643204961Srdivacky } else { 644204961Srdivacky return SDValue(); 645204961Srdivacky } 646261991Sdim SDLoc dl(N); 647204961Srdivacky SDValue LL, RL, AddendL, AddendH; 648204961Srdivacky LL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 649288943Sdim Mul.getOperand(0), DAG.getConstant(0, dl, MVT::i32)); 650204961Srdivacky RL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 651288943Sdim Mul.getOperand(1), DAG.getConstant(0, dl, MVT::i32)); 652204961Srdivacky AddendL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 653288943Sdim Other, DAG.getConstant(0, dl, MVT::i32)); 654204961Srdivacky AddendH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 655288943Sdim Other, DAG.getConstant(1, dl, MVT::i32)); 656204961Srdivacky APInt HighMask = APInt::getHighBitsSet(64, 32); 657204961Srdivacky unsigned LHSSB = DAG.ComputeNumSignBits(Mul.getOperand(0)); 658204961Srdivacky unsigned RHSSB = DAG.ComputeNumSignBits(Mul.getOperand(1)); 659204961Srdivacky if (DAG.MaskedValueIsZero(Mul.getOperand(0), HighMask) && 660204961Srdivacky DAG.MaskedValueIsZero(Mul.getOperand(1), HighMask)) { 661204961Srdivacky // The inputs are both zero-extended. 662204961Srdivacky SDValue Hi = DAG.getNode(XCoreISD::MACCU, dl, 663204961Srdivacky DAG.getVTList(MVT::i32, MVT::i32), AddendH, 664204961Srdivacky AddendL, LL, RL); 665204961Srdivacky SDValue Lo(Hi.getNode(), 1); 666204961Srdivacky return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi); 667204961Srdivacky } 668204961Srdivacky if (LHSSB > 32 && RHSSB > 32) { 669204961Srdivacky // The inputs are both sign-extended. 670204961Srdivacky SDValue Hi = DAG.getNode(XCoreISD::MACCS, dl, 671204961Srdivacky DAG.getVTList(MVT::i32, MVT::i32), AddendH, 672204961Srdivacky AddendL, LL, RL); 673204961Srdivacky SDValue Lo(Hi.getNode(), 1); 674204961Srdivacky return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi); 675204961Srdivacky } 676204961Srdivacky SDValue LH, RH; 677204961Srdivacky LH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 678288943Sdim Mul.getOperand(0), DAG.getConstant(1, dl, MVT::i32)); 679204961Srdivacky RH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 680288943Sdim Mul.getOperand(1), DAG.getConstant(1, dl, MVT::i32)); 681204961Srdivacky SDValue Hi = DAG.getNode(XCoreISD::MACCU, dl, 682204961Srdivacky DAG.getVTList(MVT::i32, MVT::i32), AddendH, 683204961Srdivacky AddendL, LL, RL); 684204961Srdivacky SDValue Lo(Hi.getNode(), 1); 685204961Srdivacky RH = DAG.getNode(ISD::MUL, dl, MVT::i32, LL, RH); 686204961Srdivacky LH = DAG.getNode(ISD::MUL, dl, MVT::i32, LH, RL); 687204961Srdivacky Hi = DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, RH); 688204961Srdivacky Hi = DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, LH); 689204961Srdivacky return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi); 690204961Srdivacky} 691204961Srdivacky 692204961SrdivackySDValue XCoreTargetLowering:: 693207618SrdivackyExpandADDSUB(SDNode *N, SelectionDAG &DAG) const 694193323Sed{ 695193323Sed assert(N->getValueType(0) == MVT::i64 && 696193323Sed (N->getOpcode() == ISD::ADD || N->getOpcode() == ISD::SUB) && 697193323Sed "Unknown operand to lower!"); 698204961Srdivacky 699309124Sdim if (N->getOpcode() == ISD::ADD) 700309124Sdim if (SDValue Result = TryExpandADDWithMul(N, DAG)) 701204961Srdivacky return Result; 702204961Srdivacky 703261991Sdim SDLoc dl(N); 704219077Sdim 705193323Sed // Extract components 706193323Sed SDValue LHSL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 707288943Sdim N->getOperand(0), 708288943Sdim DAG.getConstant(0, dl, MVT::i32)); 709193323Sed SDValue LHSH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 710288943Sdim N->getOperand(0), 711288943Sdim DAG.getConstant(1, dl, MVT::i32)); 712193323Sed SDValue RHSL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 713288943Sdim N->getOperand(1), 714288943Sdim DAG.getConstant(0, dl, MVT::i32)); 715193323Sed SDValue RHSH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 716288943Sdim N->getOperand(1), 717288943Sdim DAG.getConstant(1, dl, MVT::i32)); 718219077Sdim 719193323Sed // Expand 720193323Sed unsigned Opcode = (N->getOpcode() == ISD::ADD) ? XCoreISD::LADD : 721193323Sed XCoreISD::LSUB; 722288943Sdim SDValue Zero = DAG.getConstant(0, dl, MVT::i32); 723249423Sdim SDValue Lo = DAG.getNode(Opcode, dl, DAG.getVTList(MVT::i32, MVT::i32), 724249423Sdim LHSL, RHSL, Zero); 725249423Sdim SDValue Carry(Lo.getNode(), 1); 726219077Sdim 727249423Sdim SDValue Hi = DAG.getNode(Opcode, dl, DAG.getVTList(MVT::i32, MVT::i32), 728249423Sdim LHSH, RHSH, Carry); 729249423Sdim SDValue Ignored(Hi.getNode(), 1); 730193323Sed // Merge the pieces 731193323Sed return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi); 732193323Sed} 733193323Sed 734193323SedSDValue XCoreTargetLowering:: 735207618SrdivackyLowerVAARG(SDValue Op, SelectionDAG &DAG) const 736193323Sed{ 737261991Sdim // Whist llvm does not support aggregate varargs we can ignore 738261991Sdim // the possibility of the ValueType being an implicit byVal vararg. 739193323Sed SDNode *Node = Op.getNode(); 740261991Sdim EVT VT = Node->getValueType(0); // not an aggregate 741261991Sdim SDValue InChain = Node->getOperand(0); 742261991Sdim SDValue VAListPtr = Node->getOperand(1); 743261991Sdim EVT PtrVT = VAListPtr.getValueType(); 744261991Sdim const Value *SV = cast<SrcValueSDNode>(Node->getOperand(2))->getValue(); 745261991Sdim SDLoc dl(Node); 746309124Sdim SDValue VAList = 747309124Sdim DAG.getLoad(PtrVT, dl, InChain, VAListPtr, MachinePointerInfo(SV)); 748193323Sed // Increment the pointer, VAList, to the next vararg 749261991Sdim SDValue nextPtr = DAG.getNode(ISD::ADD, dl, PtrVT, VAList, 750288943Sdim DAG.getIntPtrConstant(VT.getSizeInBits() / 8, 751288943Sdim dl)); 752193323Sed // Store the incremented VAList to the legalized pointer 753261991Sdim InChain = DAG.getStore(VAList.getValue(1), dl, nextPtr, VAListPtr, 754309124Sdim MachinePointerInfo(SV)); 755193323Sed // Load the actual argument out of the pointer VAList 756309124Sdim return DAG.getLoad(VT, dl, InChain, VAList, MachinePointerInfo()); 757193323Sed} 758193323Sed 759193323SedSDValue XCoreTargetLowering:: 760207618SrdivackyLowerVASTART(SDValue Op, SelectionDAG &DAG) const 761193323Sed{ 762261991Sdim SDLoc dl(Op); 763193323Sed // vastart stores the address of the VarArgsFrameIndex slot into the 764193323Sed // memory location argument 765193323Sed MachineFunction &MF = DAG.getMachineFunction(); 766193323Sed XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); 767193323Sed SDValue Addr = DAG.getFrameIndex(XFI->getVarArgsFrameIndex(), MVT::i32); 768219077Sdim return DAG.getStore(Op.getOperand(0), dl, Addr, Op.getOperand(1), 769309124Sdim MachinePointerInfo()); 770193323Sed} 771193323Sed 772207618SrdivackySDValue XCoreTargetLowering::LowerFRAMEADDR(SDValue Op, 773207618Srdivacky SelectionDAG &DAG) const { 774276479Sdim // This nodes represent llvm.frameaddress on the DAG. 775276479Sdim // It takes one operand, the index of the frame address to return. 776276479Sdim // An index of zero corresponds to the current function's frame address. 777276479Sdim // An index of one to the parent's frame address, and so on. 778219077Sdim // Depths > 0 not supported yet! 779193323Sed if (cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() > 0) 780193323Sed return SDValue(); 781219077Sdim 782193323Sed MachineFunction &MF = DAG.getMachineFunction(); 783288943Sdim const TargetRegisterInfo *RegInfo = Subtarget.getRegisterInfo(); 784276479Sdim return DAG.getCopyFromReg(DAG.getEntryNode(), SDLoc(Op), 785193323Sed RegInfo->getFrameRegister(MF), MVT::i32); 786193323Sed} 787193323Sed 788218893SdimSDValue XCoreTargetLowering:: 789276479SdimLowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const { 790276479Sdim // This nodes represent llvm.returnaddress on the DAG. 791276479Sdim // It takes one operand, the index of the return address to return. 792276479Sdim // An index of zero corresponds to the current function's return address. 793276479Sdim // An index of one to the parent's return address, and so on. 794276479Sdim // Depths > 0 not supported yet! 795276479Sdim if (cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() > 0) 796276479Sdim return SDValue(); 797276479Sdim 798276479Sdim MachineFunction &MF = DAG.getMachineFunction(); 799276479Sdim XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); 800276479Sdim int FI = XFI->createLRSpillSlot(MF); 801276479Sdim SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); 802309124Sdim return DAG.getLoad(getPointerTy(DAG.getDataLayout()), SDLoc(Op), 803309124Sdim DAG.getEntryNode(), FIN, 804309124Sdim MachinePointerInfo::getFixedStack(MF, FI)); 805276479Sdim} 806276479Sdim 807276479SdimSDValue XCoreTargetLowering:: 808276479SdimLowerFRAME_TO_ARGS_OFFSET(SDValue Op, SelectionDAG &DAG) const { 809276479Sdim // This node represents offset from frame pointer to first on-stack argument. 810276479Sdim // This is needed for correct stack adjustment during unwind. 811276479Sdim // However, we don't know the offset until after the frame has be finalised. 812276479Sdim // This is done during the XCoreFTAOElim pass. 813276479Sdim return DAG.getNode(XCoreISD::FRAME_TO_ARGS_OFFSET, SDLoc(Op), MVT::i32); 814276479Sdim} 815276479Sdim 816276479SdimSDValue XCoreTargetLowering:: 817276479SdimLowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const { 818276479Sdim // OUTCHAIN = EH_RETURN(INCHAIN, OFFSET, HANDLER) 819276479Sdim // This node represents 'eh_return' gcc dwarf builtin, which is used to 820276479Sdim // return from exception. The general meaning is: adjust stack by OFFSET and 821276479Sdim // pass execution to HANDLER. 822276479Sdim MachineFunction &MF = DAG.getMachineFunction(); 823276479Sdim SDValue Chain = Op.getOperand(0); 824276479Sdim SDValue Offset = Op.getOperand(1); 825276479Sdim SDValue Handler = Op.getOperand(2); 826276479Sdim SDLoc dl(Op); 827276479Sdim 828276479Sdim // Absolute SP = (FP + FrameToArgs) + Offset 829288943Sdim const TargetRegisterInfo *RegInfo = Subtarget.getRegisterInfo(); 830276479Sdim SDValue Stack = DAG.getCopyFromReg(DAG.getEntryNode(), dl, 831276479Sdim RegInfo->getFrameRegister(MF), MVT::i32); 832276479Sdim SDValue FrameToArgs = DAG.getNode(XCoreISD::FRAME_TO_ARGS_OFFSET, dl, 833276479Sdim MVT::i32); 834276479Sdim Stack = DAG.getNode(ISD::ADD, dl, MVT::i32, Stack, FrameToArgs); 835276479Sdim Stack = DAG.getNode(ISD::ADD, dl, MVT::i32, Stack, Offset); 836276479Sdim 837276479Sdim // R0=ExceptionPointerRegister R1=ExceptionSelectorRegister 838276479Sdim // which leaves 2 caller saved registers, R2 & R3 for us to use. 839276479Sdim unsigned StackReg = XCore::R2; 840276479Sdim unsigned HandlerReg = XCore::R3; 841276479Sdim 842276479Sdim SDValue OutChains[] = { 843276479Sdim DAG.getCopyToReg(Chain, dl, StackReg, Stack), 844276479Sdim DAG.getCopyToReg(Chain, dl, HandlerReg, Handler) 845276479Sdim }; 846276479Sdim 847276479Sdim Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains); 848276479Sdim 849276479Sdim return DAG.getNode(XCoreISD::EH_RETURN, dl, MVT::Other, Chain, 850276479Sdim DAG.getRegister(StackReg, MVT::i32), 851276479Sdim DAG.getRegister(HandlerReg, MVT::i32)); 852276479Sdim 853276479Sdim} 854276479Sdim 855276479SdimSDValue XCoreTargetLowering:: 856226633SdimLowerADJUST_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const { 857226633Sdim return Op.getOperand(0); 858226633Sdim} 859226633Sdim 860226633SdimSDValue XCoreTargetLowering:: 861226633SdimLowerINIT_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const { 862218893Sdim SDValue Chain = Op.getOperand(0); 863218893Sdim SDValue Trmp = Op.getOperand(1); // trampoline 864218893Sdim SDValue FPtr = Op.getOperand(2); // nested function 865218893Sdim SDValue Nest = Op.getOperand(3); // 'nest' parameter value 866218893Sdim 867218893Sdim const Value *TrmpAddr = cast<SrcValueSDNode>(Op.getOperand(4))->getValue(); 868218893Sdim 869218893Sdim // .align 4 870218893Sdim // LDAPF_u10 r11, nest 871218893Sdim // LDW_2rus r11, r11[0] 872218893Sdim // STWSP_ru6 r11, sp[0] 873218893Sdim // LDAPF_u10 r11, fptr 874218893Sdim // LDW_2rus r11, r11[0] 875218893Sdim // BAU_1r r11 876218893Sdim // nest: 877218893Sdim // .word nest 878218893Sdim // fptr: 879218893Sdim // .word fptr 880218893Sdim SDValue OutChains[5]; 881218893Sdim 882218893Sdim SDValue Addr = Trmp; 883218893Sdim 884261991Sdim SDLoc dl(Op); 885309124Sdim OutChains[0] = 886309124Sdim DAG.getStore(Chain, dl, DAG.getConstant(0x0a3cd805, dl, MVT::i32), Addr, 887309124Sdim MachinePointerInfo(TrmpAddr)); 888218893Sdim 889218893Sdim Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp, 890288943Sdim DAG.getConstant(4, dl, MVT::i32)); 891309124Sdim OutChains[1] = 892309124Sdim DAG.getStore(Chain, dl, DAG.getConstant(0xd80456c0, dl, MVT::i32), Addr, 893309124Sdim MachinePointerInfo(TrmpAddr, 4)); 894218893Sdim 895218893Sdim Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp, 896288943Sdim DAG.getConstant(8, dl, MVT::i32)); 897309124Sdim OutChains[2] = 898309124Sdim DAG.getStore(Chain, dl, DAG.getConstant(0x27fb0a3c, dl, MVT::i32), Addr, 899309124Sdim MachinePointerInfo(TrmpAddr, 8)); 900218893Sdim 901218893Sdim Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp, 902288943Sdim DAG.getConstant(12, dl, MVT::i32)); 903309124Sdim OutChains[3] = 904309124Sdim DAG.getStore(Chain, dl, Nest, Addr, MachinePointerInfo(TrmpAddr, 12)); 905218893Sdim 906218893Sdim Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp, 907288943Sdim DAG.getConstant(16, dl, MVT::i32)); 908309124Sdim OutChains[4] = 909309124Sdim DAG.getStore(Chain, dl, FPtr, Addr, MachinePointerInfo(TrmpAddr, 16)); 910218893Sdim 911276479Sdim return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains); 912218893Sdim} 913218893Sdim 914249423SdimSDValue XCoreTargetLowering:: 915249423SdimLowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const { 916261991Sdim SDLoc DL(Op); 917249423Sdim unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); 918249423Sdim switch (IntNo) { 919249423Sdim case Intrinsic::xcore_crc8: 920249423Sdim EVT VT = Op.getValueType(); 921249423Sdim SDValue Data = 922249423Sdim DAG.getNode(XCoreISD::CRC8, DL, DAG.getVTList(VT, VT), 923249423Sdim Op.getOperand(1), Op.getOperand(2) , Op.getOperand(3)); 924249423Sdim SDValue Crc(Data.getNode(), 1); 925249423Sdim SDValue Results[] = { Crc, Data }; 926276479Sdim return DAG.getMergeValues(Results, DL); 927249423Sdim } 928249423Sdim return SDValue(); 929249423Sdim} 930249423Sdim 931261991SdimSDValue XCoreTargetLowering:: 932261991SdimLowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG) const { 933261991Sdim SDLoc DL(Op); 934261991Sdim return DAG.getNode(XCoreISD::MEMBARRIER, DL, MVT::Other, Op.getOperand(0)); 935261991Sdim} 936261991Sdim 937276479SdimSDValue XCoreTargetLowering:: 938276479SdimLowerATOMIC_LOAD(SDValue Op, SelectionDAG &DAG) const { 939276479Sdim AtomicSDNode *N = cast<AtomicSDNode>(Op); 940276479Sdim assert(N->getOpcode() == ISD::ATOMIC_LOAD && "Bad Atomic OP"); 941309124Sdim assert((N->getOrdering() == AtomicOrdering::Unordered || 942309124Sdim N->getOrdering() == AtomicOrdering::Monotonic) && 943309124Sdim "setInsertFencesForAtomic(true) expects unordered / monotonic"); 944276479Sdim if (N->getMemoryVT() == MVT::i32) { 945276479Sdim if (N->getAlignment() < 4) 946276479Sdim report_fatal_error("atomic load must be aligned"); 947288943Sdim return DAG.getLoad(getPointerTy(DAG.getDataLayout()), SDLoc(Op), 948288943Sdim N->getChain(), N->getBasePtr(), N->getPointerInfo(), 949309124Sdim N->getAlignment(), N->getMemOperand()->getFlags(), 950309124Sdim N->getAAInfo(), N->getRanges()); 951276479Sdim } 952276479Sdim if (N->getMemoryVT() == MVT::i16) { 953276479Sdim if (N->getAlignment() < 2) 954276479Sdim report_fatal_error("atomic load must be aligned"); 955276479Sdim return DAG.getExtLoad(ISD::EXTLOAD, SDLoc(Op), MVT::i32, N->getChain(), 956276479Sdim N->getBasePtr(), N->getPointerInfo(), MVT::i16, 957309124Sdim N->getAlignment(), N->getMemOperand()->getFlags(), 958309124Sdim N->getAAInfo()); 959276479Sdim } 960276479Sdim if (N->getMemoryVT() == MVT::i8) 961276479Sdim return DAG.getExtLoad(ISD::EXTLOAD, SDLoc(Op), MVT::i32, N->getChain(), 962276479Sdim N->getBasePtr(), N->getPointerInfo(), MVT::i8, 963309124Sdim N->getAlignment(), N->getMemOperand()->getFlags(), 964309124Sdim N->getAAInfo()); 965276479Sdim return SDValue(); 966276479Sdim} 967276479Sdim 968276479SdimSDValue XCoreTargetLowering:: 969276479SdimLowerATOMIC_STORE(SDValue Op, SelectionDAG &DAG) const { 970276479Sdim AtomicSDNode *N = cast<AtomicSDNode>(Op); 971276479Sdim assert(N->getOpcode() == ISD::ATOMIC_STORE && "Bad Atomic OP"); 972309124Sdim assert((N->getOrdering() == AtomicOrdering::Unordered || 973309124Sdim N->getOrdering() == AtomicOrdering::Monotonic) && 974309124Sdim "setInsertFencesForAtomic(true) expects unordered / monotonic"); 975276479Sdim if (N->getMemoryVT() == MVT::i32) { 976276479Sdim if (N->getAlignment() < 4) 977276479Sdim report_fatal_error("atomic store must be aligned"); 978309124Sdim return DAG.getStore(N->getChain(), SDLoc(Op), N->getVal(), N->getBasePtr(), 979309124Sdim N->getPointerInfo(), N->getAlignment(), 980309124Sdim N->getMemOperand()->getFlags(), N->getAAInfo()); 981276479Sdim } 982276479Sdim if (N->getMemoryVT() == MVT::i16) { 983276479Sdim if (N->getAlignment() < 2) 984276479Sdim report_fatal_error("atomic store must be aligned"); 985276479Sdim return DAG.getTruncStore(N->getChain(), SDLoc(Op), N->getVal(), 986276479Sdim N->getBasePtr(), N->getPointerInfo(), MVT::i16, 987309124Sdim N->getAlignment(), N->getMemOperand()->getFlags(), 988309124Sdim N->getAAInfo()); 989276479Sdim } 990276479Sdim if (N->getMemoryVT() == MVT::i8) 991276479Sdim return DAG.getTruncStore(N->getChain(), SDLoc(Op), N->getVal(), 992276479Sdim N->getBasePtr(), N->getPointerInfo(), MVT::i8, 993309124Sdim N->getAlignment(), N->getMemOperand()->getFlags(), 994309124Sdim N->getAAInfo()); 995276479Sdim return SDValue(); 996276479Sdim} 997276479Sdim 998353358SdimMachineMemOperand::Flags 999353358SdimXCoreTargetLowering::getMMOFlags(const Instruction &I) const { 1000353358Sdim // Because of how we convert atomic_load and atomic_store to normal loads and 1001353358Sdim // stores in the DAG, we need to ensure that the MMOs are marked volatile 1002353358Sdim // since DAGCombine hasn't been updated to account for atomic, but non 1003353358Sdim // volatile loads. (See D57601) 1004353358Sdim if (auto *SI = dyn_cast<StoreInst>(&I)) 1005353358Sdim if (SI->isAtomic()) 1006353358Sdim return MachineMemOperand::MOVolatile; 1007353358Sdim if (auto *LI = dyn_cast<LoadInst>(&I)) 1008353358Sdim if (LI->isAtomic()) 1009353358Sdim return MachineMemOperand::MOVolatile; 1010353358Sdim if (auto *AI = dyn_cast<AtomicRMWInst>(&I)) 1011353358Sdim if (AI->isAtomic()) 1012353358Sdim return MachineMemOperand::MOVolatile; 1013353358Sdim if (auto *AI = dyn_cast<AtomicCmpXchgInst>(&I)) 1014353358Sdim if (AI->isAtomic()) 1015353358Sdim return MachineMemOperand::MOVolatile; 1016353358Sdim return MachineMemOperand::MONone; 1017353358Sdim} 1018353358Sdim 1019193323Sed//===----------------------------------------------------------------------===// 1020193323Sed// Calling Convention Implementation 1021193323Sed//===----------------------------------------------------------------------===// 1022193323Sed 1023193323Sed#include "XCoreGenCallingConv.inc" 1024193323Sed 1025193323Sed//===----------------------------------------------------------------------===// 1026198090Srdivacky// Call Calling Convention Implementation 1027193323Sed//===----------------------------------------------------------------------===// 1028193323Sed 1029198090Srdivacky/// XCore call implementation 1030198090SrdivackySDValue 1031239462SdimXCoreTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, 1032207618Srdivacky SmallVectorImpl<SDValue> &InVals) const { 1033239462Sdim SelectionDAG &DAG = CLI.DAG; 1034261991Sdim SDLoc &dl = CLI.DL; 1035261991Sdim SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs; 1036261991Sdim SmallVectorImpl<SDValue> &OutVals = CLI.OutVals; 1037261991Sdim SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins; 1038239462Sdim SDValue Chain = CLI.Chain; 1039239462Sdim SDValue Callee = CLI.Callee; 1040239462Sdim bool &isTailCall = CLI.IsTailCall; 1041239462Sdim CallingConv::ID CallConv = CLI.CallConv; 1042239462Sdim bool isVarArg = CLI.IsVarArg; 1043239462Sdim 1044203954Srdivacky // XCore target does not yet support tail call optimization. 1045203954Srdivacky isTailCall = false; 1046198090Srdivacky 1047193323Sed // For now, only CallingConv::C implemented 1048198090Srdivacky switch (CallConv) 1049193323Sed { 1050193323Sed default: 1051327952Sdim report_fatal_error("Unsupported calling convention"); 1052193323Sed case CallingConv::Fast: 1053193323Sed case CallingConv::C: 1054198090Srdivacky return LowerCCCCallTo(Chain, Callee, CallConv, isVarArg, isTailCall, 1055210299Sed Outs, OutVals, Ins, dl, DAG, InVals); 1056193323Sed } 1057193323Sed} 1058193323Sed 1059276479Sdim/// LowerCallResult - Lower the result values of a call into the 1060276479Sdim/// appropriate copies out of appropriate physical registers / memory locations. 1061309124Sdimstatic SDValue LowerCallResult(SDValue Chain, SDValue InFlag, 1062309124Sdim const SmallVectorImpl<CCValAssign> &RVLocs, 1063309124Sdim const SDLoc &dl, SelectionDAG &DAG, 1064309124Sdim SmallVectorImpl<SDValue> &InVals) { 1065276479Sdim SmallVector<std::pair<int, unsigned>, 4> ResultMemLocs; 1066276479Sdim // Copy results out of physical registers. 1067276479Sdim for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) { 1068276479Sdim const CCValAssign &VA = RVLocs[i]; 1069276479Sdim if (VA.isRegLoc()) { 1070276479Sdim Chain = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), VA.getValVT(), 1071276479Sdim InFlag).getValue(1); 1072276479Sdim InFlag = Chain.getValue(2); 1073276479Sdim InVals.push_back(Chain.getValue(0)); 1074276479Sdim } else { 1075276479Sdim assert(VA.isMemLoc()); 1076276479Sdim ResultMemLocs.push_back(std::make_pair(VA.getLocMemOffset(), 1077276479Sdim InVals.size())); 1078276479Sdim // Reserve space for this result. 1079276479Sdim InVals.push_back(SDValue()); 1080276479Sdim } 1081276479Sdim } 1082276479Sdim 1083276479Sdim // Copy results out of memory. 1084276479Sdim SmallVector<SDValue, 4> MemOpChains; 1085276479Sdim for (unsigned i = 0, e = ResultMemLocs.size(); i != e; ++i) { 1086276479Sdim int offset = ResultMemLocs[i].first; 1087276479Sdim unsigned index = ResultMemLocs[i].second; 1088276479Sdim SDVTList VTs = DAG.getVTList(MVT::i32, MVT::Other); 1089288943Sdim SDValue Ops[] = { Chain, DAG.getConstant(offset / 4, dl, MVT::i32) }; 1090276479Sdim SDValue load = DAG.getNode(XCoreISD::LDWSP, dl, VTs, Ops); 1091276479Sdim InVals[index] = load; 1092276479Sdim MemOpChains.push_back(load.getValue(1)); 1093276479Sdim } 1094276479Sdim 1095276479Sdim // Transform all loads nodes into one single node because 1096276479Sdim // all load nodes are independent of each other. 1097276479Sdim if (!MemOpChains.empty()) 1098276479Sdim Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains); 1099276479Sdim 1100276479Sdim return Chain; 1101276479Sdim} 1102276479Sdim 1103193323Sed/// LowerCCCCallTo - functions arguments are copied from virtual 1104193323Sed/// regs to (physical regs)/(stack frame), CALLSEQ_START and 1105193323Sed/// CALLSEQ_END are emitted. 1106193323Sed/// TODO: isTailCall, sret. 1107309124SdimSDValue XCoreTargetLowering::LowerCCCCallTo( 1108309124Sdim SDValue Chain, SDValue Callee, CallingConv::ID CallConv, bool isVarArg, 1109309124Sdim bool isTailCall, const SmallVectorImpl<ISD::OutputArg> &Outs, 1110309124Sdim const SmallVectorImpl<SDValue> &OutVals, 1111309124Sdim const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl, 1112309124Sdim SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { 1113193323Sed 1114193323Sed // Analyze operands of the call, assigning locations to each operand. 1115193323Sed SmallVector<CCValAssign, 16> ArgLocs; 1116280031Sdim CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs, 1117280031Sdim *DAG.getContext()); 1118193323Sed 1119193323Sed // The ABI dictates there should be one stack slot available to the callee 1120193323Sed // on function entry (for saving lr). 1121193323Sed CCInfo.AllocateStack(4, 4); 1122193323Sed 1123198090Srdivacky CCInfo.AnalyzeCallOperands(Outs, CC_XCore); 1124193323Sed 1125276479Sdim SmallVector<CCValAssign, 16> RVLocs; 1126276479Sdim // Analyze return values to determine the number of bytes of stack required. 1127280031Sdim CCState RetCCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs, 1128280031Sdim *DAG.getContext()); 1129276479Sdim RetCCInfo.AllocateStack(CCInfo.getNextStackOffset(), 4); 1130276479Sdim RetCCInfo.AnalyzeCallResult(Ins, RetCC_XCore); 1131276479Sdim 1132193323Sed // Get a count of how many bytes are to be pushed on the stack. 1133276479Sdim unsigned NumBytes = RetCCInfo.getNextStackOffset(); 1134288943Sdim auto PtrVT = getPointerTy(DAG.getDataLayout()); 1135193323Sed 1136321369Sdim Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, dl); 1137193323Sed 1138193323Sed SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass; 1139193323Sed SmallVector<SDValue, 12> MemOpChains; 1140193323Sed 1141193323Sed // Walk the register/memloc assignments, inserting copies/loads. 1142193323Sed for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 1143193323Sed CCValAssign &VA = ArgLocs[i]; 1144210299Sed SDValue Arg = OutVals[i]; 1145193323Sed 1146193323Sed // Promote the value if needed. 1147193323Sed switch (VA.getLocInfo()) { 1148198090Srdivacky default: llvm_unreachable("Unknown loc info!"); 1149193323Sed case CCValAssign::Full: break; 1150193323Sed case CCValAssign::SExt: 1151193323Sed Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg); 1152193323Sed break; 1153193323Sed case CCValAssign::ZExt: 1154193323Sed Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg); 1155193323Sed break; 1156193323Sed case CCValAssign::AExt: 1157193323Sed Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg); 1158193323Sed break; 1159193323Sed } 1160219077Sdim 1161219077Sdim // Arguments that can be passed on register must be kept at 1162193323Sed // RegsToPass vector 1163193323Sed if (VA.isRegLoc()) { 1164193323Sed RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); 1165193323Sed } else { 1166193323Sed assert(VA.isMemLoc()); 1167193323Sed 1168193323Sed int Offset = VA.getLocMemOffset(); 1169193323Sed 1170219077Sdim MemOpChains.push_back(DAG.getNode(XCoreISD::STWSP, dl, MVT::Other, 1171193323Sed Chain, Arg, 1172288943Sdim DAG.getConstant(Offset/4, dl, 1173288943Sdim MVT::i32))); 1174193323Sed } 1175193323Sed } 1176193323Sed 1177193323Sed // Transform all store nodes into one single node because 1178193323Sed // all store nodes are independent of each other. 1179193323Sed if (!MemOpChains.empty()) 1180276479Sdim Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains); 1181193323Sed 1182219077Sdim // Build a sequence of copy-to-reg nodes chained together with token 1183193323Sed // chain and flag operands which copy the outgoing args into registers. 1184221345Sdim // The InFlag in necessary since all emitted instructions must be 1185193323Sed // stuck together. 1186193323Sed SDValue InFlag; 1187193323Sed for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { 1188219077Sdim Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, 1189193323Sed RegsToPass[i].second, InFlag); 1190193323Sed InFlag = Chain.getValue(1); 1191193323Sed } 1192193323Sed 1193193323Sed // If the callee is a GlobalAddress node (quite common, every direct call is) 1194193323Sed // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. 1195193323Sed // Likewise ExternalSymbol -> TargetExternalSymbol. 1196193323Sed if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) 1197210299Sed Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32); 1198193323Sed else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee)) 1199193323Sed Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32); 1200193323Sed 1201193323Sed // XCoreBranchLink = #chain, #target_address, #opt_in_flags... 1202219077Sdim // = Chain, Callee, Reg#1, Reg#2, ... 1203193323Sed // 1204193323Sed // Returns a chain & a flag for retval copy to use. 1205218893Sdim SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); 1206193323Sed SmallVector<SDValue, 8> Ops; 1207193323Sed Ops.push_back(Chain); 1208193323Sed Ops.push_back(Callee); 1209193323Sed 1210219077Sdim // Add argument registers to the end of the list so that they are 1211193323Sed // known live into the call. 1212193323Sed for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) 1213193323Sed Ops.push_back(DAG.getRegister(RegsToPass[i].first, 1214193323Sed RegsToPass[i].second.getValueType())); 1215193323Sed 1216193323Sed if (InFlag.getNode()) 1217193323Sed Ops.push_back(InFlag); 1218193323Sed 1219276479Sdim Chain = DAG.getNode(XCoreISD::BL, dl, NodeTys, Ops); 1220193323Sed InFlag = Chain.getValue(1); 1221193323Sed 1222193323Sed // Create the CALLSEQ_END node. 1223288943Sdim Chain = DAG.getCALLSEQ_END(Chain, DAG.getConstant(NumBytes, dl, PtrVT, true), 1224288943Sdim DAG.getConstant(0, dl, PtrVT, true), InFlag, dl); 1225193323Sed InFlag = Chain.getValue(1); 1226193323Sed 1227193323Sed // Handle result values, copying them out of physregs into vregs that we 1228193323Sed // return. 1229276479Sdim return LowerCallResult(Chain, InFlag, RVLocs, dl, DAG, InVals); 1230193323Sed} 1231193323Sed 1232193323Sed//===----------------------------------------------------------------------===// 1233198090Srdivacky// Formal Arguments Calling Convention Implementation 1234193323Sed//===----------------------------------------------------------------------===// 1235193323Sed 1236261991Sdimnamespace { 1237261991Sdim struct ArgDataPair { SDValue SDV; ISD::ArgFlagsTy Flags; }; 1238261991Sdim} 1239261991Sdim 1240198090Srdivacky/// XCore formal arguments implementation 1241309124SdimSDValue XCoreTargetLowering::LowerFormalArguments( 1242309124Sdim SDValue Chain, CallingConv::ID CallConv, bool isVarArg, 1243309124Sdim const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl, 1244309124Sdim SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { 1245198090Srdivacky switch (CallConv) 1246193323Sed { 1247193323Sed default: 1248327952Sdim report_fatal_error("Unsupported calling convention"); 1249193323Sed case CallingConv::C: 1250193323Sed case CallingConv::Fast: 1251198090Srdivacky return LowerCCCArguments(Chain, CallConv, isVarArg, 1252198090Srdivacky Ins, dl, DAG, InVals); 1253193323Sed } 1254193323Sed} 1255193323Sed 1256193323Sed/// LowerCCCArguments - transform physical registers into 1257193323Sed/// virtual registers and generate load operations for 1258193323Sed/// arguments places on the stack. 1259193323Sed/// TODO: sret 1260309124SdimSDValue XCoreTargetLowering::LowerCCCArguments( 1261309124Sdim SDValue Chain, CallingConv::ID CallConv, bool isVarArg, 1262309124Sdim const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl, 1263309124Sdim SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { 1264193323Sed MachineFunction &MF = DAG.getMachineFunction(); 1265314564Sdim MachineFrameInfo &MFI = MF.getFrameInfo(); 1266193323Sed MachineRegisterInfo &RegInfo = MF.getRegInfo(); 1267276479Sdim XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); 1268193323Sed 1269193323Sed // Assign locations to all of the incoming arguments. 1270193323Sed SmallVector<CCValAssign, 16> ArgLocs; 1271280031Sdim CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs, 1272280031Sdim *DAG.getContext()); 1273193323Sed 1274198090Srdivacky CCInfo.AnalyzeFormalArguments(Ins, CC_XCore); 1275193323Sed 1276218893Sdim unsigned StackSlotSize = XCoreFrameLowering::stackSlotSize(); 1277193323Sed 1278193323Sed unsigned LRSaveSize = StackSlotSize; 1279219077Sdim 1280276479Sdim if (!isVarArg) 1281276479Sdim XFI->setReturnStackOffset(CCInfo.getNextStackOffset() + LRSaveSize); 1282276479Sdim 1283261991Sdim // All getCopyFromReg ops must precede any getMemcpys to prevent the 1284261991Sdim // scheduler clobbering a register before it has been copied. 1285261991Sdim // The stages are: 1286261991Sdim // 1. CopyFromReg (and load) arg & vararg registers. 1287261991Sdim // 2. Chain CopyFromReg nodes into a TokenFactor. 1288261991Sdim // 3. Memcpy 'byVal' args & push final InVals. 1289261991Sdim // 4. Chain mem ops nodes into a TokenFactor. 1290261991Sdim SmallVector<SDValue, 4> CFRegNode; 1291261991Sdim SmallVector<ArgDataPair, 4> ArgData; 1292261991Sdim SmallVector<SDValue, 4> MemOps; 1293261991Sdim 1294261991Sdim // 1a. CopyFromReg (and load) arg registers. 1295193323Sed for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 1296193323Sed 1297193323Sed CCValAssign &VA = ArgLocs[i]; 1298261991Sdim SDValue ArgIn; 1299219077Sdim 1300193323Sed if (VA.isRegLoc()) { 1301193323Sed // Arguments passed in registers 1302198090Srdivacky EVT RegVT = VA.getLocVT(); 1303198090Srdivacky switch (RegVT.getSimpleVT().SimpleTy) { 1304193323Sed default: 1305198090Srdivacky { 1306198090Srdivacky#ifndef NDEBUG 1307198090Srdivacky errs() << "LowerFormalArguments Unhandled argument type: " 1308309124Sdim << RegVT.getEVTString() << "\n"; 1309198090Srdivacky#endif 1310276479Sdim llvm_unreachable(nullptr); 1311198090Srdivacky } 1312193323Sed case MVT::i32: 1313360784Sdim Register VReg = RegInfo.createVirtualRegister(&XCore::GRRegsRegClass); 1314193323Sed RegInfo.addLiveIn(VA.getLocReg(), VReg); 1315261991Sdim ArgIn = DAG.getCopyFromReg(Chain, dl, VReg, RegVT); 1316261991Sdim CFRegNode.push_back(ArgIn.getValue(ArgIn->getNumValues() - 1)); 1317193323Sed } 1318193323Sed } else { 1319193323Sed // sanity check 1320193323Sed assert(VA.isMemLoc()); 1321193323Sed // Load the argument to a virtual register 1322193323Sed unsigned ObjSize = VA.getLocVT().getSizeInBits()/8; 1323193323Sed if (ObjSize > StackSlotSize) { 1324198090Srdivacky errs() << "LowerFormalArguments Unhandled argument type: " 1325218893Sdim << EVT(VA.getLocVT()).getEVTString() 1326198090Srdivacky << "\n"; 1327193323Sed } 1328193323Sed // Create the frame index object for this incoming parameter... 1329314564Sdim int FI = MFI.CreateFixedObject(ObjSize, 1330314564Sdim LRSaveSize + VA.getLocMemOffset(), 1331314564Sdim true); 1332193323Sed 1333193323Sed // Create the SelectionDAG nodes corresponding to a load 1334193323Sed //from this parameter 1335193323Sed SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); 1336261991Sdim ArgIn = DAG.getLoad(VA.getLocVT(), dl, Chain, FIN, 1337309124Sdim MachinePointerInfo::getFixedStack(MF, FI)); 1338193323Sed } 1339261991Sdim const ArgDataPair ADP = { ArgIn, Ins[i].Flags }; 1340261991Sdim ArgData.push_back(ADP); 1341193323Sed } 1342219077Sdim 1343261991Sdim // 1b. CopyFromReg vararg registers. 1344193323Sed if (isVarArg) { 1345261991Sdim // Argument registers 1346276479Sdim static const MCPhysReg ArgRegs[] = { 1347193323Sed XCore::R0, XCore::R1, XCore::R2, XCore::R3 1348193323Sed }; 1349193323Sed XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); 1350288943Sdim unsigned FirstVAReg = CCInfo.getFirstUnallocated(ArgRegs); 1351193323Sed if (FirstVAReg < array_lengthof(ArgRegs)) { 1352193323Sed int offset = 0; 1353193323Sed // Save remaining registers, storing higher register numbers at a higher 1354193323Sed // address 1355226633Sdim for (int i = array_lengthof(ArgRegs) - 1; i >= (int)FirstVAReg; --i) { 1356193323Sed // Create a stack slot 1357314564Sdim int FI = MFI.CreateFixedObject(4, offset, true); 1358226633Sdim if (i == (int)FirstVAReg) { 1359193323Sed XFI->setVarArgsFrameIndex(FI); 1360193323Sed } 1361193323Sed offset -= StackSlotSize; 1362193323Sed SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); 1363193323Sed // Move argument from phys reg -> virt reg 1364360784Sdim Register VReg = RegInfo.createVirtualRegister(&XCore::GRRegsRegClass); 1365193323Sed RegInfo.addLiveIn(ArgRegs[i], VReg); 1366198090Srdivacky SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32); 1367261991Sdim CFRegNode.push_back(Val.getValue(Val->getNumValues() - 1)); 1368193323Sed // Move argument from virt reg -> stack 1369309124Sdim SDValue Store = 1370309124Sdim DAG.getStore(Val.getValue(1), dl, Val, FIN, MachinePointerInfo()); 1371193323Sed MemOps.push_back(Store); 1372193323Sed } 1373193323Sed } else { 1374193323Sed // This will point to the next argument passed via stack. 1375193323Sed XFI->setVarArgsFrameIndex( 1376314564Sdim MFI.CreateFixedObject(4, LRSaveSize + CCInfo.getNextStackOffset(), 1377314564Sdim true)); 1378193323Sed } 1379193323Sed } 1380219077Sdim 1381261991Sdim // 2. chain CopyFromReg nodes into a TokenFactor. 1382261991Sdim if (!CFRegNode.empty()) 1383276479Sdim Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, CFRegNode); 1384261991Sdim 1385261991Sdim // 3. Memcpy 'byVal' args & push final InVals. 1386261991Sdim // Aggregates passed "byVal" need to be copied by the callee. 1387261991Sdim // The callee will use a pointer to this copy, rather than the original 1388261991Sdim // pointer. 1389261991Sdim for (SmallVectorImpl<ArgDataPair>::const_iterator ArgDI = ArgData.begin(), 1390261991Sdim ArgDE = ArgData.end(); 1391261991Sdim ArgDI != ArgDE; ++ArgDI) { 1392261991Sdim if (ArgDI->Flags.isByVal() && ArgDI->Flags.getByValSize()) { 1393261991Sdim unsigned Size = ArgDI->Flags.getByValSize(); 1394261991Sdim unsigned Align = std::max(StackSlotSize, ArgDI->Flags.getByValAlign()); 1395261991Sdim // Create a new object on the stack and copy the pointee into it. 1396314564Sdim int FI = MFI.CreateStackObject(Size, Align, false); 1397261991Sdim SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); 1398261991Sdim InVals.push_back(FIN); 1399261991Sdim MemOps.push_back(DAG.getMemcpy(Chain, dl, FIN, ArgDI->SDV, 1400288943Sdim DAG.getConstant(Size, dl, MVT::i32), 1401288943Sdim Align, false, false, false, 1402261991Sdim MachinePointerInfo(), 1403261991Sdim MachinePointerInfo())); 1404261991Sdim } else { 1405261991Sdim InVals.push_back(ArgDI->SDV); 1406261991Sdim } 1407261991Sdim } 1408261991Sdim 1409261991Sdim // 4, chain mem ops nodes into a TokenFactor. 1410261991Sdim if (!MemOps.empty()) { 1411261991Sdim MemOps.push_back(Chain); 1412276479Sdim Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOps); 1413261991Sdim } 1414261991Sdim 1415198090Srdivacky return Chain; 1416193323Sed} 1417193323Sed 1418193323Sed//===----------------------------------------------------------------------===// 1419193323Sed// Return Value Calling Convention Implementation 1420193323Sed//===----------------------------------------------------------------------===// 1421193323Sed 1422199481Srdivackybool XCoreTargetLowering:: 1423223017SdimCanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, 1424239462Sdim bool isVarArg, 1425210299Sed const SmallVectorImpl<ISD::OutputArg> &Outs, 1426210299Sed LLVMContext &Context) const { 1427199481Srdivacky SmallVector<CCValAssign, 16> RVLocs; 1428280031Sdim CCState CCInfo(CallConv, isVarArg, MF, RVLocs, Context); 1429276479Sdim if (!CCInfo.CheckReturn(Outs, RetCC_XCore)) 1430276479Sdim return false; 1431276479Sdim if (CCInfo.getNextStackOffset() != 0 && isVarArg) 1432276479Sdim return false; 1433276479Sdim return true; 1434199481Srdivacky} 1435199481Srdivacky 1436198090SrdivackySDValue 1437309124SdimXCoreTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, 1438309124Sdim bool isVarArg, 1439198090Srdivacky const SmallVectorImpl<ISD::OutputArg> &Outs, 1440210299Sed const SmallVectorImpl<SDValue> &OutVals, 1441309124Sdim const SDLoc &dl, SelectionDAG &DAG) const { 1442198090Srdivacky 1443276479Sdim XCoreFunctionInfo *XFI = 1444276479Sdim DAG.getMachineFunction().getInfo<XCoreFunctionInfo>(); 1445314564Sdim MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); 1446276479Sdim 1447193323Sed // CCValAssign - represent the assignment of 1448193323Sed // the return value to a location 1449193323Sed SmallVector<CCValAssign, 16> RVLocs; 1450193323Sed 1451193323Sed // CCState - Info about the registers and stack slot. 1452280031Sdim CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs, 1453280031Sdim *DAG.getContext()); 1454193323Sed 1455223017Sdim // Analyze return values. 1456276479Sdim if (!isVarArg) 1457276479Sdim CCInfo.AllocateStack(XFI->getReturnStackOffset(), 4); 1458276479Sdim 1459198090Srdivacky CCInfo.AnalyzeReturn(Outs, RetCC_XCore); 1460193323Sed 1461193323Sed SDValue Flag; 1462249423Sdim SmallVector<SDValue, 4> RetOps(1, Chain); 1463193323Sed 1464249423Sdim // Return on XCore is always a "retsp 0" 1465288943Sdim RetOps.push_back(DAG.getConstant(0, dl, MVT::i32)); 1466249423Sdim 1467276479Sdim SmallVector<SDValue, 4> MemOpChains; 1468276479Sdim // Handle return values that must be copied to memory. 1469276479Sdim for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) { 1470193323Sed CCValAssign &VA = RVLocs[i]; 1471276479Sdim if (VA.isRegLoc()) 1472276479Sdim continue; 1473276479Sdim assert(VA.isMemLoc()); 1474276479Sdim if (isVarArg) { 1475276479Sdim report_fatal_error("Can't return value from vararg function in memory"); 1476276479Sdim } 1477193323Sed 1478276479Sdim int Offset = VA.getLocMemOffset(); 1479276479Sdim unsigned ObjSize = VA.getLocVT().getSizeInBits() / 8; 1480276479Sdim // Create the frame index object for the memory location. 1481314564Sdim int FI = MFI.CreateFixedObject(ObjSize, Offset, false); 1482193323Sed 1483276479Sdim // Create a SelectionDAG node corresponding to a store 1484276479Sdim // to this memory location. 1485276479Sdim SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); 1486296417Sdim MemOpChains.push_back(DAG.getStore( 1487296417Sdim Chain, dl, OutVals[i], FIN, 1488309124Sdim MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI))); 1489276479Sdim } 1490276479Sdim 1491276479Sdim // Transform all store nodes into one single node because 1492276479Sdim // all stores are independent of each other. 1493276479Sdim if (!MemOpChains.empty()) 1494276479Sdim Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains); 1495276479Sdim 1496276479Sdim // Now handle return values copied to registers. 1497276479Sdim for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) { 1498276479Sdim CCValAssign &VA = RVLocs[i]; 1499276479Sdim if (!VA.isRegLoc()) 1500276479Sdim continue; 1501276479Sdim // Copy the result values into the output registers. 1502276479Sdim Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Flag); 1503276479Sdim 1504193323Sed // guarantee that all emitted copies are 1505193323Sed // stuck together, avoiding something bad 1506193323Sed Flag = Chain.getValue(1); 1507249423Sdim RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); 1508193323Sed } 1509193323Sed 1510249423Sdim RetOps[0] = Chain; // Update chain. 1511249423Sdim 1512249423Sdim // Add the flag if we have it. 1513193323Sed if (Flag.getNode()) 1514249423Sdim RetOps.push_back(Flag); 1515249423Sdim 1516276479Sdim return DAG.getNode(XCoreISD::RETSP, dl, MVT::Other, RetOps); 1517193323Sed} 1518193323Sed 1519193323Sed//===----------------------------------------------------------------------===// 1520193323Sed// Other Lowering Code 1521193323Sed//===----------------------------------------------------------------------===// 1522193323Sed 1523193323SedMachineBasicBlock * 1524309124SdimXCoreTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, 1525207618Srdivacky MachineBasicBlock *BB) const { 1526288943Sdim const TargetInstrInfo &TII = *Subtarget.getInstrInfo(); 1527309124Sdim DebugLoc dl = MI.getDebugLoc(); 1528309124Sdim assert((MI.getOpcode() == XCore::SELECT_CC) && 1529193323Sed "Unexpected instr type to insert"); 1530219077Sdim 1531193323Sed // To "insert" a SELECT_CC instruction, we actually have to insert the diamond 1532193323Sed // control-flow pattern. The incoming instruction knows the destination vreg 1533193323Sed // to set, the condition code register to branch on, the true/false values to 1534193323Sed // select between, and a branch opcode to use. 1535193323Sed const BasicBlock *LLVM_BB = BB->getBasicBlock(); 1536296417Sdim MachineFunction::iterator It = ++BB->getIterator(); 1537219077Sdim 1538193323Sed // thisMBB: 1539193323Sed // ... 1540193323Sed // TrueVal = ... 1541193323Sed // cmpTY ccX, r1, r2 1542193323Sed // bCC copy1MBB 1543193323Sed // fallthrough --> copy0MBB 1544193323Sed MachineBasicBlock *thisMBB = BB; 1545193323Sed MachineFunction *F = BB->getParent(); 1546193323Sed MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); 1547193323Sed MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); 1548193323Sed F->insert(It, copy0MBB); 1549193323Sed F->insert(It, sinkMBB); 1550210299Sed 1551210299Sed // Transfer the remainder of BB and its successor edges to sinkMBB. 1552210299Sed sinkMBB->splice(sinkMBB->begin(), BB, 1553276479Sdim std::next(MachineBasicBlock::iterator(MI)), BB->end()); 1554210299Sed sinkMBB->transferSuccessorsAndUpdatePHIs(BB); 1555210299Sed 1556193323Sed // Next, add the true and fallthrough blocks as its successors. 1557193323Sed BB->addSuccessor(copy0MBB); 1558193323Sed BB->addSuccessor(sinkMBB); 1559219077Sdim 1560210299Sed BuildMI(BB, dl, TII.get(XCore::BRFT_lru6)) 1561309124Sdim .addReg(MI.getOperand(1).getReg()) 1562309124Sdim .addMBB(sinkMBB); 1563210299Sed 1564193323Sed // copy0MBB: 1565193323Sed // %FalseValue = ... 1566193323Sed // # fallthrough to sinkMBB 1567193323Sed BB = copy0MBB; 1568219077Sdim 1569193323Sed // Update machine-CFG edges 1570193323Sed BB->addSuccessor(sinkMBB); 1571219077Sdim 1572193323Sed // sinkMBB: 1573193323Sed // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] 1574193323Sed // ... 1575193323Sed BB = sinkMBB; 1576309124Sdim BuildMI(*BB, BB->begin(), dl, TII.get(XCore::PHI), MI.getOperand(0).getReg()) 1577309124Sdim .addReg(MI.getOperand(3).getReg()) 1578309124Sdim .addMBB(copy0MBB) 1579309124Sdim .addReg(MI.getOperand(2).getReg()) 1580309124Sdim .addMBB(thisMBB); 1581219077Sdim 1582309124Sdim MI.eraseFromParent(); // The pseudo instruction is gone now. 1583193323Sed return BB; 1584193323Sed} 1585193323Sed 1586193323Sed//===----------------------------------------------------------------------===// 1587198090Srdivacky// Target Optimization Hooks 1588198090Srdivacky//===----------------------------------------------------------------------===// 1589198090Srdivacky 1590198090SrdivackySDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N, 1591198090Srdivacky DAGCombinerInfo &DCI) const { 1592198090Srdivacky SelectionDAG &DAG = DCI.DAG; 1593261991Sdim SDLoc dl(N); 1594198090Srdivacky switch (N->getOpcode()) { 1595198090Srdivacky default: break; 1596276479Sdim case ISD::INTRINSIC_VOID: 1597276479Sdim switch (cast<ConstantSDNode>(N->getOperand(1))->getZExtValue()) { 1598276479Sdim case Intrinsic::xcore_outt: 1599276479Sdim case Intrinsic::xcore_outct: 1600276479Sdim case Intrinsic::xcore_chkct: { 1601276479Sdim SDValue OutVal = N->getOperand(3); 1602276479Sdim // These instructions ignore the high bits. 1603276479Sdim if (OutVal.hasOneUse()) { 1604276479Sdim unsigned BitWidth = OutVal.getValueSizeInBits(); 1605276479Sdim APInt DemandedMask = APInt::getLowBitsSet(BitWidth, 8); 1606321369Sdim KnownBits Known; 1607276479Sdim TargetLowering::TargetLoweringOpt TLO(DAG, !DCI.isBeforeLegalize(), 1608276479Sdim !DCI.isBeforeLegalizeOps()); 1609276479Sdim const TargetLowering &TLI = DAG.getTargetLoweringInfo(); 1610321369Sdim if (TLI.ShrinkDemandedConstant(OutVal, DemandedMask, TLO) || 1611321369Sdim TLI.SimplifyDemandedBits(OutVal, DemandedMask, Known, TLO)) 1612276479Sdim DCI.CommitTargetLoweringOpt(TLO); 1613276479Sdim } 1614276479Sdim break; 1615276479Sdim } 1616276479Sdim case Intrinsic::xcore_setpt: { 1617276479Sdim SDValue Time = N->getOperand(3); 1618276479Sdim // This instruction ignores the high bits. 1619276479Sdim if (Time.hasOneUse()) { 1620276479Sdim unsigned BitWidth = Time.getValueSizeInBits(); 1621276479Sdim APInt DemandedMask = APInt::getLowBitsSet(BitWidth, 16); 1622321369Sdim KnownBits Known; 1623276479Sdim TargetLowering::TargetLoweringOpt TLO(DAG, !DCI.isBeforeLegalize(), 1624276479Sdim !DCI.isBeforeLegalizeOps()); 1625276479Sdim const TargetLowering &TLI = DAG.getTargetLoweringInfo(); 1626321369Sdim if (TLI.ShrinkDemandedConstant(Time, DemandedMask, TLO) || 1627321369Sdim TLI.SimplifyDemandedBits(Time, DemandedMask, Known, TLO)) 1628276479Sdim DCI.CommitTargetLoweringOpt(TLO); 1629276479Sdim } 1630276479Sdim break; 1631276479Sdim } 1632276479Sdim } 1633276479Sdim break; 1634204961Srdivacky case XCoreISD::LADD: { 1635204961Srdivacky SDValue N0 = N->getOperand(0); 1636204961Srdivacky SDValue N1 = N->getOperand(1); 1637204961Srdivacky SDValue N2 = N->getOperand(2); 1638204961Srdivacky ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0); 1639204961Srdivacky ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1); 1640204961Srdivacky EVT VT = N0.getValueType(); 1641204961Srdivacky 1642204961Srdivacky // canonicalize constant to RHS 1643204961Srdivacky if (N0C && !N1C) 1644204961Srdivacky return DAG.getNode(XCoreISD::LADD, dl, DAG.getVTList(VT, VT), N1, N0, N2); 1645204961Srdivacky 1646204961Srdivacky // fold (ladd 0, 0, x) -> 0, x & 1 1647204961Srdivacky if (N0C && N0C->isNullValue() && N1C && N1C->isNullValue()) { 1648288943Sdim SDValue Carry = DAG.getConstant(0, dl, VT); 1649204961Srdivacky SDValue Result = DAG.getNode(ISD::AND, dl, VT, N2, 1650288943Sdim DAG.getConstant(1, dl, VT)); 1651249423Sdim SDValue Ops[] = { Result, Carry }; 1652276479Sdim return DAG.getMergeValues(Ops, dl); 1653204961Srdivacky } 1654204961Srdivacky 1655204961Srdivacky // fold (ladd x, 0, y) -> 0, add x, y iff carry is unused and y has only the 1656204961Srdivacky // low bit set 1657249423Sdim if (N1C && N1C->isNullValue() && N->hasNUsesOfValue(0, 1)) { 1658204961Srdivacky APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(), 1659204961Srdivacky VT.getSizeInBits() - 1); 1660344779Sdim KnownBits Known = DAG.computeKnownBits(N2); 1661321369Sdim if ((Known.Zero & Mask) == Mask) { 1662288943Sdim SDValue Carry = DAG.getConstant(0, dl, VT); 1663204961Srdivacky SDValue Result = DAG.getNode(ISD::ADD, dl, VT, N0, N2); 1664249423Sdim SDValue Ops[] = { Result, Carry }; 1665276479Sdim return DAG.getMergeValues(Ops, dl); 1666204961Srdivacky } 1667204961Srdivacky } 1668204961Srdivacky } 1669204961Srdivacky break; 1670204961Srdivacky case XCoreISD::LSUB: { 1671204961Srdivacky SDValue N0 = N->getOperand(0); 1672204961Srdivacky SDValue N1 = N->getOperand(1); 1673204961Srdivacky SDValue N2 = N->getOperand(2); 1674204961Srdivacky ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0); 1675204961Srdivacky ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1); 1676204961Srdivacky EVT VT = N0.getValueType(); 1677204961Srdivacky 1678204961Srdivacky // fold (lsub 0, 0, x) -> x, -x iff x has only the low bit set 1679219077Sdim if (N0C && N0C->isNullValue() && N1C && N1C->isNullValue()) { 1680204961Srdivacky APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(), 1681204961Srdivacky VT.getSizeInBits() - 1); 1682344779Sdim KnownBits Known = DAG.computeKnownBits(N2); 1683321369Sdim if ((Known.Zero & Mask) == Mask) { 1684204961Srdivacky SDValue Borrow = N2; 1685204961Srdivacky SDValue Result = DAG.getNode(ISD::SUB, dl, VT, 1686288943Sdim DAG.getConstant(0, dl, VT), N2); 1687249423Sdim SDValue Ops[] = { Result, Borrow }; 1688276479Sdim return DAG.getMergeValues(Ops, dl); 1689204961Srdivacky } 1690204961Srdivacky } 1691204961Srdivacky 1692204961Srdivacky // fold (lsub x, 0, y) -> 0, sub x, y iff borrow is unused and y has only the 1693204961Srdivacky // low bit set 1694249423Sdim if (N1C && N1C->isNullValue() && N->hasNUsesOfValue(0, 1)) { 1695204961Srdivacky APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(), 1696204961Srdivacky VT.getSizeInBits() - 1); 1697344779Sdim KnownBits Known = DAG.computeKnownBits(N2); 1698321369Sdim if ((Known.Zero & Mask) == Mask) { 1699288943Sdim SDValue Borrow = DAG.getConstant(0, dl, VT); 1700204961Srdivacky SDValue Result = DAG.getNode(ISD::SUB, dl, VT, N0, N2); 1701249423Sdim SDValue Ops[] = { Result, Borrow }; 1702276479Sdim return DAG.getMergeValues(Ops, dl); 1703204961Srdivacky } 1704204961Srdivacky } 1705204961Srdivacky } 1706204961Srdivacky break; 1707205218Srdivacky case XCoreISD::LMUL: { 1708205218Srdivacky SDValue N0 = N->getOperand(0); 1709205218Srdivacky SDValue N1 = N->getOperand(1); 1710205218Srdivacky SDValue N2 = N->getOperand(2); 1711205218Srdivacky SDValue N3 = N->getOperand(3); 1712205218Srdivacky ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0); 1713205218Srdivacky ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1); 1714205218Srdivacky EVT VT = N0.getValueType(); 1715205218Srdivacky // Canonicalize multiplicative constant to RHS. If both multiplicative 1716205218Srdivacky // operands are constant canonicalize smallest to RHS. 1717205218Srdivacky if ((N0C && !N1C) || 1718205218Srdivacky (N0C && N1C && N0C->getZExtValue() < N1C->getZExtValue())) 1719226633Sdim return DAG.getNode(XCoreISD::LMUL, dl, DAG.getVTList(VT, VT), 1720226633Sdim N1, N0, N2, N3); 1721205218Srdivacky 1722205218Srdivacky // lmul(x, 0, a, b) 1723205218Srdivacky if (N1C && N1C->isNullValue()) { 1724205218Srdivacky // If the high result is unused fold to add(a, b) 1725205218Srdivacky if (N->hasNUsesOfValue(0, 0)) { 1726205218Srdivacky SDValue Lo = DAG.getNode(ISD::ADD, dl, VT, N2, N3); 1727249423Sdim SDValue Ops[] = { Lo, Lo }; 1728276479Sdim return DAG.getMergeValues(Ops, dl); 1729205218Srdivacky } 1730205218Srdivacky // Otherwise fold to ladd(a, b, 0) 1731249423Sdim SDValue Result = 1732249423Sdim DAG.getNode(XCoreISD::LADD, dl, DAG.getVTList(VT, VT), N2, N3, N1); 1733249423Sdim SDValue Carry(Result.getNode(), 1); 1734249423Sdim SDValue Ops[] = { Carry, Result }; 1735276479Sdim return DAG.getMergeValues(Ops, dl); 1736205218Srdivacky } 1737205218Srdivacky } 1738205218Srdivacky break; 1739204961Srdivacky case ISD::ADD: { 1740205218Srdivacky // Fold 32 bit expressions such as add(add(mul(x,y),a),b) -> 1741205218Srdivacky // lmul(x, y, a, b). The high result of lmul will be ignored. 1742204961Srdivacky // This is only profitable if the intermediate results are unused 1743204961Srdivacky // elsewhere. 1744204961Srdivacky SDValue Mul0, Mul1, Addend0, Addend1; 1745205218Srdivacky if (N->getValueType(0) == MVT::i32 && 1746205218Srdivacky isADDADDMUL(SDValue(N, 0), Mul0, Mul1, Addend0, Addend1, true)) { 1747204961Srdivacky SDValue Ignored = DAG.getNode(XCoreISD::LMUL, dl, 1748204961Srdivacky DAG.getVTList(MVT::i32, MVT::i32), Mul0, 1749204961Srdivacky Mul1, Addend0, Addend1); 1750204961Srdivacky SDValue Result(Ignored.getNode(), 1); 1751204961Srdivacky return Result; 1752204961Srdivacky } 1753205218Srdivacky APInt HighMask = APInt::getHighBitsSet(64, 32); 1754205218Srdivacky // Fold 64 bit expression such as add(add(mul(x,y),a),b) -> 1755205218Srdivacky // lmul(x, y, a, b) if all operands are zero-extended. We do this 1756205218Srdivacky // before type legalization as it is messy to match the operands after 1757205218Srdivacky // that. 1758205218Srdivacky if (N->getValueType(0) == MVT::i64 && 1759205218Srdivacky isADDADDMUL(SDValue(N, 0), Mul0, Mul1, Addend0, Addend1, false) && 1760205218Srdivacky DAG.MaskedValueIsZero(Mul0, HighMask) && 1761205218Srdivacky DAG.MaskedValueIsZero(Mul1, HighMask) && 1762205218Srdivacky DAG.MaskedValueIsZero(Addend0, HighMask) && 1763205218Srdivacky DAG.MaskedValueIsZero(Addend1, HighMask)) { 1764205218Srdivacky SDValue Mul0L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 1765288943Sdim Mul0, DAG.getConstant(0, dl, MVT::i32)); 1766205218Srdivacky SDValue Mul1L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 1767288943Sdim Mul1, DAG.getConstant(0, dl, MVT::i32)); 1768205218Srdivacky SDValue Addend0L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 1769288943Sdim Addend0, DAG.getConstant(0, dl, MVT::i32)); 1770205218Srdivacky SDValue Addend1L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 1771288943Sdim Addend1, DAG.getConstant(0, dl, MVT::i32)); 1772205218Srdivacky SDValue Hi = DAG.getNode(XCoreISD::LMUL, dl, 1773205218Srdivacky DAG.getVTList(MVT::i32, MVT::i32), Mul0L, Mul1L, 1774205218Srdivacky Addend0L, Addend1L); 1775205218Srdivacky SDValue Lo(Hi.getNode(), 1); 1776205218Srdivacky return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi); 1777205218Srdivacky } 1778204961Srdivacky } 1779204961Srdivacky break; 1780198090Srdivacky case ISD::STORE: { 1781198090Srdivacky // Replace unaligned store of unaligned load with memmove. 1782353358Sdim StoreSDNode *ST = cast<StoreSDNode>(N); 1783198090Srdivacky if (!DCI.isBeforeLegalize() || 1784360784Sdim allowsMemoryAccessForAlignment(*DAG.getContext(), DAG.getDataLayout(), 1785360784Sdim ST->getMemoryVT(), 1786360784Sdim *ST->getMemOperand()) || 1787198090Srdivacky ST->isVolatile() || ST->isIndexed()) { 1788198090Srdivacky break; 1789198090Srdivacky } 1790198090Srdivacky SDValue Chain = ST->getChain(); 1791198090Srdivacky 1792198090Srdivacky unsigned StoreBits = ST->getMemoryVT().getStoreSizeInBits(); 1793296417Sdim assert((StoreBits % 8) == 0 && 1794296417Sdim "Store size in bits must be a multiple of 8"); 1795198090Srdivacky unsigned Alignment = ST->getAlignment(); 1796198090Srdivacky 1797198090Srdivacky if (LoadSDNode *LD = dyn_cast<LoadSDNode>(ST->getValue())) { 1798198090Srdivacky if (LD->hasNUsesOfValue(1, 0) && ST->getMemoryVT() == LD->getMemoryVT() && 1799198090Srdivacky LD->getAlignment() == Alignment && 1800198090Srdivacky !LD->isVolatile() && !LD->isIndexed() && 1801198090Srdivacky Chain.reachesChainWithoutSideEffects(SDValue(LD, 1))) { 1802288943Sdim bool isTail = isInTailCallPosition(DAG, ST, Chain); 1803198090Srdivacky return DAG.getMemmove(Chain, dl, ST->getBasePtr(), 1804198090Srdivacky LD->getBasePtr(), 1805288943Sdim DAG.getConstant(StoreBits/8, dl, MVT::i32), 1806288943Sdim Alignment, false, isTail, ST->getPointerInfo(), 1807218893Sdim LD->getPointerInfo()); 1808198090Srdivacky } 1809198090Srdivacky } 1810198090Srdivacky break; 1811198090Srdivacky } 1812198090Srdivacky } 1813198090Srdivacky return SDValue(); 1814198090Srdivacky} 1815198090Srdivacky 1816276479Sdimvoid XCoreTargetLowering::computeKnownBitsForTargetNode(const SDValue Op, 1817321369Sdim KnownBits &Known, 1818321369Sdim const APInt &DemandedElts, 1819276479Sdim const SelectionDAG &DAG, 1820276479Sdim unsigned Depth) const { 1821321369Sdim Known.resetAll(); 1822204961Srdivacky switch (Op.getOpcode()) { 1823204961Srdivacky default: break; 1824204961Srdivacky case XCoreISD::LADD: 1825204961Srdivacky case XCoreISD::LSUB: 1826249423Sdim if (Op.getResNo() == 1) { 1827204961Srdivacky // Top bits of carry / borrow are clear. 1828321369Sdim Known.Zero = APInt::getHighBitsSet(Known.getBitWidth(), 1829321369Sdim Known.getBitWidth() - 1); 1830204961Srdivacky } 1831204961Srdivacky break; 1832276479Sdim case ISD::INTRINSIC_W_CHAIN: 1833276479Sdim { 1834276479Sdim unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue(); 1835276479Sdim switch (IntNo) { 1836276479Sdim case Intrinsic::xcore_getts: 1837276479Sdim // High bits are known to be zero. 1838321369Sdim Known.Zero = APInt::getHighBitsSet(Known.getBitWidth(), 1839321369Sdim Known.getBitWidth() - 16); 1840276479Sdim break; 1841276479Sdim case Intrinsic::xcore_int: 1842276479Sdim case Intrinsic::xcore_inct: 1843276479Sdim // High bits are known to be zero. 1844321369Sdim Known.Zero = APInt::getHighBitsSet(Known.getBitWidth(), 1845321369Sdim Known.getBitWidth() - 8); 1846276479Sdim break; 1847276479Sdim case Intrinsic::xcore_testct: 1848276479Sdim // Result is either 0 or 1. 1849321369Sdim Known.Zero = APInt::getHighBitsSet(Known.getBitWidth(), 1850321369Sdim Known.getBitWidth() - 1); 1851276479Sdim break; 1852276479Sdim case Intrinsic::xcore_testwct: 1853276479Sdim // Result is in the range 0 - 4. 1854321369Sdim Known.Zero = APInt::getHighBitsSet(Known.getBitWidth(), 1855321369Sdim Known.getBitWidth() - 3); 1856276479Sdim break; 1857276479Sdim } 1858276479Sdim } 1859276479Sdim break; 1860204961Srdivacky } 1861204961Srdivacky} 1862204961Srdivacky 1863198090Srdivacky//===----------------------------------------------------------------------===// 1864193323Sed// Addressing mode description hooks 1865193323Sed//===----------------------------------------------------------------------===// 1866193323Sed 1867193323Sedstatic inline bool isImmUs(int64_t val) 1868193323Sed{ 1869193323Sed return (val >= 0 && val <= 11); 1870193323Sed} 1871193323Sed 1872193323Sedstatic inline bool isImmUs2(int64_t val) 1873193323Sed{ 1874193323Sed return (val%2 == 0 && isImmUs(val/2)); 1875193323Sed} 1876193323Sed 1877193323Sedstatic inline bool isImmUs4(int64_t val) 1878193323Sed{ 1879193323Sed return (val%4 == 0 && isImmUs(val/4)); 1880193323Sed} 1881193323Sed 1882193323Sed/// isLegalAddressingMode - Return true if the addressing mode represented 1883193323Sed/// by AM is legal for this target, for a load/store of the specified type. 1884288943Sdimbool XCoreTargetLowering::isLegalAddressingMode(const DataLayout &DL, 1885288943Sdim const AddrMode &AM, Type *Ty, 1886327952Sdim unsigned AS, 1887327952Sdim Instruction *I) const { 1888198090Srdivacky if (Ty->getTypeID() == Type::VoidTyID) 1889204642Srdivacky return AM.Scale == 0 && isImmUs(AM.BaseOffs) && isImmUs4(AM.BaseOffs); 1890198090Srdivacky 1891288943Sdim unsigned Size = DL.getTypeAllocSize(Ty); 1892193323Sed if (AM.BaseGV) { 1893198090Srdivacky return Size >= 4 && !AM.HasBaseReg && AM.Scale == 0 && 1894193323Sed AM.BaseOffs%4 == 0; 1895193323Sed } 1896219077Sdim 1897198090Srdivacky switch (Size) { 1898198090Srdivacky case 1: 1899193323Sed // reg + imm 1900193323Sed if (AM.Scale == 0) { 1901193323Sed return isImmUs(AM.BaseOffs); 1902193323Sed } 1903198090Srdivacky // reg + reg 1904193323Sed return AM.Scale == 1 && AM.BaseOffs == 0; 1905198090Srdivacky case 2: 1906198090Srdivacky case 3: 1907193323Sed // reg + imm 1908193323Sed if (AM.Scale == 0) { 1909193323Sed return isImmUs2(AM.BaseOffs); 1910193323Sed } 1911198090Srdivacky // reg + reg<<1 1912193323Sed return AM.Scale == 2 && AM.BaseOffs == 0; 1913198090Srdivacky default: 1914193323Sed // reg + imm 1915193323Sed if (AM.Scale == 0) { 1916193323Sed return isImmUs4(AM.BaseOffs); 1917193323Sed } 1918193323Sed // reg + reg<<2 1919193323Sed return AM.Scale == 4 && AM.BaseOffs == 0; 1920193323Sed } 1921193323Sed} 1922193323Sed 1923193323Sed//===----------------------------------------------------------------------===// 1924193323Sed// XCore Inline Assembly Support 1925193323Sed//===----------------------------------------------------------------------===// 1926193323Sed 1927288943Sdimstd::pair<unsigned, const TargetRegisterClass *> 1928288943SdimXCoreTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, 1929288943Sdim StringRef Constraint, 1930288943Sdim MVT VT) const { 1931224145Sdim if (Constraint.size() == 1) { 1932224145Sdim switch (Constraint[0]) { 1933193323Sed default : break; 1934193323Sed case 'r': 1935239462Sdim return std::make_pair(0U, &XCore::GRRegsRegClass); 1936224145Sdim } 1937193323Sed } 1938224145Sdim // Use the default implementation in TargetLowering to convert the register 1939224145Sdim // constraint into a member of a register class. 1940288943Sdim return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT); 1941193323Sed} 1942