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