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 #include "llvm/Support/KnownBits.h"
25 
26 using namespace llvm;
27 
28 #define DEBUG_TYPE "loongarch-isel-lowering"
29 
30 static cl::opt<bool> ZeroDivCheck(
31     "loongarch-check-zero-division", cl::Hidden,
32     cl::desc("Trap on integer division by zero."),
33     cl::init(false));
34 
35 LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
36                                                  const LoongArchSubtarget &STI)
37     : TargetLowering(TM), Subtarget(STI) {
38 
39   MVT GRLenVT = Subtarget.getGRLenVT();
40   // Set up the register classes.
41   addRegisterClass(GRLenVT, &LoongArch::GPRRegClass);
42   if (Subtarget.hasBasicF())
43     addRegisterClass(MVT::f32, &LoongArch::FPR32RegClass);
44   if (Subtarget.hasBasicD())
45     addRegisterClass(MVT::f64, &LoongArch::FPR64RegClass);
46 
47   setLoadExtAction({ISD::EXTLOAD, ISD::SEXTLOAD, ISD::ZEXTLOAD}, GRLenVT,
48                    MVT::i1, Promote);
49 
50   // TODO: add necessary setOperationAction calls later.
51   setOperationAction(ISD::SHL_PARTS, GRLenVT, Custom);
52   setOperationAction(ISD::SRA_PARTS, GRLenVT, Custom);
53   setOperationAction(ISD::SRL_PARTS, GRLenVT, Custom);
54   setOperationAction(ISD::FP_TO_SINT, GRLenVT, Custom);
55 
56   setOperationAction({ISD::GlobalAddress, ISD::ConstantPool}, GRLenVT, Custom);
57 
58   if (Subtarget.is64Bit()) {
59     setOperationAction(ISD::SHL, MVT::i32, Custom);
60     setOperationAction(ISD::SRA, MVT::i32, Custom);
61     setOperationAction(ISD::SRL, MVT::i32, Custom);
62     setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
63     setOperationAction(ISD::BITCAST, MVT::i32, Custom);
64     if (Subtarget.hasBasicF() && !Subtarget.hasBasicD())
65       setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom);
66   }
67 
68   static const ISD::CondCode FPCCToExpand[] = {ISD::SETOGT, ISD::SETOGE,
69                                                ISD::SETUGT, ISD::SETUGE};
70 
71   if (Subtarget.hasBasicF()) {
72     setCondCodeAction(FPCCToExpand, MVT::f32, Expand);
73     setOperationAction(ISD::SELECT_CC, MVT::f32, Expand);
74   }
75   if (Subtarget.hasBasicD()) {
76     setCondCodeAction(FPCCToExpand, MVT::f64, Expand);
77     setOperationAction(ISD::SELECT_CC, MVT::f64, Expand);
78     setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f32, Expand);
79     setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f32, Expand);
80   }
81 
82   setOperationAction(ISD::BR_CC, GRLenVT, Expand);
83   setOperationAction(ISD::SELECT_CC, GRLenVT, Expand);
84   setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
85   setOperationAction({ISD::SMUL_LOHI, ISD::UMUL_LOHI}, GRLenVT, Expand);
86   if (!Subtarget.is64Bit())
87     setLibcallName(RTLIB::MUL_I128, nullptr);
88 
89   setOperationAction(ISD::FP_TO_UINT, GRLenVT, Custom);
90   setOperationAction(ISD::UINT_TO_FP, GRLenVT, Custom);
91 
92   // Compute derived properties from the register classes.
93   computeRegisterProperties(STI.getRegisterInfo());
94 
95   setStackPointerRegisterToSaveRestore(LoongArch::R3);
96 
97   setBooleanContents(ZeroOrOneBooleanContent);
98 
99   setMaxAtomicSizeInBitsSupported(Subtarget.getGRLen());
100 
101   // Function alignments.
102   const Align FunctionAlignment(4);
103   setMinFunctionAlignment(FunctionAlignment);
104 
105   setTargetDAGCombine(ISD::AND);
106   setTargetDAGCombine(ISD::OR);
107   setTargetDAGCombine(ISD::SRL);
108 }
109 
110 SDValue LoongArchTargetLowering::LowerOperation(SDValue Op,
111                                                 SelectionDAG &DAG) const {
112   switch (Op.getOpcode()) {
113   default:
114     report_fatal_error("unimplemented operand");
115   case ISD::GlobalAddress:
116     return lowerGlobalAddress(Op, DAG);
117   case ISD::SHL_PARTS:
118     return lowerShiftLeftParts(Op, DAG);
119   case ISD::SRA_PARTS:
120     return lowerShiftRightParts(Op, DAG, true);
121   case ISD::SRL_PARTS:
122     return lowerShiftRightParts(Op, DAG, false);
123   case ISD::SHL:
124   case ISD::SRA:
125   case ISD::SRL:
126     // This can be called for an i32 shift amount that needs to be promoted.
127     assert(Op.getOperand(1).getValueType() == MVT::i32 && Subtarget.is64Bit() &&
128            "Unexpected custom legalisation");
129     return SDValue();
130   case ISD::ConstantPool:
131     return lowerConstantPool(Op, DAG);
132   case ISD::FP_TO_SINT:
133     return lowerFP_TO_SINT(Op, DAG);
134   case ISD::BITCAST:
135     return lowerBITCAST(Op, DAG);
136   case ISD::FP_TO_UINT:
137     return SDValue();
138   case ISD::UINT_TO_FP:
139     return lowerUINT_TO_FP(Op, DAG);
140   }
141 }
142 
143 SDValue LoongArchTargetLowering::lowerUINT_TO_FP(SDValue Op,
144                                                  SelectionDAG &DAG) const {
145 
146   SDLoc DL(Op);
147   auto &TLI = DAG.getTargetLoweringInfo();
148   SDValue Tmp1, Tmp2;
149   SDValue Op1 = Op.getOperand(0);
150   if (Op1->getOpcode() == ISD::AssertZext ||
151       Op1->getOpcode() == ISD::AssertSext)
152     return Op;
153   SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Op.getOperand(0));
154   SDValue Res = DAG.getNode(ISD::UINT_TO_FP, DL, MVT::f64, Trunc);
155   SDNode *N = Res.getNode();
156   TLI.expandUINT_TO_FP(N, Tmp1, Tmp2, DAG);
157   return Tmp1;
158 }
159 
160 SDValue LoongArchTargetLowering::lowerBITCAST(SDValue Op,
161                                               SelectionDAG &DAG) const {
162 
163   SDLoc DL(Op);
164   SDValue Op0 = Op.getOperand(0);
165 
166   if (Op.getValueType() == MVT::f32 && Op0.getValueType() == MVT::i32 &&
167       Subtarget.is64Bit() && Subtarget.hasBasicF()) {
168     SDValue NewOp0 = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op0);
169     return DAG.getNode(LoongArchISD::MOVGR2FR_W_LA64, DL, MVT::f32, NewOp0);
170   }
171   return Op;
172 }
173 
174 SDValue LoongArchTargetLowering::lowerFP_TO_SINT(SDValue Op,
175                                                  SelectionDAG &DAG) const {
176 
177   SDLoc DL(Op);
178 
179   if (Op.getValueSizeInBits() > 32 && Subtarget.hasBasicF() &&
180       !Subtarget.hasBasicD()) {
181     SDValue Dst =
182         DAG.getNode(LoongArchISD::FTINT, DL, MVT::f32, Op.getOperand(0));
183     return DAG.getNode(LoongArchISD::MOVFR2GR_S_LA64, DL, MVT::i64, Dst);
184   }
185 
186   EVT FPTy = EVT::getFloatingPointVT(Op.getValueSizeInBits());
187   SDValue Trunc = DAG.getNode(LoongArchISD::FTINT, DL, FPTy, Op.getOperand(0));
188   return DAG.getNode(ISD::BITCAST, DL, Op.getValueType(), Trunc);
189 }
190 
191 SDValue LoongArchTargetLowering::lowerConstantPool(SDValue Op,
192                                                    SelectionDAG &DAG) const {
193   SDLoc DL(Op);
194   EVT Ty = Op.getValueType();
195   ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op);
196 
197   // FIXME: Only support PC-relative addressing to access the symbol.
198   // Target flags will be added later.
199   if (!isPositionIndependent()) {
200     SDValue ConstantN = DAG.getTargetConstantPool(
201         N->getConstVal(), Ty, N->getAlign(), N->getOffset());
202     SDValue AddrHi(DAG.getMachineNode(LoongArch::PCALAU12I, DL, Ty, ConstantN),
203                    0);
204     SDValue Addr(DAG.getMachineNode(Subtarget.is64Bit() ? LoongArch::ADDI_D
205                                                         : LoongArch::ADDI_W,
206                                     DL, Ty, AddrHi, ConstantN),
207                  0);
208     return Addr;
209   }
210   report_fatal_error("Unable to lower ConstantPool");
211 }
212 
213 SDValue LoongArchTargetLowering::lowerGlobalAddress(SDValue Op,
214                                                     SelectionDAG &DAG) const {
215   SDLoc DL(Op);
216   EVT Ty = getPointerTy(DAG.getDataLayout());
217   const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
218   unsigned ADDIOp = Subtarget.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
219 
220   // FIXME: Only support PC-relative addressing to access the symbol.
221   // TODO: Add target flags.
222   if (!isPositionIndependent()) {
223     SDValue GA = DAG.getTargetGlobalAddress(GV, DL, Ty);
224     SDValue AddrHi(DAG.getMachineNode(LoongArch::PCALAU12I, DL, Ty, GA), 0);
225     SDValue Addr(DAG.getMachineNode(ADDIOp, DL, Ty, AddrHi, GA), 0);
226     return Addr;
227   }
228   report_fatal_error("Unable to lowerGlobalAddress");
229 }
230 
231 SDValue LoongArchTargetLowering::lowerShiftLeftParts(SDValue Op,
232                                                      SelectionDAG &DAG) const {
233   SDLoc DL(Op);
234   SDValue Lo = Op.getOperand(0);
235   SDValue Hi = Op.getOperand(1);
236   SDValue Shamt = Op.getOperand(2);
237   EVT VT = Lo.getValueType();
238 
239   // if Shamt-GRLen < 0: // Shamt < GRLen
240   //   Lo = Lo << Shamt
241   //   Hi = (Hi << Shamt) | ((Lo >>u 1) >>u (GRLen-1 ^ Shamt))
242   // else:
243   //   Lo = 0
244   //   Hi = Lo << (Shamt-GRLen)
245 
246   SDValue Zero = DAG.getConstant(0, DL, VT);
247   SDValue One = DAG.getConstant(1, DL, VT);
248   SDValue MinusGRLen = DAG.getConstant(-(int)Subtarget.getGRLen(), DL, VT);
249   SDValue GRLenMinus1 = DAG.getConstant(Subtarget.getGRLen() - 1, DL, VT);
250   SDValue ShamtMinusGRLen = DAG.getNode(ISD::ADD, DL, VT, Shamt, MinusGRLen);
251   SDValue GRLenMinus1Shamt = DAG.getNode(ISD::XOR, DL, VT, Shamt, GRLenMinus1);
252 
253   SDValue LoTrue = DAG.getNode(ISD::SHL, DL, VT, Lo, Shamt);
254   SDValue ShiftRight1Lo = DAG.getNode(ISD::SRL, DL, VT, Lo, One);
255   SDValue ShiftRightLo =
256       DAG.getNode(ISD::SRL, DL, VT, ShiftRight1Lo, GRLenMinus1Shamt);
257   SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, VT, Hi, Shamt);
258   SDValue HiTrue = DAG.getNode(ISD::OR, DL, VT, ShiftLeftHi, ShiftRightLo);
259   SDValue HiFalse = DAG.getNode(ISD::SHL, DL, VT, Lo, ShamtMinusGRLen);
260 
261   SDValue CC = DAG.getSetCC(DL, VT, ShamtMinusGRLen, Zero, ISD::SETLT);
262 
263   Lo = DAG.getNode(ISD::SELECT, DL, VT, CC, LoTrue, Zero);
264   Hi = DAG.getNode(ISD::SELECT, DL, VT, CC, HiTrue, HiFalse);
265 
266   SDValue Parts[2] = {Lo, Hi};
267   return DAG.getMergeValues(Parts, DL);
268 }
269 
270 SDValue LoongArchTargetLowering::lowerShiftRightParts(SDValue Op,
271                                                       SelectionDAG &DAG,
272                                                       bool IsSRA) const {
273   SDLoc DL(Op);
274   SDValue Lo = Op.getOperand(0);
275   SDValue Hi = Op.getOperand(1);
276   SDValue Shamt = Op.getOperand(2);
277   EVT VT = Lo.getValueType();
278 
279   // SRA expansion:
280   //   if Shamt-GRLen < 0: // Shamt < GRLen
281   //     Lo = (Lo >>u Shamt) | ((Hi << 1) << (ShAmt ^ GRLen-1))
282   //     Hi = Hi >>s Shamt
283   //   else:
284   //     Lo = Hi >>s (Shamt-GRLen);
285   //     Hi = Hi >>s (GRLen-1)
286   //
287   // SRL expansion:
288   //   if Shamt-GRLen < 0: // Shamt < GRLen
289   //     Lo = (Lo >>u Shamt) | ((Hi << 1) << (ShAmt ^ GRLen-1))
290   //     Hi = Hi >>u Shamt
291   //   else:
292   //     Lo = Hi >>u (Shamt-GRLen);
293   //     Hi = 0;
294 
295   unsigned ShiftRightOp = IsSRA ? ISD::SRA : ISD::SRL;
296 
297   SDValue Zero = DAG.getConstant(0, DL, VT);
298   SDValue One = DAG.getConstant(1, DL, VT);
299   SDValue MinusGRLen = DAG.getConstant(-(int)Subtarget.getGRLen(), DL, VT);
300   SDValue GRLenMinus1 = DAG.getConstant(Subtarget.getGRLen() - 1, DL, VT);
301   SDValue ShamtMinusGRLen = DAG.getNode(ISD::ADD, DL, VT, Shamt, MinusGRLen);
302   SDValue GRLenMinus1Shamt = DAG.getNode(ISD::XOR, DL, VT, Shamt, GRLenMinus1);
303 
304   SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, VT, Lo, Shamt);
305   SDValue ShiftLeftHi1 = DAG.getNode(ISD::SHL, DL, VT, Hi, One);
306   SDValue ShiftLeftHi =
307       DAG.getNode(ISD::SHL, DL, VT, ShiftLeftHi1, GRLenMinus1Shamt);
308   SDValue LoTrue = DAG.getNode(ISD::OR, DL, VT, ShiftRightLo, ShiftLeftHi);
309   SDValue HiTrue = DAG.getNode(ShiftRightOp, DL, VT, Hi, Shamt);
310   SDValue LoFalse = DAG.getNode(ShiftRightOp, DL, VT, Hi, ShamtMinusGRLen);
311   SDValue HiFalse =
312       IsSRA ? DAG.getNode(ISD::SRA, DL, VT, Hi, GRLenMinus1) : Zero;
313 
314   SDValue CC = DAG.getSetCC(DL, VT, ShamtMinusGRLen, Zero, ISD::SETLT);
315 
316   Lo = DAG.getNode(ISD::SELECT, DL, VT, CC, LoTrue, LoFalse);
317   Hi = DAG.getNode(ISD::SELECT, DL, VT, CC, HiTrue, HiFalse);
318 
319   SDValue Parts[2] = {Lo, Hi};
320   return DAG.getMergeValues(Parts, DL);
321 }
322 
323 // Returns the opcode of the target-specific SDNode that implements the 32-bit
324 // form of the given Opcode.
325 static LoongArchISD::NodeType getLoongArchWOpcode(unsigned Opcode) {
326   switch (Opcode) {
327   default:
328     llvm_unreachable("Unexpected opcode");
329   case ISD::SHL:
330     return LoongArchISD::SLL_W;
331   case ISD::SRA:
332     return LoongArchISD::SRA_W;
333   case ISD::SRL:
334     return LoongArchISD::SRL_W;
335   }
336 }
337 
338 // Converts the given i8/i16/i32 operation to a target-specific SelectionDAG
339 // node. Because i8/i16/i32 isn't a legal type for LA64, these operations would
340 // otherwise be promoted to i64, making it difficult to select the
341 // SLL_W/.../*W later one because the fact the operation was originally of
342 // type i8/i16/i32 is lost.
343 static SDValue customLegalizeToWOp(SDNode *N, SelectionDAG &DAG,
344                                    unsigned ExtOpc = ISD::ANY_EXTEND) {
345   SDLoc DL(N);
346   LoongArchISD::NodeType WOpcode = getLoongArchWOpcode(N->getOpcode());
347   SDValue NewOp0 = DAG.getNode(ExtOpc, DL, MVT::i64, N->getOperand(0));
348   SDValue NewOp1 = DAG.getNode(ExtOpc, DL, MVT::i64, N->getOperand(1));
349   SDValue NewRes = DAG.getNode(WOpcode, DL, MVT::i64, NewOp0, NewOp1);
350   // ReplaceNodeResults requires we maintain the same type for the return value.
351   return DAG.getNode(ISD::TRUNCATE, DL, N->getValueType(0), NewRes);
352 }
353 
354 void LoongArchTargetLowering::ReplaceNodeResults(
355     SDNode *N, SmallVectorImpl<SDValue> &Results, SelectionDAG &DAG) const {
356   SDLoc DL(N);
357   switch (N->getOpcode()) {
358   default:
359     llvm_unreachable("Don't know how to legalize this operation");
360   case ISD::SHL:
361   case ISD::SRA:
362   case ISD::SRL:
363     assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
364            "Unexpected custom legalisation");
365     if (N->getOperand(1).getOpcode() != ISD::Constant) {
366       Results.push_back(customLegalizeToWOp(N, DAG));
367       break;
368     }
369     break;
370   case ISD::FP_TO_SINT: {
371     assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
372            "Unexpected custom legalisation");
373     SDValue Src = N->getOperand(0);
374     EVT VT = EVT::getFloatingPointVT(N->getValueSizeInBits(0));
375     SDValue Dst = DAG.getNode(LoongArchISD::FTINT, DL, VT, Src);
376     Results.push_back(DAG.getNode(ISD::BITCAST, DL, N->getValueType(0), Dst));
377     break;
378   }
379   case ISD::BITCAST: {
380     EVT VT = N->getValueType(0);
381     SDValue Src = N->getOperand(0);
382     EVT SrcVT = Src.getValueType();
383     if (VT == MVT::i32 && SrcVT == MVT::f32 && Subtarget.is64Bit() &&
384         Subtarget.hasBasicF()) {
385       SDValue Dst =
386           DAG.getNode(LoongArchISD::MOVFR2GR_S_LA64, DL, MVT::i64, Src);
387       Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Dst));
388     }
389     break;
390   }
391   case ISD::FP_TO_UINT: {
392     assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
393            "Unexpected custom legalisation");
394     auto &TLI = DAG.getTargetLoweringInfo();
395     SDValue Tmp1, Tmp2;
396     TLI.expandFP_TO_UINT(N, Tmp1, Tmp2, DAG);
397     Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Tmp1));
398     break;
399   }
400   }
401 }
402 
403 static SDValue performANDCombine(SDNode *N, SelectionDAG &DAG,
404                                  TargetLowering::DAGCombinerInfo &DCI,
405                                  const LoongArchSubtarget &Subtarget) {
406   if (DCI.isBeforeLegalizeOps())
407     return SDValue();
408 
409   SDValue FirstOperand = N->getOperand(0);
410   SDValue SecondOperand = N->getOperand(1);
411   unsigned FirstOperandOpc = FirstOperand.getOpcode();
412   EVT ValTy = N->getValueType(0);
413   SDLoc DL(N);
414   uint64_t lsb, msb;
415   unsigned SMIdx, SMLen;
416   ConstantSDNode *CN;
417   SDValue NewOperand;
418   MVT GRLenVT = Subtarget.getGRLenVT();
419 
420   // Op's second operand must be a shifted mask.
421   if (!(CN = dyn_cast<ConstantSDNode>(SecondOperand)) ||
422       !isShiftedMask_64(CN->getZExtValue(), SMIdx, SMLen))
423     return SDValue();
424 
425   if (FirstOperandOpc == ISD::SRA || FirstOperandOpc == ISD::SRL) {
426     // Pattern match BSTRPICK.
427     //  $dst = and ((sra or srl) $src , lsb), (2**len - 1)
428     //  => BSTRPICK $dst, $src, msb, lsb
429     //  where msb = lsb + len - 1
430 
431     // The second operand of the shift must be an immediate.
432     if (!(CN = dyn_cast<ConstantSDNode>(FirstOperand.getOperand(1))))
433       return SDValue();
434 
435     lsb = CN->getZExtValue();
436 
437     // Return if the shifted mask does not start at bit 0 or the sum of its
438     // length and lsb exceeds the word's size.
439     if (SMIdx != 0 || lsb + SMLen > ValTy.getSizeInBits())
440       return SDValue();
441 
442     NewOperand = FirstOperand.getOperand(0);
443   } else {
444     // Pattern match BSTRPICK.
445     //  $dst = and $src, (2**len- 1) , if len > 12
446     //  => BSTRPICK $dst, $src, msb, lsb
447     //  where lsb = 0 and msb = len - 1
448 
449     // If the mask is <= 0xfff, andi can be used instead.
450     if (CN->getZExtValue() <= 0xfff)
451       return SDValue();
452 
453     // Return if the mask doesn't start at position 0.
454     if (SMIdx)
455       return SDValue();
456 
457     lsb = 0;
458     NewOperand = FirstOperand;
459   }
460   msb = lsb + SMLen - 1;
461   return DAG.getNode(LoongArchISD::BSTRPICK, DL, ValTy, NewOperand,
462                      DAG.getConstant(msb, DL, GRLenVT),
463                      DAG.getConstant(lsb, DL, GRLenVT));
464 }
465 
466 static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG,
467                                  TargetLowering::DAGCombinerInfo &DCI,
468                                  const LoongArchSubtarget &Subtarget) {
469   if (DCI.isBeforeLegalizeOps())
470     return SDValue();
471 
472   // $dst = srl (and $src, Mask), Shamt
473   // =>
474   // BSTRPICK $dst, $src, MaskIdx+MaskLen-1, Shamt
475   // when Mask is a shifted mask, and MaskIdx <= Shamt <= MaskIdx+MaskLen-1
476   //
477 
478   SDValue FirstOperand = N->getOperand(0);
479   ConstantSDNode *CN;
480   EVT ValTy = N->getValueType(0);
481   SDLoc DL(N);
482   MVT GRLenVT = Subtarget.getGRLenVT();
483   unsigned MaskIdx, MaskLen;
484   uint64_t Shamt;
485 
486   // The first operand must be an AND and the second operand of the AND must be
487   // a shifted mask.
488   if (FirstOperand.getOpcode() != ISD::AND ||
489       !(CN = dyn_cast<ConstantSDNode>(FirstOperand.getOperand(1))) ||
490       !isShiftedMask_64(CN->getZExtValue(), MaskIdx, MaskLen))
491     return SDValue();
492 
493   // The second operand (shift amount) must be an immediate.
494   if (!(CN = dyn_cast<ConstantSDNode>(N->getOperand(1))))
495     return SDValue();
496 
497   Shamt = CN->getZExtValue();
498   if (MaskIdx <= Shamt && Shamt <= MaskIdx + MaskLen - 1)
499     return DAG.getNode(LoongArchISD::BSTRPICK, DL, ValTy,
500                        FirstOperand->getOperand(0),
501                        DAG.getConstant(MaskIdx + MaskLen - 1, DL, GRLenVT),
502                        DAG.getConstant(Shamt, DL, GRLenVT));
503 
504   return SDValue();
505 }
506 
507 static SDValue performORCombine(SDNode *N, SelectionDAG &DAG,
508                                 TargetLowering::DAGCombinerInfo &DCI,
509                                 const LoongArchSubtarget &Subtarget) {
510   MVT GRLenVT = Subtarget.getGRLenVT();
511   EVT ValTy = N->getValueType(0);
512   SDValue N0 = N->getOperand(0), N1 = N->getOperand(1);
513   ConstantSDNode *CN0, *CN1;
514   SDLoc DL(N);
515   unsigned ValBits = ValTy.getSizeInBits();
516   unsigned MaskIdx0, MaskLen0, MaskIdx1, MaskLen1;
517   unsigned Shamt;
518   bool SwapAndRetried = false;
519 
520   if (DCI.isBeforeLegalizeOps())
521     return SDValue();
522 
523   if (ValBits != 32 && ValBits != 64)
524     return SDValue();
525 
526 Retry:
527   // 1st pattern to match BSTRINS:
528   //  R = or (and X, mask0), (and (shl Y, lsb), mask1)
529   //  where mask1 = (2**size - 1) << lsb, mask0 = ~mask1
530   //  =>
531   //  R = BSTRINS X, Y, msb, lsb (where msb = lsb + size - 1)
532   if (N0.getOpcode() == ISD::AND &&
533       (CN0 = dyn_cast<ConstantSDNode>(N0.getOperand(1))) &&
534       isShiftedMask_64(~CN0->getSExtValue(), MaskIdx0, MaskLen0) &&
535       N1.getOpcode() == ISD::AND && N1.getOperand(0).getOpcode() == ISD::SHL &&
536       (CN1 = dyn_cast<ConstantSDNode>(N1.getOperand(1))) &&
537       isShiftedMask_64(CN1->getZExtValue(), MaskIdx1, MaskLen1) &&
538       MaskIdx0 == MaskIdx1 && MaskLen0 == MaskLen1 &&
539       (CN1 = dyn_cast<ConstantSDNode>(N1.getOperand(0).getOperand(1))) &&
540       (Shamt = CN1->getZExtValue()) == MaskIdx0 &&
541       (MaskIdx0 + MaskLen0 <= ValBits)) {
542     LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 1\n");
543     return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0.getOperand(0),
544                        N1.getOperand(0).getOperand(0),
545                        DAG.getConstant((MaskIdx0 + MaskLen0 - 1), DL, GRLenVT),
546                        DAG.getConstant(MaskIdx0, DL, GRLenVT));
547   }
548 
549   // 2nd pattern to match BSTRINS:
550   //  R = or (and X, mask0), (shl (and Y, mask1), lsb)
551   //  where mask1 = (2**size - 1), mask0 = ~(mask1 << lsb)
552   //  =>
553   //  R = BSTRINS X, Y, msb, lsb (where msb = lsb + size - 1)
554   if (N0.getOpcode() == ISD::AND &&
555       (CN0 = dyn_cast<ConstantSDNode>(N0.getOperand(1))) &&
556       isShiftedMask_64(~CN0->getSExtValue(), MaskIdx0, MaskLen0) &&
557       N1.getOpcode() == ISD::SHL && N1.getOperand(0).getOpcode() == ISD::AND &&
558       (CN1 = dyn_cast<ConstantSDNode>(N1.getOperand(1))) &&
559       (Shamt = CN1->getZExtValue()) == MaskIdx0 &&
560       (CN1 = dyn_cast<ConstantSDNode>(N1.getOperand(0).getOperand(1))) &&
561       isShiftedMask_64(CN1->getZExtValue(), MaskIdx1, MaskLen1) &&
562       MaskLen0 == MaskLen1 && MaskIdx1 == 0 &&
563       (MaskIdx0 + MaskLen0 <= ValBits)) {
564     LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 2\n");
565     return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0.getOperand(0),
566                        N1.getOperand(0).getOperand(0),
567                        DAG.getConstant((MaskIdx0 + MaskLen0 - 1), DL, GRLenVT),
568                        DAG.getConstant(MaskIdx0, DL, GRLenVT));
569   }
570 
571   // 3rd pattern to match BSTRINS:
572   //  R = or (and X, mask0), (and Y, mask1)
573   //  where ~mask0 = (2**size - 1) << lsb, mask0 & mask1 = 0
574   //  =>
575   //  R = BSTRINS X, (shr (and Y, mask1), lsb), msb, lsb
576   //  where msb = lsb + size - 1
577   if (N0.getOpcode() == ISD::AND && N1.getOpcode() == ISD::AND &&
578       (CN0 = dyn_cast<ConstantSDNode>(N0.getOperand(1))) &&
579       isShiftedMask_64(~CN0->getSExtValue(), MaskIdx0, MaskLen0) &&
580       (MaskIdx0 + MaskLen0 <= 64) &&
581       (CN1 = dyn_cast<ConstantSDNode>(N1->getOperand(1))) &&
582       (CN1->getSExtValue() & CN0->getSExtValue()) == 0) {
583     LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 3\n");
584     return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0.getOperand(0),
585                        DAG.getNode(ISD::SRL, DL, N1->getValueType(0), N1,
586                                    DAG.getConstant(MaskIdx0, DL, GRLenVT)),
587                        DAG.getConstant(ValBits == 32
588                                            ? (MaskIdx0 + (MaskLen0 & 31) - 1)
589                                            : (MaskIdx0 + MaskLen0 - 1),
590                                        DL, GRLenVT),
591                        DAG.getConstant(MaskIdx0, DL, GRLenVT));
592   }
593 
594   // 4th pattern to match BSTRINS:
595   //  R = or (and X, mask), (shl Y, shamt)
596   //  where mask = (2**shamt - 1)
597   //  =>
598   //  R = BSTRINS X, Y, ValBits - 1, shamt
599   //  where ValBits = 32 or 64
600   if (N0.getOpcode() == ISD::AND && N1.getOpcode() == ISD::SHL &&
601       (CN0 = dyn_cast<ConstantSDNode>(N0.getOperand(1))) &&
602       isShiftedMask_64(CN0->getZExtValue(), MaskIdx0, MaskLen0) &&
603       MaskIdx0 == 0 && (CN1 = dyn_cast<ConstantSDNode>(N1.getOperand(1))) &&
604       (Shamt = CN1->getZExtValue()) == MaskLen0 &&
605       (MaskIdx0 + MaskLen0 <= ValBits)) {
606     LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 4\n");
607     return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0.getOperand(0),
608                        N1.getOperand(0),
609                        DAG.getConstant((ValBits - 1), DL, GRLenVT),
610                        DAG.getConstant(Shamt, DL, GRLenVT));
611   }
612 
613   // 5th pattern to match BSTRINS:
614   //  R = or (and X, mask), const
615   //  where ~mask = (2**size - 1) << lsb, mask & const = 0
616   //  =>
617   //  R = BSTRINS X, (const >> lsb), msb, lsb
618   //  where msb = lsb + size - 1
619   if (N0.getOpcode() == ISD::AND &&
620       (CN0 = dyn_cast<ConstantSDNode>(N0.getOperand(1))) &&
621       isShiftedMask_64(~CN0->getSExtValue(), MaskIdx0, MaskLen0) &&
622       (CN1 = dyn_cast<ConstantSDNode>(N1)) &&
623       (CN1->getSExtValue() & CN0->getSExtValue()) == 0) {
624     LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 5\n");
625     return DAG.getNode(
626         LoongArchISD::BSTRINS, DL, ValTy, N0.getOperand(0),
627         DAG.getConstant(CN1->getSExtValue() >> MaskIdx0, DL, ValTy),
628         DAG.getConstant((MaskIdx0 + MaskLen0 - 1), DL, GRLenVT),
629         DAG.getConstant(MaskIdx0, DL, GRLenVT));
630   }
631 
632   // 6th pattern.
633   // a = b | ((c & mask) << shamt), where all positions in b to be overwritten
634   // by the incoming bits are known to be zero.
635   // =>
636   // a = BSTRINS b, c, shamt + MaskLen - 1, shamt
637   //
638   // Note that the 1st pattern is a special situation of the 6th, i.e. the 6th
639   // pattern is more common than the 1st. So we put the 1st before the 6th in
640   // order to match as many nodes as possible.
641   ConstantSDNode *CNMask, *CNShamt;
642   unsigned MaskIdx, MaskLen;
643   if (N1.getOpcode() == ISD::SHL && N1.getOperand(0).getOpcode() == ISD::AND &&
644       (CNMask = dyn_cast<ConstantSDNode>(N1.getOperand(0).getOperand(1))) &&
645       isShiftedMask_64(CNMask->getZExtValue(), MaskIdx, MaskLen) &&
646       MaskIdx == 0 && (CNShamt = dyn_cast<ConstantSDNode>(N1.getOperand(1))) &&
647       CNShamt->getZExtValue() + MaskLen <= ValBits) {
648     Shamt = CNShamt->getZExtValue();
649     APInt ShMask(ValBits, CNMask->getZExtValue() << Shamt);
650     if (ShMask.isSubsetOf(DAG.computeKnownBits(N0).Zero)) {
651       LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 6\n");
652       return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0,
653                          N1.getOperand(0).getOperand(0),
654                          DAG.getConstant(Shamt + MaskLen - 1, DL, GRLenVT),
655                          DAG.getConstant(Shamt, DL, GRLenVT));
656     }
657   }
658 
659   // 7th pattern.
660   // a = b | ((c << shamt) & shifted_mask), where all positions in b to be
661   // overwritten by the incoming bits are known to be zero.
662   // =>
663   // a = BSTRINS b, c, MaskIdx + MaskLen - 1, MaskIdx
664   //
665   // Similarly, the 7th pattern is more common than the 2nd. So we put the 2nd
666   // before the 7th in order to match as many nodes as possible.
667   if (N1.getOpcode() == ISD::AND &&
668       (CNMask = dyn_cast<ConstantSDNode>(N1.getOperand(1))) &&
669       isShiftedMask_64(CNMask->getZExtValue(), MaskIdx, MaskLen) &&
670       N1.getOperand(0).getOpcode() == ISD::SHL &&
671       (CNShamt = dyn_cast<ConstantSDNode>(N1.getOperand(0).getOperand(1))) &&
672       CNShamt->getZExtValue() == MaskIdx) {
673     APInt ShMask(ValBits, CNMask->getZExtValue());
674     if (ShMask.isSubsetOf(DAG.computeKnownBits(N0).Zero)) {
675       LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 7\n");
676       return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0,
677                          N1.getOperand(0).getOperand(0),
678                          DAG.getConstant(MaskIdx + MaskLen - 1, DL, GRLenVT),
679                          DAG.getConstant(MaskIdx, DL, GRLenVT));
680     }
681   }
682 
683   // (or a, b) and (or b, a) are equivalent, so swap the operands and retry.
684   if (!SwapAndRetried) {
685     std::swap(N0, N1);
686     SwapAndRetried = true;
687     goto Retry;
688   }
689 
690   SwapAndRetried = false;
691 Retry2:
692   // 8th pattern.
693   // a = b | (c & shifted_mask), where all positions in b to be overwritten by
694   // the incoming bits are known to be zero.
695   // =>
696   // a = BSTRINS b, c >> MaskIdx, MaskIdx + MaskLen - 1, MaskIdx
697   //
698   // Similarly, the 8th pattern is more common than the 4th and 5th patterns. So
699   // we put it here in order to match as many nodes as possible or generate less
700   // instructions.
701   if (N1.getOpcode() == ISD::AND &&
702       (CNMask = dyn_cast<ConstantSDNode>(N1.getOperand(1))) &&
703       isShiftedMask_64(CNMask->getZExtValue(), MaskIdx, MaskLen)) {
704     APInt ShMask(ValBits, CNMask->getZExtValue());
705     if (ShMask.isSubsetOf(DAG.computeKnownBits(N0).Zero)) {
706       LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 8\n");
707       return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0,
708                          DAG.getNode(ISD::SRL, DL, N1->getValueType(0),
709                                      N1->getOperand(0),
710                                      DAG.getConstant(MaskIdx, DL, GRLenVT)),
711                          DAG.getConstant(MaskIdx + MaskLen - 1, DL, GRLenVT),
712                          DAG.getConstant(MaskIdx, DL, GRLenVT));
713     }
714   }
715   // Swap N0/N1 and retry.
716   if (!SwapAndRetried) {
717     std::swap(N0, N1);
718     SwapAndRetried = true;
719     goto Retry2;
720   }
721 
722   return SDValue();
723 }
724 
725 SDValue LoongArchTargetLowering::PerformDAGCombine(SDNode *N,
726                                                    DAGCombinerInfo &DCI) const {
727   SelectionDAG &DAG = DCI.DAG;
728   switch (N->getOpcode()) {
729   default:
730     break;
731   case ISD::AND:
732     return performANDCombine(N, DAG, DCI, Subtarget);
733   case ISD::OR:
734     return performORCombine(N, DAG, DCI, Subtarget);
735   case ISD::SRL:
736     return performSRLCombine(N, DAG, DCI, Subtarget);
737   }
738   return SDValue();
739 }
740 
741 static MachineBasicBlock *insertDivByZeroTrap(MachineInstr &MI,
742                                               MachineBasicBlock &MBB,
743                                               const TargetInstrInfo &TII) {
744   if (!ZeroDivCheck)
745     return &MBB;
746 
747   // Build instructions:
748   //   div(or mod)   $dst, $dividend, $divisor
749   //   bnez          $divisor, 8
750   //   break         7
751   //   fallthrough
752   MachineOperand &Divisor = MI.getOperand(2);
753   auto FallThrough = std::next(MI.getIterator());
754 
755   BuildMI(MBB, FallThrough, MI.getDebugLoc(), TII.get(LoongArch::BNEZ))
756       .addReg(Divisor.getReg(), getKillRegState(Divisor.isKill()))
757       .addImm(8);
758 
759   // See linux header file arch/loongarch/include/uapi/asm/break.h for the
760   // definition of BRK_DIVZERO.
761   BuildMI(MBB, FallThrough, MI.getDebugLoc(), TII.get(LoongArch::BREAK))
762       .addImm(7/*BRK_DIVZERO*/);
763 
764   // Clear Divisor's kill flag.
765   Divisor.setIsKill(false);
766 
767   return &MBB;
768 }
769 
770 MachineBasicBlock *LoongArchTargetLowering::EmitInstrWithCustomInserter(
771     MachineInstr &MI, MachineBasicBlock *BB) const {
772 
773   switch (MI.getOpcode()) {
774   default:
775     llvm_unreachable("Unexpected instr type to insert");
776   case LoongArch::DIV_W:
777   case LoongArch::DIV_WU:
778   case LoongArch::MOD_W:
779   case LoongArch::MOD_WU:
780   case LoongArch::DIV_D:
781   case LoongArch::DIV_DU:
782   case LoongArch::MOD_D:
783   case LoongArch::MOD_DU:
784     return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo());
785     break;
786   }
787 }
788 
789 const char *LoongArchTargetLowering::getTargetNodeName(unsigned Opcode) const {
790   switch ((LoongArchISD::NodeType)Opcode) {
791   case LoongArchISD::FIRST_NUMBER:
792     break;
793 
794 #define NODE_NAME_CASE(node)                                                   \
795   case LoongArchISD::node:                                                     \
796     return "LoongArchISD::" #node;
797 
798     // TODO: Add more target-dependent nodes later.
799     NODE_NAME_CASE(CALL)
800     NODE_NAME_CASE(RET)
801     NODE_NAME_CASE(SLL_W)
802     NODE_NAME_CASE(SRA_W)
803     NODE_NAME_CASE(SRL_W)
804     NODE_NAME_CASE(BSTRINS)
805     NODE_NAME_CASE(BSTRPICK)
806     NODE_NAME_CASE(MOVGR2FR_W_LA64)
807     NODE_NAME_CASE(MOVFR2GR_S_LA64)
808     NODE_NAME_CASE(FTINT)
809   }
810 #undef NODE_NAME_CASE
811   return nullptr;
812 }
813 
814 //===----------------------------------------------------------------------===//
815 //                     Calling Convention Implementation
816 //===----------------------------------------------------------------------===//
817 // FIXME: Now, we only support CallingConv::C with fixed arguments which are
818 // passed with integer or floating-point registers.
819 const MCPhysReg ArgGPRs[] = {LoongArch::R4,  LoongArch::R5, LoongArch::R6,
820                              LoongArch::R7,  LoongArch::R8, LoongArch::R9,
821                              LoongArch::R10, LoongArch::R11};
822 const MCPhysReg ArgFPR32s[] = {LoongArch::F0, LoongArch::F1, LoongArch::F2,
823                                LoongArch::F3, LoongArch::F4, LoongArch::F5,
824                                LoongArch::F6, LoongArch::F7};
825 const MCPhysReg ArgFPR64s[] = {
826     LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, LoongArch::F3_64,
827     LoongArch::F4_64, LoongArch::F5_64, LoongArch::F6_64, LoongArch::F7_64};
828 
829 // Implements the LoongArch calling convention. Returns true upon failure.
830 static bool CC_LoongArch(unsigned ValNo, MVT ValVT,
831                          CCValAssign::LocInfo LocInfo, CCState &State) {
832   // Allocate to a register if possible.
833   Register Reg;
834 
835   if (ValVT == MVT::f32)
836     Reg = State.AllocateReg(ArgFPR32s);
837   else if (ValVT == MVT::f64)
838     Reg = State.AllocateReg(ArgFPR64s);
839   else
840     Reg = State.AllocateReg(ArgGPRs);
841   if (Reg) {
842     State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, ValVT, LocInfo));
843     return false;
844   }
845 
846   // TODO: Handle arguments passed without register.
847   return true;
848 }
849 
850 void LoongArchTargetLowering::analyzeInputArgs(
851     CCState &CCInfo, const SmallVectorImpl<ISD::InputArg> &Ins,
852     LoongArchCCAssignFn Fn) const {
853   for (unsigned i = 0, e = Ins.size(); i != e; ++i) {
854     MVT ArgVT = Ins[i].VT;
855 
856     if (Fn(i, ArgVT, CCValAssign::Full, CCInfo)) {
857       LLVM_DEBUG(dbgs() << "InputArg #" << i << " has unhandled type "
858                         << EVT(ArgVT).getEVTString() << '\n');
859       llvm_unreachable("");
860     }
861   }
862 }
863 
864 void LoongArchTargetLowering::analyzeOutputArgs(
865     CCState &CCInfo, const SmallVectorImpl<ISD::OutputArg> &Outs,
866     LoongArchCCAssignFn Fn) const {
867   for (unsigned i = 0, e = Outs.size(); i != e; ++i) {
868     MVT ArgVT = Outs[i].VT;
869 
870     if (Fn(i, ArgVT, CCValAssign::Full, CCInfo)) {
871       LLVM_DEBUG(dbgs() << "OutputArg #" << i << " has unhandled type "
872                         << EVT(ArgVT).getEVTString() << "\n");
873       llvm_unreachable("");
874     }
875   }
876 }
877 
878 static SDValue unpackFromRegLoc(SelectionDAG &DAG, SDValue Chain,
879                                 const CCValAssign &VA, const SDLoc &DL,
880                                 const LoongArchTargetLowering &TLI) {
881   MachineFunction &MF = DAG.getMachineFunction();
882   MachineRegisterInfo &RegInfo = MF.getRegInfo();
883   EVT LocVT = VA.getLocVT();
884   const TargetRegisterClass *RC = TLI.getRegClassFor(LocVT.getSimpleVT());
885   Register VReg = RegInfo.createVirtualRegister(RC);
886   RegInfo.addLiveIn(VA.getLocReg(), VReg);
887 
888   return DAG.getCopyFromReg(Chain, DL, VReg, LocVT);
889 }
890 
891 // Transform physical registers into virtual registers.
892 SDValue LoongArchTargetLowering::LowerFormalArguments(
893     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
894     const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
895     SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
896 
897   MachineFunction &MF = DAG.getMachineFunction();
898 
899   switch (CallConv) {
900   default:
901     llvm_unreachable("Unsupported calling convention");
902   case CallingConv::C:
903     break;
904   }
905 
906   // Assign locations to all of the incoming arguments.
907   SmallVector<CCValAssign> ArgLocs;
908   CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
909 
910   analyzeInputArgs(CCInfo, Ins, CC_LoongArch);
911 
912   for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i)
913     InVals.push_back(unpackFromRegLoc(DAG, Chain, ArgLocs[i], DL, *this));
914 
915   return Chain;
916 }
917 
918 // Lower a call to a callseq_start + CALL + callseq_end chain, and add input
919 // and output parameter nodes.
920 SDValue
921 LoongArchTargetLowering::LowerCall(CallLoweringInfo &CLI,
922                                    SmallVectorImpl<SDValue> &InVals) const {
923   SelectionDAG &DAG = CLI.DAG;
924   SDLoc &DL = CLI.DL;
925   SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
926   SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
927   SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
928   SDValue Chain = CLI.Chain;
929   SDValue Callee = CLI.Callee;
930   CallingConv::ID CallConv = CLI.CallConv;
931   bool IsVarArg = CLI.IsVarArg;
932   EVT PtrVT = getPointerTy(DAG.getDataLayout());
933   CLI.IsTailCall = false;
934 
935   if (IsVarArg)
936     report_fatal_error("LowerCall with varargs not implemented");
937 
938   MachineFunction &MF = DAG.getMachineFunction();
939 
940   // Analyze the operands of the call, assigning locations to each operand.
941   SmallVector<CCValAssign> ArgLocs;
942   CCState ArgCCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
943 
944   analyzeOutputArgs(ArgCCInfo, Outs, CC_LoongArch);
945 
946   // Get a count of how many bytes are to be pushed on the stack.
947   unsigned NumBytes = ArgCCInfo.getNextStackOffset();
948 
949   for (auto &Arg : Outs) {
950     if (!Arg.Flags.isByVal())
951       continue;
952     report_fatal_error("Passing arguments byval not implemented");
953   }
954 
955   Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, CLI.DL);
956 
957   // Copy argument values to their designated locations.
958   SmallVector<std::pair<Register, SDValue>> RegsToPass;
959   for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
960     CCValAssign &VA = ArgLocs[i];
961     SDValue ArgValue = OutVals[i];
962 
963     // Promote the value if needed.
964     // For now, only handle fully promoted arguments.
965     if (VA.getLocInfo() != CCValAssign::Full)
966       report_fatal_error("Unknown loc info");
967 
968     if (VA.isRegLoc()) {
969       // Queue up the argument copies and emit them at the end.
970       RegsToPass.push_back(std::make_pair(VA.getLocReg(), ArgValue));
971     } else {
972       report_fatal_error("Passing arguments via the stack not implemented");
973     }
974   }
975 
976   SDValue Glue;
977 
978   // Build a sequence of copy-to-reg nodes, chained and glued together.
979   for (auto &Reg : RegsToPass) {
980     Chain = DAG.getCopyToReg(Chain, DL, Reg.first, Reg.second, Glue);
981     Glue = Chain.getValue(1);
982   }
983 
984   // If the callee is a GlobalAddress/ExternalSymbol node, turn it into a
985   // TargetGlobalAddress/TargetExternalSymbol node so that legalize won't
986   // split it and then direct call can be matched by PseudoCALL.
987   // FIXME: Add target flags for relocation.
988   if (GlobalAddressSDNode *S = dyn_cast<GlobalAddressSDNode>(Callee))
989     Callee = DAG.getTargetGlobalAddress(S->getGlobal(), DL, PtrVT);
990   else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
991     Callee = DAG.getTargetExternalSymbol(S->getSymbol(), PtrVT);
992 
993   // The first call operand is the chain and the second is the target address.
994   SmallVector<SDValue> Ops;
995   Ops.push_back(Chain);
996   Ops.push_back(Callee);
997 
998   // Add argument registers to the end of the list so that they are
999   // known live into the call.
1000   for (auto &Reg : RegsToPass)
1001     Ops.push_back(DAG.getRegister(Reg.first, Reg.second.getValueType()));
1002 
1003   // Add a register mask operand representing the call-preserved registers.
1004   const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
1005   const uint32_t *Mask = TRI->getCallPreservedMask(MF, CallConv);
1006   assert(Mask && "Missing call preserved mask for calling convention");
1007   Ops.push_back(DAG.getRegisterMask(Mask));
1008 
1009   // Glue the call to the argument copies, if any.
1010   if (Glue.getNode())
1011     Ops.push_back(Glue);
1012 
1013   // Emit the call.
1014   SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
1015 
1016   Chain = DAG.getNode(LoongArchISD::CALL, DL, NodeTys, Ops);
1017   DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.NoMerge);
1018   Glue = Chain.getValue(1);
1019 
1020   // Mark the end of the call, which is glued to the call itself.
1021   Chain = DAG.getCALLSEQ_END(Chain, DAG.getConstant(NumBytes, DL, PtrVT, true),
1022                              DAG.getConstant(0, DL, PtrVT, true), Glue, DL);
1023   Glue = Chain.getValue(1);
1024 
1025   // Assign locations to each value returned by this call.
1026   SmallVector<CCValAssign> RVLocs;
1027   CCState RetCCInfo(CallConv, IsVarArg, MF, RVLocs, *DAG.getContext());
1028   analyzeInputArgs(RetCCInfo, Ins, CC_LoongArch);
1029 
1030   // Copy all of the result registers out of their specified physreg.
1031   for (auto &VA : RVLocs) {
1032     // Copy the value out.
1033     SDValue RetValue =
1034         DAG.getCopyFromReg(Chain, DL, VA.getLocReg(), VA.getLocVT(), Glue);
1035     Chain = RetValue.getValue(1);
1036     Glue = RetValue.getValue(2);
1037 
1038     InVals.push_back(Chain.getValue(0));
1039   }
1040 
1041   return Chain;
1042 }
1043 
1044 bool LoongArchTargetLowering::CanLowerReturn(
1045     CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
1046     const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const {
1047   // Any return value split in to more than two values can't be returned
1048   // directly.
1049   return Outs.size() <= 2;
1050 }
1051 
1052 SDValue LoongArchTargetLowering::LowerReturn(
1053     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
1054     const SmallVectorImpl<ISD::OutputArg> &Outs,
1055     const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
1056     SelectionDAG &DAG) const {
1057   // Stores the assignment of the return value to a location.
1058   SmallVector<CCValAssign> RVLocs;
1059 
1060   // Info about the registers and stack slot.
1061   CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
1062                  *DAG.getContext());
1063 
1064   analyzeOutputArgs(CCInfo, Outs, CC_LoongArch);
1065 
1066   SDValue Glue;
1067   SmallVector<SDValue, 4> RetOps(1, Chain);
1068 
1069   // Copy the result values into the output registers.
1070   for (unsigned i = 0, e = RVLocs.size(); i < e; ++i) {
1071     CCValAssign &VA = RVLocs[i];
1072     assert(VA.isRegLoc() && "Can only return in registers!");
1073 
1074     // Handle a 'normal' return.
1075     Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVals[i], Glue);
1076 
1077     // Guarantee that all emitted copies are stuck together.
1078     Glue = Chain.getValue(1);
1079     RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
1080   }
1081 
1082   RetOps[0] = Chain; // Update chain.
1083 
1084   // Add the glue node if we have it.
1085   if (Glue.getNode())
1086     RetOps.push_back(Glue);
1087 
1088   return DAG.getNode(LoongArchISD::RET, DL, MVT::Other, RetOps);
1089 }
1090 
1091 bool LoongArchTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT,
1092                                            bool ForCodeSize) const {
1093   assert((VT == MVT::f32 || VT == MVT::f64) && "Unexpected VT");
1094 
1095   if (VT == MVT::f32 && !Subtarget.hasBasicF())
1096     return false;
1097   if (VT == MVT::f64 && !Subtarget.hasBasicD())
1098     return false;
1099   return (Imm.isZero() || Imm.isExactlyValue(+1.0));
1100 }
1101