LLVM 24.0.0git
RISCVSelectionDAGInfo.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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
10#include "RISCVSubtarget.h"
12
13#define GET_SDNODE_DESC
14#include "RISCVGenSDNodeInfo.inc"
15
16using namespace llvm;
17
20
22
24 const SDNode *N) const {
26
27#ifndef NDEBUG
28 // Some additional checks not yet implemented by verifyTargetNode.
29 switch (N->getOpcode()) {
30 case RISCVISD::TUPLE_EXTRACT:
31 assert(N->getOperand(1).getOpcode() == ISD::TargetConstant &&
32 "Expected index to be a target constant!");
33 break;
34 case RISCVISD::TUPLE_INSERT:
35 assert(N->getOperand(2).getOpcode() == ISD::TargetConstant &&
36 "Expected index to be a target constant!");
37 break;
38 case RISCVISD::TUPLE_CAST: {
39 EVT VT = N->getValueType(0);
40 EVT OpVT = N->getOperand(0).getValueType();
42 "Expected input and output of TUPLE_CAST to be vector tuples");
43 unsigned NF = VT.getRISCVVectorTupleNumFields();
44 unsigned OpNF = OpVT.getRISCVVectorTupleNumFields();
45 unsigned LMUL = divideCeil(VT.getSizeInBits().getKnownMinValue(),
47 unsigned OpLMUL = divideCeil(OpVT.getSizeInBits().getKnownMinValue(),
49 assert(NF == OpNF && LMUL == OpLMUL &&
50 "Expected input and output of TUPLE_CAST to have the same "
51 "factor and LMUL");
52 break;
53 }
54 case RISCVISD::VDOT4A_VL:
55 case RISCVISD::VDOT4AU_VL:
56 case RISCVISD::VDOT4ASU_VL: {
57 EVT VT = N->getValueType(0);
58 assert(VT.isScalableVectorOf(MVT::i32) &&
59 "Expected result to be an i32 scalable vector");
60 assert(N->getOperand(0).getValueType() == VT &&
61 N->getOperand(1).getValueType() == VT &&
62 N->getOperand(2).getValueType() == VT &&
63 "Expected result and first 3 operands to have the same type!");
64 EVT MaskVT = N->getOperand(3).getValueType();
65 assert(MaskVT.isScalableVector() &&
67 "Expected mask VT to be an i1 scalable vector with same number of "
68 "elements as the result");
69 break;
70 }
71 case RISCVISD::PNCLIPP:
72 case RISCVISD::PNCLIPUP: {
73 EVT VT = N->getValueType(0);
74 EVT OpVT = N->getOperand(0).getValueType();
75 assert(VT.isVector() && "Expected vector result");
76 assert(VT.getSizeInBits() == OpVT.getSizeInBits() &&
77 "Expected result and operands to have the same size!");
78 assert(N->getOperand(1).getValueType() == OpVT &&
79 "Expected operands to have the same type");
80 assert(((!OpVT.isVector() && VT.getVectorNumElements() == 2) ||
81 (OpVT.isVector() &&
82 OpVT.getVectorNumElements() * 2 == VT.getVectorNumElements())) &&
83 "Expected operands to be scalar or a vector with half the number of "
84 "elements");
85 break;
86 }
87 }
88#endif
89}
90
92 SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Dst, SDValue Src,
93 SDValue Size, Align Alignment, bool isVolatile, bool AlwaysInline,
94 MachinePointerInfo DstPtrInfo) const {
95 const auto &Subtarget = DAG.getSubtarget<RISCVSubtarget>();
96 // We currently do this only for Xqcilsm
97 if (!Subtarget.hasVendorXqcilsm())
98 return SDValue();
99
100 // Do this only if we know the size at compile time.
102 if (!ConstantSize)
103 return SDValue();
104
105 uint64_t NumberOfBytesToWrite = ConstantSize->getZExtValue();
106
107 // Do this only if it is word aligned and we write a multiple of 4 bytes.
108 if (!(Alignment >= 4) || !((NumberOfBytesToWrite & 3) == 0))
109 return SDValue();
110
111 SmallVector<SDValue, 8> OutChains;
112 SDValue SrcValueReplicated = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i32, Src);
113 int NumberOfWords = NumberOfBytesToWrite / 4;
115 auto Volatile =
117
118 // Helper for constructing the QC_SETWMI instruction
119 auto getSetwmiNode = [&](uint8_t SizeWords, uint8_t OffsetSetwmi) -> SDValue {
120 SDValue Ops[] = {Chain, SrcValueReplicated, Dst,
121 DAG.getTargetConstant(SizeWords, dl, MVT::i32),
122 DAG.getTargetConstant(OffsetSetwmi, dl, MVT::i32)};
123 MachineMemOperand *BaseMemOperand = MF.getMachineMemOperand(
124 DstPtrInfo.getWithOffset(OffsetSetwmi),
125 MachineMemOperand::MOStore | Volatile, SizeWords * 4, Align(4));
126 return DAG.getMemIntrinsicNode(RISCVISD::QC_SETWMI, dl,
127 DAG.getVTList(MVT::Other), Ops, MVT::i32,
128 BaseMemOperand);
129 };
130
131 // If i8 type and constant non-zero value.
132 if ((Src.getValueType() == MVT::i8) && !isNullConstant(Src))
133 // Replicate byte to word by multiplication with 0x01010101.
134 SrcValueReplicated =
135 DAG.getNode(ISD::MUL, dl, MVT::i32, SrcValueReplicated,
136 DAG.getConstant(0x01010101ul, dl, MVT::i32));
137
138 // We limit a QC_SETWMI to 16 words or less to improve interruptibility.
139 // So for 1-16 words we use a single QC_SETWMI:
140 //
141 // QC_SETWMI reg1, N, 0(reg2)
142 //
143 // For 17-32 words we use two QC_SETWMI's with the first as 16 words and the
144 // second for the remainder:
145 //
146 // QC_SETWMI reg1, 16, 0(reg2)
147 // QC_SETWMI reg1, N, 64(reg2)
148 //
149 // For 33-48 words, we would like to use (16, 16, n), but that means the last
150 // QC_SETWMI needs an offset of 128 which the instruction doesn't support.
151 // So in this case we use a length of 15 for the second instruction and we do
152 // the rest with the third instruction.
153 // This means the maximum inlined number of words is 47 (for now):
154 //
155 // QC_SETWMI R2, R0, 16, 0
156 // QC_SETWMI R2, R0, 15, 64
157 // QC_SETWMI R2, R0, N, 124
158 //
159 // For 48 words or more, call the target independent memset
160 if (NumberOfWords >= 48)
161 return SDValue();
162
163 if (NumberOfWords <= 16) {
164 // 1 - 16 words
165 return getSetwmiNode(NumberOfWords, 0);
166 }
167
168 if (NumberOfWords <= 32) {
169 // 17 - 32 words
170 OutChains.push_back(getSetwmiNode(NumberOfWords - 16, 64));
171 OutChains.push_back(getSetwmiNode(16, 0));
172 } else {
173 // 33 - 47 words
174 OutChains.push_back(getSetwmiNode(NumberOfWords - 31, 124));
175 OutChains.push_back(getSetwmiNode(15, 64));
176 OutChains.push_back(getSetwmiNode(16, 0));
177 }
178
179 return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains);
180}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
uint64_t getZExtValue() const
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
A description of a memory reference used in the backend.
@ MOVolatile
The memory access is volatile.
@ MOStore
The memory access writes data.
SDValue EmitTargetCodeForMemset(SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Dst, SDValue Src, SDValue Size, Align Alignment, bool isVolatile, bool AlwaysInline, MachinePointerInfo DstPtrInfo) const override
Emit target-specific code that performs a memset.
void verifyTargetNode(const SelectionDAG &DAG, const SDNode *N) const override
Checks that the given target-specific node is valid. Aborts if it is not.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SelectionDAGGenTargetInfo(const SDNodeInfo &GenNodeInfo)
void verifyTargetNode(const SelectionDAG &DAG, const SDNode *N) const override
Checks that the given target-specific node is valid. Aborts if it is not.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
const TargetSubtargetInfo & getSubtarget() const
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef< SDValue > Ops, EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MOLoad|MachineMemOperand::MOStore, LocationSize Size=LocationSize::precise(0), const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
MachineFunction & getMachineFunction() const
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:165
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:868
@ TargetConstant
TargetConstant* - Like Constant*, but the DAG does not do any folding, simplification,...
Definition ISDOpcodes.h:181
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
Definition ISDOpcodes.h:55
static constexpr unsigned RVVBitsPerBlock
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:389
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
Extended Value Type.
Definition ValueTypes.h:35
bool isScalableVectorOf(EVT EltVT) const
Return true if this is a scalable vector with matching element type.
Definition ValueTypes.h:192
ElementCount getVectorElementCount() const
Definition ValueTypes.h:373
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition ValueTypes.h:396
unsigned getRISCVVectorTupleNumFields() const
Given a RISCV vector tuple type, return the num_fields.
Definition ValueTypes.h:387
bool isRISCVVectorTuple() const
Return true if this is a vector value type.
Definition ValueTypes.h:197
bool isVector() const
Return true if this is a vector value type.
Definition ValueTypes.h:176
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
Definition ValueTypes.h:187
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
Definition ValueTypes.h:359
This class contains a discriminated union of information about pointers in memory operands,...
MachinePointerInfo getWithOffset(int64_t O) const