xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/LoongArch/LoongArchISelLowering.h (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
181ad6265SDimitry Andric //=- LoongArchISelLowering.h - LoongArch DAG Lowering Interface -*- C++ -*-===//
281ad6265SDimitry Andric //
381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric //
781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
881ad6265SDimitry Andric //
981ad6265SDimitry Andric // This file defines the interfaces that LoongArch uses to lower LLVM code into
1081ad6265SDimitry Andric // a selection DAG.
1181ad6265SDimitry Andric //
1281ad6265SDimitry Andric //===----------------------------------------------------------------------===//
1381ad6265SDimitry Andric 
1481ad6265SDimitry Andric #ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELLOWERING_H
1581ad6265SDimitry Andric #define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELLOWERING_H
1681ad6265SDimitry Andric 
1781ad6265SDimitry Andric #include "LoongArch.h"
1881ad6265SDimitry Andric #include "llvm/CodeGen/CallingConvLower.h"
1981ad6265SDimitry Andric #include "llvm/CodeGen/SelectionDAG.h"
2081ad6265SDimitry Andric #include "llvm/CodeGen/TargetLowering.h"
2181ad6265SDimitry Andric 
2281ad6265SDimitry Andric namespace llvm {
2381ad6265SDimitry Andric class LoongArchSubtarget;
2481ad6265SDimitry Andric struct LoongArchRegisterInfo;
2581ad6265SDimitry Andric namespace LoongArchISD {
2681ad6265SDimitry Andric enum NodeType : unsigned {
2781ad6265SDimitry Andric   FIRST_NUMBER = ISD::BUILTIN_OP_END,
2881ad6265SDimitry Andric 
2981ad6265SDimitry Andric   // TODO: add more LoongArchISDs
30753f127fSDimitry Andric   CALL,
3181ad6265SDimitry Andric   RET,
32*bdd1243dSDimitry Andric   TAIL,
33*bdd1243dSDimitry Andric 
3481ad6265SDimitry Andric   // 32-bit shifts, directly matching the semantics of the named LoongArch
3581ad6265SDimitry Andric   // instructions.
3681ad6265SDimitry Andric   SLL_W,
3781ad6265SDimitry Andric   SRA_W,
3881ad6265SDimitry Andric   SRL_W,
3981ad6265SDimitry Andric 
40*bdd1243dSDimitry Andric   ROTL_W,
41*bdd1243dSDimitry Andric   ROTR_W,
42*bdd1243dSDimitry Andric 
43753f127fSDimitry Andric   // FPR<->GPR transfer operations
44753f127fSDimitry Andric   MOVGR2FR_W_LA64,
45753f127fSDimitry Andric   MOVFR2GR_S_LA64,
46*bdd1243dSDimitry Andric   MOVFCSR2GR,
47*bdd1243dSDimitry Andric   MOVGR2FCSR,
48753f127fSDimitry Andric 
49753f127fSDimitry Andric   FTINT,
50753f127fSDimitry Andric 
51*bdd1243dSDimitry Andric   // Bit counting operations
52*bdd1243dSDimitry Andric   CLZ_W,
53*bdd1243dSDimitry Andric   CTZ_W,
54*bdd1243dSDimitry Andric 
55753f127fSDimitry Andric   BSTRINS,
5681ad6265SDimitry Andric   BSTRPICK,
5781ad6265SDimitry Andric 
58*bdd1243dSDimitry Andric   // Byte-swapping and bit-reversal
59*bdd1243dSDimitry Andric   REVB_2H,
60*bdd1243dSDimitry Andric   REVB_2W,
61*bdd1243dSDimitry Andric   BITREV_4B,
62*bdd1243dSDimitry Andric   BITREV_W,
63*bdd1243dSDimitry Andric 
64*bdd1243dSDimitry Andric   // Intrinsic operations start ============================================
65*bdd1243dSDimitry Andric   BREAK,
66*bdd1243dSDimitry Andric   CACOP_D,
67*bdd1243dSDimitry Andric   CACOP_W,
68*bdd1243dSDimitry Andric   DBAR,
69*bdd1243dSDimitry Andric   IBAR,
70*bdd1243dSDimitry Andric   SYSCALL,
71*bdd1243dSDimitry Andric 
72*bdd1243dSDimitry Andric   // CRC check operations
73*bdd1243dSDimitry Andric   CRC_W_B_W,
74*bdd1243dSDimitry Andric   CRC_W_H_W,
75*bdd1243dSDimitry Andric   CRC_W_W_W,
76*bdd1243dSDimitry Andric   CRC_W_D_W,
77*bdd1243dSDimitry Andric   CRCC_W_B_W,
78*bdd1243dSDimitry Andric   CRCC_W_H_W,
79*bdd1243dSDimitry Andric   CRCC_W_W_W,
80*bdd1243dSDimitry Andric   CRCC_W_D_W,
81*bdd1243dSDimitry Andric 
82*bdd1243dSDimitry Andric   CSRRD,
83*bdd1243dSDimitry Andric   CSRWR,
84*bdd1243dSDimitry Andric   CSRXCHG,
85*bdd1243dSDimitry Andric 
86*bdd1243dSDimitry Andric   // IOCSR access operations
87*bdd1243dSDimitry Andric   IOCSRRD_B,
88*bdd1243dSDimitry Andric   IOCSRRD_W,
89*bdd1243dSDimitry Andric   IOCSRRD_H,
90*bdd1243dSDimitry Andric   IOCSRRD_D,
91*bdd1243dSDimitry Andric   IOCSRWR_B,
92*bdd1243dSDimitry Andric   IOCSRWR_H,
93*bdd1243dSDimitry Andric   IOCSRWR_W,
94*bdd1243dSDimitry Andric   IOCSRWR_D,
95*bdd1243dSDimitry Andric 
96*bdd1243dSDimitry Andric   // Read CPU configuration information operation
97*bdd1243dSDimitry Andric   CPUCFG,
98*bdd1243dSDimitry Andric   // Intrinsic operations end =============================================
9981ad6265SDimitry Andric };
100972a253aSDimitry Andric } // end namespace LoongArchISD
10181ad6265SDimitry Andric 
10281ad6265SDimitry Andric class LoongArchTargetLowering : public TargetLowering {
10381ad6265SDimitry Andric   const LoongArchSubtarget &Subtarget;
10481ad6265SDimitry Andric 
10581ad6265SDimitry Andric public:
10681ad6265SDimitry Andric   explicit LoongArchTargetLowering(const TargetMachine &TM,
10781ad6265SDimitry Andric                                    const LoongArchSubtarget &STI);
10881ad6265SDimitry Andric 
10981ad6265SDimitry Andric   const LoongArchSubtarget &getSubtarget() const { return Subtarget; }
11081ad6265SDimitry Andric 
111*bdd1243dSDimitry Andric   bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;
112*bdd1243dSDimitry Andric 
11381ad6265SDimitry Andric   // Provide custom lowering hooks for some operations.
11481ad6265SDimitry Andric   SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;
11581ad6265SDimitry Andric   void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results,
11681ad6265SDimitry Andric                           SelectionDAG &DAG) const override;
11781ad6265SDimitry Andric 
11881ad6265SDimitry Andric   SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override;
11981ad6265SDimitry Andric 
12081ad6265SDimitry Andric   // This method returns the name of a target specific DAG node.
12181ad6265SDimitry Andric   const char *getTargetNodeName(unsigned Opcode) const override;
12281ad6265SDimitry Andric 
12381ad6265SDimitry Andric   // Lower incoming arguments, copy physregs into vregs.
12481ad6265SDimitry Andric   SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
12581ad6265SDimitry Andric                                bool IsVarArg,
12681ad6265SDimitry Andric                                const SmallVectorImpl<ISD::InputArg> &Ins,
12781ad6265SDimitry Andric                                const SDLoc &DL, SelectionDAG &DAG,
12881ad6265SDimitry Andric                                SmallVectorImpl<SDValue> &InVals) const override;
12981ad6265SDimitry Andric   bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
13081ad6265SDimitry Andric                       bool IsVarArg,
13181ad6265SDimitry Andric                       const SmallVectorImpl<ISD::OutputArg> &Outs,
13281ad6265SDimitry Andric                       LLVMContext &Context) const override;
13381ad6265SDimitry Andric   SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
13481ad6265SDimitry Andric                       const SmallVectorImpl<ISD::OutputArg> &Outs,
13581ad6265SDimitry Andric                       const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
13681ad6265SDimitry Andric                       SelectionDAG &DAG) const override;
137753f127fSDimitry Andric   SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI,
138753f127fSDimitry Andric                     SmallVectorImpl<SDValue> &InVals) const override;
139*bdd1243dSDimitry Andric   bool isCheapToSpeculateCttz(Type *Ty) const override;
140*bdd1243dSDimitry Andric   bool isCheapToSpeculateCtlz(Type *Ty) const override;
141*bdd1243dSDimitry Andric   bool hasAndNot(SDValue Y) const override;
142*bdd1243dSDimitry Andric   TargetLowering::AtomicExpansionKind
143*bdd1243dSDimitry Andric   shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override;
144*bdd1243dSDimitry Andric 
145*bdd1243dSDimitry Andric   Value *emitMaskedAtomicRMWIntrinsic(IRBuilderBase &Builder, AtomicRMWInst *AI,
146*bdd1243dSDimitry Andric                                       Value *AlignedAddr, Value *Incr,
147*bdd1243dSDimitry Andric                                       Value *Mask, Value *ShiftAmt,
148*bdd1243dSDimitry Andric                                       AtomicOrdering Ord) const override;
149*bdd1243dSDimitry Andric 
150*bdd1243dSDimitry Andric   EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context,
151*bdd1243dSDimitry Andric                          EVT VT) const override;
152*bdd1243dSDimitry Andric   TargetLowering::AtomicExpansionKind
153*bdd1243dSDimitry Andric   shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *CI) const override;
154*bdd1243dSDimitry Andric   Value *emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder,
155*bdd1243dSDimitry Andric                                           AtomicCmpXchgInst *CI,
156*bdd1243dSDimitry Andric                                           Value *AlignedAddr, Value *CmpVal,
157*bdd1243dSDimitry Andric                                           Value *NewVal, Value *Mask,
158*bdd1243dSDimitry Andric                                           AtomicOrdering Ord) const override;
159*bdd1243dSDimitry Andric 
160*bdd1243dSDimitry Andric   bool getTgtMemIntrinsic(IntrinsicInfo &Info, const CallInst &I,
161*bdd1243dSDimitry Andric                           MachineFunction &MF,
162*bdd1243dSDimitry Andric                           unsigned Intrinsic) const override;
163*bdd1243dSDimitry Andric 
164*bdd1243dSDimitry Andric   bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF,
165*bdd1243dSDimitry Andric                                   EVT VT) const override;
166*bdd1243dSDimitry Andric 
167*bdd1243dSDimitry Andric   Register
168*bdd1243dSDimitry Andric   getExceptionPointerRegister(const Constant *PersonalityFn) const override;
169*bdd1243dSDimitry Andric 
170*bdd1243dSDimitry Andric   Register
171*bdd1243dSDimitry Andric   getExceptionSelectorRegister(const Constant *PersonalityFn) const override;
172*bdd1243dSDimitry Andric 
173*bdd1243dSDimitry Andric   ISD::NodeType getExtendForAtomicOps() const override {
174*bdd1243dSDimitry Andric     return ISD::SIGN_EXTEND;
175*bdd1243dSDimitry Andric   }
176*bdd1243dSDimitry Andric 
177*bdd1243dSDimitry Andric   Register getRegisterByName(const char *RegName, LLT VT,
178*bdd1243dSDimitry Andric                              const MachineFunction &MF) const override;
179*bdd1243dSDimitry Andric   bool mayBeEmittedAsTailCall(const CallInst *CI) const override;
180*bdd1243dSDimitry Andric 
181*bdd1243dSDimitry Andric   bool decomposeMulByConstant(LLVMContext &Context, EVT VT,
182*bdd1243dSDimitry Andric                               SDValue C) const override;
18381ad6265SDimitry Andric 
18481ad6265SDimitry Andric private:
18581ad6265SDimitry Andric   /// Target-specific function used to lower LoongArch calling conventions.
186*bdd1243dSDimitry Andric   typedef bool LoongArchCCAssignFn(const DataLayout &DL, LoongArchABI::ABI ABI,
187*bdd1243dSDimitry Andric                                    unsigned ValNo, MVT ValVT,
18881ad6265SDimitry Andric                                    CCValAssign::LocInfo LocInfo,
189*bdd1243dSDimitry Andric                                    ISD::ArgFlagsTy ArgFlags, CCState &State,
190*bdd1243dSDimitry Andric                                    bool IsFixed, bool IsReg, Type *OrigTy);
19181ad6265SDimitry Andric 
192*bdd1243dSDimitry Andric   void analyzeInputArgs(MachineFunction &MF, CCState &CCInfo,
193*bdd1243dSDimitry Andric                         const SmallVectorImpl<ISD::InputArg> &Ins, bool IsRet,
19481ad6265SDimitry Andric                         LoongArchCCAssignFn Fn) const;
195*bdd1243dSDimitry Andric   void analyzeOutputArgs(MachineFunction &MF, CCState &CCInfo,
19681ad6265SDimitry Andric                          const SmallVectorImpl<ISD::OutputArg> &Outs,
197*bdd1243dSDimitry Andric                          bool IsRet, CallLoweringInfo *CLI,
19881ad6265SDimitry Andric                          LoongArchCCAssignFn Fn) const;
19981ad6265SDimitry Andric 
200*bdd1243dSDimitry Andric   template <class NodeTy>
201*bdd1243dSDimitry Andric   SDValue getAddr(NodeTy *N, SelectionDAG &DAG, bool IsLocal = true) const;
202*bdd1243dSDimitry Andric   SDValue getStaticTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG,
203*bdd1243dSDimitry Andric                            unsigned Opc) const;
204*bdd1243dSDimitry Andric   SDValue getDynamicTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG,
205*bdd1243dSDimitry Andric                             unsigned Opc) const;
206753f127fSDimitry Andric   SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
207*bdd1243dSDimitry Andric   SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
208*bdd1243dSDimitry Andric   SDValue lowerJumpTable(SDValue Op, SelectionDAG &DAG) const;
209*bdd1243dSDimitry Andric   SDValue lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;
21081ad6265SDimitry Andric   SDValue lowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const;
21181ad6265SDimitry Andric   SDValue lowerShiftRightParts(SDValue Op, SelectionDAG &DAG, bool IsSRA) const;
212753f127fSDimitry Andric 
213753f127fSDimitry Andric   MachineBasicBlock *
214753f127fSDimitry Andric   EmitInstrWithCustomInserter(MachineInstr &MI,
215753f127fSDimitry Andric                               MachineBasicBlock *BB) const override;
216753f127fSDimitry Andric   SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
217*bdd1243dSDimitry Andric   SDValue lowerEH_DWARF_CFA(SDValue Op, SelectionDAG &DAG) const;
218753f127fSDimitry Andric   SDValue lowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const;
219753f127fSDimitry Andric   SDValue lowerBITCAST(SDValue Op, SelectionDAG &DAG) const;
220753f127fSDimitry Andric   SDValue lowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG) const;
221*bdd1243dSDimitry Andric   SDValue lowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) const;
222*bdd1243dSDimitry Andric   SDValue lowerVASTART(SDValue Op, SelectionDAG &DAG) const;
223*bdd1243dSDimitry Andric   SDValue lowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const;
224*bdd1243dSDimitry Andric   SDValue lowerINTRINSIC_W_CHAIN(SDValue Op, SelectionDAG &DAG) const;
225*bdd1243dSDimitry Andric   SDValue lowerINTRINSIC_VOID(SDValue Op, SelectionDAG &DAG) const;
226*bdd1243dSDimitry Andric   SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
227*bdd1243dSDimitry Andric   SDValue lowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
228*bdd1243dSDimitry Andric   SDValue lowerWRITE_REGISTER(SDValue Op, SelectionDAG &DAG) const;
229753f127fSDimitry Andric 
230753f127fSDimitry Andric   bool isFPImmLegal(const APFloat &Imm, EVT VT,
231753f127fSDimitry Andric                     bool ForCodeSize) const override;
232753f127fSDimitry Andric 
233*bdd1243dSDimitry Andric   bool shouldInsertFencesForAtomic(const Instruction *I) const override;
234*bdd1243dSDimitry Andric 
235*bdd1243dSDimitry Andric   ConstraintType getConstraintType(StringRef Constraint) const override;
236*bdd1243dSDimitry Andric 
237*bdd1243dSDimitry Andric   unsigned getInlineAsmMemConstraint(StringRef ConstraintCode) const override;
238*bdd1243dSDimitry Andric 
239*bdd1243dSDimitry Andric   std::pair<unsigned, const TargetRegisterClass *>
240*bdd1243dSDimitry Andric   getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
241*bdd1243dSDimitry Andric                                StringRef Constraint, MVT VT) const override;
242*bdd1243dSDimitry Andric 
243*bdd1243dSDimitry Andric   void LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint,
244*bdd1243dSDimitry Andric                                     std::vector<SDValue> &Ops,
245*bdd1243dSDimitry Andric                                     SelectionDAG &DAG) const override;
246*bdd1243dSDimitry Andric 
247*bdd1243dSDimitry Andric   bool isEligibleForTailCallOptimization(
248*bdd1243dSDimitry Andric       CCState &CCInfo, CallLoweringInfo &CLI, MachineFunction &MF,
249*bdd1243dSDimitry Andric       const SmallVectorImpl<CCValAssign> &ArgLocs) const;
25081ad6265SDimitry Andric };
25181ad6265SDimitry Andric 
25281ad6265SDimitry Andric } // end namespace llvm
25381ad6265SDimitry Andric 
25481ad6265SDimitry Andric #endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELLOWERING_H
255