797 lines · cpp
1//===- ARCISelLowering.cpp - ARC DAG Lowering Impl --------------*- C++ -*-===//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 ARCTargetLowering class.10//11//===----------------------------------------------------------------------===//12 13#include "ARCISelLowering.h"14#include "ARC.h"15#include "ARCMachineFunctionInfo.h"16#include "ARCSelectionDAGInfo.h"17#include "ARCSubtarget.h"18#include "ARCTargetMachine.h"19#include "MCTargetDesc/ARCInfo.h"20#include "llvm/CodeGen/CallingConvLower.h"21#include "llvm/CodeGen/MachineFrameInfo.h"22#include "llvm/CodeGen/MachineFunction.h"23#include "llvm/CodeGen/MachineInstrBuilder.h"24#include "llvm/CodeGen/MachineJumpTableInfo.h"25#include "llvm/CodeGen/MachineRegisterInfo.h"26#include "llvm/CodeGen/ValueTypes.h"27#include "llvm/IR/CallingConv.h"28#include "llvm/IR/Intrinsics.h"29#include "llvm/Support/Debug.h"30#include <algorithm>31 32#define DEBUG_TYPE "arc-lower"33 34using namespace llvm;35 36static SDValue lowerCallResult(SDValue Chain, SDValue InGlue,37 const SmallVectorImpl<CCValAssign> &RVLocs,38 SDLoc dl, SelectionDAG &DAG,39 SmallVectorImpl<SDValue> &InVals);40 41static ARCCC::CondCode ISDCCtoARCCC(ISD::CondCode isdCC) {42 switch (isdCC) {43 case ISD::SETUEQ:44 return ARCCC::EQ;45 case ISD::SETUGT:46 return ARCCC::HI;47 case ISD::SETUGE:48 return ARCCC::HS;49 case ISD::SETULT:50 return ARCCC::LO;51 case ISD::SETULE:52 return ARCCC::LS;53 case ISD::SETUNE:54 return ARCCC::NE;55 case ISD::SETEQ:56 return ARCCC::EQ;57 case ISD::SETGT:58 return ARCCC::GT;59 case ISD::SETGE:60 return ARCCC::GE;61 case ISD::SETLT:62 return ARCCC::LT;63 case ISD::SETLE:64 return ARCCC::LE;65 case ISD::SETNE:66 return ARCCC::NE;67 default:68 llvm_unreachable("Unhandled ISDCC code.");69 }70}71 72void ARCTargetLowering::ReplaceNodeResults(SDNode *N,73 SmallVectorImpl<SDValue> &Results,74 SelectionDAG &DAG) const {75 LLVM_DEBUG(dbgs() << "[ARC-ISEL] ReplaceNodeResults ");76 LLVM_DEBUG(N->dump(&DAG));77 LLVM_DEBUG(dbgs() << "; use_count=" << N->use_size() << "\n");78 79 switch (N->getOpcode()) {80 case ISD::READCYCLECOUNTER:81 if (N->getValueType(0) == MVT::i64) {82 // We read the TIMER0 and zero-extend it to 64-bits as the intrinsic83 // requires.84 SDValue V =85 DAG.getNode(ISD::READCYCLECOUNTER, SDLoc(N),86 DAG.getVTList(MVT::i32, MVT::Other), N->getOperand(0));87 SDValue Op = DAG.getNode(ISD::ZERO_EXTEND, SDLoc(N), MVT::i64, V);88 Results.push_back(Op);89 Results.push_back(V.getValue(1));90 }91 break;92 default:93 break;94 }95}96 97ARCTargetLowering::ARCTargetLowering(const TargetMachine &TM,98 const ARCSubtarget &Subtarget)99 : TargetLowering(TM, Subtarget), Subtarget(Subtarget) {100 // Set up the register classes.101 addRegisterClass(MVT::i32, &ARC::GPR32RegClass);102 103 // Compute derived properties from the register classes104 computeRegisterProperties(Subtarget.getRegisterInfo());105 106 setStackPointerRegisterToSaveRestore(ARC::SP);107 108 setSchedulingPreference(Sched::Source);109 110 // Use i32 for setcc operations results (slt, sgt, ...).111 setBooleanContents(ZeroOrOneBooleanContent);112 setBooleanVectorContents(ZeroOrOneBooleanContent);113 114 for (unsigned Opc = 0; Opc < ISD::BUILTIN_OP_END; ++Opc)115 setOperationAction(Opc, MVT::i32, Expand);116 117 // Operations to get us off of the ground.118 // Basic.119 setOperationAction(ISD::ADD, MVT::i32, Legal);120 setOperationAction(ISD::SUB, MVT::i32, Legal);121 setOperationAction(ISD::AND, MVT::i32, Legal);122 setOperationAction(ISD::SMAX, MVT::i32, Legal);123 setOperationAction(ISD::SMIN, MVT::i32, Legal);124 125 setOperationAction(ISD::ADDC, MVT::i32, Legal);126 setOperationAction(ISD::ADDE, MVT::i32, Legal);127 setOperationAction(ISD::SUBC, MVT::i32, Legal);128 setOperationAction(ISD::SUBE, MVT::i32, Legal);129 130 // Need barrel shifter.131 setOperationAction(ISD::SHL, MVT::i32, Legal);132 setOperationAction(ISD::SRA, MVT::i32, Legal);133 setOperationAction(ISD::SRL, MVT::i32, Legal);134 setOperationAction(ISD::ROTR, MVT::i32, Legal);135 136 setOperationAction(ISD::Constant, MVT::i32, Legal);137 setOperationAction(ISD::UNDEF, MVT::i32, Legal);138 139 // Need multiplier140 setOperationAction(ISD::MUL, MVT::i32, Legal);141 setOperationAction(ISD::MULHS, MVT::i32, Legal);142 setOperationAction(ISD::MULHU, MVT::i32, Legal);143 setOperationAction(ISD::LOAD, MVT::i32, Legal);144 setOperationAction(ISD::STORE, MVT::i32, Legal);145 146 setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);147 setOperationAction(ISD::BR_CC, MVT::i32, Custom);148 setOperationAction(ISD::BRCOND, MVT::Other, Expand);149 setOperationAction(ISD::BR_JT, MVT::Other, Expand);150 setOperationAction(ISD::JumpTable, MVT::i32, Custom);151 152 // Have pseudo instruction for frame addresses.153 setOperationAction(ISD::FRAMEADDR, MVT::i32, Legal);154 // Custom lower global addresses.155 setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);156 157 // Expand var-args ops.158 setOperationAction(ISD::VASTART, MVT::Other, Custom);159 setOperationAction(ISD::VAEND, MVT::Other, Expand);160 setOperationAction(ISD::VAARG, MVT::Other, Expand);161 setOperationAction(ISD::VACOPY, MVT::Other, Expand);162 163 // Other expansions164 setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);165 setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);166 167 // Sign extend inreg168 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Custom);169 170 // TODO: Predicate these with `options.hasBitScan() ? Legal : Expand`171 // when the HasBitScan predicate is available.172 setOperationAction(ISD::CTLZ, MVT::i32, Legal);173 setOperationAction(ISD::CTTZ, MVT::i32, Legal);174 175 setOperationAction(ISD::READCYCLECOUNTER, MVT::i32, Legal);176 setOperationAction(ISD::READCYCLECOUNTER, MVT::i64,177 isTypeLegal(MVT::i64) ? Legal : Custom);178 179 setMaxAtomicSizeInBitsSupported(0);180}181 182//===----------------------------------------------------------------------===//183// Misc Lower Operation implementation184//===----------------------------------------------------------------------===//185 186SDValue ARCTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {187 SDValue LHS = Op.getOperand(0);188 SDValue RHS = Op.getOperand(1);189 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();190 SDValue TVal = Op.getOperand(2);191 SDValue FVal = Op.getOperand(3);192 SDLoc dl(Op);193 ARCCC::CondCode ArcCC = ISDCCtoARCCC(CC);194 assert(LHS.getValueType() == MVT::i32 && "Only know how to SELECT_CC i32");195 SDValue Cmp = DAG.getNode(ARCISD::CMP, dl, MVT::Glue, LHS, RHS);196 return DAG.getNode(ARCISD::CMOV, dl, TVal.getValueType(), TVal, FVal,197 DAG.getConstant(ArcCC, dl, MVT::i32), Cmp);198}199 200SDValue ARCTargetLowering::LowerSIGN_EXTEND_INREG(SDValue Op,201 SelectionDAG &DAG) const {202 SDValue Op0 = Op.getOperand(0);203 SDLoc dl(Op);204 assert(Op.getValueType() == MVT::i32 &&205 "Unhandled target sign_extend_inreg.");206 // These are legal207 unsigned Width = cast<VTSDNode>(Op.getOperand(1))->getVT().getSizeInBits();208 if (Width == 16 || Width == 8)209 return Op;210 if (Width >= 32) {211 return {};212 }213 SDValue LS = DAG.getNode(ISD::SHL, dl, MVT::i32, Op0,214 DAG.getConstant(32 - Width, dl, MVT::i32));215 SDValue SR = DAG.getNode(ISD::SRA, dl, MVT::i32, LS,216 DAG.getConstant(32 - Width, dl, MVT::i32));217 return SR;218}219 220SDValue ARCTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {221 SDValue Chain = Op.getOperand(0);222 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();223 SDValue LHS = Op.getOperand(2);224 SDValue RHS = Op.getOperand(3);225 SDValue Dest = Op.getOperand(4);226 SDLoc dl(Op);227 ARCCC::CondCode arcCC = ISDCCtoARCCC(CC);228 assert(LHS.getValueType() == MVT::i32 && "Only know how to BR_CC i32");229 return DAG.getNode(ARCISD::BRcc, dl, MVT::Other, Chain, Dest, LHS, RHS,230 DAG.getConstant(arcCC, dl, MVT::i32));231}232 233SDValue ARCTargetLowering::LowerJumpTable(SDValue Op, SelectionDAG &DAG) const {234 auto *N = cast<JumpTableSDNode>(Op);235 SDValue GA = DAG.getTargetJumpTable(N->getIndex(), MVT::i32);236 return DAG.getNode(ARCISD::GAWRAPPER, SDLoc(N), MVT::i32, GA);237}238 239#include "ARCGenCallingConv.inc"240 241//===----------------------------------------------------------------------===//242// Call Calling Convention Implementation243//===----------------------------------------------------------------------===//244 245/// ARC call implementation246SDValue ARCTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,247 SmallVectorImpl<SDValue> &InVals) const {248 SelectionDAG &DAG = CLI.DAG;249 SDLoc &dl = CLI.DL;250 SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;251 SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;252 SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;253 SDValue Chain = CLI.Chain;254 SDValue Callee = CLI.Callee;255 CallingConv::ID CallConv = CLI.CallConv;256 bool IsVarArg = CLI.IsVarArg;257 bool &IsTailCall = CLI.IsTailCall;258 259 IsTailCall = false; // Do not support tail calls yet.260 261 SmallVector<CCValAssign, 16> ArgLocs;262 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,263 *DAG.getContext());264 265 CCInfo.AnalyzeCallOperands(Outs, CC_ARC);266 267 SmallVector<CCValAssign, 16> RVLocs;268 // Analyze return values to determine the number of bytes of stack required.269 CCState RetCCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,270 *DAG.getContext());271 RetCCInfo.AllocateStack(CCInfo.getStackSize(), Align(4));272 RetCCInfo.AnalyzeCallResult(Ins, RetCC_ARC);273 274 // Get a count of how many bytes are to be pushed on the stack.275 unsigned NumBytes = RetCCInfo.getStackSize();276 277 Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, dl);278 279 SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass;280 SmallVector<SDValue, 12> MemOpChains;281 282 SDValue StackPtr;283 // Walk the register/memloc assignments, inserting copies/loads.284 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {285 CCValAssign &VA = ArgLocs[i];286 SDValue Arg = OutVals[i];287 288 // Promote the value if needed.289 switch (VA.getLocInfo()) {290 default:291 llvm_unreachable("Unknown loc info!");292 case CCValAssign::Full:293 break;294 case CCValAssign::SExt:295 Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);296 break;297 case CCValAssign::ZExt:298 Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg);299 break;300 case CCValAssign::AExt:301 Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);302 break;303 }304 305 // Arguments that can be passed on register must be kept at306 // RegsToPass vector307 if (VA.isRegLoc()) {308 RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));309 } else {310 assert(VA.isMemLoc() && "Must be register or memory argument.");311 if (!StackPtr.getNode())312 StackPtr = DAG.getCopyFromReg(Chain, dl, ARC::SP,313 getPointerTy(DAG.getDataLayout()));314 // Calculate the stack position.315 SDValue SOffset = DAG.getIntPtrConstant(VA.getLocMemOffset(), dl);316 SDValue PtrOff = DAG.getNode(317 ISD::ADD, dl, getPointerTy(DAG.getDataLayout()), StackPtr, SOffset);318 319 SDValue Store =320 DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo());321 MemOpChains.push_back(Store);322 IsTailCall = false;323 }324 }325 326 // Transform all store nodes into one single node because327 // all store nodes are independent of each other.328 if (!MemOpChains.empty())329 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);330 331 // Build a sequence of copy-to-reg nodes chained together with token332 // chain and flag operands which copy the outgoing args into registers.333 // The Glue in necessary since all emitted instructions must be334 // stuck together.335 SDValue Glue;336 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {337 Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,338 RegsToPass[i].second, Glue);339 Glue = Chain.getValue(1);340 }341 342 // If the callee is a GlobalAddress node (quite common, every direct call is)343 // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.344 // Likewise ExternalSymbol -> TargetExternalSymbol.345 bool IsDirect = true;346 if (auto *G = dyn_cast<GlobalAddressSDNode>(Callee))347 Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32);348 else if (auto *E = dyn_cast<ExternalSymbolSDNode>(Callee))349 Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32);350 else351 IsDirect = false;352 // Branch + Link = #chain, #target_address, #opt_in_flags...353 // = Chain, Callee, Reg#1, Reg#2, ...354 //355 // Returns a chain & a glue for retval copy to use.356 SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);357 SmallVector<SDValue, 8> Ops;358 Ops.push_back(Chain);359 Ops.push_back(Callee);360 361 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)362 Ops.push_back(DAG.getRegister(RegsToPass[i].first,363 RegsToPass[i].second.getValueType()));364 365 // Add a register mask operand representing the call-preserved registers.366 const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();367 const uint32_t *Mask =368 TRI->getCallPreservedMask(DAG.getMachineFunction(), CallConv);369 assert(Mask && "Missing call preserved mask for calling convention");370 Ops.push_back(DAG.getRegisterMask(Mask));371 372 if (Glue.getNode())373 Ops.push_back(Glue);374 375 Chain = DAG.getNode(IsDirect ? ARCISD::BL : ARCISD::JL, dl, NodeTys, Ops);376 Glue = Chain.getValue(1);377 378 // Create the CALLSEQ_END node.379 Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, Glue, dl);380 Glue = Chain.getValue(1);381 382 // Handle result values, copying them out of physregs into vregs that we383 // return.384 if (IsTailCall)385 return Chain;386 return lowerCallResult(Chain, Glue, RVLocs, dl, DAG, InVals);387}388 389/// Lower the result values of a call into the appropriate copies out of390/// physical registers / memory locations.391static SDValue lowerCallResult(SDValue Chain, SDValue Glue,392 const SmallVectorImpl<CCValAssign> &RVLocs,393 SDLoc dl, SelectionDAG &DAG,394 SmallVectorImpl<SDValue> &InVals) {395 SmallVector<std::pair<int, unsigned>, 4> ResultMemLocs;396 // Copy results out of physical registers.397 for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {398 const CCValAssign &VA = RVLocs[i];399 if (VA.isRegLoc()) {400 SDValue RetValue;401 RetValue =402 DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), VA.getValVT(), Glue);403 Chain = RetValue.getValue(1);404 Glue = RetValue.getValue(2);405 InVals.push_back(RetValue);406 } else {407 assert(VA.isMemLoc() && "Must be memory location.");408 ResultMemLocs.push_back(409 std::make_pair(VA.getLocMemOffset(), InVals.size()));410 411 // Reserve space for this result.412 InVals.push_back(SDValue());413 }414 }415 416 // Copy results out of memory.417 SmallVector<SDValue, 4> MemOpChains;418 for (unsigned i = 0, e = ResultMemLocs.size(); i != e; ++i) {419 int Offset = ResultMemLocs[i].first;420 unsigned Index = ResultMemLocs[i].second;421 SDValue StackPtr = DAG.getRegister(ARC::SP, MVT::i32);422 SDValue SpLoc = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr,423 DAG.getConstant(Offset, dl, MVT::i32));424 SDValue Load =425 DAG.getLoad(MVT::i32, dl, Chain, SpLoc, MachinePointerInfo());426 InVals[Index] = Load;427 MemOpChains.push_back(Load.getValue(1));428 }429 430 // Transform all loads nodes into one single node because431 // all load nodes are independent of each other.432 if (!MemOpChains.empty())433 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);434 435 return Chain;436}437 438//===----------------------------------------------------------------------===//439// Formal Arguments Calling Convention Implementation440//===----------------------------------------------------------------------===//441 442namespace {443 444struct ArgDataPair {445 SDValue SDV;446 ISD::ArgFlagsTy Flags;447};448 449} // end anonymous namespace450 451/// ARC formal arguments implementation452SDValue ARCTargetLowering::LowerFormalArguments(453 SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,454 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,455 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {456 switch (CallConv) {457 default:458 llvm_unreachable("Unsupported calling convention");459 case CallingConv::C:460 case CallingConv::Fast:461 return LowerCallArguments(Chain, CallConv, IsVarArg, Ins, dl, DAG, InVals);462 }463}464 465/// Transform physical registers into virtual registers, and generate load466/// operations for argument places on the stack.467SDValue ARCTargetLowering::LowerCallArguments(468 SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,469 const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc dl, SelectionDAG &DAG,470 SmallVectorImpl<SDValue> &InVals) const {471 MachineFunction &MF = DAG.getMachineFunction();472 MachineFrameInfo &MFI = MF.getFrameInfo();473 MachineRegisterInfo &RegInfo = MF.getRegInfo();474 auto *AFI = MF.getInfo<ARCFunctionInfo>();475 476 // Assign locations to all of the incoming arguments.477 SmallVector<CCValAssign, 16> ArgLocs;478 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,479 *DAG.getContext());480 481 CCInfo.AnalyzeFormalArguments(Ins, CC_ARC);482 483 unsigned StackSlotSize = 4;484 485 if (!IsVarArg)486 AFI->setReturnStackOffset(CCInfo.getStackSize());487 488 // All getCopyFromReg ops must precede any getMemcpys to prevent the489 // scheduler clobbering a register before it has been copied.490 // The stages are:491 // 1. CopyFromReg (and load) arg & vararg registers.492 // 2. Chain CopyFromReg nodes into a TokenFactor.493 // 3. Memcpy 'byVal' args & push final InVals.494 // 4. Chain mem ops nodes into a TokenFactor.495 SmallVector<SDValue, 4> CFRegNode;496 SmallVector<ArgDataPair, 4> ArgData;497 SmallVector<SDValue, 4> MemOps;498 499 // 1a. CopyFromReg (and load) arg registers.500 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {501 CCValAssign &VA = ArgLocs[i];502 SDValue ArgIn;503 504 if (VA.isRegLoc()) {505 // Arguments passed in registers506 EVT RegVT = VA.getLocVT();507 switch (RegVT.getSimpleVT().SimpleTy) {508 default: {509 LLVM_DEBUG(errs() << "LowerFormalArguments Unhandled argument type: "510 << (unsigned)RegVT.getSimpleVT().SimpleTy << "\n");511 llvm_unreachable("Unhandled LowerFormalArguments type.");512 }513 case MVT::i32:514 unsigned VReg = RegInfo.createVirtualRegister(&ARC::GPR32RegClass);515 RegInfo.addLiveIn(VA.getLocReg(), VReg);516 ArgIn = DAG.getCopyFromReg(Chain, dl, VReg, RegVT);517 CFRegNode.push_back(ArgIn.getValue(ArgIn->getNumValues() - 1));518 }519 } else {520 // Only arguments passed on the stack should make it here.521 assert(VA.isMemLoc());522 // Load the argument to a virtual register523 unsigned ObjSize = VA.getLocVT().getStoreSize();524 assert((ObjSize <= StackSlotSize) && "Unhandled argument");525 526 // Create the frame index object for this incoming parameter...527 int FI = MFI.CreateFixedObject(ObjSize, VA.getLocMemOffset(), true);528 529 // Create the SelectionDAG nodes corresponding to a load530 // from this parameter531 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);532 ArgIn = DAG.getLoad(VA.getLocVT(), dl, Chain, FIN,533 MachinePointerInfo::getFixedStack(MF, FI));534 }535 const ArgDataPair ADP = {ArgIn, Ins[i].Flags};536 ArgData.push_back(ADP);537 }538 539 // 1b. CopyFromReg vararg registers.540 if (IsVarArg) {541 // Argument registers542 static const MCPhysReg ArgRegs[] = {ARC::R0, ARC::R1, ARC::R2, ARC::R3,543 ARC::R4, ARC::R5, ARC::R6, ARC::R7};544 auto *AFI = MF.getInfo<ARCFunctionInfo>();545 unsigned FirstVAReg = CCInfo.getFirstUnallocated(ArgRegs);546 if (FirstVAReg < std::size(ArgRegs)) {547 int Offset = 0;548 // Save remaining registers, storing higher register numbers at a higher549 // address550 // There are (std::size(ArgRegs) - FirstVAReg) registers which551 // need to be saved.552 int VarFI = MFI.CreateFixedObject((std::size(ArgRegs) - FirstVAReg) * 4,553 CCInfo.getStackSize(), true);554 AFI->setVarArgsFrameIndex(VarFI);555 SDValue FIN = DAG.getFrameIndex(VarFI, MVT::i32);556 for (unsigned i = FirstVAReg; i < std::size(ArgRegs); i++) {557 // Move argument from phys reg -> virt reg558 unsigned VReg = RegInfo.createVirtualRegister(&ARC::GPR32RegClass);559 RegInfo.addLiveIn(ArgRegs[i], VReg);560 SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);561 CFRegNode.push_back(Val.getValue(Val->getNumValues() - 1));562 SDValue VAObj = DAG.getNode(ISD::ADD, dl, MVT::i32, FIN,563 DAG.getConstant(Offset, dl, MVT::i32));564 // Move argument from virt reg -> stack565 SDValue Store =566 DAG.getStore(Val.getValue(1), dl, Val, VAObj, MachinePointerInfo());567 MemOps.push_back(Store);568 Offset += 4;569 }570 } else {571 llvm_unreachable("Too many var args parameters.");572 }573 }574 575 // 2. Chain CopyFromReg nodes into a TokenFactor.576 if (!CFRegNode.empty())577 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, CFRegNode);578 579 // 3. Memcpy 'byVal' args & push final InVals.580 // Aggregates passed "byVal" need to be copied by the callee.581 // The callee will use a pointer to this copy, rather than the original582 // pointer.583 for (const auto &ArgDI : ArgData) {584 if (ArgDI.Flags.isByVal() && ArgDI.Flags.getByValSize()) {585 unsigned Size = ArgDI.Flags.getByValSize();586 Align Alignment =587 std::max(Align(StackSlotSize), ArgDI.Flags.getNonZeroByValAlign());588 // Create a new object on the stack and copy the pointee into it.589 int FI = MFI.CreateStackObject(Size, Alignment, false);590 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);591 InVals.push_back(FIN);592 MemOps.push_back(DAG.getMemcpy(593 Chain, dl, FIN, ArgDI.SDV, DAG.getConstant(Size, dl, MVT::i32),594 Alignment, false, false, /*CI=*/nullptr, false, MachinePointerInfo(),595 MachinePointerInfo()));596 } else {597 InVals.push_back(ArgDI.SDV);598 }599 }600 601 // 4. Chain mem ops nodes into a TokenFactor.602 if (!MemOps.empty()) {603 MemOps.push_back(Chain);604 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOps);605 }606 607 return Chain;608}609 610//===----------------------------------------------------------------------===//611// Return Value Calling Convention Implementation612//===----------------------------------------------------------------------===//613 614bool ARCTargetLowering::CanLowerReturn(615 CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,616 const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context,617 const Type *RetTy) const {618 SmallVector<CCValAssign, 16> RVLocs;619 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);620 if (!CCInfo.CheckReturn(Outs, RetCC_ARC))621 return false;622 if (CCInfo.getStackSize() != 0 && IsVarArg)623 return false;624 return true;625}626 627SDValue628ARCTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,629 bool IsVarArg,630 const SmallVectorImpl<ISD::OutputArg> &Outs,631 const SmallVectorImpl<SDValue> &OutVals,632 const SDLoc &dl, SelectionDAG &DAG) const {633 auto *AFI = DAG.getMachineFunction().getInfo<ARCFunctionInfo>();634 MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();635 636 // CCValAssign - represent the assignment of637 // the return value to a location638 SmallVector<CCValAssign, 16> RVLocs;639 640 // CCState - Info about the registers and stack slot.641 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,642 *DAG.getContext());643 644 // Analyze return values.645 if (!IsVarArg)646 CCInfo.AllocateStack(AFI->getReturnStackOffset(), Align(4));647 648 CCInfo.AnalyzeReturn(Outs, RetCC_ARC);649 650 SDValue Glue;651 SmallVector<SDValue, 4> RetOps(1, Chain);652 SmallVector<SDValue, 4> MemOpChains;653 // Handle return values that must be copied to memory.654 for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {655 CCValAssign &VA = RVLocs[i];656 if (VA.isRegLoc())657 continue;658 assert(VA.isMemLoc());659 if (IsVarArg) {660 report_fatal_error("Can't return value from vararg function in memory");661 }662 663 int Offset = VA.getLocMemOffset();664 unsigned ObjSize = VA.getLocVT().getStoreSize();665 // Create the frame index object for the memory location.666 int FI = MFI.CreateFixedObject(ObjSize, Offset, false);667 668 // Create a SelectionDAG node corresponding to a store669 // to this memory location.670 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);671 MemOpChains.push_back(DAG.getStore(672 Chain, dl, OutVals[i], FIN,673 MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI)));674 }675 676 // Transform all store nodes into one single node because677 // all stores are independent of each other.678 if (!MemOpChains.empty())679 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);680 681 // Now handle return values copied to registers.682 for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {683 CCValAssign &VA = RVLocs[i];684 if (!VA.isRegLoc())685 continue;686 // Copy the result values into the output registers.687 Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Glue);688 689 // guarantee that all emitted copies are690 // stuck together, avoiding something bad691 Glue = Chain.getValue(1);692 RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));693 }694 695 RetOps[0] = Chain; // Update chain.696 697 // Add the glue if we have it.698 if (Glue.getNode())699 RetOps.push_back(Glue);700 701 // What to do with the RetOps?702 return DAG.getNode(ARCISD::RET, dl, MVT::Other, RetOps);703}704 705//===----------------------------------------------------------------------===//706// Target Optimization Hooks707//===----------------------------------------------------------------------===//708 709SDValue ARCTargetLowering::PerformDAGCombine(SDNode *N,710 DAGCombinerInfo &DCI) const {711 return {};712}713 714//===----------------------------------------------------------------------===//715// Addressing mode description hooks716//===----------------------------------------------------------------------===//717 718/// Return true if the addressing mode represented by AM is legal for this719/// target, for a load/store of the specified type.720bool ARCTargetLowering::isLegalAddressingMode(const DataLayout &DL,721 const AddrMode &AM, Type *Ty,722 unsigned AS,723 Instruction *I) const {724 return AM.Scale == 0;725}726 727// Don't emit tail calls for the time being.728bool ARCTargetLowering::mayBeEmittedAsTailCall(const CallInst *CI) const {729 return false;730}731 732SDValue ARCTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const {733 const ARCRegisterInfo &ARI = *Subtarget.getRegisterInfo();734 MachineFunction &MF = DAG.getMachineFunction();735 MachineFrameInfo &MFI = MF.getFrameInfo();736 MFI.setFrameAddressIsTaken(true);737 738 EVT VT = Op.getValueType();739 SDLoc dl(Op);740 assert(Op.getConstantOperandVal(0) == 0 &&741 "Only support lowering frame addr of current frame.");742 Register FrameReg = ARI.getFrameRegister(MF);743 return DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT);744}745 746SDValue ARCTargetLowering::LowerGlobalAddress(SDValue Op,747 SelectionDAG &DAG) const {748 const GlobalAddressSDNode *GN = cast<GlobalAddressSDNode>(Op);749 const GlobalValue *GV = GN->getGlobal();750 SDLoc dl(GN);751 int64_t Offset = GN->getOffset();752 SDValue GA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, Offset);753 return DAG.getNode(ARCISD::GAWRAPPER, dl, MVT::i32, GA);754}755 756static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) {757 MachineFunction &MF = DAG.getMachineFunction();758 auto *FuncInfo = MF.getInfo<ARCFunctionInfo>();759 760 // vastart just stores the address of the VarArgsFrameIndex slot into the761 // memory location argument.762 SDLoc dl(Op);763 EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(DAG.getDataLayout());764 SDValue FR = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), PtrVT);765 const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();766 return DAG.getStore(Op.getOperand(0), dl, FR, Op.getOperand(1),767 MachinePointerInfo(SV));768}769 770SDValue ARCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {771 switch (Op.getOpcode()) {772 case ISD::GlobalAddress:773 return LowerGlobalAddress(Op, DAG);774 case ISD::FRAMEADDR:775 return LowerFRAMEADDR(Op, DAG);776 case ISD::SELECT_CC:777 return LowerSELECT_CC(Op, DAG);778 case ISD::BR_CC:779 return LowerBR_CC(Op, DAG);780 case ISD::SIGN_EXTEND_INREG:781 return LowerSIGN_EXTEND_INREG(Op, DAG);782 case ISD::JumpTable:783 return LowerJumpTable(Op, DAG);784 case ISD::VASTART:785 return LowerVASTART(Op, DAG);786 case ISD::READCYCLECOUNTER:787 // As of LLVM 3.8, the lowering code insists that we customize it even788 // though we've declared the i32 version as legal. This is because it only789 // thinks i64 is the truly supported version. We've already converted the790 // i64 version to a widened i32.791 assert(Op.getSimpleValueType() == MVT::i32);792 return Op;793 default:794 llvm_unreachable("unimplemented operand");795 }796}797