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

source code of llvm/lib/Target/ARC/ARCISelLowering.cpp