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 // Select
38 SELECT_CC,
39
40 // 32-bit shifts, directly matching the semantics of the named LoongArch
41 // instructions.
42 SLL_W,
43 SRA_W,
44 SRL_W,
45
46 ROTL_W,
47 ROTR_W,
48
49 // unsigned 32-bit integer division
50 DIV_W,
51 MOD_W,
52 DIV_WU,
53 MOD_WU,
54
55 // FPR<->GPR transfer operations
56 MOVGR2FR_W_LA64,
57 MOVFR2GR_S_LA64,
58 MOVFCSR2GR,
59 MOVGR2FCSR,
60
61 FTINT,
62
63 // Build and split F64 pair
64 BUILD_PAIR_F64,
65 SPLIT_PAIR_F64,
66
67 // Bit counting operations
68 CLZ_W,
69 CTZ_W,
70
71 BSTRINS,
72 BSTRPICK,
73
74 // Byte-swapping and bit-reversal
75 REVB_2H,
76 REVB_2W,
77 BITREV_4B,
78 BITREV_8B,
79 BITREV_W,
80
81 // Intrinsic operations start ============================================
82 BREAK,
83 CACOP_D,
84 CACOP_W,
85 DBAR,
86 IBAR,
87 SYSCALL,
88
89 // CRC check operations
90 CRC_W_B_W,
91 CRC_W_H_W,
92 CRC_W_W_W,
93 CRC_W_D_W,
94 CRCC_W_B_W,
95 CRCC_W_H_W,
96 CRCC_W_W_W,
97 CRCC_W_D_W,
98
99 CSRRD,
100
101 // Write new value to CSR and return old value.
102 // Operand 0: A chain pointer.
103 // Operand 1: The new value to write.
104 // Operand 2: The address of the required CSR.
105 // Result 0: The old value of the CSR.
106 // Result 1: The new chain pointer.
107 CSRWR,
108
109 // Similar to CSRWR but with a write mask.
110 // Operand 0: A chain pointer.
111 // Operand 1: The new value to write.
112 // Operand 2: The write mask.
113 // Operand 3: The address of the required CSR.
114 // Result 0: The old value of the CSR.
115 // Result 1: The new chain pointer.
116 CSRXCHG,
117
118 // IOCSR access operations
119 IOCSRRD_B,
120 IOCSRRD_W,
121 IOCSRRD_H,
122 IOCSRRD_D,
123 IOCSRWR_B,
124 IOCSRWR_H,
125 IOCSRWR_W,
126 IOCSRWR_D,
127
128 // Read CPU configuration information operation
129 CPUCFG,
130
131 // Vector Shuffle
132 VREPLVE,
133 VSHUF,
134 VPICKEV,
135 VPICKOD,
136 VPACKEV,
137 VPACKOD,
138 VILVL,
139 VILVH,
140 VSHUF4I,
141 VREPLVEI,
142 VREPLGR2VR,
143 XVPERMI,
144
145 // Extended vector element extraction
146 VPICK_SEXT_ELT,
147 VPICK_ZEXT_ELT,
148
149 // Vector comparisons
150 VALL_ZERO,
151 VANY_ZERO,
152 VALL_NONZERO,
153 VANY_NONZERO,
154
155 // Floating point approximate reciprocal operation
156 FRECIPE,
157 FRSQRTE,
158
159 // Vector logicial left / right shift by immediate
160 VSLLI,
161 VSRLI,
162
163 // Vector byte logicial left / right shift
164 VBSLL,
165 VBSRL,
166
167 // Scalar load broadcast to vector
168 VLDREPL,
169
170 // Vector mask set by condition
171 VMSKLTZ,
172 VMSKGEZ,
173 VMSKEQZ,
174 VMSKNEZ,
175 XVMSKLTZ,
176 XVMSKGEZ,
177 XVMSKEQZ,
178 XVMSKNEZ,
179
180 // Intrinsic operations end =============================================
181};
182} // end namespace LoongArchISD
183
184class LoongArchTargetLowering : public TargetLowering {
185 const LoongArchSubtarget &Subtarget;
186
187public:
188 explicit LoongArchTargetLowering(const TargetMachine &TM,
189 const LoongArchSubtarget &STI);
190
191 const LoongArchSubtarget &getSubtarget() const { return Subtarget; }
192
193 bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;
194
195 // Provide custom lowering hooks for some operations.
196 SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;
197 void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results,
198 SelectionDAG &DAG) const override;
199
200 SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override;
201
202 // This method returns the name of a target specific DAG node.
203 const char *getTargetNodeName(unsigned Opcode) const override;
204
205 // Lower incoming arguments, copy physregs into vregs.
206 SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
207 bool IsVarArg,
208 const SmallVectorImpl<ISD::InputArg> &Ins,
209 const SDLoc &DL, SelectionDAG &DAG,
210 SmallVectorImpl<SDValue> &InVals) const override;
211 bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
212 bool IsVarArg,
213 const SmallVectorImpl<ISD::OutputArg> &Outs,
214 LLVMContext &Context, const Type *RetTy) const override;
215 SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
216 const SmallVectorImpl<ISD::OutputArg> &Outs,
217 const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
218 SelectionDAG &DAG) const override;
219 SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI,
220 SmallVectorImpl<SDValue> &InVals) const override;
221 bool isCheapToSpeculateCttz(Type *Ty) const override;
222 bool isCheapToSpeculateCtlz(Type *Ty) const override;
223 bool hasAndNot(SDValue Y) const override;
224 TargetLowering::AtomicExpansionKind
225 shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override;
226 void emitExpandAtomicRMW(AtomicRMWInst *AI) const override;
227
228 Value *emitMaskedAtomicRMWIntrinsic(IRBuilderBase &Builder, AtomicRMWInst *AI,
229 Value *AlignedAddr, Value *Incr,
230 Value *Mask, Value *ShiftAmt,
231 AtomicOrdering Ord) const override;
232
233 EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context,
234 EVT VT) const override;
235 TargetLowering::AtomicExpansionKind
236 shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *CI) const override;
237 Value *emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder,
238 AtomicCmpXchgInst *CI,
239 Value *AlignedAddr, Value *CmpVal,
240 Value *NewVal, Value *Mask,
241 AtomicOrdering Ord) const override;
242
243 bool getTgtMemIntrinsic(IntrinsicInfo &Info, const CallInst &I,
244 MachineFunction &MF,
245 unsigned Intrinsic) const override;
246
247 bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF,
248 EVT VT) const override;
249
250 Register
251 getExceptionPointerRegister(const Constant *PersonalityFn) const override;
252
253 Register
254 getExceptionSelectorRegister(const Constant *PersonalityFn) const override;
255
256 bool isFsqrtCheap(SDValue Operand, SelectionDAG &DAG) const override {
257 return true;
258 }
259
260 SDValue getSqrtEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled,
261 int &RefinementSteps, bool &UseOneConstNR,
262 bool Reciprocal) const override;
263
264 SDValue getRecipEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled,
265 int &RefinementSteps) const override;
266
267 ISD::NodeType getExtendForAtomicOps() const override {
268 return ISD::SIGN_EXTEND;
269 }
270
271 ISD::NodeType getExtendForAtomicCmpSwapArg() const override;
272
273 Register getRegisterByName(const char *RegName, LLT VT,
274 const MachineFunction &MF) const override;
275 bool mayBeEmittedAsTailCall(const CallInst *CI) const override;
276
277 bool decomposeMulByConstant(LLVMContext &Context, EVT VT,
278 SDValue C) const override;
279
280 bool isUsedByReturnOnly(SDNode *N, SDValue &Chain) const override;
281
282 bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty,
283 unsigned AS,
284 Instruction *I = nullptr) const override;
285
286 bool isLegalICmpImmediate(int64_t Imm) const override;
287 bool isLegalAddImmediate(int64_t Imm) const override;
288 bool isZExtFree(SDValue Val, EVT VT2) const override;
289 bool isSExtCheaperThanZExt(EVT SrcVT, EVT DstVT) const override;
290 bool signExtendConstant(const ConstantInt *CI) const override;
291
292 bool hasAndNotCompare(SDValue Y) const override;
293
294 bool convertSelectOfConstantsToMath(EVT VT) const override { return true; }
295
296 bool allowsMisalignedMemoryAccesses(
297 EVT VT, unsigned AddrSpace = 0, Align Alignment = Align(1),
298 MachineMemOperand::Flags Flags = MachineMemOperand::MONone,
299 unsigned *Fast = nullptr) const override;
300
301 bool isShuffleMaskLegal(ArrayRef<int> Mask, EVT VT) const override {
302 if (!VT.isSimple())
303 return false;
304
305 // Not for i1 vectors
306 if (VT.getSimpleVT().getScalarType() == MVT::i1)
307 return false;
308
309 return isTypeLegal(VT: VT.getSimpleVT());
310 }
311 bool shouldConsiderGEPOffsetSplit() const override { return true; }
312 bool shouldSignExtendTypeInLibCall(Type *Ty, bool IsSigned) const override;
313 bool shouldExtendTypeInLibCall(EVT Type) const override;
314
315 bool shouldAlignPointerArgs(CallInst *CI, unsigned &MinSize,
316 Align &PrefAlign) const override;
317
318 bool isFPImmVLDILegal(const APFloat &Imm, EVT VT) const;
319 LegalizeTypeAction getPreferredVectorAction(MVT VT) const override;
320
321 bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits,
322 const APInt &DemandedElts,
323 KnownBits &Known,
324 TargetLoweringOpt &TLO,
325 unsigned Depth) const override;
326
327private:
328 /// Target-specific function used to lower LoongArch calling conventions.
329 typedef bool LoongArchCCAssignFn(const DataLayout &DL, LoongArchABI::ABI ABI,
330 unsigned ValNo, MVT ValVT,
331 CCValAssign::LocInfo LocInfo,
332 ISD::ArgFlagsTy ArgFlags, CCState &State,
333 bool IsFixed, bool IsRet, Type *OrigTy);
334
335 void analyzeInputArgs(MachineFunction &MF, CCState &CCInfo,
336 const SmallVectorImpl<ISD::InputArg> &Ins, bool IsRet,
337 LoongArchCCAssignFn Fn) const;
338 void analyzeOutputArgs(MachineFunction &MF, CCState &CCInfo,
339 const SmallVectorImpl<ISD::OutputArg> &Outs,
340 bool IsRet, CallLoweringInfo *CLI,
341 LoongArchCCAssignFn Fn) const;
342
343 template <class NodeTy>
344 SDValue getAddr(NodeTy *N, SelectionDAG &DAG, CodeModel::Model M,
345 bool IsLocal = true) const;
346 SDValue getStaticTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG,
347 unsigned Opc, bool UseGOT, bool Large = false) const;
348 SDValue getDynamicTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG,
349 unsigned Opc, bool Large = false) const;
350 SDValue getTLSDescAddr(GlobalAddressSDNode *N, SelectionDAG &DAG,
351 unsigned Opc, bool Large = false) const;
352 SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
353 SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
354 SDValue lowerJumpTable(SDValue Op, SelectionDAG &DAG) const;
355 SDValue lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;
356 SDValue lowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const;
357 SDValue lowerShiftRightParts(SDValue Op, SelectionDAG &DAG, bool IsSRA) const;
358
359 MachineBasicBlock *
360 EmitInstrWithCustomInserter(MachineInstr &MI,
361 MachineBasicBlock *BB) const override;
362 SDValue lowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG) const;
363 SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
364 SDValue lowerEH_DWARF_CFA(SDValue Op, SelectionDAG &DAG) const;
365 SDValue lowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const;
366 SDValue lowerBITCAST(SDValue Op, SelectionDAG &DAG) const;
367 SDValue lowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG) const;
368 SDValue lowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) const;
369 SDValue lowerVASTART(SDValue Op, SelectionDAG &DAG) const;
370 SDValue lowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const;
371 SDValue lowerINTRINSIC_W_CHAIN(SDValue Op, SelectionDAG &DAG) const;
372 SDValue lowerINTRINSIC_VOID(SDValue Op, SelectionDAG &DAG) const;
373 SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
374 SDValue lowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
375 SDValue lowerWRITE_REGISTER(SDValue Op, SelectionDAG &DAG) const;
376 SDValue lowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const;
377 SDValue lowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const;
378 SDValue lowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const;
379 SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const;
380 SDValue lowerBITREVERSE(SDValue Op, SelectionDAG &DAG) const;
381 SDValue lowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) const;
382 SDValue lowerPREFETCH(SDValue Op, SelectionDAG &DAG) const;
383 SDValue lowerSELECT(SDValue Op, SelectionDAG &DAG) const;
384 SDValue lowerFP_TO_FP16(SDValue Op, SelectionDAG &DAG) const;
385 SDValue lowerFP16_TO_FP(SDValue Op, SelectionDAG &DAG) const;
386 SDValue lowerFP_TO_BF16(SDValue Op, SelectionDAG &DAG) const;
387 SDValue lowerBF16_TO_FP(SDValue Op, SelectionDAG &DAG) const;
388
389 bool isFPImmLegal(const APFloat &Imm, EVT VT,
390 bool ForCodeSize) const override;
391
392 bool shouldInsertFencesForAtomic(const Instruction *I) const override;
393
394 ConstraintType getConstraintType(StringRef Constraint) const override;
395
396 InlineAsm::ConstraintCode
397 getInlineAsmMemConstraint(StringRef ConstraintCode) const override;
398
399 std::pair<unsigned, const TargetRegisterClass *>
400 getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
401 StringRef Constraint, MVT VT) const override;
402
403 void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint,
404 std::vector<SDValue> &Ops,
405 SelectionDAG &DAG) const override;
406
407 bool isEligibleForTailCallOptimization(
408 CCState &CCInfo, CallLoweringInfo &CLI, MachineFunction &MF,
409 const SmallVectorImpl<CCValAssign> &ArgLocs) const;
410
411 bool softPromoteHalfType() const override { return true; }
412
413 bool
414 splitValueIntoRegisterParts(SelectionDAG &DAG, const SDLoc &DL, SDValue Val,
415 SDValue *Parts, unsigned NumParts, MVT PartVT,
416 std::optional<CallingConv::ID> CC) const override;
417
418 SDValue
419 joinRegisterPartsIntoValue(SelectionDAG &DAG, const SDLoc &DL,
420 const SDValue *Parts, unsigned NumParts,
421 MVT PartVT, EVT ValueVT,
422 std::optional<CallingConv::ID> CC) const override;
423
424 /// Return the register type for a given MVT, ensuring vectors are treated
425 /// as a series of gpr sized integers.
426 MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC,
427 EVT VT) const override;
428
429 /// Return the number of registers for a given MVT, ensuring vectors are
430 /// treated as a series of gpr sized integers.
431 unsigned getNumRegistersForCallingConv(LLVMContext &Context,
432 CallingConv::ID CC,
433 EVT VT) const override;
434};
435
436} // end namespace llvm
437
438#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELLOWERING_H
439