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