Path: blob/main/contrib/llvm-project/llvm/lib/Target/ARC/ARCISelLowering.cpp
35269 views
//===- ARCISelLowering.cpp - ARC DAG Lowering Impl --------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements the ARCTargetLowering class.9//10//===----------------------------------------------------------------------===//1112#include "ARCISelLowering.h"13#include "ARC.h"14#include "ARCMachineFunctionInfo.h"15#include "ARCSubtarget.h"16#include "ARCTargetMachine.h"17#include "MCTargetDesc/ARCInfo.h"18#include "llvm/CodeGen/CallingConvLower.h"19#include "llvm/CodeGen/MachineFrameInfo.h"20#include "llvm/CodeGen/MachineFunction.h"21#include "llvm/CodeGen/MachineInstrBuilder.h"22#include "llvm/CodeGen/MachineJumpTableInfo.h"23#include "llvm/CodeGen/MachineRegisterInfo.h"24#include "llvm/CodeGen/ValueTypes.h"25#include "llvm/IR/CallingConv.h"26#include "llvm/IR/Intrinsics.h"27#include "llvm/Support/Debug.h"28#include <algorithm>2930#define DEBUG_TYPE "arc-lower"3132using namespace llvm;3334static SDValue lowerCallResult(SDValue Chain, SDValue InGlue,35const SmallVectorImpl<CCValAssign> &RVLocs,36SDLoc dl, SelectionDAG &DAG,37SmallVectorImpl<SDValue> &InVals);3839static ARCCC::CondCode ISDCCtoARCCC(ISD::CondCode isdCC) {40switch (isdCC) {41case ISD::SETUEQ:42return ARCCC::EQ;43case ISD::SETUGT:44return ARCCC::HI;45case ISD::SETUGE:46return ARCCC::HS;47case ISD::SETULT:48return ARCCC::LO;49case ISD::SETULE:50return ARCCC::LS;51case ISD::SETUNE:52return ARCCC::NE;53case ISD::SETEQ:54return ARCCC::EQ;55case ISD::SETGT:56return ARCCC::GT;57case ISD::SETGE:58return ARCCC::GE;59case ISD::SETLT:60return ARCCC::LT;61case ISD::SETLE:62return ARCCC::LE;63case ISD::SETNE:64return ARCCC::NE;65default:66llvm_unreachable("Unhandled ISDCC code.");67}68}6970void ARCTargetLowering::ReplaceNodeResults(SDNode *N,71SmallVectorImpl<SDValue> &Results,72SelectionDAG &DAG) const {73LLVM_DEBUG(dbgs() << "[ARC-ISEL] ReplaceNodeResults ");74LLVM_DEBUG(N->dump(&DAG));75LLVM_DEBUG(dbgs() << "; use_count=" << N->use_size() << "\n");7677switch (N->getOpcode()) {78case ISD::READCYCLECOUNTER:79if (N->getValueType(0) == MVT::i64) {80// We read the TIMER0 and zero-extend it to 64-bits as the intrinsic81// requires.82SDValue V =83DAG.getNode(ISD::READCYCLECOUNTER, SDLoc(N),84DAG.getVTList(MVT::i32, MVT::Other), N->getOperand(0));85SDValue Op = DAG.getNode(ISD::ZERO_EXTEND, SDLoc(N), MVT::i64, V);86Results.push_back(Op);87Results.push_back(V.getValue(1));88}89break;90default:91break;92}93}9495ARCTargetLowering::ARCTargetLowering(const TargetMachine &TM,96const ARCSubtarget &Subtarget)97: TargetLowering(TM), Subtarget(Subtarget) {98// Set up the register classes.99addRegisterClass(MVT::i32, &ARC::GPR32RegClass);100101// Compute derived properties from the register classes102computeRegisterProperties(Subtarget.getRegisterInfo());103104setStackPointerRegisterToSaveRestore(ARC::SP);105106setSchedulingPreference(Sched::Source);107108// Use i32 for setcc operations results (slt, sgt, ...).109setBooleanContents(ZeroOrOneBooleanContent);110setBooleanVectorContents(ZeroOrOneBooleanContent);111112for (unsigned Opc = 0; Opc < ISD::BUILTIN_OP_END; ++Opc)113setOperationAction(Opc, MVT::i32, Expand);114115// Operations to get us off of the ground.116// Basic.117setOperationAction(ISD::ADD, MVT::i32, Legal);118setOperationAction(ISD::SUB, MVT::i32, Legal);119setOperationAction(ISD::AND, MVT::i32, Legal);120setOperationAction(ISD::SMAX, MVT::i32, Legal);121setOperationAction(ISD::SMIN, MVT::i32, Legal);122123setOperationAction(ISD::ADDC, MVT::i32, Legal);124setOperationAction(ISD::ADDE, MVT::i32, Legal);125setOperationAction(ISD::SUBC, MVT::i32, Legal);126setOperationAction(ISD::SUBE, MVT::i32, Legal);127128// Need barrel shifter.129setOperationAction(ISD::SHL, MVT::i32, Legal);130setOperationAction(ISD::SRA, MVT::i32, Legal);131setOperationAction(ISD::SRL, MVT::i32, Legal);132setOperationAction(ISD::ROTR, MVT::i32, Legal);133134setOperationAction(ISD::Constant, MVT::i32, Legal);135setOperationAction(ISD::UNDEF, MVT::i32, Legal);136137// Need multiplier138setOperationAction(ISD::MUL, MVT::i32, Legal);139setOperationAction(ISD::MULHS, MVT::i32, Legal);140setOperationAction(ISD::MULHU, MVT::i32, Legal);141setOperationAction(ISD::LOAD, MVT::i32, Legal);142setOperationAction(ISD::STORE, MVT::i32, Legal);143144setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);145setOperationAction(ISD::BR_CC, MVT::i32, Custom);146setOperationAction(ISD::BRCOND, MVT::Other, Expand);147setOperationAction(ISD::BR_JT, MVT::Other, Expand);148setOperationAction(ISD::JumpTable, MVT::i32, Custom);149150// Have pseudo instruction for frame addresses.151setOperationAction(ISD::FRAMEADDR, MVT::i32, Legal);152// Custom lower global addresses.153setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);154155// Expand var-args ops.156setOperationAction(ISD::VASTART, MVT::Other, Custom);157setOperationAction(ISD::VAEND, MVT::Other, Expand);158setOperationAction(ISD::VAARG, MVT::Other, Expand);159setOperationAction(ISD::VACOPY, MVT::Other, Expand);160161// Other expansions162setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);163setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);164165// Sign extend inreg166setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Custom);167168// TODO: Predicate these with `options.hasBitScan() ? Legal : Expand`169// when the HasBitScan predicate is available.170setOperationAction(ISD::CTLZ, MVT::i32, Legal);171setOperationAction(ISD::CTTZ, MVT::i32, Legal);172173setOperationAction(ISD::READCYCLECOUNTER, MVT::i32, Legal);174setOperationAction(ISD::READCYCLECOUNTER, MVT::i64,175isTypeLegal(MVT::i64) ? Legal : Custom);176177setMaxAtomicSizeInBitsSupported(0);178}179180const char *ARCTargetLowering::getTargetNodeName(unsigned Opcode) const {181switch (Opcode) {182case ARCISD::BL:183return "ARCISD::BL";184case ARCISD::CMOV:185return "ARCISD::CMOV";186case ARCISD::CMP:187return "ARCISD::CMP";188case ARCISD::BRcc:189return "ARCISD::BRcc";190case ARCISD::RET:191return "ARCISD::RET";192case ARCISD::GAWRAPPER:193return "ARCISD::GAWRAPPER";194}195return nullptr;196}197198//===----------------------------------------------------------------------===//199// Misc Lower Operation implementation200//===----------------------------------------------------------------------===//201202SDValue ARCTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {203SDValue LHS = Op.getOperand(0);204SDValue RHS = Op.getOperand(1);205ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();206SDValue TVal = Op.getOperand(2);207SDValue FVal = Op.getOperand(3);208SDLoc dl(Op);209ARCCC::CondCode ArcCC = ISDCCtoARCCC(CC);210assert(LHS.getValueType() == MVT::i32 && "Only know how to SELECT_CC i32");211SDValue Cmp = DAG.getNode(ARCISD::CMP, dl, MVT::Glue, LHS, RHS);212return DAG.getNode(ARCISD::CMOV, dl, TVal.getValueType(), TVal, FVal,213DAG.getConstant(ArcCC, dl, MVT::i32), Cmp);214}215216SDValue ARCTargetLowering::LowerSIGN_EXTEND_INREG(SDValue Op,217SelectionDAG &DAG) const {218SDValue Op0 = Op.getOperand(0);219SDLoc dl(Op);220assert(Op.getValueType() == MVT::i32 &&221"Unhandled target sign_extend_inreg.");222// These are legal223unsigned Width = cast<VTSDNode>(Op.getOperand(1))->getVT().getSizeInBits();224if (Width == 16 || Width == 8)225return Op;226if (Width >= 32) {227return {};228}229SDValue LS = DAG.getNode(ISD::SHL, dl, MVT::i32, Op0,230DAG.getConstant(32 - Width, dl, MVT::i32));231SDValue SR = DAG.getNode(ISD::SRA, dl, MVT::i32, LS,232DAG.getConstant(32 - Width, dl, MVT::i32));233return SR;234}235236SDValue ARCTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {237SDValue Chain = Op.getOperand(0);238ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();239SDValue LHS = Op.getOperand(2);240SDValue RHS = Op.getOperand(3);241SDValue Dest = Op.getOperand(4);242SDLoc dl(Op);243ARCCC::CondCode arcCC = ISDCCtoARCCC(CC);244assert(LHS.getValueType() == MVT::i32 && "Only know how to BR_CC i32");245return DAG.getNode(ARCISD::BRcc, dl, MVT::Other, Chain, Dest, LHS, RHS,246DAG.getConstant(arcCC, dl, MVT::i32));247}248249SDValue ARCTargetLowering::LowerJumpTable(SDValue Op, SelectionDAG &DAG) const {250auto *N = cast<JumpTableSDNode>(Op);251SDValue GA = DAG.getTargetJumpTable(N->getIndex(), MVT::i32);252return DAG.getNode(ARCISD::GAWRAPPER, SDLoc(N), MVT::i32, GA);253}254255#include "ARCGenCallingConv.inc"256257//===----------------------------------------------------------------------===//258// Call Calling Convention Implementation259//===----------------------------------------------------------------------===//260261/// ARC call implementation262SDValue ARCTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,263SmallVectorImpl<SDValue> &InVals) const {264SelectionDAG &DAG = CLI.DAG;265SDLoc &dl = CLI.DL;266SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;267SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;268SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;269SDValue Chain = CLI.Chain;270SDValue Callee = CLI.Callee;271CallingConv::ID CallConv = CLI.CallConv;272bool IsVarArg = CLI.IsVarArg;273bool &IsTailCall = CLI.IsTailCall;274275IsTailCall = false; // Do not support tail calls yet.276277SmallVector<CCValAssign, 16> ArgLocs;278CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,279*DAG.getContext());280281CCInfo.AnalyzeCallOperands(Outs, CC_ARC);282283SmallVector<CCValAssign, 16> RVLocs;284// Analyze return values to determine the number of bytes of stack required.285CCState RetCCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,286*DAG.getContext());287RetCCInfo.AllocateStack(CCInfo.getStackSize(), Align(4));288RetCCInfo.AnalyzeCallResult(Ins, RetCC_ARC);289290// Get a count of how many bytes are to be pushed on the stack.291unsigned NumBytes = RetCCInfo.getStackSize();292293Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, dl);294295SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass;296SmallVector<SDValue, 12> MemOpChains;297298SDValue StackPtr;299// Walk the register/memloc assignments, inserting copies/loads.300for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {301CCValAssign &VA = ArgLocs[i];302SDValue Arg = OutVals[i];303304// Promote the value if needed.305switch (VA.getLocInfo()) {306default:307llvm_unreachable("Unknown loc info!");308case CCValAssign::Full:309break;310case CCValAssign::SExt:311Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);312break;313case CCValAssign::ZExt:314Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg);315break;316case CCValAssign::AExt:317Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);318break;319}320321// Arguments that can be passed on register must be kept at322// RegsToPass vector323if (VA.isRegLoc()) {324RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));325} else {326assert(VA.isMemLoc() && "Must be register or memory argument.");327if (!StackPtr.getNode())328StackPtr = DAG.getCopyFromReg(Chain, dl, ARC::SP,329getPointerTy(DAG.getDataLayout()));330// Calculate the stack position.331SDValue SOffset = DAG.getIntPtrConstant(VA.getLocMemOffset(), dl);332SDValue PtrOff = DAG.getNode(333ISD::ADD, dl, getPointerTy(DAG.getDataLayout()), StackPtr, SOffset);334335SDValue Store =336DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo());337MemOpChains.push_back(Store);338IsTailCall = false;339}340}341342// Transform all store nodes into one single node because343// all store nodes are independent of each other.344if (!MemOpChains.empty())345Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);346347// Build a sequence of copy-to-reg nodes chained together with token348// chain and flag operands which copy the outgoing args into registers.349// The Glue in necessary since all emitted instructions must be350// stuck together.351SDValue Glue;352for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {353Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,354RegsToPass[i].second, Glue);355Glue = Chain.getValue(1);356}357358// If the callee is a GlobalAddress node (quite common, every direct call is)359// turn it into a TargetGlobalAddress node so that legalize doesn't hack it.360// Likewise ExternalSymbol -> TargetExternalSymbol.361bool IsDirect = true;362if (auto *G = dyn_cast<GlobalAddressSDNode>(Callee))363Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32);364else if (auto *E = dyn_cast<ExternalSymbolSDNode>(Callee))365Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32);366else367IsDirect = false;368// Branch + Link = #chain, #target_address, #opt_in_flags...369// = Chain, Callee, Reg#1, Reg#2, ...370//371// Returns a chain & a glue for retval copy to use.372SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);373SmallVector<SDValue, 8> Ops;374Ops.push_back(Chain);375Ops.push_back(Callee);376377for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)378Ops.push_back(DAG.getRegister(RegsToPass[i].first,379RegsToPass[i].second.getValueType()));380381// Add a register mask operand representing the call-preserved registers.382const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();383const uint32_t *Mask =384TRI->getCallPreservedMask(DAG.getMachineFunction(), CallConv);385assert(Mask && "Missing call preserved mask for calling convention");386Ops.push_back(DAG.getRegisterMask(Mask));387388if (Glue.getNode())389Ops.push_back(Glue);390391Chain = DAG.getNode(IsDirect ? ARCISD::BL : ARCISD::JL, dl, NodeTys, Ops);392Glue = Chain.getValue(1);393394// Create the CALLSEQ_END node.395Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, Glue, dl);396Glue = Chain.getValue(1);397398// Handle result values, copying them out of physregs into vregs that we399// return.400if (IsTailCall)401return Chain;402return lowerCallResult(Chain, Glue, RVLocs, dl, DAG, InVals);403}404405/// Lower the result values of a call into the appropriate copies out of406/// physical registers / memory locations.407static SDValue lowerCallResult(SDValue Chain, SDValue Glue,408const SmallVectorImpl<CCValAssign> &RVLocs,409SDLoc dl, SelectionDAG &DAG,410SmallVectorImpl<SDValue> &InVals) {411SmallVector<std::pair<int, unsigned>, 4> ResultMemLocs;412// Copy results out of physical registers.413for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {414const CCValAssign &VA = RVLocs[i];415if (VA.isRegLoc()) {416SDValue RetValue;417RetValue =418DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), VA.getValVT(), Glue);419Chain = RetValue.getValue(1);420Glue = RetValue.getValue(2);421InVals.push_back(RetValue);422} else {423assert(VA.isMemLoc() && "Must be memory location.");424ResultMemLocs.push_back(425std::make_pair(VA.getLocMemOffset(), InVals.size()));426427// Reserve space for this result.428InVals.push_back(SDValue());429}430}431432// Copy results out of memory.433SmallVector<SDValue, 4> MemOpChains;434for (unsigned i = 0, e = ResultMemLocs.size(); i != e; ++i) {435int Offset = ResultMemLocs[i].first;436unsigned Index = ResultMemLocs[i].second;437SDValue StackPtr = DAG.getRegister(ARC::SP, MVT::i32);438SDValue SpLoc = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr,439DAG.getConstant(Offset, dl, MVT::i32));440SDValue Load =441DAG.getLoad(MVT::i32, dl, Chain, SpLoc, MachinePointerInfo());442InVals[Index] = Load;443MemOpChains.push_back(Load.getValue(1));444}445446// Transform all loads nodes into one single node because447// all load nodes are independent of each other.448if (!MemOpChains.empty())449Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);450451return Chain;452}453454//===----------------------------------------------------------------------===//455// Formal Arguments Calling Convention Implementation456//===----------------------------------------------------------------------===//457458namespace {459460struct ArgDataPair {461SDValue SDV;462ISD::ArgFlagsTy Flags;463};464465} // end anonymous namespace466467/// ARC formal arguments implementation468SDValue ARCTargetLowering::LowerFormalArguments(469SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,470const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,471SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {472switch (CallConv) {473default:474llvm_unreachable("Unsupported calling convention");475case CallingConv::C:476case CallingConv::Fast:477return LowerCallArguments(Chain, CallConv, IsVarArg, Ins, dl, DAG, InVals);478}479}480481/// Transform physical registers into virtual registers, and generate load482/// operations for argument places on the stack.483SDValue ARCTargetLowering::LowerCallArguments(484SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,485const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc dl, SelectionDAG &DAG,486SmallVectorImpl<SDValue> &InVals) const {487MachineFunction &MF = DAG.getMachineFunction();488MachineFrameInfo &MFI = MF.getFrameInfo();489MachineRegisterInfo &RegInfo = MF.getRegInfo();490auto *AFI = MF.getInfo<ARCFunctionInfo>();491492// Assign locations to all of the incoming arguments.493SmallVector<CCValAssign, 16> ArgLocs;494CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,495*DAG.getContext());496497CCInfo.AnalyzeFormalArguments(Ins, CC_ARC);498499unsigned StackSlotSize = 4;500501if (!IsVarArg)502AFI->setReturnStackOffset(CCInfo.getStackSize());503504// All getCopyFromReg ops must precede any getMemcpys to prevent the505// scheduler clobbering a register before it has been copied.506// The stages are:507// 1. CopyFromReg (and load) arg & vararg registers.508// 2. Chain CopyFromReg nodes into a TokenFactor.509// 3. Memcpy 'byVal' args & push final InVals.510// 4. Chain mem ops nodes into a TokenFactor.511SmallVector<SDValue, 4> CFRegNode;512SmallVector<ArgDataPair, 4> ArgData;513SmallVector<SDValue, 4> MemOps;514515// 1a. CopyFromReg (and load) arg registers.516for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {517CCValAssign &VA = ArgLocs[i];518SDValue ArgIn;519520if (VA.isRegLoc()) {521// Arguments passed in registers522EVT RegVT = VA.getLocVT();523switch (RegVT.getSimpleVT().SimpleTy) {524default: {525LLVM_DEBUG(errs() << "LowerFormalArguments Unhandled argument type: "526<< (unsigned)RegVT.getSimpleVT().SimpleTy << "\n");527llvm_unreachable("Unhandled LowerFormalArguments type.");528}529case MVT::i32:530unsigned VReg = RegInfo.createVirtualRegister(&ARC::GPR32RegClass);531RegInfo.addLiveIn(VA.getLocReg(), VReg);532ArgIn = DAG.getCopyFromReg(Chain, dl, VReg, RegVT);533CFRegNode.push_back(ArgIn.getValue(ArgIn->getNumValues() - 1));534}535} else {536// Only arguments passed on the stack should make it here.537assert(VA.isMemLoc());538// Load the argument to a virtual register539unsigned ObjSize = VA.getLocVT().getStoreSize();540assert((ObjSize <= StackSlotSize) && "Unhandled argument");541542// Create the frame index object for this incoming parameter...543int FI = MFI.CreateFixedObject(ObjSize, VA.getLocMemOffset(), true);544545// Create the SelectionDAG nodes corresponding to a load546// from this parameter547SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);548ArgIn = DAG.getLoad(VA.getLocVT(), dl, Chain, FIN,549MachinePointerInfo::getFixedStack(MF, FI));550}551const ArgDataPair ADP = {ArgIn, Ins[i].Flags};552ArgData.push_back(ADP);553}554555// 1b. CopyFromReg vararg registers.556if (IsVarArg) {557// Argument registers558static const MCPhysReg ArgRegs[] = {ARC::R0, ARC::R1, ARC::R2, ARC::R3,559ARC::R4, ARC::R5, ARC::R6, ARC::R7};560auto *AFI = MF.getInfo<ARCFunctionInfo>();561unsigned FirstVAReg = CCInfo.getFirstUnallocated(ArgRegs);562if (FirstVAReg < std::size(ArgRegs)) {563int Offset = 0;564// Save remaining registers, storing higher register numbers at a higher565// address566// There are (std::size(ArgRegs) - FirstVAReg) registers which567// need to be saved.568int VarFI = MFI.CreateFixedObject((std::size(ArgRegs) - FirstVAReg) * 4,569CCInfo.getStackSize(), true);570AFI->setVarArgsFrameIndex(VarFI);571SDValue FIN = DAG.getFrameIndex(VarFI, MVT::i32);572for (unsigned i = FirstVAReg; i < std::size(ArgRegs); i++) {573// Move argument from phys reg -> virt reg574unsigned VReg = RegInfo.createVirtualRegister(&ARC::GPR32RegClass);575RegInfo.addLiveIn(ArgRegs[i], VReg);576SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);577CFRegNode.push_back(Val.getValue(Val->getNumValues() - 1));578SDValue VAObj = DAG.getNode(ISD::ADD, dl, MVT::i32, FIN,579DAG.getConstant(Offset, dl, MVT::i32));580// Move argument from virt reg -> stack581SDValue Store =582DAG.getStore(Val.getValue(1), dl, Val, VAObj, MachinePointerInfo());583MemOps.push_back(Store);584Offset += 4;585}586} else {587llvm_unreachable("Too many var args parameters.");588}589}590591// 2. Chain CopyFromReg nodes into a TokenFactor.592if (!CFRegNode.empty())593Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, CFRegNode);594595// 3. Memcpy 'byVal' args & push final InVals.596// Aggregates passed "byVal" need to be copied by the callee.597// The callee will use a pointer to this copy, rather than the original598// pointer.599for (const auto &ArgDI : ArgData) {600if (ArgDI.Flags.isByVal() && ArgDI.Flags.getByValSize()) {601unsigned Size = ArgDI.Flags.getByValSize();602Align Alignment =603std::max(Align(StackSlotSize), ArgDI.Flags.getNonZeroByValAlign());604// Create a new object on the stack and copy the pointee into it.605int FI = MFI.CreateStackObject(Size, Alignment, false);606SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);607InVals.push_back(FIN);608MemOps.push_back(DAG.getMemcpy(609Chain, dl, FIN, ArgDI.SDV, DAG.getConstant(Size, dl, MVT::i32),610Alignment, false, false, /*CI=*/nullptr, false, MachinePointerInfo(),611MachinePointerInfo()));612} else {613InVals.push_back(ArgDI.SDV);614}615}616617// 4. Chain mem ops nodes into a TokenFactor.618if (!MemOps.empty()) {619MemOps.push_back(Chain);620Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOps);621}622623return Chain;624}625626//===----------------------------------------------------------------------===//627// Return Value Calling Convention Implementation628//===----------------------------------------------------------------------===//629630bool ARCTargetLowering::CanLowerReturn(631CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,632const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const {633SmallVector<CCValAssign, 16> RVLocs;634CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);635if (!CCInfo.CheckReturn(Outs, RetCC_ARC))636return false;637if (CCInfo.getStackSize() != 0 && IsVarArg)638return false;639return true;640}641642SDValue643ARCTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,644bool IsVarArg,645const SmallVectorImpl<ISD::OutputArg> &Outs,646const SmallVectorImpl<SDValue> &OutVals,647const SDLoc &dl, SelectionDAG &DAG) const {648auto *AFI = DAG.getMachineFunction().getInfo<ARCFunctionInfo>();649MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();650651// CCValAssign - represent the assignment of652// the return value to a location653SmallVector<CCValAssign, 16> RVLocs;654655// CCState - Info about the registers and stack slot.656CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,657*DAG.getContext());658659// Analyze return values.660if (!IsVarArg)661CCInfo.AllocateStack(AFI->getReturnStackOffset(), Align(4));662663CCInfo.AnalyzeReturn(Outs, RetCC_ARC);664665SDValue Glue;666SmallVector<SDValue, 4> RetOps(1, Chain);667SmallVector<SDValue, 4> MemOpChains;668// Handle return values that must be copied to memory.669for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {670CCValAssign &VA = RVLocs[i];671if (VA.isRegLoc())672continue;673assert(VA.isMemLoc());674if (IsVarArg) {675report_fatal_error("Can't return value from vararg function in memory");676}677678int Offset = VA.getLocMemOffset();679unsigned ObjSize = VA.getLocVT().getStoreSize();680// Create the frame index object for the memory location.681int FI = MFI.CreateFixedObject(ObjSize, Offset, false);682683// Create a SelectionDAG node corresponding to a store684// to this memory location.685SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);686MemOpChains.push_back(DAG.getStore(687Chain, dl, OutVals[i], FIN,688MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI)));689}690691// Transform all store nodes into one single node because692// all stores are independent of each other.693if (!MemOpChains.empty())694Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);695696// Now handle return values copied to registers.697for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {698CCValAssign &VA = RVLocs[i];699if (!VA.isRegLoc())700continue;701// Copy the result values into the output registers.702Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Glue);703704// guarantee that all emitted copies are705// stuck together, avoiding something bad706Glue = Chain.getValue(1);707RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));708}709710RetOps[0] = Chain; // Update chain.711712// Add the glue if we have it.713if (Glue.getNode())714RetOps.push_back(Glue);715716// What to do with the RetOps?717return DAG.getNode(ARCISD::RET, dl, MVT::Other, RetOps);718}719720//===----------------------------------------------------------------------===//721// Target Optimization Hooks722//===----------------------------------------------------------------------===//723724SDValue ARCTargetLowering::PerformDAGCombine(SDNode *N,725DAGCombinerInfo &DCI) const {726return {};727}728729//===----------------------------------------------------------------------===//730// Addressing mode description hooks731//===----------------------------------------------------------------------===//732733/// Return true if the addressing mode represented by AM is legal for this734/// target, for a load/store of the specified type.735bool ARCTargetLowering::isLegalAddressingMode(const DataLayout &DL,736const AddrMode &AM, Type *Ty,737unsigned AS,738Instruction *I) const {739return AM.Scale == 0;740}741742// Don't emit tail calls for the time being.743bool ARCTargetLowering::mayBeEmittedAsTailCall(const CallInst *CI) const {744return false;745}746747SDValue ARCTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const {748const ARCRegisterInfo &ARI = *Subtarget.getRegisterInfo();749MachineFunction &MF = DAG.getMachineFunction();750MachineFrameInfo &MFI = MF.getFrameInfo();751MFI.setFrameAddressIsTaken(true);752753EVT VT = Op.getValueType();754SDLoc dl(Op);755assert(Op.getConstantOperandVal(0) == 0 &&756"Only support lowering frame addr of current frame.");757Register FrameReg = ARI.getFrameRegister(MF);758return DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT);759}760761SDValue ARCTargetLowering::LowerGlobalAddress(SDValue Op,762SelectionDAG &DAG) const {763const GlobalAddressSDNode *GN = cast<GlobalAddressSDNode>(Op);764const GlobalValue *GV = GN->getGlobal();765SDLoc dl(GN);766int64_t Offset = GN->getOffset();767SDValue GA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, Offset);768return DAG.getNode(ARCISD::GAWRAPPER, dl, MVT::i32, GA);769}770771static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) {772MachineFunction &MF = DAG.getMachineFunction();773auto *FuncInfo = MF.getInfo<ARCFunctionInfo>();774775// vastart just stores the address of the VarArgsFrameIndex slot into the776// memory location argument.777SDLoc dl(Op);778EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(DAG.getDataLayout());779SDValue FR = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), PtrVT);780const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();781return DAG.getStore(Op.getOperand(0), dl, FR, Op.getOperand(1),782MachinePointerInfo(SV));783}784785SDValue ARCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {786switch (Op.getOpcode()) {787case ISD::GlobalAddress:788return LowerGlobalAddress(Op, DAG);789case ISD::FRAMEADDR:790return LowerFRAMEADDR(Op, DAG);791case ISD::SELECT_CC:792return LowerSELECT_CC(Op, DAG);793case ISD::BR_CC:794return LowerBR_CC(Op, DAG);795case ISD::SIGN_EXTEND_INREG:796return LowerSIGN_EXTEND_INREG(Op, DAG);797case ISD::JumpTable:798return LowerJumpTable(Op, DAG);799case ISD::VASTART:800return LowerVASTART(Op, DAG);801case ISD::READCYCLECOUNTER:802// As of LLVM 3.8, the lowering code insists that we customize it even803// though we've declared the i32 version as legal. This is because it only804// thinks i64 is the truly supported version. We've already converted the805// i64 version to a widened i32.806assert(Op.getSimpleValueType() == MVT::i32);807return Op;808default:809llvm_unreachable("unimplemented operand");810}811}812813814