1 //=- LoongArchISelLowering.cpp - LoongArch DAG Lowering Implementation  ---===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the interfaces that LoongArch uses to lower LLVM code into
10 // a selection DAG.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "LoongArchISelLowering.h"
15 #include "LoongArch.h"
16 #include "LoongArchMachineFunctionInfo.h"
17 #include "LoongArchRegisterInfo.h"
18 #include "LoongArchSubtarget.h"
19 #include "LoongArchTargetMachine.h"
20 #include "MCTargetDesc/LoongArchMCTargetDesc.h"
21 #include "llvm/ADT/Statistic.h"
22 #include "llvm/CodeGen/ISDOpcodes.h"
23 #include "llvm/Support/Debug.h"
24 
25 using namespace llvm;
26 
27 #define DEBUG_TYPE "loongarch-isel-lowering"
28 
29 LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
30                                                  const LoongArchSubtarget &STI)
31     : TargetLowering(TM), Subtarget(STI) {
32 
33   MVT GRLenVT = Subtarget.getGRLenVT();
34   // Set up the register classes.
35   addRegisterClass(GRLenVT, &LoongArch::GPRRegClass);
36   if (Subtarget.hasBasicF())
37     addRegisterClass(MVT::f32, &LoongArch::FPR32RegClass);
38   if (Subtarget.hasBasicD())
39     addRegisterClass(MVT::f64, &LoongArch::FPR64RegClass);
40 
41   setLoadExtAction({ISD::EXTLOAD, ISD::SEXTLOAD, ISD::ZEXTLOAD}, GRLenVT,
42                    MVT::i1, Promote);
43 
44   // TODO: add necessary setOperationAction calls later.
45   setOperationAction(ISD::SHL_PARTS, GRLenVT, Custom);
46   setOperationAction(ISD::SRA_PARTS, GRLenVT, Custom);
47   setOperationAction(ISD::SRL_PARTS, GRLenVT, Custom);
48 
49   setOperationAction(ISD::GlobalAddress, GRLenVT, Custom);
50 
51   if (Subtarget.is64Bit()) {
52     setOperationAction(ISD::SHL, MVT::i32, Custom);
53     setOperationAction(ISD::SRA, MVT::i32, Custom);
54     setOperationAction(ISD::SRL, MVT::i32, Custom);
55   }
56 
57   static const ISD::CondCode FPCCToExpand[] = {ISD::SETOGT, ISD::SETOGE,
58                                                ISD::SETUGT, ISD::SETUGE};
59 
60   if (Subtarget.hasBasicF()) {
61     setCondCodeAction(FPCCToExpand, MVT::f32, Expand);
62     setOperationAction(ISD::SELECT_CC, MVT::f32, Expand);
63   }
64   if (Subtarget.hasBasicD()) {
65     setCondCodeAction(FPCCToExpand, MVT::f64, Expand);
66     setOperationAction(ISD::SELECT_CC, MVT::f64, Expand);
67   }
68 
69   setOperationAction(ISD::BR_CC, GRLenVT, Expand);
70   setOperationAction(ISD::SELECT_CC, GRLenVT, Expand);
71   setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
72 
73   // Compute derived properties from the register classes.
74   computeRegisterProperties(STI.getRegisterInfo());
75 
76   setStackPointerRegisterToSaveRestore(LoongArch::R3);
77 
78   setBooleanContents(ZeroOrOneBooleanContent);
79 
80   // Function alignments.
81   const Align FunctionAlignment(4);
82   setMinFunctionAlignment(FunctionAlignment);
83 
84   setTargetDAGCombine(ISD::AND);
85   setTargetDAGCombine(ISD::SRL);
86 }
87 
88 SDValue LoongArchTargetLowering::LowerOperation(SDValue Op,
89                                                 SelectionDAG &DAG) const {
90   switch (Op.getOpcode()) {
91   default:
92     report_fatal_error("unimplemented operand");
93   case ISD::GlobalAddress:
94     return lowerGlobalAddress(Op, DAG);
95   case ISD::SHL_PARTS:
96     return lowerShiftLeftParts(Op, DAG);
97   case ISD::SRA_PARTS:
98     return lowerShiftRightParts(Op, DAG, true);
99   case ISD::SRL_PARTS:
100     return lowerShiftRightParts(Op, DAG, false);
101   case ISD::SHL:
102   case ISD::SRA:
103   case ISD::SRL:
104     // This can be called for an i32 shift amount that needs to be promoted.
105     assert(Op.getOperand(1).getValueType() == MVT::i32 && Subtarget.is64Bit() &&
106            "Unexpected custom legalisation");
107     return SDValue();
108   }
109 }
110 
111 SDValue LoongArchTargetLowering::lowerGlobalAddress(SDValue Op,
112                                                     SelectionDAG &DAG) const {
113   SDLoc DL(Op);
114   EVT Ty = getPointerTy(DAG.getDataLayout());
115   const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
116   unsigned ADDIOp = Subtarget.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
117 
118   // FIXME: Only support PC-relative addressing to access the symbol.
119   // TODO: Add target flags.
120   if (!isPositionIndependent()) {
121     SDValue GA = DAG.getTargetGlobalAddress(GV, DL, Ty);
122     SDValue AddrHi(DAG.getMachineNode(LoongArch::PCALAU12I, DL, Ty, GA), 0);
123     SDValue Addr(DAG.getMachineNode(ADDIOp, DL, Ty, AddrHi, GA), 0);
124     return Addr;
125   }
126   report_fatal_error("Unable to lowerGlobalAddress");
127 }
128 
129 SDValue LoongArchTargetLowering::lowerShiftLeftParts(SDValue Op,
130                                                      SelectionDAG &DAG) const {
131   SDLoc DL(Op);
132   SDValue Lo = Op.getOperand(0);
133   SDValue Hi = Op.getOperand(1);
134   SDValue Shamt = Op.getOperand(2);
135   EVT VT = Lo.getValueType();
136 
137   // if Shamt-GRLen < 0: // Shamt < GRLen
138   //   Lo = Lo << Shamt
139   //   Hi = (Hi << Shamt) | ((Lo >>u 1) >>u (GRLen-1 ^ Shamt))
140   // else:
141   //   Lo = 0
142   //   Hi = Lo << (Shamt-GRLen)
143 
144   SDValue Zero = DAG.getConstant(0, DL, VT);
145   SDValue One = DAG.getConstant(1, DL, VT);
146   SDValue MinusGRLen = DAG.getConstant(-(int)Subtarget.getGRLen(), DL, VT);
147   SDValue GRLenMinus1 = DAG.getConstant(Subtarget.getGRLen() - 1, DL, VT);
148   SDValue ShamtMinusGRLen = DAG.getNode(ISD::ADD, DL, VT, Shamt, MinusGRLen);
149   SDValue GRLenMinus1Shamt = DAG.getNode(ISD::XOR, DL, VT, Shamt, GRLenMinus1);
150 
151   SDValue LoTrue = DAG.getNode(ISD::SHL, DL, VT, Lo, Shamt);
152   SDValue ShiftRight1Lo = DAG.getNode(ISD::SRL, DL, VT, Lo, One);
153   SDValue ShiftRightLo =
154       DAG.getNode(ISD::SRL, DL, VT, ShiftRight1Lo, GRLenMinus1Shamt);
155   SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, VT, Hi, Shamt);
156   SDValue HiTrue = DAG.getNode(ISD::OR, DL, VT, ShiftLeftHi, ShiftRightLo);
157   SDValue HiFalse = DAG.getNode(ISD::SHL, DL, VT, Lo, ShamtMinusGRLen);
158 
159   SDValue CC = DAG.getSetCC(DL, VT, ShamtMinusGRLen, Zero, ISD::SETLT);
160 
161   Lo = DAG.getNode(ISD::SELECT, DL, VT, CC, LoTrue, Zero);
162   Hi = DAG.getNode(ISD::SELECT, DL, VT, CC, HiTrue, HiFalse);
163 
164   SDValue Parts[2] = {Lo, Hi};
165   return DAG.getMergeValues(Parts, DL);
166 }
167 
168 SDValue LoongArchTargetLowering::lowerShiftRightParts(SDValue Op,
169                                                       SelectionDAG &DAG,
170                                                       bool IsSRA) const {
171   SDLoc DL(Op);
172   SDValue Lo = Op.getOperand(0);
173   SDValue Hi = Op.getOperand(1);
174   SDValue Shamt = Op.getOperand(2);
175   EVT VT = Lo.getValueType();
176 
177   // SRA expansion:
178   //   if Shamt-GRLen < 0: // Shamt < GRLen
179   //     Lo = (Lo >>u Shamt) | ((Hi << 1) << (ShAmt ^ GRLen-1))
180   //     Hi = Hi >>s Shamt
181   //   else:
182   //     Lo = Hi >>s (Shamt-GRLen);
183   //     Hi = Hi >>s (GRLen-1)
184   //
185   // SRL expansion:
186   //   if Shamt-GRLen < 0: // Shamt < GRLen
187   //     Lo = (Lo >>u Shamt) | ((Hi << 1) << (ShAmt ^ GRLen-1))
188   //     Hi = Hi >>u Shamt
189   //   else:
190   //     Lo = Hi >>u (Shamt-GRLen);
191   //     Hi = 0;
192 
193   unsigned ShiftRightOp = IsSRA ? ISD::SRA : ISD::SRL;
194 
195   SDValue Zero = DAG.getConstant(0, DL, VT);
196   SDValue One = DAG.getConstant(1, DL, VT);
197   SDValue MinusGRLen = DAG.getConstant(-(int)Subtarget.getGRLen(), DL, VT);
198   SDValue GRLenMinus1 = DAG.getConstant(Subtarget.getGRLen() - 1, DL, VT);
199   SDValue ShamtMinusGRLen = DAG.getNode(ISD::ADD, DL, VT, Shamt, MinusGRLen);
200   SDValue GRLenMinus1Shamt = DAG.getNode(ISD::XOR, DL, VT, Shamt, GRLenMinus1);
201 
202   SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, VT, Lo, Shamt);
203   SDValue ShiftLeftHi1 = DAG.getNode(ISD::SHL, DL, VT, Hi, One);
204   SDValue ShiftLeftHi =
205       DAG.getNode(ISD::SHL, DL, VT, ShiftLeftHi1, GRLenMinus1Shamt);
206   SDValue LoTrue = DAG.getNode(ISD::OR, DL, VT, ShiftRightLo, ShiftLeftHi);
207   SDValue HiTrue = DAG.getNode(ShiftRightOp, DL, VT, Hi, Shamt);
208   SDValue LoFalse = DAG.getNode(ShiftRightOp, DL, VT, Hi, ShamtMinusGRLen);
209   SDValue HiFalse =
210       IsSRA ? DAG.getNode(ISD::SRA, DL, VT, Hi, GRLenMinus1) : Zero;
211 
212   SDValue CC = DAG.getSetCC(DL, VT, ShamtMinusGRLen, Zero, ISD::SETLT);
213 
214   Lo = DAG.getNode(ISD::SELECT, DL, VT, CC, LoTrue, LoFalse);
215   Hi = DAG.getNode(ISD::SELECT, DL, VT, CC, HiTrue, HiFalse);
216 
217   SDValue Parts[2] = {Lo, Hi};
218   return DAG.getMergeValues(Parts, DL);
219 }
220 
221 // Returns the opcode of the target-specific SDNode that implements the 32-bit
222 // form of the given Opcode.
223 static LoongArchISD::NodeType getLoongArchWOpcode(unsigned Opcode) {
224   switch (Opcode) {
225   default:
226     llvm_unreachable("Unexpected opcode");
227   case ISD::SHL:
228     return LoongArchISD::SLL_W;
229   case ISD::SRA:
230     return LoongArchISD::SRA_W;
231   case ISD::SRL:
232     return LoongArchISD::SRL_W;
233   }
234 }
235 
236 // Converts the given i8/i16/i32 operation to a target-specific SelectionDAG
237 // node. Because i8/i16/i32 isn't a legal type for LA64, these operations would
238 // otherwise be promoted to i64, making it difficult to select the
239 // SLL_W/.../*W later one because the fact the operation was originally of
240 // type i8/i16/i32 is lost.
241 static SDValue customLegalizeToWOp(SDNode *N, SelectionDAG &DAG,
242                                    unsigned ExtOpc = ISD::ANY_EXTEND) {
243   SDLoc DL(N);
244   LoongArchISD::NodeType WOpcode = getLoongArchWOpcode(N->getOpcode());
245   SDValue NewOp0 = DAG.getNode(ExtOpc, DL, MVT::i64, N->getOperand(0));
246   SDValue NewOp1 = DAG.getNode(ExtOpc, DL, MVT::i64, N->getOperand(1));
247   SDValue NewRes = DAG.getNode(WOpcode, DL, MVT::i64, NewOp0, NewOp1);
248   // ReplaceNodeResults requires we maintain the same type for the return value.
249   return DAG.getNode(ISD::TRUNCATE, DL, N->getValueType(0), NewRes);
250 }
251 
252 void LoongArchTargetLowering::ReplaceNodeResults(
253     SDNode *N, SmallVectorImpl<SDValue> &Results, SelectionDAG &DAG) const {
254   SDLoc DL(N);
255   switch (N->getOpcode()) {
256   default:
257     llvm_unreachable("Don't know how to legalize this operation");
258   case ISD::SHL:
259   case ISD::SRA:
260   case ISD::SRL:
261     assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
262            "Unexpected custom legalisation");
263     if (N->getOperand(1).getOpcode() != ISD::Constant) {
264       Results.push_back(customLegalizeToWOp(N, DAG));
265       break;
266     }
267     break;
268   }
269 }
270 
271 static SDValue performANDCombine(SDNode *N, SelectionDAG &DAG,
272                                  TargetLowering::DAGCombinerInfo &DCI,
273                                  const LoongArchSubtarget &Subtarget) {
274   if (DCI.isBeforeLegalizeOps())
275     return SDValue();
276 
277   SDValue FirstOperand = N->getOperand(0);
278   SDValue SecondOperand = N->getOperand(1);
279   unsigned FirstOperandOpc = FirstOperand.getOpcode();
280   EVT ValTy = N->getValueType(0);
281   SDLoc DL(N);
282   uint64_t lsb, msb;
283   unsigned SMIdx, SMLen;
284   ConstantSDNode *CN;
285   SDValue NewOperand;
286   MVT GRLenVT = Subtarget.getGRLenVT();
287 
288   // Op's second operand must be a shifted mask.
289   if (!(CN = dyn_cast<ConstantSDNode>(SecondOperand)) ||
290       !isShiftedMask_64(CN->getZExtValue(), SMIdx, SMLen))
291     return SDValue();
292 
293   if (FirstOperandOpc == ISD::SRA || FirstOperandOpc == ISD::SRL) {
294     // Pattern match BSTRPICK.
295     //  $dst = and ((sra or srl) $src , lsb), (2**len - 1)
296     //  => BSTRPICK $dst, $src, msb, lsb
297     //  where msb = lsb + len - 1
298 
299     // The second operand of the shift must be an immediate.
300     if (!(CN = dyn_cast<ConstantSDNode>(FirstOperand.getOperand(1))))
301       return SDValue();
302 
303     lsb = CN->getZExtValue();
304 
305     // Return if the shifted mask does not start at bit 0 or the sum of its
306     // length and lsb exceeds the word's size.
307     if (SMIdx != 0 || lsb + SMLen > ValTy.getSizeInBits())
308       return SDValue();
309 
310     NewOperand = FirstOperand.getOperand(0);
311   } else {
312     // Pattern match BSTRPICK.
313     //  $dst = and $src, (2**len- 1) , if len > 12
314     //  => BSTRPICK $dst, $src, msb, lsb
315     //  where lsb = 0 and msb = len - 1
316 
317     // If the mask is <= 0xfff, andi can be used instead.
318     if (CN->getZExtValue() <= 0xfff)
319       return SDValue();
320 
321     // Return if the mask doesn't start at position 0.
322     if (SMIdx)
323       return SDValue();
324 
325     lsb = 0;
326     NewOperand = FirstOperand;
327   }
328   msb = lsb + SMLen - 1;
329   return DAG.getNode(LoongArchISD::BSTRPICK, DL, ValTy, NewOperand,
330                      DAG.getConstant(msb, DL, GRLenVT),
331                      DAG.getConstant(lsb, DL, GRLenVT));
332 }
333 
334 static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG,
335                                  TargetLowering::DAGCombinerInfo &DCI,
336                                  const LoongArchSubtarget &Subtarget) {
337   if (DCI.isBeforeLegalizeOps())
338     return SDValue();
339 
340   // $dst = srl (and $src, Mask), Shamt
341   // =>
342   // BSTRPICK $dst, $src, MaskIdx+MaskLen-1, Shamt
343   // when Mask is a shifted mask, and MaskIdx <= Shamt <= MaskIdx+MaskLen-1
344   //
345 
346   SDValue FirstOperand = N->getOperand(0);
347   ConstantSDNode *CN;
348   EVT ValTy = N->getValueType(0);
349   SDLoc DL(N);
350   MVT GRLenVT = Subtarget.getGRLenVT();
351   unsigned MaskIdx, MaskLen;
352   uint64_t Shamt;
353 
354   // The first operand must be an AND and the second operand of the AND must be
355   // a shifted mask.
356   if (FirstOperand.getOpcode() != ISD::AND ||
357       !(CN = dyn_cast<ConstantSDNode>(FirstOperand.getOperand(1))) ||
358       !isShiftedMask_64(CN->getZExtValue(), MaskIdx, MaskLen))
359     return SDValue();
360 
361   // The second operand (shift amount) must be an immediate.
362   if (!(CN = dyn_cast<ConstantSDNode>(N->getOperand(1))))
363     return SDValue();
364 
365   Shamt = CN->getZExtValue();
366   if (MaskIdx <= Shamt && Shamt <= MaskIdx + MaskLen - 1)
367     return DAG.getNode(LoongArchISD::BSTRPICK, DL, ValTy,
368                        FirstOperand->getOperand(0),
369                        DAG.getConstant(MaskIdx + MaskLen - 1, DL, GRLenVT),
370                        DAG.getConstant(Shamt, DL, GRLenVT));
371 
372   return SDValue();
373 }
374 
375 SDValue LoongArchTargetLowering::PerformDAGCombine(SDNode *N,
376                                                    DAGCombinerInfo &DCI) const {
377   SelectionDAG &DAG = DCI.DAG;
378   switch (N->getOpcode()) {
379   default:
380     break;
381   case ISD::AND:
382     return performANDCombine(N, DAG, DCI, Subtarget);
383   case ISD::SRL:
384     return performSRLCombine(N, DAG, DCI, Subtarget);
385   }
386   return SDValue();
387 }
388 
389 const char *LoongArchTargetLowering::getTargetNodeName(unsigned Opcode) const {
390   switch ((LoongArchISD::NodeType)Opcode) {
391   case LoongArchISD::FIRST_NUMBER:
392     break;
393 
394 #define NODE_NAME_CASE(node)                                                   \
395   case LoongArchISD::node:                                                     \
396     return "LoongArchISD::" #node;
397 
398     // TODO: Add more target-dependent nodes later.
399     NODE_NAME_CASE(CALL)
400     NODE_NAME_CASE(RET)
401     NODE_NAME_CASE(SLL_W)
402     NODE_NAME_CASE(SRA_W)
403     NODE_NAME_CASE(SRL_W)
404     NODE_NAME_CASE(BSTRPICK)
405   }
406 #undef NODE_NAME_CASE
407   return nullptr;
408 }
409 
410 //===----------------------------------------------------------------------===//
411 //                     Calling Convention Implementation
412 //===----------------------------------------------------------------------===//
413 // FIXME: Now, we only support CallingConv::C with fixed arguments which are
414 // passed with integer or floating-point registers.
415 const MCPhysReg ArgGPRs[] = {LoongArch::R4,  LoongArch::R5, LoongArch::R6,
416                              LoongArch::R7,  LoongArch::R8, LoongArch::R9,
417                              LoongArch::R10, LoongArch::R11};
418 const MCPhysReg ArgFPR32s[] = {LoongArch::F0, LoongArch::F1, LoongArch::F2,
419                                LoongArch::F3, LoongArch::F4, LoongArch::F5,
420                                LoongArch::F6, LoongArch::F7};
421 const MCPhysReg ArgFPR64s[] = {
422     LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, LoongArch::F3_64,
423     LoongArch::F4_64, LoongArch::F5_64, LoongArch::F6_64, LoongArch::F7_64};
424 
425 // Implements the LoongArch calling convention. Returns true upon failure.
426 static bool CC_LoongArch(unsigned ValNo, MVT ValVT,
427                          CCValAssign::LocInfo LocInfo, CCState &State) {
428   // Allocate to a register if possible.
429   Register Reg;
430 
431   if (ValVT == MVT::f32)
432     Reg = State.AllocateReg(ArgFPR32s);
433   else if (ValVT == MVT::f64)
434     Reg = State.AllocateReg(ArgFPR64s);
435   else
436     Reg = State.AllocateReg(ArgGPRs);
437   if (Reg) {
438     State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, ValVT, LocInfo));
439     return false;
440   }
441 
442   // TODO: Handle arguments passed without register.
443   return true;
444 }
445 
446 void LoongArchTargetLowering::analyzeInputArgs(
447     CCState &CCInfo, const SmallVectorImpl<ISD::InputArg> &Ins,
448     LoongArchCCAssignFn Fn) const {
449   for (unsigned i = 0, e = Ins.size(); i != e; ++i) {
450     MVT ArgVT = Ins[i].VT;
451 
452     if (Fn(i, ArgVT, CCValAssign::Full, CCInfo)) {
453       LLVM_DEBUG(dbgs() << "InputArg #" << i << " has unhandled type "
454                         << EVT(ArgVT).getEVTString() << '\n');
455       llvm_unreachable("");
456     }
457   }
458 }
459 
460 void LoongArchTargetLowering::analyzeOutputArgs(
461     CCState &CCInfo, const SmallVectorImpl<ISD::OutputArg> &Outs,
462     LoongArchCCAssignFn Fn) const {
463   for (unsigned i = 0, e = Outs.size(); i != e; ++i) {
464     MVT ArgVT = Outs[i].VT;
465 
466     if (Fn(i, ArgVT, CCValAssign::Full, CCInfo)) {
467       LLVM_DEBUG(dbgs() << "OutputArg #" << i << " has unhandled type "
468                         << EVT(ArgVT).getEVTString() << "\n");
469       llvm_unreachable("");
470     }
471   }
472 }
473 
474 static SDValue unpackFromRegLoc(SelectionDAG &DAG, SDValue Chain,
475                                 const CCValAssign &VA, const SDLoc &DL,
476                                 const LoongArchTargetLowering &TLI) {
477   MachineFunction &MF = DAG.getMachineFunction();
478   MachineRegisterInfo &RegInfo = MF.getRegInfo();
479   EVT LocVT = VA.getLocVT();
480   const TargetRegisterClass *RC = TLI.getRegClassFor(LocVT.getSimpleVT());
481   Register VReg = RegInfo.createVirtualRegister(RC);
482   RegInfo.addLiveIn(VA.getLocReg(), VReg);
483 
484   return DAG.getCopyFromReg(Chain, DL, VReg, LocVT);
485 }
486 
487 // Transform physical registers into virtual registers.
488 SDValue LoongArchTargetLowering::LowerFormalArguments(
489     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
490     const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
491     SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
492 
493   MachineFunction &MF = DAG.getMachineFunction();
494 
495   switch (CallConv) {
496   default:
497     llvm_unreachable("Unsupported calling convention");
498   case CallingConv::C:
499     break;
500   }
501 
502   // Assign locations to all of the incoming arguments.
503   SmallVector<CCValAssign> ArgLocs;
504   CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
505 
506   analyzeInputArgs(CCInfo, Ins, CC_LoongArch);
507 
508   for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i)
509     InVals.push_back(unpackFromRegLoc(DAG, Chain, ArgLocs[i], DL, *this));
510 
511   return Chain;
512 }
513 
514 // Lower a call to a callseq_start + CALL + callseq_end chain, and add input
515 // and output parameter nodes.
516 SDValue
517 LoongArchTargetLowering::LowerCall(CallLoweringInfo &CLI,
518                                    SmallVectorImpl<SDValue> &InVals) const {
519   SelectionDAG &DAG = CLI.DAG;
520   SDLoc &DL = CLI.DL;
521   SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
522   SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
523   SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
524   SDValue Chain = CLI.Chain;
525   SDValue Callee = CLI.Callee;
526   CallingConv::ID CallConv = CLI.CallConv;
527   bool IsVarArg = CLI.IsVarArg;
528   EVT PtrVT = getPointerTy(DAG.getDataLayout());
529   CLI.IsTailCall = false;
530 
531   if (IsVarArg)
532     report_fatal_error("LowerCall with varargs not implemented");
533 
534   MachineFunction &MF = DAG.getMachineFunction();
535 
536   // Analyze the operands of the call, assigning locations to each operand.
537   SmallVector<CCValAssign> ArgLocs;
538   CCState ArgCCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
539 
540   analyzeOutputArgs(ArgCCInfo, Outs, CC_LoongArch);
541 
542   // Get a count of how many bytes are to be pushed on the stack.
543   unsigned NumBytes = ArgCCInfo.getNextStackOffset();
544 
545   for (auto &Arg : Outs) {
546     if (!Arg.Flags.isByVal())
547       continue;
548     report_fatal_error("Passing arguments byval not implemented");
549   }
550 
551   Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, CLI.DL);
552 
553   // Copy argument values to their designated locations.
554   SmallVector<std::pair<Register, SDValue>> RegsToPass;
555   for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
556     CCValAssign &VA = ArgLocs[i];
557     SDValue ArgValue = OutVals[i];
558 
559     // Promote the value if needed.
560     // For now, only handle fully promoted arguments.
561     if (VA.getLocInfo() != CCValAssign::Full)
562       report_fatal_error("Unknown loc info");
563 
564     if (VA.isRegLoc()) {
565       // Queue up the argument copies and emit them at the end.
566       RegsToPass.push_back(std::make_pair(VA.getLocReg(), ArgValue));
567     } else {
568       report_fatal_error("Passing arguments via the stack not implemented");
569     }
570   }
571 
572   SDValue Glue;
573 
574   // Build a sequence of copy-to-reg nodes, chained and glued together.
575   for (auto &Reg : RegsToPass) {
576     Chain = DAG.getCopyToReg(Chain, DL, Reg.first, Reg.second, Glue);
577     Glue = Chain.getValue(1);
578   }
579 
580   // If the callee is a GlobalAddress/ExternalSymbol node, turn it into a
581   // TargetGlobalAddress/TargetExternalSymbol node so that legalize won't
582   // split it and then direct call can be matched by PseudoCALL.
583   // FIXME: Add target flags for relocation.
584   if (GlobalAddressSDNode *S = dyn_cast<GlobalAddressSDNode>(Callee))
585     Callee = DAG.getTargetGlobalAddress(S->getGlobal(), DL, PtrVT);
586   else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
587     Callee = DAG.getTargetExternalSymbol(S->getSymbol(), PtrVT);
588 
589   // The first call operand is the chain and the second is the target address.
590   SmallVector<SDValue> Ops;
591   Ops.push_back(Chain);
592   Ops.push_back(Callee);
593 
594   // Add argument registers to the end of the list so that they are
595   // known live into the call.
596   for (auto &Reg : RegsToPass)
597     Ops.push_back(DAG.getRegister(Reg.first, Reg.second.getValueType()));
598 
599   // Add a register mask operand representing the call-preserved registers.
600   const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
601   const uint32_t *Mask = TRI->getCallPreservedMask(MF, CallConv);
602   assert(Mask && "Missing call preserved mask for calling convention");
603   Ops.push_back(DAG.getRegisterMask(Mask));
604 
605   // Glue the call to the argument copies, if any.
606   if (Glue.getNode())
607     Ops.push_back(Glue);
608 
609   // Emit the call.
610   SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
611 
612   Chain = DAG.getNode(LoongArchISD::CALL, DL, NodeTys, Ops);
613   DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.NoMerge);
614   Glue = Chain.getValue(1);
615 
616   // Mark the end of the call, which is glued to the call itself.
617   Chain = DAG.getCALLSEQ_END(Chain, DAG.getConstant(NumBytes, DL, PtrVT, true),
618                              DAG.getConstant(0, DL, PtrVT, true), Glue, DL);
619   Glue = Chain.getValue(1);
620 
621   // Assign locations to each value returned by this call.
622   SmallVector<CCValAssign> RVLocs;
623   CCState RetCCInfo(CallConv, IsVarArg, MF, RVLocs, *DAG.getContext());
624   analyzeInputArgs(RetCCInfo, Ins, CC_LoongArch);
625 
626   // Copy all of the result registers out of their specified physreg.
627   for (auto &VA : RVLocs) {
628     // Copy the value out.
629     SDValue RetValue =
630         DAG.getCopyFromReg(Chain, DL, VA.getLocReg(), VA.getLocVT(), Glue);
631     Chain = RetValue.getValue(1);
632     Glue = RetValue.getValue(2);
633 
634     InVals.push_back(Chain.getValue(0));
635   }
636 
637   return Chain;
638 }
639 
640 bool LoongArchTargetLowering::CanLowerReturn(
641     CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
642     const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const {
643   // Any return value split in to more than two values can't be returned
644   // directly.
645   return Outs.size() <= 2;
646 }
647 
648 SDValue LoongArchTargetLowering::LowerReturn(
649     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
650     const SmallVectorImpl<ISD::OutputArg> &Outs,
651     const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
652     SelectionDAG &DAG) const {
653   // Stores the assignment of the return value to a location.
654   SmallVector<CCValAssign> RVLocs;
655 
656   // Info about the registers and stack slot.
657   CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
658                  *DAG.getContext());
659 
660   analyzeOutputArgs(CCInfo, Outs, CC_LoongArch);
661 
662   SDValue Glue;
663   SmallVector<SDValue, 4> RetOps(1, Chain);
664 
665   // Copy the result values into the output registers.
666   for (unsigned i = 0, e = RVLocs.size(); i < e; ++i) {
667     CCValAssign &VA = RVLocs[i];
668     assert(VA.isRegLoc() && "Can only return in registers!");
669 
670     // Handle a 'normal' return.
671     Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVals[i], Glue);
672 
673     // Guarantee that all emitted copies are stuck together.
674     Glue = Chain.getValue(1);
675     RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
676   }
677 
678   RetOps[0] = Chain; // Update chain.
679 
680   // Add the glue node if we have it.
681   if (Glue.getNode())
682     RetOps.push_back(Glue);
683 
684   return DAG.getNode(LoongArchISD::RET, DL, MVT::Other, RetOps);
685 }
686