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