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/SelectionDAGNodes.h"
21#include "llvm/CodeGen/TargetLowering.h"
22
23namespace llvm {
24class LoongArchSubtarget;
25class LoongArchTargetLowering : public TargetLowering {
26 const LoongArchSubtarget &Subtarget;
27
28public:
29 explicit LoongArchTargetLowering(const TargetMachine &TM,
30 const LoongArchSubtarget &STI);
31
32 const LoongArchSubtarget &getSubtarget() const { return Subtarget; }
33
34 bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;
35
36 // Provide custom lowering hooks for some operations.
37 SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;
38 void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results,
39 SelectionDAG &DAG) const override;
40
41 SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override;
42
43 // Lower incoming arguments, copy physregs into vregs.
44 SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
45 bool IsVarArg,
46 const SmallVectorImpl<ISD::InputArg> &Ins,
47 const SDLoc &DL, SelectionDAG &DAG,
48 SmallVectorImpl<SDValue> &InVals) const override;
49 bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
50 bool IsVarArg,
51 const SmallVectorImpl<ISD::OutputArg> &Outs,
52 LLVMContext &Context, const Type *RetTy) const override;
53 SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
54 const SmallVectorImpl<ISD::OutputArg> &Outs,
55 const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
56 SelectionDAG &DAG) const override;
57 SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI,
58 SmallVectorImpl<SDValue> &InVals) const override;
59 bool canMergeStoresTo(unsigned AddressSpace, EVT MemVT,
60 const MachineFunction &MF) const override;
61 bool isCheapToSpeculateCttz(Type *Ty) const override;
62 bool isCheapToSpeculateCtlz(Type *Ty) const override;
63 bool hasAndNot(SDValue Y) const override;
64 TargetLowering::AtomicExpansionKind
65 shouldExpandAtomicRMWInIR(const AtomicRMWInst *AI) const override;
66 void emitExpandAtomicRMW(AtomicRMWInst *AI) const override;
67
68 Value *emitMaskedAtomicRMWIntrinsic(IRBuilderBase &Builder, AtomicRMWInst *AI,
69 Value *AlignedAddr, Value *Incr,
70 Value *Mask, Value *ShiftAmt,
71 AtomicOrdering Ord) const override;
72
73 EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context,
74 EVT VT) const override;
75 TargetLowering::AtomicExpansionKind
76 shouldExpandAtomicCmpXchgInIR(const AtomicCmpXchgInst *CI) const override;
77 Value *emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder,
78 AtomicCmpXchgInst *CI,
79 Value *AlignedAddr, Value *CmpVal,
80 Value *NewVal, Value *Mask,
81 AtomicOrdering Ord) const override;
82
83 void getTgtMemIntrinsic(SmallVectorImpl<IntrinsicInfo> &Infos,
84 const CallBase &I, MachineFunction &MF,
85 unsigned Intrinsic) const override;
86
87 bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF,
88 EVT VT) const override;
89
90 Register
91 getExceptionPointerRegister(ExceptionHandling EH,
92 const Constant *PersonalityFn) const override;
93
94 Register
95 getExceptionSelectorRegister(ExceptionHandling EH,
96 const Constant *PersonalityFn) const override;
97
98 bool isFsqrtCheap(SDValue Operand, SelectionDAG &DAG) const override {
99 return true;
100 }
101
102 SDValue getSqrtEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled,
103 int &RefinementSteps, bool &UseOneConstNR,
104 bool Reciprocal) const override;
105
106 SDValue getRecipEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled,
107 int &RefinementSteps) const override;
108
109 ISD::NodeType getExtendForAtomicOps() const override {
110 return ISD::SIGN_EXTEND;
111 }
112
113 ISD::NodeType getExtendForAtomicCmpSwapArg() const override;
114
115 Register getRegisterByName(const char *RegName, LLT VT,
116 const MachineFunction &MF) const override;
117 bool mayBeEmittedAsTailCall(const CallInst *CI) const override;
118
119 bool decomposeMulByConstant(LLVMContext &Context, EVT VT,
120 SDValue C) const override;
121
122 bool isUsedByReturnOnly(SDNode *N, SDValue &Chain) const override;
123
124 bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty,
125 unsigned AS,
126 Instruction *I = nullptr) const override;
127
128 bool isLegalICmpImmediate(int64_t Imm) const override;
129 bool isLegalAddImmediate(int64_t Imm) const override;
130 bool isZExtFree(SDValue Val, EVT VT2) const override;
131 bool isSExtCheaperThanZExt(EVT SrcVT, EVT DstVT) const override;
132 bool signExtendConstant(const ConstantInt *CI) const override;
133
134 bool hasAndNotCompare(SDValue Y) const override;
135
136 bool convertSelectOfConstantsToMath(EVT VT) const override { return true; }
137
138 bool allowsMisalignedMemoryAccesses(
139 EVT VT, unsigned AddrSpace = 0, Align Alignment = Align(1),
140 MachineMemOperand::Flags Flags = MachineMemOperand::MONone,
141 unsigned *Fast = nullptr) const override;
142
143 bool isShuffleMaskLegal(ArrayRef<int> Mask, EVT VT) const override {
144 if (!VT.isSimple())
145 return false;
146
147 // Not for i1 vectors
148 if (VT.getSimpleVT().getScalarType() == MVT::i1)
149 return false;
150
151 return isTypeLegal(VT: VT.getSimpleVT());
152 }
153 bool shouldConsiderGEPOffsetSplit() const override { return true; }
154 bool shouldSignExtendTypeInLibCall(Type *Ty, bool IsSigned) const override;
155 bool shouldExtendTypeInLibCall(EVT Type) const override;
156
157 bool shouldAlignPointerArgs(CallInst *CI, unsigned &MinSize,
158 Align &PrefAlign) const override;
159
160 bool isFPImmVLDILegal(const APFloat &Imm, EVT VT) const;
161 LegalizeTypeAction getPreferredVectorAction(MVT VT) const override;
162
163 void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known,
164 const APInt &DemandedElts,
165 const SelectionDAG &DAG,
166 unsigned Depth) const override;
167 bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits,
168 const APInt &DemandedElts,
169 KnownBits &Known,
170 TargetLoweringOpt &TLO,
171 unsigned Depth) const override;
172
173 bool shouldScalarizeBinop(SDValue VecOp) const override;
174 ExtractSubvectorCost getExtractSubvectorCost(EVT ResVT, EVT SrcVT,
175 unsigned Index) const override;
176 bool isExtractVecEltCheap(EVT VT, unsigned Index) const override;
177
178 /// Check if a constant splat can be generated using [x]vldi, where imm[12]
179 /// is 1.
180 std::pair<bool, uint64_t>
181 isImmVLDILegalForMode1(const APInt &SplatValue,
182 const unsigned SplatBitSize) const;
183
184 /// True if stack clash protection is enabled for this function.
185 bool hasInlineStackProbe(const MachineFunction &MF) const override;
186
187 unsigned getStackProbeSize(const MachineFunction &MF, Align StackAlign) const;
188
189 MachineBasicBlock *emitDynamicProbedAlloc(MachineInstr &MI,
190 MachineBasicBlock *MBB) const;
191
192private:
193 /// Target-specific function used to lower LoongArch calling conventions.
194 typedef bool LoongArchCCAssignFn(const DataLayout &DL, LoongArchABI::ABI ABI,
195 unsigned ValNo, MVT ValVT,
196 CCValAssign::LocInfo LocInfo,
197 ISD::ArgFlagsTy ArgFlags, CCState &State,
198 bool IsRet, Type *OrigTy);
199
200 void analyzeInputArgs(MachineFunction &MF, CCState &CCInfo,
201 const SmallVectorImpl<ISD::InputArg> &Ins, bool IsRet,
202 LoongArchCCAssignFn Fn) const;
203 void analyzeOutputArgs(MachineFunction &MF, CCState &CCInfo,
204 const SmallVectorImpl<ISD::OutputArg> &Outs,
205 bool IsRet, CallLoweringInfo *CLI,
206 LoongArchCCAssignFn Fn) const;
207
208 template <class NodeTy>
209 SDValue getAddr(NodeTy *N, SelectionDAG &DAG, CodeModel::Model M,
210 bool IsLocal = true) const;
211 SDValue getStaticTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG,
212 unsigned Opc, bool UseGOT, bool Large = false) const;
213 SDValue getDynamicTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG,
214 unsigned Opc, bool Large = false) const;
215 SDValue getTLSDescAddr(GlobalAddressSDNode *N, SelectionDAG &DAG,
216 unsigned Opc, bool Large = false) const;
217 SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
218 SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
219 SDValue lowerJumpTable(SDValue Op, SelectionDAG &DAG) const;
220 SDValue lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;
221 SDValue lowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const;
222 SDValue lowerShiftRightParts(SDValue Op, SelectionDAG &DAG, bool IsSRA) const;
223
224 MachineBasicBlock *
225 EmitInstrWithCustomInserter(MachineInstr &MI,
226 MachineBasicBlock *BB) const override;
227 SDValue lowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG) const;
228 SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
229 SDValue lowerEH_DWARF_CFA(SDValue Op, SelectionDAG &DAG) const;
230 SDValue lowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const;
231 SDValue lowerFP_TO_UINT(SDValue Op, SelectionDAG &DAG) const;
232 SDValue lowerBITCAST(SDValue Op, SelectionDAG &DAG) const;
233 SDValue lowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG) const;
234 SDValue lowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) const;
235 SDValue lowerVASTART(SDValue Op, SelectionDAG &DAG) const;
236 SDValue lowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const;
237 SDValue lowerINTRINSIC_W_CHAIN(SDValue Op, SelectionDAG &DAG) const;
238 SDValue lowerINTRINSIC_VOID(SDValue Op, SelectionDAG &DAG) const;
239 SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
240 SDValue lowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
241 SDValue lowerSET_ROUNDING(SDValue Op, SelectionDAG &DAG) const;
242 SDValue lowerGET_ROUNDING(SDValue Op, SelectionDAG &DAG) const;
243 SDValue lowerWRITE_REGISTER(SDValue Op, SelectionDAG &DAG) const;
244 SDValue lowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const;
245 SDValue lowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const;
246 SDValue lowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const;
247 SDValue lowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG) const;
248 SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const;
249 SDValue lowerBITREVERSE(SDValue Op, SelectionDAG &DAG) const;
250 SDValue lowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) const;
251 SDValue lowerPREFETCH(SDValue Op, SelectionDAG &DAG) const;
252 SDValue lowerSELECT(SDValue Op, SelectionDAG &DAG) const;
253 SDValue lowerBRCOND(SDValue Op, SelectionDAG &DAG) const;
254 SDValue lowerFP_TO_FP16(SDValue Op, SelectionDAG &DAG) const;
255 SDValue lowerFP16_TO_FP(SDValue Op, SelectionDAG &DAG) const;
256 SDValue lowerFP_TO_BF16(SDValue Op, SelectionDAG &DAG) const;
257 SDValue lowerBF16_TO_FP(SDValue Op, SelectionDAG &DAG) const;
258 SDValue lowerVECREDUCE_ADD(SDValue Op, SelectionDAG &DAG) const;
259 SDValue lowerVECREDUCE(SDValue Op, SelectionDAG &DAG) const;
260 SDValue lowerConstantFP(SDValue Op, SelectionDAG &DAG) const;
261 SDValue lowerSETCC(SDValue Op, SelectionDAG &DAG) const;
262 SDValue lowerRotate(SDValue Op, SelectionDAG &DAG) const;
263 SDValue lowerFP_ROUND(SDValue Op, SelectionDAG &DAG) const;
264 SDValue lowerFP_EXTEND(SDValue Op, SelectionDAG &DAG) const;
265 SDValue lowerSIGN_EXTEND_VECTOR_INREG(SDValue Op, SelectionDAG &DAG) const;
266 SDValue lowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const;
267 SDValue lowerANY_EXTEND(SDValue Op, SelectionDAG &DAG) const;
268
269 bool isFPImmLegal(const APFloat &Imm, EVT VT,
270 bool ForCodeSize) const override;
271
272 bool shouldInsertFencesForAtomic(const Instruction *I) const override;
273
274 ConstraintType getConstraintType(StringRef Constraint) const override;
275
276 InlineAsm::ConstraintCode
277 getInlineAsmMemConstraint(StringRef ConstraintCode) const override;
278
279 std::pair<unsigned, const TargetRegisterClass *>
280 getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
281 StringRef Constraint, MVT VT) const override;
282
283 void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint,
284 std::vector<SDValue> &Ops,
285 SelectionDAG &DAG) const override;
286
287 bool isEligibleForTailCallOptimization(
288 CCState &CCInfo, CallLoweringInfo &CLI, MachineFunction &MF,
289 const SmallVectorImpl<CCValAssign> &ArgLocs) const;
290
291 bool
292 splitValueIntoRegisterParts(SelectionDAG &DAG, const SDLoc &DL, SDValue Val,
293 SDValue *Parts, unsigned NumParts, MVT PartVT,
294 std::optional<CallingConv::ID> CC) const override;
295
296 SDValue
297 joinRegisterPartsIntoValue(SelectionDAG &DAG, const SDLoc &DL,
298 const SDValue *Parts, unsigned NumParts,
299 MVT PartVT, EVT ValueVT,
300 std::optional<CallingConv::ID> CC) const override;
301
302 /// Return the register type for a given MVT, ensuring vectors are treated
303 /// as a series of gpr sized integers.
304 MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC,
305 EVT VT) const override;
306
307 /// Return the number of registers for a given MVT, ensuring vectors are
308 /// treated as a series of gpr sized integers.
309 unsigned getNumRegistersForCallingConv(LLVMContext &Context,
310 CallingConv::ID CC,
311 EVT VT) const override;
312};
313
314} // end namespace llvm
315
316#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELLOWERING_H
317