xref: /llvm-project/llvm/lib/Target/LoongArch/LoongArchISelLowering.h (revision dedf014901cecd7ba3bbc1aadb17098a5a95b8a7)
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   // 32-bit shifts, directly matching the semantics of the named LoongArch
38   // instructions.
39   SLL_W,
40   SRA_W,
41   SRL_W,
42 
43   ROTL_W,
44   ROTR_W,
45 
46   // unsigned 32-bit integer division
47   DIV_W,
48   MOD_W,
49   DIV_WU,
50   MOD_WU,
51 
52   // FPR<->GPR transfer operations
53   MOVGR2FR_W_LA64,
54   MOVFR2GR_S_LA64,
55   MOVFCSR2GR,
56   MOVGR2FCSR,
57 
58   FTINT,
59 
60   // Bit counting operations
61   CLZ_W,
62   CTZ_W,
63 
64   BSTRINS,
65   BSTRPICK,
66 
67   // Byte-swapping and bit-reversal
68   REVB_2H,
69   REVB_2W,
70   BITREV_4B,
71   BITREV_8B,
72   BITREV_W,
73 
74   // Intrinsic operations start ============================================
75   BREAK,
76   CACOP_D,
77   CACOP_W,
78   DBAR,
79   IBAR,
80   SYSCALL,
81 
82   // CRC check operations
83   CRC_W_B_W,
84   CRC_W_H_W,
85   CRC_W_W_W,
86   CRC_W_D_W,
87   CRCC_W_B_W,
88   CRCC_W_H_W,
89   CRCC_W_W_W,
90   CRCC_W_D_W,
91 
92   CSRRD,
93 
94   // Write new value to CSR and return old value.
95   // Operand 0: A chain pointer.
96   // Operand 1: The new value to write.
97   // Operand 2: The address of the required CSR.
98   // Result 0: The old value of the CSR.
99   // Result 1: The new chain pointer.
100   CSRWR,
101 
102   // Similar to CSRWR but with a write mask.
103   // Operand 0: A chain pointer.
104   // Operand 1: The new value to write.
105   // Operand 2: The write mask.
106   // Operand 3: The address of the required CSR.
107   // Result 0: The old value of the CSR.
108   // Result 1: The new chain pointer.
109   CSRXCHG,
110 
111   // IOCSR access operations
112   IOCSRRD_B,
113   IOCSRRD_W,
114   IOCSRRD_H,
115   IOCSRRD_D,
116   IOCSRWR_B,
117   IOCSRWR_H,
118   IOCSRWR_W,
119   IOCSRWR_D,
120 
121   // Read CPU configuration information operation
122   CPUCFG,
123 
124   // Vector Shuffle
125   VREPLVE,
126   VSHUF,
127   VPICKEV,
128   VPICKOD,
129   VPACKEV,
130   VPACKOD,
131   VILVL,
132   VILVH,
133   VSHUF4I,
134   VREPLVEI,
135   VREPLGR2VR,
136   XVPERMI,
137 
138   // Extended vector element extraction
139   VPICK_SEXT_ELT,
140   VPICK_ZEXT_ELT,
141 
142   // Vector comparisons
143   VALL_ZERO,
144   VANY_ZERO,
145   VALL_NONZERO,
146   VANY_NONZERO,
147 
148   // Floating point approximate reciprocal operation
149   FRECIPE,
150   FRSQRTE
151 
152   // Intrinsic operations end =============================================
153 };
154 } // end namespace LoongArchISD
155 
156 class LoongArchTargetLowering : public TargetLowering {
157   const LoongArchSubtarget &Subtarget;
158 
159 public:
160   explicit LoongArchTargetLowering(const TargetMachine &TM,
161                                    const LoongArchSubtarget &STI);
162 
163   const LoongArchSubtarget &getSubtarget() const { return Subtarget; }
164 
165   bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;
166 
167   // Provide custom lowering hooks for some operations.
168   SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;
169   void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results,
170                           SelectionDAG &DAG) const override;
171 
172   SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override;
173 
174   // This method returns the name of a target specific DAG node.
175   const char *getTargetNodeName(unsigned Opcode) const override;
176 
177   // Lower incoming arguments, copy physregs into vregs.
178   SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
179                                bool IsVarArg,
180                                const SmallVectorImpl<ISD::InputArg> &Ins,
181                                const SDLoc &DL, SelectionDAG &DAG,
182                                SmallVectorImpl<SDValue> &InVals) const override;
183   bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
184                       bool IsVarArg,
185                       const SmallVectorImpl<ISD::OutputArg> &Outs,
186                       LLVMContext &Context, const Type *RetTy) const override;
187   SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
188                       const SmallVectorImpl<ISD::OutputArg> &Outs,
189                       const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
190                       SelectionDAG &DAG) const override;
191   SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI,
192                     SmallVectorImpl<SDValue> &InVals) const override;
193   bool isCheapToSpeculateCttz(Type *Ty) const override;
194   bool isCheapToSpeculateCtlz(Type *Ty) const override;
195   bool hasAndNot(SDValue Y) const override;
196   TargetLowering::AtomicExpansionKind
197   shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override;
198   void emitExpandAtomicRMW(AtomicRMWInst *AI) const override;
199 
200   Value *emitMaskedAtomicRMWIntrinsic(IRBuilderBase &Builder, AtomicRMWInst *AI,
201                                       Value *AlignedAddr, Value *Incr,
202                                       Value *Mask, Value *ShiftAmt,
203                                       AtomicOrdering Ord) const override;
204 
205   EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context,
206                          EVT VT) const override;
207   TargetLowering::AtomicExpansionKind
208   shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *CI) const override;
209   Value *emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder,
210                                           AtomicCmpXchgInst *CI,
211                                           Value *AlignedAddr, Value *CmpVal,
212                                           Value *NewVal, Value *Mask,
213                                           AtomicOrdering Ord) const override;
214 
215   bool getTgtMemIntrinsic(IntrinsicInfo &Info, const CallInst &I,
216                           MachineFunction &MF,
217                           unsigned Intrinsic) const override;
218 
219   bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF,
220                                   EVT VT) const override;
221 
222   Register
223   getExceptionPointerRegister(const Constant *PersonalityFn) const override;
224 
225   Register
226   getExceptionSelectorRegister(const Constant *PersonalityFn) const override;
227 
228   bool isFsqrtCheap(SDValue Operand, SelectionDAG &DAG) const override {
229     return true;
230   }
231 
232   SDValue getSqrtEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled,
233                           int &RefinementSteps, bool &UseOneConstNR,
234                           bool Reciprocal) const override;
235 
236   SDValue getRecipEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled,
237                            int &RefinementSteps) const override;
238 
239   ISD::NodeType getExtendForAtomicOps() const override {
240     return ISD::SIGN_EXTEND;
241   }
242 
243   ISD::NodeType getExtendForAtomicCmpSwapArg() const override;
244 
245   Register getRegisterByName(const char *RegName, LLT VT,
246                              const MachineFunction &MF) const override;
247   bool mayBeEmittedAsTailCall(const CallInst *CI) const override;
248 
249   bool decomposeMulByConstant(LLVMContext &Context, EVT VT,
250                               SDValue C) const override;
251 
252   bool isUsedByReturnOnly(SDNode *N, SDValue &Chain) const override;
253 
254   bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty,
255                              unsigned AS,
256                              Instruction *I = nullptr) const override;
257 
258   bool isLegalICmpImmediate(int64_t Imm) const override;
259   bool isLegalAddImmediate(int64_t Imm) const override;
260   bool isZExtFree(SDValue Val, EVT VT2) const override;
261   bool isSExtCheaperThanZExt(EVT SrcVT, EVT DstVT) const override;
262   bool signExtendConstant(const ConstantInt *CI) const override;
263 
264   bool hasAndNotCompare(SDValue Y) const override;
265 
266   bool convertSelectOfConstantsToMath(EVT VT) const override { return true; }
267 
268   bool allowsMisalignedMemoryAccesses(
269       EVT VT, unsigned AddrSpace = 0, Align Alignment = Align(1),
270       MachineMemOperand::Flags Flags = MachineMemOperand::MONone,
271       unsigned *Fast = nullptr) const override;
272 
273   bool isShuffleMaskLegal(ArrayRef<int> Mask, EVT VT) const override {
274     return false;
275   }
276   bool shouldConsiderGEPOffsetSplit() const override { return true; }
277   bool shouldSignExtendTypeInLibCall(Type *Ty, bool IsSigned) const override;
278   bool shouldExtendTypeInLibCall(EVT Type) const override;
279 
280   bool shouldAlignPointerArgs(CallInst *CI, unsigned &MinSize,
281                               Align &PrefAlign) const override;
282 
283   bool isFPImmVLDILegal(const APFloat &Imm, EVT VT) const;
284 
285 private:
286   /// Target-specific function used to lower LoongArch calling conventions.
287   typedef bool LoongArchCCAssignFn(const DataLayout &DL, LoongArchABI::ABI ABI,
288                                    unsigned ValNo, MVT ValVT,
289                                    CCValAssign::LocInfo LocInfo,
290                                    ISD::ArgFlagsTy ArgFlags, CCState &State,
291                                    bool IsFixed, bool IsRet, Type *OrigTy);
292 
293   void analyzeInputArgs(MachineFunction &MF, CCState &CCInfo,
294                         const SmallVectorImpl<ISD::InputArg> &Ins, bool IsRet,
295                         LoongArchCCAssignFn Fn) const;
296   void analyzeOutputArgs(MachineFunction &MF, CCState &CCInfo,
297                          const SmallVectorImpl<ISD::OutputArg> &Outs,
298                          bool IsRet, CallLoweringInfo *CLI,
299                          LoongArchCCAssignFn Fn) const;
300 
301   template <class NodeTy>
302   SDValue getAddr(NodeTy *N, SelectionDAG &DAG, CodeModel::Model M,
303                   bool IsLocal = true) const;
304   SDValue getStaticTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG,
305                            unsigned Opc, bool UseGOT, bool Large = false) const;
306   SDValue getDynamicTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG,
307                             unsigned Opc, bool Large = false) const;
308   SDValue getTLSDescAddr(GlobalAddressSDNode *N, SelectionDAG &DAG,
309                          unsigned Opc, bool Large = false) const;
310   SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
311   SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
312   SDValue lowerJumpTable(SDValue Op, SelectionDAG &DAG) const;
313   SDValue lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;
314   SDValue lowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const;
315   SDValue lowerShiftRightParts(SDValue Op, SelectionDAG &DAG, bool IsSRA) const;
316 
317   MachineBasicBlock *
318   EmitInstrWithCustomInserter(MachineInstr &MI,
319                               MachineBasicBlock *BB) const override;
320   SDValue lowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG) const;
321   SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
322   SDValue lowerEH_DWARF_CFA(SDValue Op, SelectionDAG &DAG) const;
323   SDValue lowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const;
324   SDValue lowerBITCAST(SDValue Op, SelectionDAG &DAG) const;
325   SDValue lowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG) const;
326   SDValue lowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) const;
327   SDValue lowerVASTART(SDValue Op, SelectionDAG &DAG) const;
328   SDValue lowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const;
329   SDValue lowerINTRINSIC_W_CHAIN(SDValue Op, SelectionDAG &DAG) const;
330   SDValue lowerINTRINSIC_VOID(SDValue Op, SelectionDAG &DAG) const;
331   SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
332   SDValue lowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
333   SDValue lowerWRITE_REGISTER(SDValue Op, SelectionDAG &DAG) const;
334   SDValue lowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const;
335   SDValue lowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const;
336   SDValue lowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const;
337   SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const;
338   SDValue lowerBITREVERSE(SDValue Op, SelectionDAG &DAG) const;
339   SDValue lowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) const;
340 
341   bool isFPImmLegal(const APFloat &Imm, EVT VT,
342                     bool ForCodeSize) const override;
343 
344   bool shouldInsertFencesForAtomic(const Instruction *I) const override;
345 
346   ConstraintType getConstraintType(StringRef Constraint) const override;
347 
348   InlineAsm::ConstraintCode
349   getInlineAsmMemConstraint(StringRef ConstraintCode) const override;
350 
351   std::pair<unsigned, const TargetRegisterClass *>
352   getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
353                                StringRef Constraint, MVT VT) const override;
354 
355   void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint,
356                                     std::vector<SDValue> &Ops,
357                                     SelectionDAG &DAG) const override;
358 
359   bool isEligibleForTailCallOptimization(
360       CCState &CCInfo, CallLoweringInfo &CLI, MachineFunction &MF,
361       const SmallVectorImpl<CCValAssign> &ArgLocs) const;
362 
363   bool softPromoteHalfType() const override { return true; }
364 };
365 
366 } // end namespace llvm
367 
368 #endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELLOWERING_H
369