1//===-- NVPTXISelLowering.h - NVPTX 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 NVPTX uses to lower LLVM code into a
10// selection DAG.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_LIB_TARGET_NVPTX_NVPTXISELLOWERING_H
15#define LLVM_LIB_TARGET_NVPTX_NVPTXISELLOWERING_H
16
17#include "NVPTX.h"
18#include "llvm/CodeGen/SelectionDAG.h"
19#include "llvm/CodeGen/TargetLowering.h"
20#include "llvm/Support/AtomicOrdering.h"
21
22namespace llvm {
23
24class NVPTXSubtarget;
25
26//===--------------------------------------------------------------------===//
27// TargetLowering Implementation
28//===--------------------------------------------------------------------===//
29class NVPTXTargetLowering : public TargetLowering {
30public:
31 explicit NVPTXTargetLowering(const NVPTXTargetMachine &TM,
32 const NVPTXSubtarget &STI);
33 SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;
34
35 void getTgtMemIntrinsic(SmallVectorImpl<IntrinsicInfo> &Infos,
36 const CallBase &I, MachineFunction &MF,
37 unsigned Intrinsic) const override;
38
39 // Helper for getting a function parameter name. Name is composed from
40 // its index and the function name. Negative index corresponds to special
41 // parameter (unsized array) used for passing variable arguments.
42 std::string getParamName(const Function *F, int Idx) const;
43
44 /// isLegalAddressingMode - Return true if the addressing mode represented
45 /// by AM is legal for this target, for a load/store of the specified type
46 /// Used to guide target specific optimizations, like loop strength
47 /// reduction (LoopStrengthReduce.cpp) and memory optimization for
48 /// address mode (CodeGenPrepare.cpp)
49 bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty,
50 unsigned AS,
51 Instruction *I = nullptr) const override;
52
53 bool isTruncateFree(Type *SrcTy, Type *DstTy) const override {
54 // Truncating 64-bit to 32-bit is free in SASS.
55 if (!SrcTy->isIntegerTy() || !DstTy->isIntegerTy())
56 return false;
57 return SrcTy->getPrimitiveSizeInBits() == 64 &&
58 DstTy->getPrimitiveSizeInBits() == 32;
59 }
60
61 EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Ctx,
62 EVT VT) const override {
63 if (VT.isVector())
64 return EVT::getVectorVT(Context&: Ctx, VT: MVT::i1, NumElements: VT.getVectorNumElements());
65 return MVT::i1;
66 }
67
68 ConstraintType getConstraintType(StringRef Constraint) const override;
69 std::pair<unsigned, const TargetRegisterClass *>
70 getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
71 StringRef Constraint, MVT VT) const override;
72
73 SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
74 bool isVarArg,
75 const SmallVectorImpl<ISD::InputArg> &Ins,
76 const SDLoc &dl, SelectionDAG &DAG,
77 SmallVectorImpl<SDValue> &InVals) const override;
78
79 SDValue LowerCall(CallLoweringInfo &CLI,
80 SmallVectorImpl<SDValue> &InVals) const override;
81
82 SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const;
83 SDValue LowerSTACKSAVE(SDValue Op, SelectionDAG &DAG) const;
84 SDValue LowerSTACKRESTORE(SDValue Op, SelectionDAG &DAG) const;
85
86 SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
87 const SmallVectorImpl<ISD::OutputArg> &Outs,
88 const SmallVectorImpl<SDValue> &OutVals, const SDLoc &dl,
89 SelectionDAG &DAG) const override;
90
91 void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint,
92 std::vector<SDValue> &Ops,
93 SelectionDAG &DAG) const override;
94
95 const NVPTXTargetMachine *nvTM;
96
97 // PTX always uses 32-bit shift amounts
98 MVT getScalarShiftAmountTy(const DataLayout &, EVT) const override {
99 return MVT::i32;
100 }
101
102 TargetLoweringBase::LegalizeTypeAction
103 getPreferredVectorAction(MVT VT) const override;
104
105 // Get the degree of precision we want from 32-bit floating point division
106 // operations.
107 NVPTX::DivPrecisionLevel getDivF32Level(const MachineFunction &MF,
108 const SDNode &N) const;
109
110 // Get whether we should use a precise or approximate 32-bit floating point
111 // sqrt instruction.
112 bool usePrecSqrtF32(const SDNode *N = nullptr) const;
113
114 // Get whether we should use instructions that flush floating-point denormals
115 // to sign-preserving zero.
116 bool useF32FTZ(const MachineFunction &MF) const;
117
118 SDValue getSqrtEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled,
119 int &ExtraSteps, bool &UseOneConst,
120 bool Reciprocal) const override;
121
122 unsigned combineRepeatedFPDivisors() const override { return 2; }
123
124 bool allowFMA(MachineFunction &MF, CodeGenOptLevel OptLevel) const;
125
126 bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF,
127 EVT) const override {
128 return true;
129 }
130
131 // The default is the same as pointer type, but brx.idx only accepts i32
132 MVT getJumpTableRegTy(const DataLayout &) const override { return MVT::i32; }
133
134 unsigned getJumpTableEncoding() const override;
135
136 bool enableAggressiveFMAFusion(EVT VT) const override { return true; }
137
138 // The default is to transform llvm.ctlz(x, false) (where false indicates that
139 // x == 0 is not undefined behavior) into a branch that checks whether x is 0
140 // and avoids calling ctlz in that case. We have a dedicated ctlz
141 // instruction, so we say that ctlz is cheap to speculate.
142 bool isCheapToSpeculateCtlz(Type *Ty) const override { return true; }
143
144 AtomicExpansionKind shouldCastAtomicLoadInIR(LoadInst *LI) const override {
145 return AtomicExpansionKind::None;
146 }
147
148 AtomicExpansionKind shouldCastAtomicStoreInIR(StoreInst *SI) const override {
149 return AtomicExpansionKind::None;
150 }
151
152 AtomicExpansionKind
153 shouldExpandAtomicRMWInIR(const AtomicRMWInst *AI) const override;
154
155 bool aggressivelyPreferBuildVectorSources(EVT VecVT) const override {
156 // There's rarely any point of packing something into a vector type if we
157 // already have the source data.
158 return true;
159 }
160
161 bool shouldInsertFencesForAtomic(const Instruction *) const override;
162
163 AtomicOrdering
164 atomicOperationOrderAfterFenceSplit(const Instruction *I) const override;
165
166 Instruction *emitLeadingFence(IRBuilderBase &Builder, Instruction *Inst,
167 AtomicOrdering Ord) const override;
168 Instruction *emitTrailingFence(IRBuilderBase &Builder, Instruction *Inst,
169 AtomicOrdering Ord) const override;
170
171 unsigned getPreferredFPToIntOpcode(unsigned Op, EVT FromVT,
172 EVT ToVT) const override;
173
174 void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known,
175 const APInt &DemandedElts,
176 const SelectionDAG &DAG,
177 unsigned Depth = 0) const override;
178 bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits,
179 const APInt &DemandedElts,
180 KnownBits &Known,
181 TargetLoweringOpt &TLO,
182 unsigned Depth = 0) const override;
183
184private:
185 const NVPTXSubtarget &STI; // cache the subtarget here
186 mutable unsigned GlobalUniqueCallSite;
187
188 SDValue getParamSymbol(SelectionDAG &DAG, int I, EVT T) const;
189 SDValue getCallParamSymbol(SelectionDAG &DAG, int I, EVT T) const;
190 SDValue LowerADDRSPACECAST(SDValue Op, SelectionDAG &DAG) const;
191 SDValue LowerBITCAST(SDValue Op, SelectionDAG &DAG) const;
192
193 SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const;
194 SDValue LowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG) const;
195 SDValue LowerVECREDUCE(SDValue Op, SelectionDAG &DAG) const;
196 SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const;
197 SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const;
198 SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const;
199
200 SDValue LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const;
201
202 SDValue LowerFROUND(SDValue Op, SelectionDAG &DAG) const;
203 SDValue LowerFROUND32(SDValue Op, SelectionDAG &DAG) const;
204 SDValue LowerFROUND64(SDValue Op, SelectionDAG &DAG) const;
205
206 SDValue PromoteBinOpIfF32FTZ(SDValue Op, SelectionDAG &DAG) const;
207
208 SDValue LowerINT_TO_FP(SDValue Op, SelectionDAG &DAG) const;
209 SDValue LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG) const;
210
211 SDValue LowerFP_ROUND(SDValue Op, SelectionDAG &DAG) const;
212 SDValue LowerFP_EXTEND(SDValue Op, SelectionDAG &DAG) const;
213
214 SDValue LowerLOAD(SDValue Op, SelectionDAG &DAG) const;
215 SDValue LowerMLOAD(SDValue Op, SelectionDAG &DAG) const;
216 SDValue LowerSTORE(SDValue Op, SelectionDAG &DAG) const;
217 SDValue LowerSTOREi1(SDValue Op, SelectionDAG &DAG) const;
218
219 SDValue LowerShiftRightParts(SDValue Op, SelectionDAG &DAG) const;
220 SDValue LowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const;
221
222 SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG) const;
223 SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const;
224
225 SDValue LowerCopyToReg_128(SDValue Op, SelectionDAG &DAG) const;
226 unsigned getNumRegisters(LLVMContext &Context, EVT VT,
227 std::optional<MVT> RegisterVT) const override;
228 bool
229 splitValueIntoRegisterParts(SelectionDAG &DAG, const SDLoc &DL, SDValue Val,
230 SDValue *Parts, unsigned NumParts, MVT PartVT,
231 std::optional<CallingConv::ID> CC) const override;
232
233 void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results,
234 SelectionDAG &DAG) const override;
235 SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override;
236
237 bool mayFoldFMULIntoFMA(SDNode *N, MachineFunction &MF,
238 CodeGenOptLevel OptLevel) const;
239 SDValue performScalarizeV2F32Op(SDNode *N, DAGCombinerInfo &DCI,
240 CodeGenOptLevel OptLevel) const;
241 SDValue performFADDCombineWithOperands(SDNode *N, SDValue N0, SDValue N1,
242 DAGCombinerInfo &DCI,
243 CodeGenOptLevel OptLevel) const;
244 SDValue performFADDCombine(SDNode *N, DAGCombinerInfo &DCI,
245 CodeGenOptLevel OptLevel) const;
246};
247
248} // namespace llvm
249
250#endif
251