xref: /freebsd/contrib/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelLowering.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //=- LoongArchISelLowering.h - LoongArch DAG Lowering Interface -*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the interfaces that LoongArch uses to lower LLVM code into
10 // a selection DAG.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELLOWERING_H
15 #define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELLOWERING_H
16 
17 #include "LoongArch.h"
18 #include "llvm/CodeGen/CallingConvLower.h"
19 #include "llvm/CodeGen/SelectionDAG.h"
20 #include "llvm/CodeGen/TargetLowering.h"
21 
22 namespace llvm {
23 class LoongArchSubtarget;
24 namespace LoongArchISD {
25 enum NodeType : unsigned {
26   FIRST_NUMBER = ISD::BUILTIN_OP_END,
27 
28   // TODO: add more LoongArchISDs
29   CALL,
30   CALL_MEDIUM,
31   CALL_LARGE,
32   RET,
33   TAIL,
34   TAIL_MEDIUM,
35   TAIL_LARGE,
36 
37   // Select
38   SELECT_CC,
39 
40   // 32-bit shifts, directly matching the semantics of the named LoongArch
41   // instructions.
42   SLL_W,
43   SRA_W,
44   SRL_W,
45 
46   ROTL_W,
47   ROTR_W,
48 
49   // unsigned 32-bit integer division
50   DIV_W,
51   MOD_W,
52   DIV_WU,
53   MOD_WU,
54 
55   // FPR<->GPR transfer operations
56   MOVGR2FR_W_LA64,
57   MOVFR2GR_S_LA64,
58   MOVFCSR2GR,
59   MOVGR2FCSR,
60 
61   FTINT,
62 
63   // Build and split F64 pair
64   BUILD_PAIR_F64,
65   SPLIT_PAIR_F64,
66 
67   // Bit counting operations
68   CLZ_W,
69   CTZ_W,
70 
71   BSTRINS,
72   BSTRPICK,
73 
74   // Byte-swapping and bit-reversal
75   REVB_2H,
76   REVB_2W,
77   BITREV_4B,
78   BITREV_8B,
79   BITREV_W,
80 
81   // Intrinsic operations start ============================================
82   BREAK,
83   CACOP_D,
84   CACOP_W,
85   DBAR,
86   IBAR,
87   SYSCALL,
88 
89   // CRC check operations
90   CRC_W_B_W,
91   CRC_W_H_W,
92   CRC_W_W_W,
93   CRC_W_D_W,
94   CRCC_W_B_W,
95   CRCC_W_H_W,
96   CRCC_W_W_W,
97   CRCC_W_D_W,
98 
99   CSRRD,
100 
101   // Write new value to CSR and return old value.
102   // Operand 0: A chain pointer.
103   // Operand 1: The new value to write.
104   // Operand 2: The address of the required CSR.
105   // Result 0: The old value of the CSR.
106   // Result 1: The new chain pointer.
107   CSRWR,
108 
109   // Similar to CSRWR but with a write mask.
110   // Operand 0: A chain pointer.
111   // Operand 1: The new value to write.
112   // Operand 2: The write mask.
113   // Operand 3: The address of the required CSR.
114   // Result 0: The old value of the CSR.
115   // Result 1: The new chain pointer.
116   CSRXCHG,
117 
118   // IOCSR access operations
119   IOCSRRD_B,
120   IOCSRRD_W,
121   IOCSRRD_H,
122   IOCSRRD_D,
123   IOCSRWR_B,
124   IOCSRWR_H,
125   IOCSRWR_W,
126   IOCSRWR_D,
127 
128   // Read CPU configuration information operation
129   CPUCFG,
130 
131   // Vector Shuffle
132   VREPLVE,
133   VSHUF,
134   VPICKEV,
135   VPICKOD,
136   VPACKEV,
137   VPACKOD,
138   VILVL,
139   VILVH,
140   VSHUF4I,
141   VREPLVEI,
142   VREPLGR2VR,
143   XVPERMI,
144 
145   // Extended vector element extraction
146   VPICK_SEXT_ELT,
147   VPICK_ZEXT_ELT,
148 
149   // Vector comparisons
150   VALL_ZERO,
151   VANY_ZERO,
152   VALL_NONZERO,
153   VANY_NONZERO,
154 
155   // Floating point approximate reciprocal operation
156   FRECIPE,
157   FRSQRTE,
158 
159   // Vector logicial left / right shift by immediate
160   VSLLI,
161   VSRLI,
162 
163   // Vector byte logicial left / right shift
164   VBSLL,
165   VBSRL,
166 
167   // Scalar load broadcast to vector
168   VLDREPL,
169 
170   // Vector mask set by condition
171   VMSKLTZ,
172   VMSKGEZ,
173   VMSKEQZ,
174   VMSKNEZ,
175   XVMSKLTZ,
176   XVMSKGEZ,
177   XVMSKEQZ,
178   XVMSKNEZ,
179 
180   // Intrinsic operations end =============================================
181 };
182 } // end namespace LoongArchISD
183 
184 class LoongArchTargetLowering : public TargetLowering {
185   const LoongArchSubtarget &Subtarget;
186 
187 public:
188   explicit LoongArchTargetLowering(const TargetMachine &TM,
189                                    const LoongArchSubtarget &STI);
190 
getSubtarget()191   const LoongArchSubtarget &getSubtarget() const { return Subtarget; }
192 
193   bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;
194 
195   // Provide custom lowering hooks for some operations.
196   SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;
197   void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results,
198                           SelectionDAG &DAG) const override;
199 
200   SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override;
201 
202   // This method returns the name of a target specific DAG node.
203   const char *getTargetNodeName(unsigned Opcode) const override;
204 
205   // Lower incoming arguments, copy physregs into vregs.
206   SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
207                                bool IsVarArg,
208                                const SmallVectorImpl<ISD::InputArg> &Ins,
209                                const SDLoc &DL, SelectionDAG &DAG,
210                                SmallVectorImpl<SDValue> &InVals) const override;
211   bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
212                       bool IsVarArg,
213                       const SmallVectorImpl<ISD::OutputArg> &Outs,
214                       LLVMContext &Context, const Type *RetTy) const override;
215   SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
216                       const SmallVectorImpl<ISD::OutputArg> &Outs,
217                       const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
218                       SelectionDAG &DAG) const override;
219   SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI,
220                     SmallVectorImpl<SDValue> &InVals) const override;
221   bool isCheapToSpeculateCttz(Type *Ty) const override;
222   bool isCheapToSpeculateCtlz(Type *Ty) const override;
223   bool hasAndNot(SDValue Y) const override;
224   TargetLowering::AtomicExpansionKind
225   shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override;
226   void emitExpandAtomicRMW(AtomicRMWInst *AI) const override;
227 
228   Value *emitMaskedAtomicRMWIntrinsic(IRBuilderBase &Builder, AtomicRMWInst *AI,
229                                       Value *AlignedAddr, Value *Incr,
230                                       Value *Mask, Value *ShiftAmt,
231                                       AtomicOrdering Ord) const override;
232 
233   EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context,
234                          EVT VT) const override;
235   TargetLowering::AtomicExpansionKind
236   shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *CI) const override;
237   Value *emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder,
238                                           AtomicCmpXchgInst *CI,
239                                           Value *AlignedAddr, Value *CmpVal,
240                                           Value *NewVal, Value *Mask,
241                                           AtomicOrdering Ord) const override;
242 
243   bool getTgtMemIntrinsic(IntrinsicInfo &Info, const CallInst &I,
244                           MachineFunction &MF,
245                           unsigned Intrinsic) const override;
246 
247   bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF,
248                                   EVT VT) const override;
249 
250   Register
251   getExceptionPointerRegister(const Constant *PersonalityFn) const override;
252 
253   Register
254   getExceptionSelectorRegister(const Constant *PersonalityFn) const override;
255 
isFsqrtCheap(SDValue Operand,SelectionDAG & DAG)256   bool isFsqrtCheap(SDValue Operand, SelectionDAG &DAG) const override {
257     return true;
258   }
259 
260   SDValue getSqrtEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled,
261                           int &RefinementSteps, bool &UseOneConstNR,
262                           bool Reciprocal) const override;
263 
264   SDValue getRecipEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled,
265                            int &RefinementSteps) const override;
266 
getExtendForAtomicOps()267   ISD::NodeType getExtendForAtomicOps() const override {
268     return ISD::SIGN_EXTEND;
269   }
270 
271   ISD::NodeType getExtendForAtomicCmpSwapArg() const override;
272 
273   Register getRegisterByName(const char *RegName, LLT VT,
274                              const MachineFunction &MF) const override;
275   bool mayBeEmittedAsTailCall(const CallInst *CI) const override;
276 
277   bool decomposeMulByConstant(LLVMContext &Context, EVT VT,
278                               SDValue C) const override;
279 
280   bool isUsedByReturnOnly(SDNode *N, SDValue &Chain) const override;
281 
282   bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty,
283                              unsigned AS,
284                              Instruction *I = nullptr) const override;
285 
286   bool isLegalICmpImmediate(int64_t Imm) const override;
287   bool isLegalAddImmediate(int64_t Imm) const override;
288   bool isZExtFree(SDValue Val, EVT VT2) const override;
289   bool isSExtCheaperThanZExt(EVT SrcVT, EVT DstVT) const override;
290   bool signExtendConstant(const ConstantInt *CI) const override;
291 
292   bool hasAndNotCompare(SDValue Y) const override;
293 
convertSelectOfConstantsToMath(EVT VT)294   bool convertSelectOfConstantsToMath(EVT VT) const override { return true; }
295 
296   bool allowsMisalignedMemoryAccesses(
297       EVT VT, unsigned AddrSpace = 0, Align Alignment = Align(1),
298       MachineMemOperand::Flags Flags = MachineMemOperand::MONone,
299       unsigned *Fast = nullptr) const override;
300 
isShuffleMaskLegal(ArrayRef<int> Mask,EVT VT)301   bool isShuffleMaskLegal(ArrayRef<int> Mask, EVT VT) const override {
302     if (!VT.isSimple())
303       return false;
304 
305     // Not for i1 vectors
306     if (VT.getSimpleVT().getScalarType() == MVT::i1)
307       return false;
308 
309     return isTypeLegal(VT.getSimpleVT());
310   }
shouldConsiderGEPOffsetSplit()311   bool shouldConsiderGEPOffsetSplit() const override { return true; }
312   bool shouldSignExtendTypeInLibCall(Type *Ty, bool IsSigned) const override;
313   bool shouldExtendTypeInLibCall(EVT Type) const override;
314 
315   bool shouldAlignPointerArgs(CallInst *CI, unsigned &MinSize,
316                               Align &PrefAlign) const override;
317 
318   bool isFPImmVLDILegal(const APFloat &Imm, EVT VT) const;
319   LegalizeTypeAction getPreferredVectorAction(MVT VT) const override;
320 
321   bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits,
322                                          const APInt &DemandedElts,
323                                          KnownBits &Known,
324                                          TargetLoweringOpt &TLO,
325                                          unsigned Depth) const override;
326 
327 private:
328   /// Target-specific function used to lower LoongArch calling conventions.
329   typedef bool LoongArchCCAssignFn(const DataLayout &DL, LoongArchABI::ABI ABI,
330                                    unsigned ValNo, MVT ValVT,
331                                    CCValAssign::LocInfo LocInfo,
332                                    ISD::ArgFlagsTy ArgFlags, CCState &State,
333                                    bool IsFixed, bool IsRet, Type *OrigTy);
334 
335   void analyzeInputArgs(MachineFunction &MF, CCState &CCInfo,
336                         const SmallVectorImpl<ISD::InputArg> &Ins, bool IsRet,
337                         LoongArchCCAssignFn Fn) const;
338   void analyzeOutputArgs(MachineFunction &MF, CCState &CCInfo,
339                          const SmallVectorImpl<ISD::OutputArg> &Outs,
340                          bool IsRet, CallLoweringInfo *CLI,
341                          LoongArchCCAssignFn Fn) const;
342 
343   template <class NodeTy>
344   SDValue getAddr(NodeTy *N, SelectionDAG &DAG, CodeModel::Model M,
345                   bool IsLocal = true) const;
346   SDValue getStaticTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG,
347                            unsigned Opc, bool UseGOT, bool Large = false) const;
348   SDValue getDynamicTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG,
349                             unsigned Opc, bool Large = false) const;
350   SDValue getTLSDescAddr(GlobalAddressSDNode *N, SelectionDAG &DAG,
351                          unsigned Opc, bool Large = false) const;
352   SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
353   SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
354   SDValue lowerJumpTable(SDValue Op, SelectionDAG &DAG) const;
355   SDValue lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;
356   SDValue lowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const;
357   SDValue lowerShiftRightParts(SDValue Op, SelectionDAG &DAG, bool IsSRA) const;
358 
359   MachineBasicBlock *
360   EmitInstrWithCustomInserter(MachineInstr &MI,
361                               MachineBasicBlock *BB) const override;
362   SDValue lowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG) const;
363   SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
364   SDValue lowerEH_DWARF_CFA(SDValue Op, SelectionDAG &DAG) const;
365   SDValue lowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const;
366   SDValue lowerBITCAST(SDValue Op, SelectionDAG &DAG) const;
367   SDValue lowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG) const;
368   SDValue lowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) const;
369   SDValue lowerVASTART(SDValue Op, SelectionDAG &DAG) const;
370   SDValue lowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const;
371   SDValue lowerINTRINSIC_W_CHAIN(SDValue Op, SelectionDAG &DAG) const;
372   SDValue lowerINTRINSIC_VOID(SDValue Op, SelectionDAG &DAG) const;
373   SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
374   SDValue lowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
375   SDValue lowerWRITE_REGISTER(SDValue Op, SelectionDAG &DAG) const;
376   SDValue lowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const;
377   SDValue lowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const;
378   SDValue lowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const;
379   SDValue lowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG) const;
380   SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const;
381   SDValue lowerBITREVERSE(SDValue Op, SelectionDAG &DAG) const;
382   SDValue lowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) const;
383   SDValue lowerPREFETCH(SDValue Op, SelectionDAG &DAG) const;
384   SDValue lowerSELECT(SDValue Op, SelectionDAG &DAG) const;
385   SDValue lowerFP_TO_FP16(SDValue Op, SelectionDAG &DAG) const;
386   SDValue lowerFP16_TO_FP(SDValue Op, SelectionDAG &DAG) const;
387   SDValue lowerFP_TO_BF16(SDValue Op, SelectionDAG &DAG) const;
388   SDValue lowerBF16_TO_FP(SDValue Op, SelectionDAG &DAG) const;
389 
390   bool isFPImmLegal(const APFloat &Imm, EVT VT,
391                     bool ForCodeSize) const override;
392 
393   bool shouldInsertFencesForAtomic(const Instruction *I) const override;
394 
395   ConstraintType getConstraintType(StringRef Constraint) const override;
396 
397   InlineAsm::ConstraintCode
398   getInlineAsmMemConstraint(StringRef ConstraintCode) const override;
399 
400   std::pair<unsigned, const TargetRegisterClass *>
401   getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
402                                StringRef Constraint, MVT VT) const override;
403 
404   void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint,
405                                     std::vector<SDValue> &Ops,
406                                     SelectionDAG &DAG) const override;
407 
408   bool isEligibleForTailCallOptimization(
409       CCState &CCInfo, CallLoweringInfo &CLI, MachineFunction &MF,
410       const SmallVectorImpl<CCValAssign> &ArgLocs) const;
411 
softPromoteHalfType()412   bool softPromoteHalfType() const override { return true; }
413 
414   bool
415   splitValueIntoRegisterParts(SelectionDAG &DAG, const SDLoc &DL, SDValue Val,
416                               SDValue *Parts, unsigned NumParts, MVT PartVT,
417                               std::optional<CallingConv::ID> CC) const override;
418 
419   SDValue
420   joinRegisterPartsIntoValue(SelectionDAG &DAG, const SDLoc &DL,
421                              const SDValue *Parts, unsigned NumParts,
422                              MVT PartVT, EVT ValueVT,
423                              std::optional<CallingConv::ID> CC) const override;
424 
425   /// Return the register type for a given MVT, ensuring vectors are treated
426   /// as a series of gpr sized integers.
427   MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC,
428                                     EVT VT) const override;
429 
430   /// Return the number of registers for a given MVT, ensuring vectors are
431   /// treated as a series of gpr sized integers.
432   unsigned getNumRegistersForCallingConv(LLVMContext &Context,
433                                          CallingConv::ID CC,
434                                          EVT VT) const override;
435 };
436 
437 } // end namespace llvm
438 
439 #endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELLOWERING_H
440