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