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