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   CSRWR,
84   CSRXCHG,
85 
86   // IOCSR access operations
87   IOCSRRD_B,
88   IOCSRRD_W,
89   IOCSRRD_H,
90   IOCSRRD_D,
91   IOCSRWR_B,
92   IOCSRWR_H,
93   IOCSRWR_W,
94   IOCSRWR_D,
95 
96   // Read CPU configuration information operation
97   CPUCFG,
98   // Intrinsic operations end =============================================
99 };
100 } // end namespace LoongArchISD
101 
102 class LoongArchTargetLowering : public TargetLowering {
103   const LoongArchSubtarget &Subtarget;
104 
105 public:
106   explicit LoongArchTargetLowering(const TargetMachine &TM,
107                                    const LoongArchSubtarget &STI);
108 
109   const LoongArchSubtarget &getSubtarget() const { return Subtarget; }
110 
111   bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;
112 
113   // Provide custom lowering hooks for some operations.
114   SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;
115   void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results,
116                           SelectionDAG &DAG) const override;
117 
118   SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override;
119 
120   // This method returns the name of a target specific DAG node.
121   const char *getTargetNodeName(unsigned Opcode) const override;
122 
123   // Lower incoming arguments, copy physregs into vregs.
124   SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
125                                bool IsVarArg,
126                                const SmallVectorImpl<ISD::InputArg> &Ins,
127                                const SDLoc &DL, SelectionDAG &DAG,
128                                SmallVectorImpl<SDValue> &InVals) const override;
129   bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
130                       bool IsVarArg,
131                       const SmallVectorImpl<ISD::OutputArg> &Outs,
132                       LLVMContext &Context) const override;
133   SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
134                       const SmallVectorImpl<ISD::OutputArg> &Outs,
135                       const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
136                       SelectionDAG &DAG) const override;
137   SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI,
138                     SmallVectorImpl<SDValue> &InVals) const override;
139   bool isCheapToSpeculateCttz(Type *Ty) const override;
140   bool isCheapToSpeculateCtlz(Type *Ty) const override;
141   bool hasAndNot(SDValue Y) const override;
142   TargetLowering::AtomicExpansionKind
143   shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override;
144 
145   Value *emitMaskedAtomicRMWIntrinsic(IRBuilderBase &Builder, AtomicRMWInst *AI,
146                                       Value *AlignedAddr, Value *Incr,
147                                       Value *Mask, Value *ShiftAmt,
148                                       AtomicOrdering Ord) const override;
149 
150   EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context,
151                          EVT VT) const override;
152   TargetLowering::AtomicExpansionKind
153   shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *CI) const override;
154   Value *emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder,
155                                           AtomicCmpXchgInst *CI,
156                                           Value *AlignedAddr, Value *CmpVal,
157                                           Value *NewVal, Value *Mask,
158                                           AtomicOrdering Ord) const override;
159 
160   bool getTgtMemIntrinsic(IntrinsicInfo &Info, const CallInst &I,
161                           MachineFunction &MF,
162                           unsigned Intrinsic) const override;
163 
164   bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF,
165                                   EVT VT) const override;
166 
167   Register
168   getExceptionPointerRegister(const Constant *PersonalityFn) const override;
169 
170   Register
171   getExceptionSelectorRegister(const Constant *PersonalityFn) const override;
172 
173   ISD::NodeType getExtendForAtomicOps() const override {
174     return ISD::SIGN_EXTEND;
175   }
176 
177   Register getRegisterByName(const char *RegName, LLT VT,
178                              const MachineFunction &MF) const override;
179   bool mayBeEmittedAsTailCall(const CallInst *CI) const override;
180 
181   bool decomposeMulByConstant(LLVMContext &Context, EVT VT,
182                               SDValue C) const override;
183 
184 private:
185   /// Target-specific function used to lower LoongArch calling conventions.
186   typedef bool LoongArchCCAssignFn(const DataLayout &DL, LoongArchABI::ABI ABI,
187                                    unsigned ValNo, MVT ValVT,
188                                    CCValAssign::LocInfo LocInfo,
189                                    ISD::ArgFlagsTy ArgFlags, CCState &State,
190                                    bool IsFixed, bool IsReg, Type *OrigTy);
191 
192   void analyzeInputArgs(MachineFunction &MF, CCState &CCInfo,
193                         const SmallVectorImpl<ISD::InputArg> &Ins, bool IsRet,
194                         LoongArchCCAssignFn Fn) const;
195   void analyzeOutputArgs(MachineFunction &MF, CCState &CCInfo,
196                          const SmallVectorImpl<ISD::OutputArg> &Outs,
197                          bool IsRet, CallLoweringInfo *CLI,
198                          LoongArchCCAssignFn Fn) const;
199 
200   template <class NodeTy>
201   SDValue getAddr(NodeTy *N, SelectionDAG &DAG, bool IsLocal = true) const;
202   SDValue getStaticTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG,
203                            unsigned Opc) const;
204   SDValue getDynamicTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG,
205                             unsigned Opc) const;
206   SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
207   SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
208   SDValue lowerJumpTable(SDValue Op, SelectionDAG &DAG) const;
209   SDValue lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;
210   SDValue lowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const;
211   SDValue lowerShiftRightParts(SDValue Op, SelectionDAG &DAG, bool IsSRA) const;
212 
213   MachineBasicBlock *
214   EmitInstrWithCustomInserter(MachineInstr &MI,
215                               MachineBasicBlock *BB) const override;
216   SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
217   SDValue lowerEH_DWARF_CFA(SDValue Op, SelectionDAG &DAG) const;
218   SDValue lowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const;
219   SDValue lowerBITCAST(SDValue Op, SelectionDAG &DAG) const;
220   SDValue lowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG) const;
221   SDValue lowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) const;
222   SDValue lowerVASTART(SDValue Op, SelectionDAG &DAG) const;
223   SDValue lowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const;
224   SDValue lowerINTRINSIC_W_CHAIN(SDValue Op, SelectionDAG &DAG) const;
225   SDValue lowerINTRINSIC_VOID(SDValue Op, SelectionDAG &DAG) const;
226   SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
227   SDValue lowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
228   SDValue lowerWRITE_REGISTER(SDValue Op, SelectionDAG &DAG) const;
229 
230   bool isFPImmLegal(const APFloat &Imm, EVT VT,
231                     bool ForCodeSize) const override;
232 
233   bool shouldInsertFencesForAtomic(const Instruction *I) const override;
234 
235   ConstraintType getConstraintType(StringRef Constraint) const override;
236 
237   unsigned getInlineAsmMemConstraint(StringRef ConstraintCode) const override;
238 
239   std::pair<unsigned, const TargetRegisterClass *>
240   getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
241                                StringRef Constraint, MVT VT) const override;
242 
243   void LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint,
244                                     std::vector<SDValue> &Ops,
245                                     SelectionDAG &DAG) const override;
246 
247   bool isEligibleForTailCallOptimization(
248       CCState &CCInfo, CallLoweringInfo &CLI, MachineFunction &MF,
249       const SmallVectorImpl<CCValAssign> &ArgLocs) const;
250 };
251 
252 } // end namespace llvm
253 
254 #endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELLOWERING_H
255