brintos

brintos / llvm-project-archived public Read only

0
0
Text · 68.3 KiB · 7c49e5b Raw
1804 lines · cpp
1//===-- XCoreISelLowering.cpp - XCore DAG Lowering Implementation ---------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements the XCoreTargetLowering class.10//11//===----------------------------------------------------------------------===//12 13#include "XCoreISelLowering.h"14#include "XCore.h"15#include "XCoreMachineFunctionInfo.h"16#include "XCoreSubtarget.h"17#include "XCoreTargetMachine.h"18#include "XCoreTargetObjectFile.h"19#include "llvm/CodeGen/CallingConvLower.h"20#include "llvm/CodeGen/MachineFrameInfo.h"21#include "llvm/CodeGen/MachineFunction.h"22#include "llvm/CodeGen/MachineInstrBuilder.h"23#include "llvm/CodeGen/MachineJumpTableInfo.h"24#include "llvm/CodeGen/MachineRegisterInfo.h"25#include "llvm/CodeGen/ValueTypes.h"26#include "llvm/IR/CallingConv.h"27#include "llvm/IR/Constants.h"28#include "llvm/IR/DerivedTypes.h"29#include "llvm/IR/Function.h"30#include "llvm/IR/GlobalVariable.h"31#include "llvm/IR/Intrinsics.h"32#include "llvm/IR/IntrinsicsXCore.h"33#include "llvm/Support/Debug.h"34#include "llvm/Support/ErrorHandling.h"35#include "llvm/Support/KnownBits.h"36#include "llvm/Support/raw_ostream.h"37#include <algorithm>38 39using namespace llvm;40 41#define DEBUG_TYPE "xcore-lower"42 43XCoreTargetLowering::XCoreTargetLowering(const TargetMachine &TM,44                                         const XCoreSubtarget &Subtarget)45    : TargetLowering(TM, Subtarget), TM(TM), Subtarget(Subtarget) {46 47  // Set up the register classes.48  addRegisterClass(MVT::i32, &XCore::GRRegsRegClass);49 50  // Compute derived properties from the register classes51  computeRegisterProperties(Subtarget.getRegisterInfo());52 53  setStackPointerRegisterToSaveRestore(XCore::SP);54 55  setSchedulingPreference(Sched::Source);56 57  // Use i32 for setcc operations results (slt, sgt, ...).58  setBooleanContents(ZeroOrOneBooleanContent);59  setBooleanVectorContents(ZeroOrOneBooleanContent); // FIXME: Is this correct?60 61  // XCore does not have the NodeTypes below.62  setOperationAction(ISD::BR_CC,     MVT::i32,   Expand);63  setOperationAction(ISD::SELECT_CC, MVT::i32,   Expand);64 65  // 64bit66  setOperationAction(ISD::ADD, MVT::i64, Custom);67  setOperationAction(ISD::SUB, MVT::i64, Custom);68  setOperationAction(ISD::SMUL_LOHI, MVT::i32, Custom);69  setOperationAction(ISD::UMUL_LOHI, MVT::i32, Custom);70  setOperationAction(ISD::MULHS, MVT::i32, Expand);71  setOperationAction(ISD::MULHU, MVT::i32, Expand);72  setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);73  setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);74  setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);75 76  // Bit Manipulation77  setOperationAction(ISD::CTPOP, MVT::i32, Expand);78  setOperationAction(ISD::ROTL , MVT::i32, Expand);79  setOperationAction(ISD::ROTR , MVT::i32, Expand);80  setOperationAction(ISD::BITREVERSE , MVT::i32, Legal);81 82  setOperationAction(ISD::TRAP, MVT::Other, Legal);83 84  // Jump tables.85  setOperationAction(ISD::BR_JT, MVT::Other, Custom);86 87  setOperationAction(ISD::GlobalAddress, MVT::i32,   Custom);88  setOperationAction(ISD::BlockAddress, MVT::i32 , Custom);89 90  // Conversion of i64 -> double produces constantpool nodes91  setOperationAction(ISD::ConstantPool, MVT::i32,   Custom);92 93  // Loads94  for (MVT VT : MVT::integer_valuetypes()) {95    setLoadExtAction(ISD::EXTLOAD, VT, MVT::i1, Promote);96    setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i1, Promote);97    setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote);98 99    setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i8, Expand);100    setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i16, Expand);101  }102 103  // Custom expand misaligned loads / stores.104  setOperationAction(ISD::LOAD, MVT::i32, Custom);105  setOperationAction(ISD::STORE, MVT::i32, Custom);106 107  // Varargs108  setOperationAction(ISD::VAEND, MVT::Other, Expand);109  setOperationAction(ISD::VACOPY, MVT::Other, Expand);110  setOperationAction(ISD::VAARG, MVT::Other, Custom);111  setOperationAction(ISD::VASTART, MVT::Other, Custom);112 113  // Dynamic stack114  setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);115  setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);116  setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand);117 118  // Exception handling119  setOperationAction(ISD::EH_RETURN, MVT::Other, Custom);120  setOperationAction(ISD::FRAME_TO_ARGS_OFFSET, MVT::i32, Custom);121 122  setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom);123 124  // TRAMPOLINE is custom lowered.125  setOperationAction(ISD::INIT_TRAMPOLINE, MVT::Other, Custom);126  setOperationAction(ISD::ADJUST_TRAMPOLINE, MVT::Other, Custom);127 128  // We want to custom lower some of our intrinsics.129  setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);130 131  MaxStoresPerMemset = MaxStoresPerMemsetOptSize = 4;132  MaxStoresPerMemmove = MaxStoresPerMemmoveOptSize133    = MaxStoresPerMemcpy = MaxStoresPerMemcpyOptSize = 2;134 135  // We have target-specific dag combine patterns for the following nodes:136  setTargetDAGCombine(137      {ISD::STORE, ISD::ADD, ISD::INTRINSIC_VOID, ISD::INTRINSIC_W_CHAIN});138 139  setMinFunctionAlignment(Align(2));140  setPrefFunctionAlignment(Align(4));141 142  // This target doesn't implement native atomics.143  setMaxAtomicSizeInBitsSupported(0);144}145 146bool XCoreTargetLowering::isZExtFree(SDValue Val, EVT VT2) const {147  if (Val.getOpcode() != ISD::LOAD)148    return false;149 150  EVT VT1 = Val.getValueType();151  if (!VT1.isSimple() || !VT1.isInteger() ||152      !VT2.isSimple() || !VT2.isInteger())153    return false;154 155  switch (VT1.getSimpleVT().SimpleTy) {156  default: break;157  case MVT::i8:158    return true;159  }160 161  return false;162}163 164SDValue XCoreTargetLowering::165LowerOperation(SDValue Op, SelectionDAG &DAG) const {166  switch (Op.getOpcode())167  {168  case ISD::EH_RETURN:          return LowerEH_RETURN(Op, DAG);169  case ISD::GlobalAddress:      return LowerGlobalAddress(Op, DAG);170  case ISD::BlockAddress:       return LowerBlockAddress(Op, DAG);171  case ISD::ConstantPool:       return LowerConstantPool(Op, DAG);172  case ISD::BR_JT:              return LowerBR_JT(Op, DAG);173  case ISD::LOAD:               return LowerLOAD(Op, DAG);174  case ISD::STORE:              return LowerSTORE(Op, DAG);175  case ISD::VAARG:              return LowerVAARG(Op, DAG);176  case ISD::VASTART:            return LowerVASTART(Op, DAG);177  case ISD::SMUL_LOHI:          return LowerSMUL_LOHI(Op, DAG);178  case ISD::UMUL_LOHI:          return LowerUMUL_LOHI(Op, DAG);179  // FIXME: Remove these when LegalizeDAGTypes lands.180  case ISD::ADD:181  case ISD::SUB:                return ExpandADDSUB(Op.getNode(), DAG);182  case ISD::FRAMEADDR:          return LowerFRAMEADDR(Op, DAG);183  case ISD::RETURNADDR:         return LowerRETURNADDR(Op, DAG);184  case ISD::FRAME_TO_ARGS_OFFSET: return LowerFRAME_TO_ARGS_OFFSET(Op, DAG);185  case ISD::INIT_TRAMPOLINE:    return LowerINIT_TRAMPOLINE(Op, DAG);186  case ISD::ADJUST_TRAMPOLINE:  return LowerADJUST_TRAMPOLINE(Op, DAG);187  case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG);188  case ISD::ATOMIC_FENCE:189    return LowerATOMIC_FENCE(Op, DAG);190  default:191    llvm_unreachable("unimplemented operand");192  }193}194 195/// ReplaceNodeResults - Replace the results of node with an illegal result196/// type with new values built out of custom code.197void XCoreTargetLowering::ReplaceNodeResults(SDNode *N,198                                             SmallVectorImpl<SDValue>&Results,199                                             SelectionDAG &DAG) const {200  switch (N->getOpcode()) {201  default:202    llvm_unreachable("Don't know how to custom expand this!");203  case ISD::ADD:204  case ISD::SUB:205    Results.push_back(ExpandADDSUB(N, DAG));206    return;207  }208}209 210//===----------------------------------------------------------------------===//211//  Misc Lower Operation implementation212//===----------------------------------------------------------------------===//213 214SDValue XCoreTargetLowering::getGlobalAddressWrapper(SDValue GA,215                                                     const GlobalValue *GV,216                                                     SelectionDAG &DAG) const {217  // FIXME there is no actual debug info here218  SDLoc dl(GA);219 220  if (GV->getValueType()->isFunctionTy())221    return DAG.getNode(XCoreISD::PCRelativeWrapper, dl, MVT::i32, GA);222 223  const auto *GVar = dyn_cast<GlobalVariable>(GV);224  if ((GV->hasSection() && GV->getSection().starts_with(".cp.")) ||225      (GVar && GVar->isConstant() && GV->hasLocalLinkage()))226    return DAG.getNode(XCoreISD::CPRelativeWrapper, dl, MVT::i32, GA);227 228  return DAG.getNode(XCoreISD::DPRelativeWrapper, dl, MVT::i32, GA);229}230 231static bool IsSmallObject(const GlobalValue *GV, const XCoreTargetLowering &XTL) {232  if (XTL.getTargetMachine().getCodeModel() == CodeModel::Small)233    return true;234 235  Type *ObjType = GV->getValueType();236  if (!ObjType->isSized())237    return false;238 239  auto &DL = GV->getDataLayout();240  unsigned ObjSize = DL.getTypeAllocSize(ObjType);241  return ObjSize < CodeModelLargeSize && ObjSize != 0;242}243 244SDValue XCoreTargetLowering::245LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const246{247  const GlobalAddressSDNode *GN = cast<GlobalAddressSDNode>(Op);248  const GlobalValue *GV = GN->getGlobal();249  SDLoc DL(GN);250  int64_t Offset = GN->getOffset();251  if (IsSmallObject(GV, *this)) {252    // We can only fold positive offsets that are a multiple of the word size.253    int64_t FoldedOffset = std::max(Offset & ~3, (int64_t)0);254    SDValue GA = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, FoldedOffset);255    GA = getGlobalAddressWrapper(GA, GV, DAG);256    // Handle the rest of the offset.257    if (Offset != FoldedOffset) {258      SDValue Remaining =259          DAG.getSignedConstant(Offset - FoldedOffset, DL, MVT::i32);260      GA = DAG.getNode(ISD::ADD, DL, MVT::i32, GA, Remaining);261    }262    return GA;263  } else {264    // Ideally we would not fold in offset with an index <= 11.265    Type *Ty = Type::getInt32Ty(*DAG.getContext());266    Constant *Idx = ConstantInt::get(Ty, Offset);267    Constant *GAI = ConstantExpr::getGetElementPtr(268        Type::getInt8Ty(*DAG.getContext()), const_cast<GlobalValue *>(GV), Idx);269    SDValue CP = DAG.getConstantPool(GAI, MVT::i32);270    return DAG.getLoad(getPointerTy(DAG.getDataLayout()), DL,271                       DAG.getEntryNode(), CP, MachinePointerInfo());272  }273}274 275SDValue XCoreTargetLowering::276LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const277{278  SDLoc DL(Op);279  auto PtrVT = getPointerTy(DAG.getDataLayout());280  const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress();281  SDValue Result = DAG.getTargetBlockAddress(BA, PtrVT);282 283  return DAG.getNode(XCoreISD::PCRelativeWrapper, DL, PtrVT, Result);284}285 286SDValue XCoreTargetLowering::287LowerConstantPool(SDValue Op, SelectionDAG &DAG) const288{289  ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);290  // FIXME there isn't really debug info here291  SDLoc dl(CP);292  EVT PtrVT = Op.getValueType();293  SDValue Res;294  if (CP->isMachineConstantPoolEntry()) {295    Res = DAG.getTargetConstantPool(CP->getMachineCPVal(), PtrVT,296                                    CP->getAlign(), CP->getOffset());297  } else {298    Res = DAG.getTargetConstantPool(CP->getConstVal(), PtrVT, CP->getAlign(),299                                    CP->getOffset());300  }301  return DAG.getNode(XCoreISD::CPRelativeWrapper, dl, MVT::i32, Res);302}303 304unsigned XCoreTargetLowering::getJumpTableEncoding() const {305  return MachineJumpTableInfo::EK_Inline;306}307 308SDValue XCoreTargetLowering::309LowerBR_JT(SDValue Op, SelectionDAG &DAG) const310{311  SDValue Chain = Op.getOperand(0);312  SDValue Table = Op.getOperand(1);313  SDValue Index = Op.getOperand(2);314  SDLoc dl(Op);315  JumpTableSDNode *JT = cast<JumpTableSDNode>(Table);316  unsigned JTI = JT->getIndex();317  MachineFunction &MF = DAG.getMachineFunction();318  const MachineJumpTableInfo *MJTI = MF.getJumpTableInfo();319  SDValue TargetJT = DAG.getTargetJumpTable(JT->getIndex(), MVT::i32);320 321  unsigned NumEntries = MJTI->getJumpTables()[JTI].MBBs.size();322  if (NumEntries <= 32) {323    return DAG.getNode(XCoreISD::BR_JT, dl, MVT::Other, Chain, TargetJT, Index);324  }325  assert((NumEntries >> 31) == 0);326  SDValue ScaledIndex = DAG.getNode(ISD::SHL, dl, MVT::i32, Index,327                                    DAG.getConstant(1, dl, MVT::i32));328  return DAG.getNode(XCoreISD::BR_JT32, dl, MVT::Other, Chain, TargetJT,329                     ScaledIndex);330}331 332SDValue XCoreTargetLowering::lowerLoadWordFromAlignedBasePlusOffset(333    const SDLoc &DL, SDValue Chain, SDValue Base, int64_t Offset,334    SelectionDAG &DAG) const {335  auto PtrVT = getPointerTy(DAG.getDataLayout());336  if ((Offset & 0x3) == 0) {337    return DAG.getLoad(PtrVT, DL, Chain, Base, MachinePointerInfo());338  }339  // Lower to pair of consecutive word aligned loads plus some bit shifting.340  int32_t HighOffset = alignTo(Offset, 4);341  int32_t LowOffset = HighOffset - 4;342  SDValue LowAddr, HighAddr;343  if (GlobalAddressSDNode *GASD =344        dyn_cast<GlobalAddressSDNode>(Base.getNode())) {345    LowAddr = DAG.getGlobalAddress(GASD->getGlobal(), DL, Base.getValueType(),346                                   LowOffset);347    HighAddr = DAG.getGlobalAddress(GASD->getGlobal(), DL, Base.getValueType(),348                                    HighOffset);349  } else {350    LowAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, Base,351                          DAG.getConstant(LowOffset, DL, MVT::i32));352    HighAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, Base,353                           DAG.getConstant(HighOffset, DL, MVT::i32));354  }355  SDValue LowShift = DAG.getConstant((Offset - LowOffset) * 8, DL, MVT::i32);356  SDValue HighShift = DAG.getConstant((HighOffset - Offset) * 8, DL, MVT::i32);357 358  SDValue Low = DAG.getLoad(PtrVT, DL, Chain, LowAddr, MachinePointerInfo());359  SDValue High = DAG.getLoad(PtrVT, DL, Chain, HighAddr, MachinePointerInfo());360  SDValue LowShifted = DAG.getNode(ISD::SRL, DL, MVT::i32, Low, LowShift);361  SDValue HighShifted = DAG.getNode(ISD::SHL, DL, MVT::i32, High, HighShift);362  SDValue Result = DAG.getNode(ISD::OR, DL, MVT::i32, LowShifted, HighShifted);363  Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Low.getValue(1),364                      High.getValue(1));365  SDValue Ops[] = { Result, Chain };366  return DAG.getMergeValues(Ops, DL);367}368 369static bool isWordAligned(SDValue Value, SelectionDAG &DAG)370{371  KnownBits Known = DAG.computeKnownBits(Value);372  return Known.countMinTrailingZeros() >= 2;373}374 375SDValue XCoreTargetLowering::LowerLOAD(SDValue Op, SelectionDAG &DAG) const {376  const TargetLowering &TLI = DAG.getTargetLoweringInfo();377  LLVMContext &Context = *DAG.getContext();378  LoadSDNode *LD = cast<LoadSDNode>(Op);379  assert(LD->getExtensionType() == ISD::NON_EXTLOAD &&380         "Unexpected extension type");381  assert(LD->getMemoryVT() == MVT::i32 && "Unexpected load EVT");382 383  if (allowsMemoryAccessForAlignment(Context, DAG.getDataLayout(),384                                     LD->getMemoryVT(), *LD->getMemOperand()))385    return SDValue();386 387  SDValue Chain = LD->getChain();388  SDValue BasePtr = LD->getBasePtr();389  SDLoc DL(Op);390 391  if (!LD->isVolatile()) {392    const GlobalValue *GV;393    int64_t Offset = 0;394    if (DAG.isBaseWithConstantOffset(BasePtr) &&395        isWordAligned(BasePtr->getOperand(0), DAG)) {396      SDValue NewBasePtr = BasePtr->getOperand(0);397      Offset = cast<ConstantSDNode>(BasePtr->getOperand(1))->getSExtValue();398      return lowerLoadWordFromAlignedBasePlusOffset(DL, Chain, NewBasePtr,399                                                    Offset, DAG);400    }401    if (TLI.isGAPlusOffset(BasePtr.getNode(), GV, Offset) &&402        GV->getPointerAlignment(DAG.getDataLayout()) >= 4) {403      SDValue NewBasePtr = DAG.getGlobalAddress(GV, DL,404                                                BasePtr->getValueType(0));405      return lowerLoadWordFromAlignedBasePlusOffset(DL, Chain, NewBasePtr,406                                                    Offset, DAG);407    }408  }409 410  if (LD->getAlign() == Align(2)) {411    SDValue Low = DAG.getExtLoad(ISD::ZEXTLOAD, DL, MVT::i32, Chain, BasePtr,412                                 LD->getPointerInfo(), MVT::i16, Align(2),413                                 LD->getMemOperand()->getFlags());414    SDValue HighAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, BasePtr,415                                   DAG.getConstant(2, DL, MVT::i32));416    SDValue High =417        DAG.getExtLoad(ISD::EXTLOAD, DL, MVT::i32, Chain, HighAddr,418                       LD->getPointerInfo().getWithOffset(2), MVT::i16,419                       Align(2), LD->getMemOperand()->getFlags());420    SDValue HighShifted = DAG.getNode(ISD::SHL, DL, MVT::i32, High,421                                      DAG.getConstant(16, DL, MVT::i32));422    SDValue Result = DAG.getNode(ISD::OR, DL, MVT::i32, Low, HighShifted);423    Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Low.getValue(1),424                             High.getValue(1));425    SDValue Ops[] = { Result, Chain };426    return DAG.getMergeValues(Ops, DL);427  }428 429  // Lower to a call to __misaligned_load(BasePtr).430  Type *IntPtrTy = DAG.getDataLayout().getIntPtrType(Context);431  TargetLowering::ArgListTy Args;432  Args.emplace_back(BasePtr, IntPtrTy);433 434  TargetLowering::CallLoweringInfo CLI(DAG);435  CLI.setDebugLoc(DL).setChain(Chain).setLibCallee(436      CallingConv::C, IntPtrTy,437      DAG.getExternalSymbol("__misaligned_load",438                            getPointerTy(DAG.getDataLayout())),439      std::move(Args));440 441  std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI);442  SDValue Ops[] = { CallResult.first, CallResult.second };443  return DAG.getMergeValues(Ops, DL);444}445 446SDValue XCoreTargetLowering::LowerSTORE(SDValue Op, SelectionDAG &DAG) const {447  LLVMContext &Context = *DAG.getContext();448  StoreSDNode *ST = cast<StoreSDNode>(Op);449  assert(!ST->isTruncatingStore() && "Unexpected store type");450  assert(ST->getMemoryVT() == MVT::i32 && "Unexpected store EVT");451 452  if (allowsMemoryAccessForAlignment(Context, DAG.getDataLayout(),453                                     ST->getMemoryVT(), *ST->getMemOperand()))454    return SDValue();455 456  SDValue Chain = ST->getChain();457  SDValue BasePtr = ST->getBasePtr();458  SDValue Value = ST->getValue();459  SDLoc dl(Op);460 461  if (ST->getAlign() == Align(2)) {462    SDValue Low = Value;463    SDValue High = DAG.getNode(ISD::SRL, dl, MVT::i32, Value,464                               DAG.getConstant(16, dl, MVT::i32));465    SDValue StoreLow =466        DAG.getTruncStore(Chain, dl, Low, BasePtr, ST->getPointerInfo(),467                          MVT::i16, Align(2), ST->getMemOperand()->getFlags());468    SDValue HighAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, BasePtr,469                                   DAG.getConstant(2, dl, MVT::i32));470    SDValue StoreHigh = DAG.getTruncStore(471        Chain, dl, High, HighAddr, ST->getPointerInfo().getWithOffset(2),472        MVT::i16, Align(2), ST->getMemOperand()->getFlags());473    return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, StoreLow, StoreHigh);474  }475 476  // Lower to a call to __misaligned_store(BasePtr, Value).477  Type *IntPtrTy = DAG.getDataLayout().getIntPtrType(Context);478  TargetLowering::ArgListTy Args;479  Args.emplace_back(BasePtr, IntPtrTy);480  Args.emplace_back(Value, IntPtrTy);481 482  TargetLowering::CallLoweringInfo CLI(DAG);483  CLI.setDebugLoc(dl).setChain(Chain).setCallee(484      CallingConv::C, Type::getVoidTy(Context),485      DAG.getExternalSymbol("__misaligned_store",486                            getPointerTy(DAG.getDataLayout())),487      std::move(Args));488 489  std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI);490  return CallResult.second;491}492 493SDValue XCoreTargetLowering::494LowerSMUL_LOHI(SDValue Op, SelectionDAG &DAG) const495{496  assert(Op.getValueType() == MVT::i32 && Op.getOpcode() == ISD::SMUL_LOHI &&497         "Unexpected operand to lower!");498  SDLoc dl(Op);499  SDValue LHS = Op.getOperand(0);500  SDValue RHS = Op.getOperand(1);501  SDValue Zero = DAG.getConstant(0, dl, MVT::i32);502  SDValue Hi = DAG.getNode(XCoreISD::MACCS, dl,503                           DAG.getVTList(MVT::i32, MVT::i32), Zero, Zero,504                           LHS, RHS);505  SDValue Lo(Hi.getNode(), 1);506  SDValue Ops[] = { Lo, Hi };507  return DAG.getMergeValues(Ops, dl);508}509 510SDValue XCoreTargetLowering::511LowerUMUL_LOHI(SDValue Op, SelectionDAG &DAG) const512{513  assert(Op.getValueType() == MVT::i32 && Op.getOpcode() == ISD::UMUL_LOHI &&514         "Unexpected operand to lower!");515  SDLoc dl(Op);516  SDValue LHS = Op.getOperand(0);517  SDValue RHS = Op.getOperand(1);518  SDValue Zero = DAG.getConstant(0, dl, MVT::i32);519  SDValue Hi = DAG.getNode(XCoreISD::LMUL, dl,520                           DAG.getVTList(MVT::i32, MVT::i32), LHS, RHS,521                           Zero, Zero);522  SDValue Lo(Hi.getNode(), 1);523  SDValue Ops[] = { Lo, Hi };524  return DAG.getMergeValues(Ops, dl);525}526 527/// isADDADDMUL - Return whether Op is in a form that is equivalent to528/// add(add(mul(x,y),a),b). If requireIntermediatesHaveOneUse is true then529/// each intermediate result in the calculation must also have a single use.530/// If the Op is in the correct form the constituent parts are written to Mul0,531/// Mul1, Addend0 and Addend1.532static bool533isADDADDMUL(SDValue Op, SDValue &Mul0, SDValue &Mul1, SDValue &Addend0,534            SDValue &Addend1, bool requireIntermediatesHaveOneUse)535{536  if (Op.getOpcode() != ISD::ADD)537    return false;538  SDValue N0 = Op.getOperand(0);539  SDValue N1 = Op.getOperand(1);540  SDValue AddOp;541  SDValue OtherOp;542  if (N0.getOpcode() == ISD::ADD) {543    AddOp = N0;544    OtherOp = N1;545  } else if (N1.getOpcode() == ISD::ADD) {546    AddOp = N1;547    OtherOp = N0;548  } else {549    return false;550  }551  if (requireIntermediatesHaveOneUse && !AddOp.hasOneUse())552    return false;553  if (OtherOp.getOpcode() == ISD::MUL) {554    // add(add(a,b),mul(x,y))555    if (requireIntermediatesHaveOneUse && !OtherOp.hasOneUse())556      return false;557    Mul0 = OtherOp.getOperand(0);558    Mul1 = OtherOp.getOperand(1);559    Addend0 = AddOp.getOperand(0);560    Addend1 = AddOp.getOperand(1);561    return true;562  }563  if (AddOp.getOperand(0).getOpcode() == ISD::MUL) {564    // add(add(mul(x,y),a),b)565    if (requireIntermediatesHaveOneUse && !AddOp.getOperand(0).hasOneUse())566      return false;567    Mul0 = AddOp.getOperand(0).getOperand(0);568    Mul1 = AddOp.getOperand(0).getOperand(1);569    Addend0 = AddOp.getOperand(1);570    Addend1 = OtherOp;571    return true;572  }573  if (AddOp.getOperand(1).getOpcode() == ISD::MUL) {574    // add(add(a,mul(x,y)),b)575    if (requireIntermediatesHaveOneUse && !AddOp.getOperand(1).hasOneUse())576      return false;577    Mul0 = AddOp.getOperand(1).getOperand(0);578    Mul1 = AddOp.getOperand(1).getOperand(1);579    Addend0 = AddOp.getOperand(0);580    Addend1 = OtherOp;581    return true;582  }583  return false;584}585 586SDValue XCoreTargetLowering::587TryExpandADDWithMul(SDNode *N, SelectionDAG &DAG) const588{589  SDValue Mul;590  SDValue Other;591  if (N->getOperand(0).getOpcode() == ISD::MUL) {592    Mul = N->getOperand(0);593    Other = N->getOperand(1);594  } else if (N->getOperand(1).getOpcode() == ISD::MUL) {595    Mul = N->getOperand(1);596    Other = N->getOperand(0);597  } else {598    return SDValue();599  }600  SDLoc dl(N);601  SDValue LL, RL, AddendL, AddendH;602  LL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,603                   Mul.getOperand(0), DAG.getConstant(0, dl, MVT::i32));604  RL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,605                   Mul.getOperand(1), DAG.getConstant(0, dl, MVT::i32));606  AddendL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,607                        Other, DAG.getConstant(0, dl, MVT::i32));608  AddendH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,609                        Other, DAG.getConstant(1, dl, MVT::i32));610  APInt HighMask = APInt::getHighBitsSet(64, 32);611  unsigned LHSSB = DAG.ComputeNumSignBits(Mul.getOperand(0));612  unsigned RHSSB = DAG.ComputeNumSignBits(Mul.getOperand(1));613  if (DAG.MaskedValueIsZero(Mul.getOperand(0), HighMask) &&614      DAG.MaskedValueIsZero(Mul.getOperand(1), HighMask)) {615    // The inputs are both zero-extended.616    SDValue Hi = DAG.getNode(XCoreISD::MACCU, dl,617                             DAG.getVTList(MVT::i32, MVT::i32), AddendH,618                             AddendL, LL, RL);619    SDValue Lo(Hi.getNode(), 1);620    return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi);621  }622  if (LHSSB > 32 && RHSSB > 32) {623    // The inputs are both sign-extended.624    SDValue Hi = DAG.getNode(XCoreISD::MACCS, dl,625                             DAG.getVTList(MVT::i32, MVT::i32), AddendH,626                             AddendL, LL, RL);627    SDValue Lo(Hi.getNode(), 1);628    return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi);629  }630  SDValue LH, RH;631  LH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,632                   Mul.getOperand(0), DAG.getConstant(1, dl, MVT::i32));633  RH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,634                   Mul.getOperand(1), DAG.getConstant(1, dl, MVT::i32));635  SDValue Hi = DAG.getNode(XCoreISD::MACCU, dl,636                           DAG.getVTList(MVT::i32, MVT::i32), AddendH,637                           AddendL, LL, RL);638  SDValue Lo(Hi.getNode(), 1);639  RH = DAG.getNode(ISD::MUL, dl, MVT::i32, LL, RH);640  LH = DAG.getNode(ISD::MUL, dl, MVT::i32, LH, RL);641  Hi = DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, RH);642  Hi = DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, LH);643  return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi);644}645 646SDValue XCoreTargetLowering::647ExpandADDSUB(SDNode *N, SelectionDAG &DAG) const648{649  assert(N->getValueType(0) == MVT::i64 &&650         (N->getOpcode() == ISD::ADD || N->getOpcode() == ISD::SUB) &&651        "Unknown operand to lower!");652 653  if (N->getOpcode() == ISD::ADD)654    if (SDValue Result = TryExpandADDWithMul(N, DAG))655      return Result;656 657  SDLoc dl(N);658 659  // Extract components660  SDValue LHSL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,661                             N->getOperand(0),662                             DAG.getConstant(0, dl, MVT::i32));663  SDValue LHSH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,664                             N->getOperand(0),665                             DAG.getConstant(1, dl, MVT::i32));666  SDValue RHSL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,667                             N->getOperand(1),668                             DAG.getConstant(0, dl, MVT::i32));669  SDValue RHSH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,670                             N->getOperand(1),671                             DAG.getConstant(1, dl, MVT::i32));672 673  // Expand674  unsigned Opcode = (N->getOpcode() == ISD::ADD) ? XCoreISD::LADD :675                                                   XCoreISD::LSUB;676  SDValue Zero = DAG.getConstant(0, dl, MVT::i32);677  SDValue Lo = DAG.getNode(Opcode, dl, DAG.getVTList(MVT::i32, MVT::i32),678                           LHSL, RHSL, Zero);679  SDValue Carry(Lo.getNode(), 1);680 681  SDValue Hi = DAG.getNode(Opcode, dl, DAG.getVTList(MVT::i32, MVT::i32),682                           LHSH, RHSH, Carry);683  SDValue Ignored(Hi.getNode(), 1);684  // Merge the pieces685  return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi);686}687 688SDValue XCoreTargetLowering::689LowerVAARG(SDValue Op, SelectionDAG &DAG) const690{691  // Whist llvm does not support aggregate varargs we can ignore692  // the possibility of the ValueType being an implicit byVal vararg.693  SDNode *Node = Op.getNode();694  EVT VT = Node->getValueType(0); // not an aggregate695  SDValue InChain = Node->getOperand(0);696  SDValue VAListPtr = Node->getOperand(1);697  EVT PtrVT = VAListPtr.getValueType();698  const Value *SV = cast<SrcValueSDNode>(Node->getOperand(2))->getValue();699  SDLoc dl(Node);700  SDValue VAList =701      DAG.getLoad(PtrVT, dl, InChain, VAListPtr, MachinePointerInfo(SV));702  // Increment the pointer, VAList, to the next vararg703  SDValue nextPtr = DAG.getNode(ISD::ADD, dl, PtrVT, VAList,704                                DAG.getIntPtrConstant(VT.getSizeInBits() / 8,705                                                      dl));706  // Store the incremented VAList to the legalized pointer707  InChain = DAG.getStore(VAList.getValue(1), dl, nextPtr, VAListPtr,708                         MachinePointerInfo(SV));709  // Load the actual argument out of the pointer VAList710  return DAG.getLoad(VT, dl, InChain, VAList, MachinePointerInfo());711}712 713SDValue XCoreTargetLowering::714LowerVASTART(SDValue Op, SelectionDAG &DAG) const715{716  SDLoc dl(Op);717  // vastart stores the address of the VarArgsFrameIndex slot into the718  // memory location argument719  MachineFunction &MF = DAG.getMachineFunction();720  XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();721  SDValue Addr = DAG.getFrameIndex(XFI->getVarArgsFrameIndex(), MVT::i32);722  return DAG.getStore(Op.getOperand(0), dl, Addr, Op.getOperand(1),723                      MachinePointerInfo());724}725 726SDValue XCoreTargetLowering::LowerFRAMEADDR(SDValue Op,727                                            SelectionDAG &DAG) const {728  // This nodes represent llvm.frameaddress on the DAG.729  // It takes one operand, the index of the frame address to return.730  // An index of zero corresponds to the current function's frame address.731  // An index of one to the parent's frame address, and so on.732  // Depths > 0 not supported yet!733  if (Op.getConstantOperandVal(0) > 0)734    return SDValue();735 736  MachineFunction &MF = DAG.getMachineFunction();737  const TargetRegisterInfo *RegInfo = Subtarget.getRegisterInfo();738  return DAG.getCopyFromReg(DAG.getEntryNode(), SDLoc(Op),739                            RegInfo->getFrameRegister(MF), MVT::i32);740}741 742SDValue XCoreTargetLowering::743LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const {744  // This nodes represent llvm.returnaddress on the DAG.745  // It takes one operand, the index of the return address to return.746  // An index of zero corresponds to the current function's return address.747  // An index of one to the parent's return address, and so on.748  // Depths > 0 not supported yet!749  if (Op.getConstantOperandVal(0) > 0)750    return SDValue();751 752  MachineFunction &MF = DAG.getMachineFunction();753  XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();754  int FI = XFI->createLRSpillSlot(MF);755  SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);756  return DAG.getLoad(getPointerTy(DAG.getDataLayout()), SDLoc(Op),757                     DAG.getEntryNode(), FIN,758                     MachinePointerInfo::getFixedStack(MF, FI));759}760 761SDValue XCoreTargetLowering::762LowerFRAME_TO_ARGS_OFFSET(SDValue Op, SelectionDAG &DAG) const {763  // This node represents offset from frame pointer to first on-stack argument.764  // This is needed for correct stack adjustment during unwind.765  // However, we don't know the offset until after the frame has be finalised.766  // This is done during the XCoreFTAOElim pass.767  return DAG.getNode(XCoreISD::FRAME_TO_ARGS_OFFSET, SDLoc(Op), MVT::i32);768}769 770SDValue XCoreTargetLowering::771LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const {772  // OUTCHAIN = EH_RETURN(INCHAIN, OFFSET, HANDLER)773  // This node represents 'eh_return' gcc dwarf builtin, which is used to774  // return from exception. The general meaning is: adjust stack by OFFSET and775  // pass execution to HANDLER.776  MachineFunction &MF = DAG.getMachineFunction();777  SDValue Chain     = Op.getOperand(0);778  SDValue Offset    = Op.getOperand(1);779  SDValue Handler   = Op.getOperand(2);780  SDLoc dl(Op);781 782  // Absolute SP = (FP + FrameToArgs) + Offset783  const TargetRegisterInfo *RegInfo = Subtarget.getRegisterInfo();784  SDValue Stack = DAG.getCopyFromReg(DAG.getEntryNode(), dl,785                            RegInfo->getFrameRegister(MF), MVT::i32);786  SDValue FrameToArgs = DAG.getNode(XCoreISD::FRAME_TO_ARGS_OFFSET, dl,787                                    MVT::i32);788  Stack = DAG.getNode(ISD::ADD, dl, MVT::i32, Stack, FrameToArgs);789  Stack = DAG.getNode(ISD::ADD, dl, MVT::i32, Stack, Offset);790 791  // R0=ExceptionPointerRegister R1=ExceptionSelectorRegister792  // which leaves 2 caller saved registers, R2 & R3 for us to use.793  unsigned StackReg = XCore::R2;794  unsigned HandlerReg = XCore::R3;795 796  SDValue OutChains[] = {797    DAG.getCopyToReg(Chain, dl, StackReg, Stack),798    DAG.getCopyToReg(Chain, dl, HandlerReg, Handler)799  };800 801  Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains);802 803  return DAG.getNode(XCoreISD::EH_RETURN, dl, MVT::Other, Chain,804                     DAG.getRegister(StackReg, MVT::i32),805                     DAG.getRegister(HandlerReg, MVT::i32));806 807}808 809SDValue XCoreTargetLowering::810LowerADJUST_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const {811  return Op.getOperand(0);812}813 814SDValue XCoreTargetLowering::815LowerINIT_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const {816  SDValue Chain = Op.getOperand(0);817  SDValue Trmp = Op.getOperand(1); // trampoline818  SDValue FPtr = Op.getOperand(2); // nested function819  SDValue Nest = Op.getOperand(3); // 'nest' parameter value820 821  const Value *TrmpAddr = cast<SrcValueSDNode>(Op.getOperand(4))->getValue();822 823  // .align 4824  // LDAPF_u10 r11, nest825  // LDW_2rus r11, r11[0]826  // STWSP_ru6 r11, sp[0]827  // LDAPF_u10 r11, fptr828  // LDW_2rus r11, r11[0]829  // BAU_1r r11830  // nest:831  // .word nest832  // fptr:833  // .word fptr834  SDValue OutChains[5];835 836  SDValue Addr = Trmp;837 838  SDLoc dl(Op);839  OutChains[0] =840      DAG.getStore(Chain, dl, DAG.getConstant(0x0a3cd805, dl, MVT::i32), Addr,841                   MachinePointerInfo(TrmpAddr));842 843  Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp,844                     DAG.getConstant(4, dl, MVT::i32));845  OutChains[1] =846      DAG.getStore(Chain, dl, DAG.getConstant(0xd80456c0, dl, MVT::i32), Addr,847                   MachinePointerInfo(TrmpAddr, 4));848 849  Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp,850                     DAG.getConstant(8, dl, MVT::i32));851  OutChains[2] =852      DAG.getStore(Chain, dl, DAG.getConstant(0x27fb0a3c, dl, MVT::i32), Addr,853                   MachinePointerInfo(TrmpAddr, 8));854 855  Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp,856                     DAG.getConstant(12, dl, MVT::i32));857  OutChains[3] =858      DAG.getStore(Chain, dl, Nest, Addr, MachinePointerInfo(TrmpAddr, 12));859 860  Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp,861                     DAG.getConstant(16, dl, MVT::i32));862  OutChains[4] =863      DAG.getStore(Chain, dl, FPtr, Addr, MachinePointerInfo(TrmpAddr, 16));864 865  return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains);866}867 868SDValue XCoreTargetLowering::869LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const {870  SDLoc DL(Op);871  unsigned IntNo = Op.getConstantOperandVal(0);872  switch (IntNo) {873    case Intrinsic::xcore_crc8:874      EVT VT = Op.getValueType();875      SDValue Data =876        DAG.getNode(XCoreISD::CRC8, DL, DAG.getVTList(VT, VT),877                    Op.getOperand(1), Op.getOperand(2) , Op.getOperand(3));878      SDValue Crc(Data.getNode(), 1);879      SDValue Results[] = { Crc, Data };880      return DAG.getMergeValues(Results, DL);881  }882  return SDValue();883}884 885SDValue XCoreTargetLowering::886LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG) const {887  SDLoc DL(Op);888  return DAG.getNode(ISD::MEMBARRIER, DL, MVT::Other, Op.getOperand(0));889}890 891//===----------------------------------------------------------------------===//892//                      Calling Convention Implementation893//===----------------------------------------------------------------------===//894 895#include "XCoreGenCallingConv.inc"896 897//===----------------------------------------------------------------------===//898//                  Call Calling Convention Implementation899//===----------------------------------------------------------------------===//900 901/// XCore call implementation902SDValue903XCoreTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,904                               SmallVectorImpl<SDValue> &InVals) const {905  SelectionDAG &DAG                     = CLI.DAG;906  SDLoc &dl                             = CLI.DL;907  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;908  SmallVectorImpl<SDValue> &OutVals     = CLI.OutVals;909  SmallVectorImpl<ISD::InputArg> &Ins   = CLI.Ins;910  SDValue Chain                         = CLI.Chain;911  SDValue Callee                        = CLI.Callee;912  bool &isTailCall                      = CLI.IsTailCall;913  CallingConv::ID CallConv              = CLI.CallConv;914  bool isVarArg                         = CLI.IsVarArg;915 916  // XCore target does not yet support tail call optimization.917  isTailCall = false;918 919  // For now, only CallingConv::C implemented920  switch (CallConv)921  {922    default:923      report_fatal_error("Unsupported calling convention");924    case CallingConv::Fast:925    case CallingConv::C:926      return LowerCCCCallTo(Chain, Callee, CallConv, isVarArg, isTailCall,927                            Outs, OutVals, Ins, dl, DAG, InVals);928  }929}930 931/// LowerCallResult - Lower the result values of a call into the932/// appropriate copies out of appropriate physical registers / memory locations.933static SDValue LowerCallResult(SDValue Chain, SDValue InGlue,934                               const SmallVectorImpl<CCValAssign> &RVLocs,935                               const SDLoc &dl, SelectionDAG &DAG,936                               SmallVectorImpl<SDValue> &InVals) {937  SmallVector<std::pair<int, unsigned>, 4> ResultMemLocs;938  // Copy results out of physical registers.939  for (const CCValAssign &VA : RVLocs) {940    if (VA.isRegLoc()) {941      Chain = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), VA.getValVT(),942                                 InGlue).getValue(1);943      InGlue = Chain.getValue(2);944      InVals.push_back(Chain.getValue(0));945    } else {946      assert(VA.isMemLoc());947      ResultMemLocs.push_back(std::make_pair(VA.getLocMemOffset(),948                                             InVals.size()));949      // Reserve space for this result.950      InVals.push_back(SDValue());951    }952  }953 954  // Copy results out of memory.955  SmallVector<SDValue, 4> MemOpChains;956  for (unsigned i = 0, e = ResultMemLocs.size(); i != e; ++i) {957    int offset = ResultMemLocs[i].first;958    unsigned index = ResultMemLocs[i].second;959    SDVTList VTs = DAG.getVTList(MVT::i32, MVT::Other);960    SDValue Ops[] = { Chain, DAG.getConstant(offset / 4, dl, MVT::i32) };961    SDValue load = DAG.getNode(XCoreISD::LDWSP, dl, VTs, Ops);962    InVals[index] = load;963    MemOpChains.push_back(load.getValue(1));964  }965 966  // Transform all loads nodes into one single node because967  // all load nodes are independent of each other.968  if (!MemOpChains.empty())969    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);970 971  return Chain;972}973 974/// LowerCCCCallTo - functions arguments are copied from virtual975/// regs to (physical regs)/(stack frame), CALLSEQ_START and976/// CALLSEQ_END are emitted.977/// TODO: isTailCall, sret.978SDValue XCoreTargetLowering::LowerCCCCallTo(979    SDValue Chain, SDValue Callee, CallingConv::ID CallConv, bool isVarArg,980    bool isTailCall, const SmallVectorImpl<ISD::OutputArg> &Outs,981    const SmallVectorImpl<SDValue> &OutVals,982    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,983    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {984 985  // Analyze operands of the call, assigning locations to each operand.986  SmallVector<CCValAssign, 16> ArgLocs;987  CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,988                 *DAG.getContext());989 990  // The ABI dictates there should be one stack slot available to the callee991  // on function entry (for saving lr).992  CCInfo.AllocateStack(4, Align(4));993 994  CCInfo.AnalyzeCallOperands(Outs, CC_XCore);995 996  SmallVector<CCValAssign, 16> RVLocs;997  // Analyze return values to determine the number of bytes of stack required.998  CCState RetCCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,999                    *DAG.getContext());1000  RetCCInfo.AllocateStack(CCInfo.getStackSize(), Align(4));1001  RetCCInfo.AnalyzeCallResult(Ins, RetCC_XCore);1002 1003  // Get a count of how many bytes are to be pushed on the stack.1004  unsigned NumBytes = RetCCInfo.getStackSize();1005 1006  Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, dl);1007 1008  SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass;1009  SmallVector<SDValue, 12> MemOpChains;1010 1011  // Walk the register/memloc assignments, inserting copies/loads.1012  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {1013    CCValAssign &VA = ArgLocs[i];1014    SDValue Arg = OutVals[i];1015 1016    // Promote the value if needed.1017    switch (VA.getLocInfo()) {1018      default: llvm_unreachable("Unknown loc info!");1019      case CCValAssign::Full: break;1020      case CCValAssign::SExt:1021        Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);1022        break;1023      case CCValAssign::ZExt:1024        Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg);1025        break;1026      case CCValAssign::AExt:1027        Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);1028        break;1029    }1030 1031    // Arguments that can be passed on register must be kept at1032    // RegsToPass vector1033    if (VA.isRegLoc()) {1034      RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));1035    } else {1036      assert(VA.isMemLoc());1037 1038      int Offset = VA.getLocMemOffset();1039 1040      MemOpChains.push_back(DAG.getNode(XCoreISD::STWSP, dl, MVT::Other,1041                                        Chain, Arg,1042                                        DAG.getConstant(Offset/4, dl,1043                                                        MVT::i32)));1044    }1045  }1046 1047  // Transform all store nodes into one single node because1048  // all store nodes are independent of each other.1049  if (!MemOpChains.empty())1050    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);1051 1052  // Build a sequence of copy-to-reg nodes chained together with token1053  // chain and flag operands which copy the outgoing args into registers.1054  // The InGlue in necessary since all emitted instructions must be1055  // stuck together.1056  SDValue InGlue;1057  for (const auto &[Reg, N] : RegsToPass) {1058    Chain = DAG.getCopyToReg(Chain, dl, Reg, N, InGlue);1059    InGlue = Chain.getValue(1);1060  }1061 1062  // If the callee is a GlobalAddress node (quite common, every direct call is)1063  // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.1064  // Likewise ExternalSymbol -> TargetExternalSymbol.1065  if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))1066    Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32);1067  else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))1068    Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32);1069 1070  // XCoreBranchLink = #chain, #target_address, #opt_in_flags...1071  //             = Chain, Callee, Reg#1, Reg#2, ...1072  //1073  // Returns a chain & a flag for retval copy to use.1074  SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);1075  SmallVector<SDValue, 8> Ops;1076  Ops.push_back(Chain);1077  Ops.push_back(Callee);1078 1079  // Add argument registers to the end of the list so that they are1080  // known live into the call.1081  for (const auto &[Reg, N] : RegsToPass)1082    Ops.push_back(DAG.getRegister(Reg, N.getValueType()));1083 1084  if (InGlue.getNode())1085    Ops.push_back(InGlue);1086 1087  Chain  = DAG.getNode(XCoreISD::BL, dl, NodeTys, Ops);1088  InGlue = Chain.getValue(1);1089 1090  // Create the CALLSEQ_END node.1091  Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, InGlue, dl);1092  InGlue = Chain.getValue(1);1093 1094  // Handle result values, copying them out of physregs into vregs that we1095  // return.1096  return LowerCallResult(Chain, InGlue, RVLocs, dl, DAG, InVals);1097}1098 1099//===----------------------------------------------------------------------===//1100//             Formal Arguments Calling Convention Implementation1101//===----------------------------------------------------------------------===//1102 1103namespace {1104  struct ArgDataPair { SDValue SDV; ISD::ArgFlagsTy Flags; };1105}1106 1107/// XCore formal arguments implementation1108SDValue XCoreTargetLowering::LowerFormalArguments(1109    SDValue Chain, CallingConv::ID CallConv, bool isVarArg,1110    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,1111    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {1112  switch (CallConv)1113  {1114    default:1115      report_fatal_error("Unsupported calling convention");1116    case CallingConv::C:1117    case CallingConv::Fast:1118      return LowerCCCArguments(Chain, CallConv, isVarArg,1119                               Ins, dl, DAG, InVals);1120  }1121}1122 1123/// LowerCCCArguments - transform physical registers into1124/// virtual registers and generate load operations for1125/// arguments places on the stack.1126/// TODO: sret1127SDValue XCoreTargetLowering::LowerCCCArguments(1128    SDValue Chain, CallingConv::ID CallConv, bool isVarArg,1129    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,1130    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {1131  MachineFunction &MF = DAG.getMachineFunction();1132  MachineFrameInfo &MFI = MF.getFrameInfo();1133  MachineRegisterInfo &RegInfo = MF.getRegInfo();1134  XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();1135 1136  // Assign locations to all of the incoming arguments.1137  SmallVector<CCValAssign, 16> ArgLocs;1138  CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,1139                 *DAG.getContext());1140 1141  CCInfo.AnalyzeFormalArguments(Ins, CC_XCore);1142 1143  unsigned StackSlotSize = XCoreFrameLowering::stackSlotSize();1144 1145  unsigned LRSaveSize = StackSlotSize;1146 1147  if (!isVarArg)1148    XFI->setReturnStackOffset(CCInfo.getStackSize() + LRSaveSize);1149 1150  // All getCopyFromReg ops must precede any getMemcpys to prevent the1151  // scheduler clobbering a register before it has been copied.1152  // The stages are:1153  // 1. CopyFromReg (and load) arg & vararg registers.1154  // 2. Chain CopyFromReg nodes into a TokenFactor.1155  // 3. Memcpy 'byVal' args & push final InVals.1156  // 4. Chain mem ops nodes into a TokenFactor.1157  SmallVector<SDValue, 4> CFRegNode;1158  SmallVector<ArgDataPair, 4> ArgData;1159  SmallVector<SDValue, 4> MemOps;1160 1161  // 1a. CopyFromReg (and load) arg registers.1162  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {1163 1164    CCValAssign &VA = ArgLocs[i];1165    SDValue ArgIn;1166 1167    if (VA.isRegLoc()) {1168      // Arguments passed in registers1169      EVT RegVT = VA.getLocVT();1170      switch (RegVT.getSimpleVT().SimpleTy) {1171      default:1172        {1173#ifndef NDEBUG1174          errs() << "LowerFormalArguments Unhandled argument type: "1175                 << RegVT << "\n";1176#endif1177          llvm_unreachable(nullptr);1178        }1179      case MVT::i32:1180        Register VReg = RegInfo.createVirtualRegister(&XCore::GRRegsRegClass);1181        RegInfo.addLiveIn(VA.getLocReg(), VReg);1182        ArgIn = DAG.getCopyFromReg(Chain, dl, VReg, RegVT);1183        CFRegNode.push_back(ArgIn.getValue(ArgIn->getNumValues() - 1));1184      }1185    } else {1186      // Only arguments passed on the stack should make it here. 1187      assert(VA.isMemLoc());1188      // Load the argument to a virtual register1189      unsigned ObjSize = VA.getLocVT().getSizeInBits()/8;1190      if (ObjSize > StackSlotSize) {1191        errs() << "LowerFormalArguments Unhandled argument type: "1192               << VA.getLocVT() << "\n";1193      }1194      // Create the frame index object for this incoming parameter...1195      int FI = MFI.CreateFixedObject(ObjSize,1196                                     LRSaveSize + VA.getLocMemOffset(),1197                                     true);1198 1199      // Create the SelectionDAG nodes corresponding to a load1200      //from this parameter1201      SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);1202      ArgIn = DAG.getLoad(VA.getLocVT(), dl, Chain, FIN,1203                          MachinePointerInfo::getFixedStack(MF, FI));1204    }1205    const ArgDataPair ADP = { ArgIn, Ins[i].Flags };1206    ArgData.push_back(ADP);1207  }1208 1209  // 1b. CopyFromReg vararg registers.1210  if (isVarArg) {1211    // Argument registers1212    static const MCPhysReg ArgRegs[] = {1213      XCore::R0, XCore::R1, XCore::R2, XCore::R31214    };1215    XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();1216    unsigned FirstVAReg = CCInfo.getFirstUnallocated(ArgRegs);1217    if (FirstVAReg < std::size(ArgRegs)) {1218      int offset = 0;1219      // Save remaining registers, storing higher register numbers at a higher1220      // address1221      for (int i = std::size(ArgRegs) - 1; i >= (int)FirstVAReg; --i) {1222        // Create a stack slot1223        int FI = MFI.CreateFixedObject(4, offset, true);1224        if (i == (int)FirstVAReg) {1225          XFI->setVarArgsFrameIndex(FI);1226        }1227        offset -= StackSlotSize;1228        SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);1229        // Move argument from phys reg -> virt reg1230        Register VReg = RegInfo.createVirtualRegister(&XCore::GRRegsRegClass);1231        RegInfo.addLiveIn(ArgRegs[i], VReg);1232        SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);1233        CFRegNode.push_back(Val.getValue(Val->getNumValues() - 1));1234        // Move argument from virt reg -> stack1235        SDValue Store =1236            DAG.getStore(Val.getValue(1), dl, Val, FIN, MachinePointerInfo());1237        MemOps.push_back(Store);1238      }1239    } else {1240      // This will point to the next argument passed via stack.1241      XFI->setVarArgsFrameIndex(1242          MFI.CreateFixedObject(4, LRSaveSize + CCInfo.getStackSize(), true));1243    }1244  }1245 1246  // 2. chain CopyFromReg nodes into a TokenFactor.1247  if (!CFRegNode.empty())1248    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, CFRegNode);1249 1250  // 3. Memcpy 'byVal' args & push final InVals.1251  // Aggregates passed "byVal" need to be copied by the callee.1252  // The callee will use a pointer to this copy, rather than the original1253  // pointer.1254  for (const ArgDataPair &ArgDI : ArgData) {1255    if (ArgDI.Flags.isByVal() && ArgDI.Flags.getByValSize()) {1256      unsigned Size = ArgDI.Flags.getByValSize();1257      Align Alignment =1258          std::max(Align(StackSlotSize), ArgDI.Flags.getNonZeroByValAlign());1259      // Create a new object on the stack and copy the pointee into it.1260      int FI = MFI.CreateStackObject(Size, Alignment, false);1261      SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);1262      InVals.push_back(FIN);1263      MemOps.push_back(DAG.getMemcpy(1264          Chain, dl, FIN, ArgDI.SDV, DAG.getConstant(Size, dl, MVT::i32),1265          Alignment, false, false, /*CI=*/nullptr, std::nullopt,1266          MachinePointerInfo(), MachinePointerInfo()));1267    } else {1268      InVals.push_back(ArgDI.SDV);1269    }1270  }1271 1272  // 4, chain mem ops nodes into a TokenFactor.1273  if (!MemOps.empty()) {1274    MemOps.push_back(Chain);1275    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOps);1276  }1277 1278  return Chain;1279}1280 1281//===----------------------------------------------------------------------===//1282//               Return Value Calling Convention Implementation1283//===----------------------------------------------------------------------===//1284 1285bool XCoreTargetLowering::1286CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,1287               bool isVarArg,1288               const SmallVectorImpl<ISD::OutputArg> &Outs,1289               LLVMContext &Context, const Type *RetTy) const {1290  SmallVector<CCValAssign, 16> RVLocs;1291  CCState CCInfo(CallConv, isVarArg, MF, RVLocs, Context);1292  if (!CCInfo.CheckReturn(Outs, RetCC_XCore))1293    return false;1294  if (CCInfo.getStackSize() != 0 && isVarArg)1295    return false;1296  return true;1297}1298 1299SDValue1300XCoreTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,1301                                 bool isVarArg,1302                                 const SmallVectorImpl<ISD::OutputArg> &Outs,1303                                 const SmallVectorImpl<SDValue> &OutVals,1304                                 const SDLoc &dl, SelectionDAG &DAG) const {1305 1306  XCoreFunctionInfo *XFI =1307    DAG.getMachineFunction().getInfo<XCoreFunctionInfo>();1308  MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();1309 1310  // CCValAssign - represent the assignment of1311  // the return value to a location1312  SmallVector<CCValAssign, 16> RVLocs;1313 1314  // CCState - Info about the registers and stack slot.1315  CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,1316                 *DAG.getContext());1317 1318  // Analyze return values.1319  if (!isVarArg)1320    CCInfo.AllocateStack(XFI->getReturnStackOffset(), Align(4));1321 1322  CCInfo.AnalyzeReturn(Outs, RetCC_XCore);1323 1324  SDValue Glue;1325  SmallVector<SDValue, 4> RetOps(1, Chain);1326 1327  // Return on XCore is always a "retsp 0"1328  RetOps.push_back(DAG.getConstant(0, dl, MVT::i32));1329 1330  SmallVector<SDValue, 4> MemOpChains;1331  // Handle return values that must be copied to memory.1332  for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {1333    CCValAssign &VA = RVLocs[i];1334    if (VA.isRegLoc())1335      continue;1336    assert(VA.isMemLoc());1337    if (isVarArg) {1338      report_fatal_error("Can't return value from vararg function in memory");1339    }1340 1341    int Offset = VA.getLocMemOffset();1342    unsigned ObjSize = VA.getLocVT().getSizeInBits() / 8;1343    // Create the frame index object for the memory location.1344    int FI = MFI.CreateFixedObject(ObjSize, Offset, false);1345 1346    // Create a SelectionDAG node corresponding to a store1347    // to this memory location.1348    SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);1349    MemOpChains.push_back(DAG.getStore(1350        Chain, dl, OutVals[i], FIN,1351        MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI)));1352  }1353 1354  // Transform all store nodes into one single node because1355  // all stores are independent of each other.1356  if (!MemOpChains.empty())1357    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);1358 1359  // Now handle return values copied to registers.1360  for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {1361    CCValAssign &VA = RVLocs[i];1362    if (!VA.isRegLoc())1363      continue;1364    // Copy the result values into the output registers.1365    Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Glue);1366 1367    // guarantee that all emitted copies are1368    // stuck together, avoiding something bad1369    Glue = Chain.getValue(1);1370    RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));1371  }1372 1373  RetOps[0] = Chain;  // Update chain.1374 1375  // Add the glue if we have it.1376  if (Glue.getNode())1377    RetOps.push_back(Glue);1378 1379  return DAG.getNode(XCoreISD::RETSP, dl, MVT::Other, RetOps);1380}1381 1382//===----------------------------------------------------------------------===//1383//  Other Lowering Code1384//===----------------------------------------------------------------------===//1385 1386MachineBasicBlock *1387XCoreTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,1388                                                 MachineBasicBlock *BB) const {1389  const TargetInstrInfo &TII = *Subtarget.getInstrInfo();1390  DebugLoc dl = MI.getDebugLoc();1391  assert((MI.getOpcode() == XCore::SELECT_CC) &&1392         "Unexpected instr type to insert");1393 1394  // To "insert" a SELECT_CC instruction, we actually have to insert the diamond1395  // control-flow pattern.  The incoming instruction knows the destination vreg1396  // to set, the condition code register to branch on, the true/false values to1397  // select between, and a branch opcode to use.1398  const BasicBlock *LLVM_BB = BB->getBasicBlock();1399  MachineFunction::iterator It = ++BB->getIterator();1400 1401  //  thisMBB:1402  //  ...1403  //   TrueVal = ...1404  //   cmpTY ccX, r1, r21405  //   bCC copy1MBB1406  //   fallthrough --> copy0MBB1407  MachineBasicBlock *thisMBB = BB;1408  MachineFunction *F = BB->getParent();1409  MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);1410  MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);1411  F->insert(It, copy0MBB);1412  F->insert(It, sinkMBB);1413 1414  // Transfer the remainder of BB and its successor edges to sinkMBB.1415  sinkMBB->splice(sinkMBB->begin(), BB,1416                  std::next(MachineBasicBlock::iterator(MI)), BB->end());1417  sinkMBB->transferSuccessorsAndUpdatePHIs(BB);1418 1419  // Next, add the true and fallthrough blocks as its successors.1420  BB->addSuccessor(copy0MBB);1421  BB->addSuccessor(sinkMBB);1422 1423  BuildMI(BB, dl, TII.get(XCore::BRFT_lru6))1424      .addReg(MI.getOperand(1).getReg())1425      .addMBB(sinkMBB);1426 1427  //  copy0MBB:1428  //   %FalseValue = ...1429  //   # fallthrough to sinkMBB1430  BB = copy0MBB;1431 1432  // Update machine-CFG edges1433  BB->addSuccessor(sinkMBB);1434 1435  //  sinkMBB:1436  //   %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ]1437  //  ...1438  BB = sinkMBB;1439  BuildMI(*BB, BB->begin(), dl, TII.get(XCore::PHI), MI.getOperand(0).getReg())1440      .addReg(MI.getOperand(3).getReg())1441      .addMBB(copy0MBB)1442      .addReg(MI.getOperand(2).getReg())1443      .addMBB(thisMBB);1444 1445  MI.eraseFromParent(); // The pseudo instruction is gone now.1446  return BB;1447}1448 1449//===----------------------------------------------------------------------===//1450// Target Optimization Hooks1451//===----------------------------------------------------------------------===//1452 1453SDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N,1454                                             DAGCombinerInfo &DCI) const {1455  SelectionDAG &DAG = DCI.DAG;1456  SDLoc dl(N);1457  switch (N->getOpcode()) {1458  default: break;1459  case ISD::INTRINSIC_VOID:1460    switch (N->getConstantOperandVal(1)) {1461    case Intrinsic::xcore_outt:1462    case Intrinsic::xcore_outct:1463    case Intrinsic::xcore_chkct: {1464      SDValue OutVal = N->getOperand(3);1465      // These instructions ignore the high bits.1466      if (OutVal.hasOneUse()) {1467        unsigned BitWidth = OutVal.getValueSizeInBits();1468        APInt DemandedMask = APInt::getLowBitsSet(BitWidth, 8);1469        KnownBits Known;1470        TargetLowering::TargetLoweringOpt TLO(DAG, !DCI.isBeforeLegalize(),1471                                              !DCI.isBeforeLegalizeOps());1472        const TargetLowering &TLI = DAG.getTargetLoweringInfo();1473        if (TLI.ShrinkDemandedConstant(OutVal, DemandedMask, TLO) ||1474            TLI.SimplifyDemandedBits(OutVal, DemandedMask, Known, TLO))1475          DCI.CommitTargetLoweringOpt(TLO);1476      }1477      break;1478    }1479    case Intrinsic::xcore_setpt: {1480      SDValue Time = N->getOperand(3);1481      // This instruction ignores the high bits.1482      if (Time.hasOneUse()) {1483        unsigned BitWidth = Time.getValueSizeInBits();1484        APInt DemandedMask = APInt::getLowBitsSet(BitWidth, 16);1485        KnownBits Known;1486        TargetLowering::TargetLoweringOpt TLO(DAG, !DCI.isBeforeLegalize(),1487                                              !DCI.isBeforeLegalizeOps());1488        const TargetLowering &TLI = DAG.getTargetLoweringInfo();1489        if (TLI.ShrinkDemandedConstant(Time, DemandedMask, TLO) ||1490            TLI.SimplifyDemandedBits(Time, DemandedMask, Known, TLO))1491          DCI.CommitTargetLoweringOpt(TLO);1492      }1493      break;1494    }1495    }1496    break;1497  case XCoreISD::LADD: {1498    SDValue N0 = N->getOperand(0);1499    SDValue N1 = N->getOperand(1);1500    SDValue N2 = N->getOperand(2);1501    ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);1502    ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);1503    EVT VT = N0.getValueType();1504 1505    // canonicalize constant to RHS1506    if (N0C && !N1C)1507      return DAG.getNode(XCoreISD::LADD, dl, DAG.getVTList(VT, VT), N1, N0, N2);1508 1509    // fold (ladd 0, 0, x) -> 0, x & 11510    if (N0C && N0C->isZero() && N1C && N1C->isZero()) {1511      SDValue Carry = DAG.getConstant(0, dl, VT);1512      SDValue Result = DAG.getNode(ISD::AND, dl, VT, N2,1513                                   DAG.getConstant(1, dl, VT));1514      SDValue Ops[] = { Result, Carry };1515      return DAG.getMergeValues(Ops, dl);1516    }1517 1518    // fold (ladd x, 0, y) -> 0, add x, y iff carry is unused and y has only the1519    // low bit set1520    if (N1C && N1C->isZero() && N->hasNUsesOfValue(0, 1)) {1521      APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(),1522                                         VT.getSizeInBits() - 1);1523      KnownBits Known = DAG.computeKnownBits(N2);1524      if ((Known.Zero & Mask) == Mask) {1525        SDValue Carry = DAG.getConstant(0, dl, VT);1526        SDValue Result = DAG.getNode(ISD::ADD, dl, VT, N0, N2);1527        SDValue Ops[] = { Result, Carry };1528        return DAG.getMergeValues(Ops, dl);1529      }1530    }1531  }1532  break;1533  case XCoreISD::LSUB: {1534    SDValue N0 = N->getOperand(0);1535    SDValue N1 = N->getOperand(1);1536    SDValue N2 = N->getOperand(2);1537    ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);1538    ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);1539    EVT VT = N0.getValueType();1540 1541    // fold (lsub 0, 0, x) -> x, -x iff x has only the low bit set1542    if (N0C && N0C->isZero() && N1C && N1C->isZero()) {1543      APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(),1544                                         VT.getSizeInBits() - 1);1545      KnownBits Known = DAG.computeKnownBits(N2);1546      if ((Known.Zero & Mask) == Mask) {1547        SDValue Borrow = N2;1548        SDValue Result = DAG.getNode(ISD::SUB, dl, VT,1549                                     DAG.getConstant(0, dl, VT), N2);1550        SDValue Ops[] = { Result, Borrow };1551        return DAG.getMergeValues(Ops, dl);1552      }1553    }1554 1555    // fold (lsub x, 0, y) -> 0, sub x, y iff borrow is unused and y has only the1556    // low bit set1557    if (N1C && N1C->isZero() && N->hasNUsesOfValue(0, 1)) {1558      APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(),1559                                         VT.getSizeInBits() - 1);1560      KnownBits Known = DAG.computeKnownBits(N2);1561      if ((Known.Zero & Mask) == Mask) {1562        SDValue Borrow = DAG.getConstant(0, dl, VT);1563        SDValue Result = DAG.getNode(ISD::SUB, dl, VT, N0, N2);1564        SDValue Ops[] = { Result, Borrow };1565        return DAG.getMergeValues(Ops, dl);1566      }1567    }1568  }1569  break;1570  case XCoreISD::LMUL: {1571    SDValue N0 = N->getOperand(0);1572    SDValue N1 = N->getOperand(1);1573    SDValue N2 = N->getOperand(2);1574    SDValue N3 = N->getOperand(3);1575    ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);1576    ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);1577    EVT VT = N0.getValueType();1578    // Canonicalize multiplicative constant to RHS. If both multiplicative1579    // operands are constant canonicalize smallest to RHS.1580    if ((N0C && !N1C) ||1581        (N0C && N1C && N0C->getZExtValue() < N1C->getZExtValue()))1582      return DAG.getNode(XCoreISD::LMUL, dl, DAG.getVTList(VT, VT),1583                         N1, N0, N2, N3);1584 1585    // lmul(x, 0, a, b)1586    if (N1C && N1C->isZero()) {1587      // If the high result is unused fold to add(a, b)1588      if (N->hasNUsesOfValue(0, 0)) {1589        SDValue Lo = DAG.getNode(ISD::ADD, dl, VT, N2, N3);1590        SDValue Ops[] = { Lo, Lo };1591        return DAG.getMergeValues(Ops, dl);1592      }1593      // Otherwise fold to ladd(a, b, 0)1594      SDValue Result =1595        DAG.getNode(XCoreISD::LADD, dl, DAG.getVTList(VT, VT), N2, N3, N1);1596      SDValue Carry(Result.getNode(), 1);1597      SDValue Ops[] = { Carry, Result };1598      return DAG.getMergeValues(Ops, dl);1599    }1600  }1601  break;1602  case ISD::ADD: {1603    // Fold 32 bit expressions such as add(add(mul(x,y),a),b) ->1604    // lmul(x, y, a, b). The high result of lmul will be ignored.1605    // This is only profitable if the intermediate results are unused1606    // elsewhere.1607    SDValue Mul0, Mul1, Addend0, Addend1;1608    if (N->getValueType(0) == MVT::i32 &&1609        isADDADDMUL(SDValue(N, 0), Mul0, Mul1, Addend0, Addend1, true)) {1610      SDValue Ignored = DAG.getNode(XCoreISD::LMUL, dl,1611                                    DAG.getVTList(MVT::i32, MVT::i32), Mul0,1612                                    Mul1, Addend0, Addend1);1613      SDValue Result(Ignored.getNode(), 1);1614      return Result;1615    }1616    APInt HighMask = APInt::getHighBitsSet(64, 32);1617    // Fold 64 bit expression such as add(add(mul(x,y),a),b) ->1618    // lmul(x, y, a, b) if all operands are zero-extended. We do this1619    // before type legalization as it is messy to match the operands after1620    // that.1621    if (N->getValueType(0) == MVT::i64 &&1622        isADDADDMUL(SDValue(N, 0), Mul0, Mul1, Addend0, Addend1, false) &&1623        DAG.MaskedValueIsZero(Mul0, HighMask) &&1624        DAG.MaskedValueIsZero(Mul1, HighMask) &&1625        DAG.MaskedValueIsZero(Addend0, HighMask) &&1626        DAG.MaskedValueIsZero(Addend1, HighMask)) {1627      SDValue Mul0L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,1628                                  Mul0, DAG.getConstant(0, dl, MVT::i32));1629      SDValue Mul1L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,1630                                  Mul1, DAG.getConstant(0, dl, MVT::i32));1631      SDValue Addend0L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,1632                                     Addend0, DAG.getConstant(0, dl, MVT::i32));1633      SDValue Addend1L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,1634                                     Addend1, DAG.getConstant(0, dl, MVT::i32));1635      SDValue Hi = DAG.getNode(XCoreISD::LMUL, dl,1636                               DAG.getVTList(MVT::i32, MVT::i32), Mul0L, Mul1L,1637                               Addend0L, Addend1L);1638      SDValue Lo(Hi.getNode(), 1);1639      return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi);1640    }1641  }1642  break;1643  case ISD::STORE: {1644    // Replace unaligned store of unaligned load with memmove.1645    StoreSDNode *ST = cast<StoreSDNode>(N);1646    if (!DCI.isBeforeLegalize() ||1647        allowsMemoryAccessForAlignment(*DAG.getContext(), DAG.getDataLayout(),1648                                       ST->getMemoryVT(),1649                                       *ST->getMemOperand()) ||1650        ST->isVolatile() || ST->isIndexed()) {1651      break;1652    }1653    SDValue Chain = ST->getChain();1654 1655    unsigned StoreBits = ST->getMemoryVT().getStoreSizeInBits();1656    assert((StoreBits % 8) == 0 &&1657           "Store size in bits must be a multiple of 8");1658    Align Alignment = ST->getAlign();1659 1660    if (LoadSDNode *LD = dyn_cast<LoadSDNode>(ST->getValue())) {1661      if (LD->hasNUsesOfValue(1, 0) && ST->getMemoryVT() == LD->getMemoryVT() &&1662        LD->getAlign() == Alignment &&1663        !LD->isVolatile() && !LD->isIndexed() &&1664        Chain.reachesChainWithoutSideEffects(SDValue(LD, 1))) {1665        bool isTail = isInTailCallPosition(DAG, ST, Chain);1666        return DAG.getMemmove(Chain, dl, ST->getBasePtr(), LD->getBasePtr(),1667                              DAG.getConstant(StoreBits / 8, dl, MVT::i32),1668                              Alignment, false, nullptr, isTail,1669                              ST->getPointerInfo(), LD->getPointerInfo());1670      }1671    }1672    break;1673  }1674  }1675  return SDValue();1676}1677 1678void XCoreTargetLowering::computeKnownBitsForTargetNode(const SDValue Op,1679                                                        KnownBits &Known,1680                                                        const APInt &DemandedElts,1681                                                        const SelectionDAG &DAG,1682                                                        unsigned Depth) const {1683  Known.resetAll();1684  switch (Op.getOpcode()) {1685  default: break;1686  case XCoreISD::LADD:1687  case XCoreISD::LSUB:1688    if (Op.getResNo() == 1) {1689      // Top bits of carry / borrow are clear.1690      Known.Zero = APInt::getHighBitsSet(Known.getBitWidth(),1691                                         Known.getBitWidth() - 1);1692    }1693    break;1694  case ISD::INTRINSIC_W_CHAIN:1695    {1696    unsigned IntNo = Op.getConstantOperandVal(1);1697    switch (IntNo) {1698    case Intrinsic::xcore_getts:1699      // High bits are known to be zero.1700      Known.Zero =1701          APInt::getHighBitsSet(Known.getBitWidth(), Known.getBitWidth() - 16);1702      break;1703    case Intrinsic::xcore_int:1704    case Intrinsic::xcore_inct:1705      // High bits are known to be zero.1706      Known.Zero =1707          APInt::getHighBitsSet(Known.getBitWidth(), Known.getBitWidth() - 8);1708      break;1709    case Intrinsic::xcore_testct:1710      // Result is either 0 or 1.1711      Known.Zero =1712          APInt::getHighBitsSet(Known.getBitWidth(), Known.getBitWidth() - 1);1713      break;1714    case Intrinsic::xcore_testwct:1715      // Result is in the range 0 - 4.1716      Known.Zero =1717          APInt::getHighBitsSet(Known.getBitWidth(), Known.getBitWidth() - 3);1718      break;1719    }1720    }1721    break;1722  }1723}1724 1725//===----------------------------------------------------------------------===//1726//  Addressing mode description hooks1727//===----------------------------------------------------------------------===//1728 1729static inline bool isImmUs(int64_t val)1730{1731  return (val >= 0 && val <= 11);1732}1733 1734static inline bool isImmUs2(int64_t val)1735{1736  return (val%2 == 0 && isImmUs(val/2));1737}1738 1739static inline bool isImmUs4(int64_t val)1740{1741  return (val%4 == 0 && isImmUs(val/4));1742}1743 1744/// isLegalAddressingMode - Return true if the addressing mode represented1745/// by AM is legal for this target, for a load/store of the specified type.1746bool XCoreTargetLowering::isLegalAddressingMode(const DataLayout &DL,1747                                                const AddrMode &AM, Type *Ty,1748                                                unsigned AS,1749                                                Instruction *I) const {1750  if (Ty->getTypeID() == Type::VoidTyID)1751    return AM.Scale == 0 && isImmUs(AM.BaseOffs) && isImmUs4(AM.BaseOffs);1752 1753  unsigned Size = DL.getTypeAllocSize(Ty);1754  if (AM.BaseGV) {1755    return Size >= 4 && !AM.HasBaseReg && AM.Scale == 0 &&1756                 AM.BaseOffs%4 == 0;1757  }1758 1759  switch (Size) {1760  case 1:1761    // reg + imm1762    if (AM.Scale == 0) {1763      return isImmUs(AM.BaseOffs);1764    }1765    // reg + reg1766    return AM.Scale == 1 && AM.BaseOffs == 0;1767  case 2:1768  case 3:1769    // reg + imm1770    if (AM.Scale == 0) {1771      return isImmUs2(AM.BaseOffs);1772    }1773    // reg + reg<<11774    return AM.Scale == 2 && AM.BaseOffs == 0;1775  default:1776    // reg + imm1777    if (AM.Scale == 0) {1778      return isImmUs4(AM.BaseOffs);1779    }1780    // reg + reg<<21781    return AM.Scale == 4 && AM.BaseOffs == 0;1782  }1783}1784 1785//===----------------------------------------------------------------------===//1786//                           XCore Inline Assembly Support1787//===----------------------------------------------------------------------===//1788 1789std::pair<unsigned, const TargetRegisterClass *>1790XCoreTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,1791                                                  StringRef Constraint,1792                                                  MVT VT) const {1793  if (Constraint.size() == 1) {1794    switch (Constraint[0]) {1795    default : break;1796    case 'r':1797      return std::make_pair(0U, &XCore::GRRegsRegClass);1798    }1799  }1800  // Use the default implementation in TargetLowering to convert the register1801  // constraint into a member of a register class.1802  return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);1803}1804