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