1326938Sdim//===- ARCISelLowering.cpp - ARC DAG Lowering Impl --------------*- C++ -*-===// 2326938Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6326938Sdim// 7326938Sdim//===----------------------------------------------------------------------===// 8326938Sdim// 9326938Sdim// This file implements the ARCTargetLowering class. 10326938Sdim// 11326938Sdim//===----------------------------------------------------------------------===// 12326938Sdim 13326938Sdim#include "ARCISelLowering.h" 14326938Sdim#include "ARC.h" 15326938Sdim#include "ARCMachineFunctionInfo.h" 16326938Sdim#include "ARCSubtarget.h" 17326938Sdim#include "ARCTargetMachine.h" 18326938Sdim#include "MCTargetDesc/ARCInfo.h" 19326938Sdim#include "llvm/CodeGen/CallingConvLower.h" 20326938Sdim#include "llvm/CodeGen/MachineFrameInfo.h" 21326938Sdim#include "llvm/CodeGen/MachineFunction.h" 22326938Sdim#include "llvm/CodeGen/MachineInstrBuilder.h" 23326938Sdim#include "llvm/CodeGen/MachineJumpTableInfo.h" 24326938Sdim#include "llvm/CodeGen/MachineRegisterInfo.h" 25326938Sdim#include "llvm/CodeGen/SelectionDAGISel.h" 26326938Sdim#include "llvm/CodeGen/ValueTypes.h" 27326938Sdim#include "llvm/IR/CallingConv.h" 28326938Sdim#include "llvm/IR/Intrinsics.h" 29326938Sdim#include "llvm/Support/Debug.h" 30326938Sdim#include <algorithm> 31326938Sdim 32326938Sdim#define DEBUG_TYPE "arc-lower" 33326938Sdim 34326938Sdimusing namespace llvm; 35326938Sdim 36326938Sdimstatic SDValue lowerCallResult(SDValue Chain, SDValue InFlag, 37326938Sdim const SmallVectorImpl<CCValAssign> &RVLocs, 38326938Sdim SDLoc dl, SelectionDAG &DAG, 39326938Sdim SmallVectorImpl<SDValue> &InVals); 40326938Sdim 41326938Sdimstatic ARCCC::CondCode ISDCCtoARCCC(ISD::CondCode isdCC) { 42326938Sdim switch (isdCC) { 43326938Sdim case ISD::SETUEQ: 44326938Sdim return ARCCC::EQ; 45326938Sdim case ISD::SETUGT: 46326938Sdim return ARCCC::HI; 47326938Sdim case ISD::SETUGE: 48326938Sdim return ARCCC::HS; 49326938Sdim case ISD::SETULT: 50326938Sdim return ARCCC::LO; 51326938Sdim case ISD::SETULE: 52326938Sdim return ARCCC::LS; 53326938Sdim case ISD::SETUNE: 54326938Sdim return ARCCC::NE; 55326938Sdim case ISD::SETEQ: 56326938Sdim return ARCCC::EQ; 57326938Sdim case ISD::SETGT: 58326938Sdim return ARCCC::GT; 59326938Sdim case ISD::SETGE: 60326938Sdim return ARCCC::GE; 61326938Sdim case ISD::SETLT: 62326938Sdim return ARCCC::LT; 63326938Sdim case ISD::SETLE: 64326938Sdim return ARCCC::LE; 65326938Sdim case ISD::SETNE: 66326938Sdim return ARCCC::NE; 67326938Sdim default: 68326938Sdim llvm_unreachable("Unhandled ISDCC code."); 69326938Sdim } 70326938Sdim} 71326938Sdim 72326938SdimARCTargetLowering::ARCTargetLowering(const TargetMachine &TM, 73326938Sdim const ARCSubtarget &Subtarget) 74341825Sdim : TargetLowering(TM), Subtarget(Subtarget) { 75326938Sdim // Set up the register classes. 76326938Sdim addRegisterClass(MVT::i32, &ARC::GPR32RegClass); 77326938Sdim 78326938Sdim // Compute derived properties from the register classes 79326938Sdim computeRegisterProperties(Subtarget.getRegisterInfo()); 80326938Sdim 81326938Sdim setStackPointerRegisterToSaveRestore(ARC::SP); 82326938Sdim 83326938Sdim setSchedulingPreference(Sched::Source); 84326938Sdim 85326938Sdim // Use i32 for setcc operations results (slt, sgt, ...). 86326938Sdim setBooleanContents(ZeroOrOneBooleanContent); 87326938Sdim setBooleanVectorContents(ZeroOrOneBooleanContent); 88326938Sdim 89326938Sdim for (unsigned Opc = 0; Opc < ISD::BUILTIN_OP_END; ++Opc) 90326938Sdim setOperationAction(Opc, MVT::i32, Expand); 91326938Sdim 92326938Sdim // Operations to get us off of the ground. 93326938Sdim // Basic. 94326938Sdim setOperationAction(ISD::ADD, MVT::i32, Legal); 95326938Sdim setOperationAction(ISD::SUB, MVT::i32, Legal); 96326938Sdim setOperationAction(ISD::AND, MVT::i32, Legal); 97326938Sdim setOperationAction(ISD::SMAX, MVT::i32, Legal); 98326938Sdim setOperationAction(ISD::SMIN, MVT::i32, Legal); 99326938Sdim 100326938Sdim // Need barrel shifter. 101326938Sdim setOperationAction(ISD::SHL, MVT::i32, Legal); 102326938Sdim setOperationAction(ISD::SRA, MVT::i32, Legal); 103326938Sdim setOperationAction(ISD::SRL, MVT::i32, Legal); 104326938Sdim setOperationAction(ISD::ROTR, MVT::i32, Legal); 105326938Sdim 106326938Sdim setOperationAction(ISD::Constant, MVT::i32, Legal); 107326938Sdim setOperationAction(ISD::UNDEF, MVT::i32, Legal); 108326938Sdim 109326938Sdim // Need multiplier 110326938Sdim setOperationAction(ISD::MUL, MVT::i32, Legal); 111326938Sdim setOperationAction(ISD::MULHS, MVT::i32, Legal); 112326938Sdim setOperationAction(ISD::MULHU, MVT::i32, Legal); 113326938Sdim setOperationAction(ISD::LOAD, MVT::i32, Legal); 114326938Sdim setOperationAction(ISD::STORE, MVT::i32, Legal); 115326938Sdim 116326938Sdim setOperationAction(ISD::SELECT_CC, MVT::i32, Custom); 117326938Sdim setOperationAction(ISD::BR_CC, MVT::i32, Custom); 118326938Sdim setOperationAction(ISD::BRCOND, MVT::Other, Expand); 119326938Sdim setOperationAction(ISD::BR_JT, MVT::Other, Expand); 120326938Sdim setOperationAction(ISD::JumpTable, MVT::i32, Custom); 121326938Sdim 122360784Sdim // Have pseudo instruction for frame addresses. 123326938Sdim setOperationAction(ISD::FRAMEADDR, MVT::i32, Legal); 124326938Sdim // Custom lower global addresses. 125326938Sdim setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); 126326938Sdim 127326938Sdim // Expand var-args ops. 128326938Sdim setOperationAction(ISD::VASTART, MVT::Other, Custom); 129326938Sdim setOperationAction(ISD::VAEND, MVT::Other, Expand); 130326938Sdim setOperationAction(ISD::VAARG, MVT::Other, Expand); 131326938Sdim setOperationAction(ISD::VACOPY, MVT::Other, Expand); 132326938Sdim 133326938Sdim // Other expansions 134326938Sdim setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); 135326938Sdim setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); 136326938Sdim 137326938Sdim // Sign extend inreg 138326938Sdim setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Custom); 139326938Sdim} 140326938Sdim 141326938Sdimconst char *ARCTargetLowering::getTargetNodeName(unsigned Opcode) const { 142326938Sdim switch (Opcode) { 143326938Sdim case ARCISD::BL: 144326938Sdim return "ARCISD::BL"; 145326938Sdim case ARCISD::CMOV: 146326938Sdim return "ARCISD::CMOV"; 147326938Sdim case ARCISD::CMP: 148326938Sdim return "ARCISD::CMP"; 149326938Sdim case ARCISD::BRcc: 150326938Sdim return "ARCISD::BRcc"; 151326938Sdim case ARCISD::RET: 152326938Sdim return "ARCISD::RET"; 153326938Sdim case ARCISD::GAWRAPPER: 154326938Sdim return "ARCISD::GAWRAPPER"; 155326938Sdim } 156326938Sdim return nullptr; 157326938Sdim} 158326938Sdim 159326938Sdim//===----------------------------------------------------------------------===// 160326938Sdim// Misc Lower Operation implementation 161326938Sdim//===----------------------------------------------------------------------===// 162326938Sdim 163326938SdimSDValue ARCTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const { 164326938Sdim SDValue LHS = Op.getOperand(0); 165326938Sdim SDValue RHS = Op.getOperand(1); 166326938Sdim ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get(); 167326938Sdim SDValue TVal = Op.getOperand(2); 168326938Sdim SDValue FVal = Op.getOperand(3); 169326938Sdim SDLoc dl(Op); 170326938Sdim ARCCC::CondCode ArcCC = ISDCCtoARCCC(CC); 171326938Sdim assert(LHS.getValueType() == MVT::i32 && "Only know how to SELECT_CC i32"); 172326938Sdim SDValue Cmp = DAG.getNode(ARCISD::CMP, dl, MVT::Glue, LHS, RHS); 173326938Sdim return DAG.getNode(ARCISD::CMOV, dl, TVal.getValueType(), TVal, FVal, 174326938Sdim DAG.getConstant(ArcCC, dl, MVT::i32), Cmp); 175326938Sdim} 176326938Sdim 177326938SdimSDValue ARCTargetLowering::LowerSIGN_EXTEND_INREG(SDValue Op, 178326938Sdim SelectionDAG &DAG) const { 179326938Sdim SDValue Op0 = Op.getOperand(0); 180326938Sdim SDLoc dl(Op); 181326938Sdim assert(Op.getValueType() == MVT::i32 && 182326938Sdim "Unhandled target sign_extend_inreg."); 183326938Sdim // These are legal 184326938Sdim unsigned Width = cast<VTSDNode>(Op.getOperand(1))->getVT().getSizeInBits(); 185326938Sdim if (Width == 16 || Width == 8) 186326938Sdim return Op; 187326938Sdim if (Width >= 32) { 188326938Sdim return {}; 189326938Sdim } 190326938Sdim SDValue LS = DAG.getNode(ISD::SHL, dl, MVT::i32, Op0, 191326938Sdim DAG.getConstant(32 - Width, dl, MVT::i32)); 192326938Sdim SDValue SR = DAG.getNode(ISD::SRA, dl, MVT::i32, LS, 193326938Sdim DAG.getConstant(32 - Width, dl, MVT::i32)); 194326938Sdim return SR; 195326938Sdim} 196326938Sdim 197326938SdimSDValue ARCTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const { 198326938Sdim SDValue Chain = Op.getOperand(0); 199326938Sdim ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get(); 200326938Sdim SDValue LHS = Op.getOperand(2); 201326938Sdim SDValue RHS = Op.getOperand(3); 202326938Sdim SDValue Dest = Op.getOperand(4); 203326938Sdim SDLoc dl(Op); 204326938Sdim ARCCC::CondCode arcCC = ISDCCtoARCCC(CC); 205326938Sdim assert(LHS.getValueType() == MVT::i32 && "Only know how to BR_CC i32"); 206326938Sdim return DAG.getNode(ARCISD::BRcc, dl, MVT::Other, Chain, Dest, LHS, RHS, 207326938Sdim DAG.getConstant(arcCC, dl, MVT::i32)); 208326938Sdim} 209326938Sdim 210326938SdimSDValue ARCTargetLowering::LowerJumpTable(SDValue Op, SelectionDAG &DAG) const { 211326938Sdim auto *N = cast<JumpTableSDNode>(Op); 212326938Sdim SDValue GA = DAG.getTargetJumpTable(N->getIndex(), MVT::i32); 213326938Sdim return DAG.getNode(ARCISD::GAWRAPPER, SDLoc(N), MVT::i32, GA); 214326938Sdim} 215326938Sdim 216326938Sdim#include "ARCGenCallingConv.inc" 217326938Sdim 218326938Sdim//===----------------------------------------------------------------------===// 219326938Sdim// Call Calling Convention Implementation 220326938Sdim//===----------------------------------------------------------------------===// 221326938Sdim 222326938Sdim/// ARC call implementation 223326938SdimSDValue ARCTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, 224326938Sdim SmallVectorImpl<SDValue> &InVals) const { 225326938Sdim SelectionDAG &DAG = CLI.DAG; 226326938Sdim SDLoc &dl = CLI.DL; 227326938Sdim SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs; 228326938Sdim SmallVectorImpl<SDValue> &OutVals = CLI.OutVals; 229326938Sdim SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins; 230326938Sdim SDValue Chain = CLI.Chain; 231326938Sdim SDValue Callee = CLI.Callee; 232326938Sdim CallingConv::ID CallConv = CLI.CallConv; 233326938Sdim bool IsVarArg = CLI.IsVarArg; 234326938Sdim bool &IsTailCall = CLI.IsTailCall; 235326938Sdim 236326938Sdim IsTailCall = false; // Do not support tail calls yet. 237326938Sdim 238326938Sdim SmallVector<CCValAssign, 16> ArgLocs; 239326938Sdim CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, 240326938Sdim *DAG.getContext()); 241326938Sdim 242326938Sdim CCInfo.AnalyzeCallOperands(Outs, CC_ARC); 243326938Sdim 244326938Sdim SmallVector<CCValAssign, 16> RVLocs; 245326938Sdim // Analyze return values to determine the number of bytes of stack required. 246326938Sdim CCState RetCCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs, 247326938Sdim *DAG.getContext()); 248326938Sdim RetCCInfo.AllocateStack(CCInfo.getNextStackOffset(), 4); 249326938Sdim RetCCInfo.AnalyzeCallResult(Ins, RetCC_ARC); 250326938Sdim 251326938Sdim // Get a count of how many bytes are to be pushed on the stack. 252326938Sdim unsigned NumBytes = RetCCInfo.getNextStackOffset(); 253326938Sdim auto PtrVT = getPointerTy(DAG.getDataLayout()); 254326938Sdim 255326938Sdim Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, dl); 256326938Sdim 257326938Sdim SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass; 258326938Sdim SmallVector<SDValue, 12> MemOpChains; 259326938Sdim 260326938Sdim SDValue StackPtr; 261326938Sdim // Walk the register/memloc assignments, inserting copies/loads. 262326938Sdim for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 263326938Sdim CCValAssign &VA = ArgLocs[i]; 264326938Sdim SDValue Arg = OutVals[i]; 265326938Sdim 266326938Sdim // Promote the value if needed. 267326938Sdim switch (VA.getLocInfo()) { 268326938Sdim default: 269326938Sdim llvm_unreachable("Unknown loc info!"); 270326938Sdim case CCValAssign::Full: 271326938Sdim break; 272326938Sdim case CCValAssign::SExt: 273326938Sdim Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg); 274326938Sdim break; 275326938Sdim case CCValAssign::ZExt: 276326938Sdim Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg); 277326938Sdim break; 278326938Sdim case CCValAssign::AExt: 279326938Sdim Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg); 280326938Sdim break; 281326938Sdim } 282326938Sdim 283326938Sdim // Arguments that can be passed on register must be kept at 284326938Sdim // RegsToPass vector 285326938Sdim if (VA.isRegLoc()) { 286326938Sdim RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); 287326938Sdim } else { 288326938Sdim assert(VA.isMemLoc() && "Must be register or memory argument."); 289326938Sdim if (!StackPtr.getNode()) 290326938Sdim StackPtr = DAG.getCopyFromReg(Chain, dl, ARC::SP, 291326938Sdim getPointerTy(DAG.getDataLayout())); 292326938Sdim // Calculate the stack position. 293326938Sdim SDValue SOffset = DAG.getIntPtrConstant(VA.getLocMemOffset(), dl); 294326938Sdim SDValue PtrOff = DAG.getNode( 295326938Sdim ISD::ADD, dl, getPointerTy(DAG.getDataLayout()), StackPtr, SOffset); 296326938Sdim 297326938Sdim SDValue Store = 298326938Sdim DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo()); 299326938Sdim MemOpChains.push_back(Store); 300326938Sdim IsTailCall = false; 301326938Sdim } 302326938Sdim } 303326938Sdim 304326938Sdim // Transform all store nodes into one single node because 305326938Sdim // all store nodes are independent of each other. 306326938Sdim if (!MemOpChains.empty()) 307326938Sdim Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains); 308326938Sdim 309326938Sdim // Build a sequence of copy-to-reg nodes chained together with token 310326938Sdim // chain and flag operands which copy the outgoing args into registers. 311326938Sdim // The InFlag in necessary since all emitted instructions must be 312326938Sdim // stuck together. 313326938Sdim SDValue Glue; 314326938Sdim for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { 315326938Sdim Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, 316326938Sdim RegsToPass[i].second, Glue); 317326938Sdim Glue = Chain.getValue(1); 318326938Sdim } 319326938Sdim 320326938Sdim // If the callee is a GlobalAddress node (quite common, every direct call is) 321326938Sdim // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. 322326938Sdim // Likewise ExternalSymbol -> TargetExternalSymbol. 323326938Sdim bool IsDirect = true; 324326938Sdim if (auto *G = dyn_cast<GlobalAddressSDNode>(Callee)) 325326938Sdim Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32); 326326938Sdim else if (auto *E = dyn_cast<ExternalSymbolSDNode>(Callee)) 327326938Sdim Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32); 328326938Sdim else 329326938Sdim IsDirect = false; 330326938Sdim // Branch + Link = #chain, #target_address, #opt_in_flags... 331326938Sdim // = Chain, Callee, Reg#1, Reg#2, ... 332326938Sdim // 333326938Sdim // Returns a chain & a flag for retval copy to use. 334326938Sdim SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); 335326938Sdim SmallVector<SDValue, 8> Ops; 336326938Sdim Ops.push_back(Chain); 337326938Sdim Ops.push_back(Callee); 338326938Sdim 339326938Sdim for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) 340326938Sdim Ops.push_back(DAG.getRegister(RegsToPass[i].first, 341326938Sdim RegsToPass[i].second.getValueType())); 342326938Sdim 343326938Sdim // Add a register mask operand representing the call-preserved registers. 344326938Sdim const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); 345326938Sdim const uint32_t *Mask = 346326938Sdim TRI->getCallPreservedMask(DAG.getMachineFunction(), CallConv); 347326938Sdim assert(Mask && "Missing call preserved mask for calling convention"); 348326938Sdim Ops.push_back(DAG.getRegisterMask(Mask)); 349326938Sdim 350326938Sdim if (Glue.getNode()) 351326938Sdim Ops.push_back(Glue); 352326938Sdim 353326938Sdim Chain = DAG.getNode(IsDirect ? ARCISD::BL : ARCISD::JL, dl, NodeTys, Ops); 354326938Sdim Glue = Chain.getValue(1); 355326938Sdim 356326938Sdim // Create the CALLSEQ_END node. 357326938Sdim Chain = DAG.getCALLSEQ_END(Chain, DAG.getConstant(NumBytes, dl, PtrVT, true), 358326938Sdim DAG.getConstant(0, dl, PtrVT, true), Glue, dl); 359326938Sdim Glue = Chain.getValue(1); 360326938Sdim 361326938Sdim // Handle result values, copying them out of physregs into vregs that we 362326938Sdim // return. 363326938Sdim if (IsTailCall) 364326938Sdim return Chain; 365326938Sdim return lowerCallResult(Chain, Glue, RVLocs, dl, DAG, InVals); 366326938Sdim} 367326938Sdim 368326938Sdim/// Lower the result values of a call into the appropriate copies out of 369326938Sdim/// physical registers / memory locations. 370326938Sdimstatic SDValue lowerCallResult(SDValue Chain, SDValue Glue, 371326938Sdim const SmallVectorImpl<CCValAssign> &RVLocs, 372326938Sdim SDLoc dl, SelectionDAG &DAG, 373326938Sdim SmallVectorImpl<SDValue> &InVals) { 374326938Sdim SmallVector<std::pair<int, unsigned>, 4> ResultMemLocs; 375326938Sdim // Copy results out of physical registers. 376326938Sdim for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) { 377326938Sdim const CCValAssign &VA = RVLocs[i]; 378326938Sdim if (VA.isRegLoc()) { 379326938Sdim SDValue RetValue; 380326938Sdim RetValue = 381326938Sdim DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), VA.getValVT(), Glue); 382326938Sdim Chain = RetValue.getValue(1); 383326938Sdim Glue = RetValue.getValue(2); 384326938Sdim InVals.push_back(RetValue); 385326938Sdim } else { 386326938Sdim assert(VA.isMemLoc() && "Must be memory location."); 387326938Sdim ResultMemLocs.push_back( 388326938Sdim std::make_pair(VA.getLocMemOffset(), InVals.size())); 389326938Sdim 390326938Sdim // Reserve space for this result. 391326938Sdim InVals.push_back(SDValue()); 392326938Sdim } 393326938Sdim } 394326938Sdim 395326938Sdim // Copy results out of memory. 396326938Sdim SmallVector<SDValue, 4> MemOpChains; 397326938Sdim for (unsigned i = 0, e = ResultMemLocs.size(); i != e; ++i) { 398326938Sdim int Offset = ResultMemLocs[i].first; 399326938Sdim unsigned Index = ResultMemLocs[i].second; 400326938Sdim SDValue StackPtr = DAG.getRegister(ARC::SP, MVT::i32); 401326938Sdim SDValue SpLoc = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, 402326938Sdim DAG.getConstant(Offset, dl, MVT::i32)); 403326938Sdim SDValue Load = 404326938Sdim DAG.getLoad(MVT::i32, dl, Chain, SpLoc, MachinePointerInfo()); 405326938Sdim InVals[Index] = Load; 406326938Sdim MemOpChains.push_back(Load.getValue(1)); 407326938Sdim } 408326938Sdim 409326938Sdim // Transform all loads nodes into one single node because 410326938Sdim // all load nodes are independent of each other. 411326938Sdim if (!MemOpChains.empty()) 412326938Sdim Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains); 413326938Sdim 414326938Sdim return Chain; 415326938Sdim} 416326938Sdim 417326938Sdim//===----------------------------------------------------------------------===// 418326938Sdim// Formal Arguments Calling Convention Implementation 419326938Sdim//===----------------------------------------------------------------------===// 420326938Sdim 421326938Sdimnamespace { 422326938Sdim 423326938Sdimstruct ArgDataPair { 424326938Sdim SDValue SDV; 425326938Sdim ISD::ArgFlagsTy Flags; 426326938Sdim}; 427326938Sdim 428326938Sdim} // end anonymous namespace 429326938Sdim 430326938Sdim/// ARC formal arguments implementation 431326938SdimSDValue ARCTargetLowering::LowerFormalArguments( 432326938Sdim SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, 433326938Sdim const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl, 434326938Sdim SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { 435326938Sdim switch (CallConv) { 436326938Sdim default: 437326938Sdim llvm_unreachable("Unsupported calling convention"); 438326938Sdim case CallingConv::C: 439326938Sdim case CallingConv::Fast: 440326938Sdim return LowerCallArguments(Chain, CallConv, IsVarArg, Ins, dl, DAG, InVals); 441326938Sdim } 442326938Sdim} 443326938Sdim 444326938Sdim/// Transform physical registers into virtual registers, and generate load 445326938Sdim/// operations for argument places on the stack. 446326938SdimSDValue ARCTargetLowering::LowerCallArguments( 447326938Sdim SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, 448326938Sdim const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc dl, SelectionDAG &DAG, 449326938Sdim SmallVectorImpl<SDValue> &InVals) const { 450326938Sdim MachineFunction &MF = DAG.getMachineFunction(); 451326938Sdim MachineFrameInfo &MFI = MF.getFrameInfo(); 452326938Sdim MachineRegisterInfo &RegInfo = MF.getRegInfo(); 453326938Sdim auto *AFI = MF.getInfo<ARCFunctionInfo>(); 454326938Sdim 455326938Sdim // Assign locations to all of the incoming arguments. 456326938Sdim SmallVector<CCValAssign, 16> ArgLocs; 457326938Sdim CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, 458326938Sdim *DAG.getContext()); 459326938Sdim 460326938Sdim CCInfo.AnalyzeFormalArguments(Ins, CC_ARC); 461326938Sdim 462326938Sdim unsigned StackSlotSize = 4; 463326938Sdim 464326938Sdim if (!IsVarArg) 465326938Sdim AFI->setReturnStackOffset(CCInfo.getNextStackOffset()); 466326938Sdim 467326938Sdim // All getCopyFromReg ops must precede any getMemcpys to prevent the 468326938Sdim // scheduler clobbering a register before it has been copied. 469326938Sdim // The stages are: 470326938Sdim // 1. CopyFromReg (and load) arg & vararg registers. 471326938Sdim // 2. Chain CopyFromReg nodes into a TokenFactor. 472326938Sdim // 3. Memcpy 'byVal' args & push final InVals. 473326938Sdim // 4. Chain mem ops nodes into a TokenFactor. 474326938Sdim SmallVector<SDValue, 4> CFRegNode; 475326938Sdim SmallVector<ArgDataPair, 4> ArgData; 476326938Sdim SmallVector<SDValue, 4> MemOps; 477326938Sdim 478326938Sdim // 1a. CopyFromReg (and load) arg registers. 479326938Sdim for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 480326938Sdim CCValAssign &VA = ArgLocs[i]; 481326938Sdim SDValue ArgIn; 482326938Sdim 483326938Sdim if (VA.isRegLoc()) { 484326938Sdim // Arguments passed in registers 485326938Sdim EVT RegVT = VA.getLocVT(); 486326938Sdim switch (RegVT.getSimpleVT().SimpleTy) { 487326938Sdim default: { 488341825Sdim LLVM_DEBUG(errs() << "LowerFormalArguments Unhandled argument type: " 489341825Sdim << (unsigned)RegVT.getSimpleVT().SimpleTy << "\n"); 490326938Sdim llvm_unreachable("Unhandled LowerFormalArguments type."); 491326938Sdim } 492326938Sdim case MVT::i32: 493326938Sdim unsigned VReg = RegInfo.createVirtualRegister(&ARC::GPR32RegClass); 494326938Sdim RegInfo.addLiveIn(VA.getLocReg(), VReg); 495326938Sdim ArgIn = DAG.getCopyFromReg(Chain, dl, VReg, RegVT); 496326938Sdim CFRegNode.push_back(ArgIn.getValue(ArgIn->getNumValues() - 1)); 497326938Sdim } 498326938Sdim } else { 499326938Sdim // sanity check 500326938Sdim assert(VA.isMemLoc()); 501326938Sdim // Load the argument to a virtual register 502326938Sdim unsigned ObjSize = VA.getLocVT().getStoreSize(); 503326938Sdim assert((ObjSize <= StackSlotSize) && "Unhandled argument"); 504326938Sdim 505326938Sdim // Create the frame index object for this incoming parameter... 506326938Sdim int FI = MFI.CreateFixedObject(ObjSize, VA.getLocMemOffset(), true); 507326938Sdim 508326938Sdim // Create the SelectionDAG nodes corresponding to a load 509326938Sdim // from this parameter 510326938Sdim SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); 511326938Sdim ArgIn = DAG.getLoad(VA.getLocVT(), dl, Chain, FIN, 512326938Sdim MachinePointerInfo::getFixedStack(MF, FI)); 513326938Sdim } 514326938Sdim const ArgDataPair ADP = {ArgIn, Ins[i].Flags}; 515326938Sdim ArgData.push_back(ADP); 516326938Sdim } 517326938Sdim 518326938Sdim // 1b. CopyFromReg vararg registers. 519326938Sdim if (IsVarArg) { 520326938Sdim // Argument registers 521326938Sdim static const MCPhysReg ArgRegs[] = {ARC::R0, ARC::R1, ARC::R2, ARC::R3, 522326938Sdim ARC::R4, ARC::R5, ARC::R6, ARC::R7}; 523326938Sdim auto *AFI = MF.getInfo<ARCFunctionInfo>(); 524326938Sdim unsigned FirstVAReg = CCInfo.getFirstUnallocated(ArgRegs); 525326938Sdim if (FirstVAReg < array_lengthof(ArgRegs)) { 526326938Sdim int Offset = 0; 527326938Sdim // Save remaining registers, storing higher register numbers at a higher 528326938Sdim // address 529326938Sdim // There are (array_lengthof(ArgRegs) - FirstVAReg) registers which 530326938Sdim // need to be saved. 531326938Sdim int VarFI = 532326938Sdim MFI.CreateFixedObject((array_lengthof(ArgRegs) - FirstVAReg) * 4, 533326938Sdim CCInfo.getNextStackOffset(), true); 534326938Sdim AFI->setVarArgsFrameIndex(VarFI); 535326938Sdim SDValue FIN = DAG.getFrameIndex(VarFI, MVT::i32); 536326938Sdim for (unsigned i = FirstVAReg; i < array_lengthof(ArgRegs); i++) { 537326938Sdim // Move argument from phys reg -> virt reg 538326938Sdim unsigned VReg = RegInfo.createVirtualRegister(&ARC::GPR32RegClass); 539326938Sdim RegInfo.addLiveIn(ArgRegs[i], VReg); 540326938Sdim SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32); 541326938Sdim CFRegNode.push_back(Val.getValue(Val->getNumValues() - 1)); 542326938Sdim SDValue VAObj = DAG.getNode(ISD::ADD, dl, MVT::i32, FIN, 543326938Sdim DAG.getConstant(Offset, dl, MVT::i32)); 544326938Sdim // Move argument from virt reg -> stack 545326938Sdim SDValue Store = 546326938Sdim DAG.getStore(Val.getValue(1), dl, Val, VAObj, MachinePointerInfo()); 547326938Sdim MemOps.push_back(Store); 548326938Sdim Offset += 4; 549326938Sdim } 550326938Sdim } else { 551326938Sdim llvm_unreachable("Too many var args parameters."); 552326938Sdim } 553326938Sdim } 554326938Sdim 555326938Sdim // 2. Chain CopyFromReg nodes into a TokenFactor. 556326938Sdim if (!CFRegNode.empty()) 557326938Sdim Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, CFRegNode); 558326938Sdim 559326938Sdim // 3. Memcpy 'byVal' args & push final InVals. 560326938Sdim // Aggregates passed "byVal" need to be copied by the callee. 561326938Sdim // The callee will use a pointer to this copy, rather than the original 562326938Sdim // pointer. 563326938Sdim for (const auto &ArgDI : ArgData) { 564326938Sdim if (ArgDI.Flags.isByVal() && ArgDI.Flags.getByValSize()) { 565326938Sdim unsigned Size = ArgDI.Flags.getByValSize(); 566326938Sdim unsigned Align = std::max(StackSlotSize, ArgDI.Flags.getByValAlign()); 567326938Sdim // Create a new object on the stack and copy the pointee into it. 568326938Sdim int FI = MFI.CreateStackObject(Size, Align, false); 569326938Sdim SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); 570326938Sdim InVals.push_back(FIN); 571326938Sdim MemOps.push_back(DAG.getMemcpy( 572326938Sdim Chain, dl, FIN, ArgDI.SDV, DAG.getConstant(Size, dl, MVT::i32), Align, 573326938Sdim false, false, false, MachinePointerInfo(), MachinePointerInfo())); 574326938Sdim } else { 575326938Sdim InVals.push_back(ArgDI.SDV); 576326938Sdim } 577326938Sdim } 578326938Sdim 579326938Sdim // 4. Chain mem ops nodes into a TokenFactor. 580326938Sdim if (!MemOps.empty()) { 581326938Sdim MemOps.push_back(Chain); 582326938Sdim Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOps); 583326938Sdim } 584326938Sdim 585326938Sdim return Chain; 586326938Sdim} 587326938Sdim 588326938Sdim//===----------------------------------------------------------------------===// 589326938Sdim// Return Value Calling Convention Implementation 590326938Sdim//===----------------------------------------------------------------------===// 591326938Sdim 592326938Sdimbool ARCTargetLowering::CanLowerReturn( 593326938Sdim CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, 594326938Sdim const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const { 595326938Sdim SmallVector<CCValAssign, 16> RVLocs; 596326938Sdim CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context); 597326938Sdim if (!CCInfo.CheckReturn(Outs, RetCC_ARC)) 598326938Sdim return false; 599326938Sdim if (CCInfo.getNextStackOffset() != 0 && IsVarArg) 600326938Sdim return false; 601326938Sdim return true; 602326938Sdim} 603326938Sdim 604326938SdimSDValue 605326938SdimARCTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, 606326938Sdim bool IsVarArg, 607326938Sdim const SmallVectorImpl<ISD::OutputArg> &Outs, 608326938Sdim const SmallVectorImpl<SDValue> &OutVals, 609326938Sdim const SDLoc &dl, SelectionDAG &DAG) const { 610326938Sdim auto *AFI = DAG.getMachineFunction().getInfo<ARCFunctionInfo>(); 611326938Sdim MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); 612326938Sdim 613326938Sdim // CCValAssign - represent the assignment of 614326938Sdim // the return value to a location 615326938Sdim SmallVector<CCValAssign, 16> RVLocs; 616326938Sdim 617326938Sdim // CCState - Info about the registers and stack slot. 618326938Sdim CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs, 619326938Sdim *DAG.getContext()); 620326938Sdim 621326938Sdim // Analyze return values. 622326938Sdim if (!IsVarArg) 623326938Sdim CCInfo.AllocateStack(AFI->getReturnStackOffset(), 4); 624326938Sdim 625326938Sdim CCInfo.AnalyzeReturn(Outs, RetCC_ARC); 626326938Sdim 627326938Sdim SDValue Flag; 628326938Sdim SmallVector<SDValue, 4> RetOps(1, Chain); 629326938Sdim SmallVector<SDValue, 4> MemOpChains; 630326938Sdim // Handle return values that must be copied to memory. 631326938Sdim for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) { 632326938Sdim CCValAssign &VA = RVLocs[i]; 633326938Sdim if (VA.isRegLoc()) 634326938Sdim continue; 635326938Sdim assert(VA.isMemLoc()); 636326938Sdim if (IsVarArg) { 637326938Sdim report_fatal_error("Can't return value from vararg function in memory"); 638326938Sdim } 639326938Sdim 640326938Sdim int Offset = VA.getLocMemOffset(); 641326938Sdim unsigned ObjSize = VA.getLocVT().getStoreSize(); 642326938Sdim // Create the frame index object for the memory location. 643326938Sdim int FI = MFI.CreateFixedObject(ObjSize, Offset, false); 644326938Sdim 645326938Sdim // Create a SelectionDAG node corresponding to a store 646326938Sdim // to this memory location. 647326938Sdim SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); 648326938Sdim MemOpChains.push_back(DAG.getStore( 649326938Sdim Chain, dl, OutVals[i], FIN, 650326938Sdim MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI))); 651326938Sdim } 652326938Sdim 653326938Sdim // Transform all store nodes into one single node because 654326938Sdim // all stores are independent of each other. 655326938Sdim if (!MemOpChains.empty()) 656326938Sdim Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains); 657326938Sdim 658326938Sdim // Now handle return values copied to registers. 659326938Sdim for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) { 660326938Sdim CCValAssign &VA = RVLocs[i]; 661326938Sdim if (!VA.isRegLoc()) 662326938Sdim continue; 663326938Sdim // Copy the result values into the output registers. 664326938Sdim Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Flag); 665326938Sdim 666326938Sdim // guarantee that all emitted copies are 667326938Sdim // stuck together, avoiding something bad 668326938Sdim Flag = Chain.getValue(1); 669326938Sdim RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); 670326938Sdim } 671326938Sdim 672326938Sdim RetOps[0] = Chain; // Update chain. 673326938Sdim 674326938Sdim // Add the flag if we have it. 675326938Sdim if (Flag.getNode()) 676326938Sdim RetOps.push_back(Flag); 677326938Sdim 678326938Sdim // What to do with the RetOps? 679326938Sdim return DAG.getNode(ARCISD::RET, dl, MVT::Other, RetOps); 680326938Sdim} 681326938Sdim 682326938Sdim//===----------------------------------------------------------------------===// 683326938Sdim// Target Optimization Hooks 684326938Sdim//===----------------------------------------------------------------------===// 685326938Sdim 686326938SdimSDValue ARCTargetLowering::PerformDAGCombine(SDNode *N, 687326938Sdim DAGCombinerInfo &DCI) const { 688326938Sdim return {}; 689326938Sdim} 690326938Sdim 691326938Sdim//===----------------------------------------------------------------------===// 692326938Sdim// Addressing mode description hooks 693326938Sdim//===----------------------------------------------------------------------===// 694326938Sdim 695326938Sdim/// Return true if the addressing mode represented by AM is legal for this 696326938Sdim/// target, for a load/store of the specified type. 697326938Sdimbool ARCTargetLowering::isLegalAddressingMode(const DataLayout &DL, 698326938Sdim const AddrMode &AM, Type *Ty, 699326938Sdim unsigned AS, 700326938Sdim Instruction *I) const { 701326938Sdim return AM.Scale == 0; 702326938Sdim} 703326938Sdim 704326938Sdim// Don't emit tail calls for the time being. 705326938Sdimbool ARCTargetLowering::mayBeEmittedAsTailCall(const CallInst *CI) const { 706326938Sdim return false; 707326938Sdim} 708326938Sdim 709326938SdimSDValue ARCTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { 710326938Sdim const ARCRegisterInfo &ARI = *Subtarget.getRegisterInfo(); 711326938Sdim MachineFunction &MF = DAG.getMachineFunction(); 712326938Sdim MachineFrameInfo &MFI = MF.getFrameInfo(); 713326938Sdim MFI.setFrameAddressIsTaken(true); 714326938Sdim 715326938Sdim EVT VT = Op.getValueType(); 716326938Sdim SDLoc dl(Op); 717326938Sdim assert(cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() == 0 && 718326938Sdim "Only support lowering frame addr of current frame."); 719360784Sdim Register FrameReg = ARI.getFrameRegister(MF); 720326938Sdim return DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT); 721326938Sdim} 722326938Sdim 723326938SdimSDValue ARCTargetLowering::LowerGlobalAddress(SDValue Op, 724326938Sdim SelectionDAG &DAG) const { 725326938Sdim const GlobalAddressSDNode *GN = cast<GlobalAddressSDNode>(Op); 726326938Sdim const GlobalValue *GV = GN->getGlobal(); 727326938Sdim SDLoc dl(GN); 728326938Sdim int64_t Offset = GN->getOffset(); 729326938Sdim SDValue GA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, Offset); 730326938Sdim return DAG.getNode(ARCISD::GAWRAPPER, dl, MVT::i32, GA); 731326938Sdim} 732326938Sdim 733326938Sdimstatic SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) { 734326938Sdim MachineFunction &MF = DAG.getMachineFunction(); 735326938Sdim auto *FuncInfo = MF.getInfo<ARCFunctionInfo>(); 736326938Sdim 737326938Sdim // vastart just stores the address of the VarArgsFrameIndex slot into the 738326938Sdim // memory location argument. 739326938Sdim SDLoc dl(Op); 740326938Sdim EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(DAG.getDataLayout()); 741326938Sdim SDValue FR = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), PtrVT); 742326938Sdim const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); 743326938Sdim return DAG.getStore(Op.getOperand(0), dl, FR, Op.getOperand(1), 744326938Sdim MachinePointerInfo(SV)); 745326938Sdim} 746326938Sdim 747326938SdimSDValue ARCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { 748326938Sdim switch (Op.getOpcode()) { 749326938Sdim case ISD::GlobalAddress: 750326938Sdim return LowerGlobalAddress(Op, DAG); 751326938Sdim case ISD::FRAMEADDR: 752326938Sdim return LowerFRAMEADDR(Op, DAG); 753326938Sdim case ISD::SELECT_CC: 754326938Sdim return LowerSELECT_CC(Op, DAG); 755326938Sdim case ISD::BR_CC: 756326938Sdim return LowerBR_CC(Op, DAG); 757326938Sdim case ISD::SIGN_EXTEND_INREG: 758326938Sdim return LowerSIGN_EXTEND_INREG(Op, DAG); 759326938Sdim case ISD::JumpTable: 760326938Sdim return LowerJumpTable(Op, DAG); 761326938Sdim case ISD::VASTART: 762326938Sdim return LowerVASTART(Op, DAG); 763326938Sdim default: 764326938Sdim llvm_unreachable("unimplemented operand"); 765326938Sdim } 766326938Sdim} 767