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