LLVM 22.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
19 : SelectionDAGGenTargetInfo(RISCVGenSDNodeInfo) {}
20
22
24 const SDNode *N) const {
25#ifndef NDEBUG
26 switch (N->getOpcode()) {
27 default:
29 case RISCVISD::TUPLE_EXTRACT:
30 assert(N->getNumOperands() == 2 && "Expected three operands!");
31 assert(N->getOperand(1).getOpcode() == ISD::TargetConstant &&
32 N->getOperand(1).getValueType() == MVT::i32 &&
33 "Expected index to be an i32 target constant!");
34 break;
35 case RISCVISD::TUPLE_INSERT:
36 assert(N->getNumOperands() == 3 && "Expected three operands!");
37 assert(N->getOperand(2).getOpcode() == ISD::TargetConstant &&
38 N->getOperand(2).getValueType() == MVT::i32 &&
39 "Expected index to be an i32 target constant!");
40 break;
41 case RISCVISD::VQDOT_VL:
42 case RISCVISD::VQDOTU_VL:
43 case RISCVISD::VQDOTSU_VL: {
44 assert(N->getNumValues() == 1 && "Expected one result!");
45 assert(N->getNumOperands() == 5 && "Expected five operands!");
46 EVT VT = N->getValueType(0);
47 assert(VT.isScalableVector() && VT.getVectorElementType() == MVT::i32 &&
48 "Expected result to be an i32 scalable vector");
49 assert(N->getOperand(0).getValueType() == VT &&
50 N->getOperand(1).getValueType() == VT &&
51 N->getOperand(2).getValueType() == VT &&
52 "Expected result and first 3 operands to have the same type!");
53 EVT MaskVT = N->getOperand(3).getValueType();
54 assert(MaskVT.isScalableVector() &&
55 MaskVT.getVectorElementType() == MVT::i1 &&
57 "Expected mask VT to be an i1 scalable vector with same number of "
58 "elements as the result");
59 assert((N->getOperand(4).getValueType() == MVT::i32 ||
60 N->getOperand(4).getValueType() == MVT::i64) &&
61 "Expect VL operand to be i32 or i64");
62 break;
63 }
64 }
65#endif
66}
67
69 SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Dst, SDValue Src,
70 SDValue Size, Align Alignment, bool isVolatile, bool AlwaysInline,
71 MachinePointerInfo DstPtrInfo) const {
72 const auto &Subtarget = DAG.getSubtarget<RISCVSubtarget>();
73 // We currently do this only for Xqcilsm
74 if (!Subtarget.hasVendorXqcilsm())
75 return SDValue();
76
77 // Do this only if we know the size at compile time.
78 ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
79 if (!ConstantSize)
80 return SDValue();
81
82 uint64_t NumberOfBytesToWrite = ConstantSize->getZExtValue();
83
84 // Do this only if it is word aligned and we write a multiple of 4 bytes.
85 if (!(Alignment >= 4) || !((NumberOfBytesToWrite & 3) == 0))
86 return SDValue();
87
89 SDValue SrcValueReplicated = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i32, Src);
90 int NumberOfWords = NumberOfBytesToWrite / 4;
92 auto Volatile =
94
95 // Helper for constructing the QC_SETWMI instruction
96 auto getSetwmiNode = [&](uint8_t SizeWords, uint8_t OffsetSetwmi) -> SDValue {
97 SDValue Ops[] = {Chain, SrcValueReplicated, Dst,
98 DAG.getTargetConstant(SizeWords, dl, MVT::i32),
99 DAG.getTargetConstant(OffsetSetwmi, dl, MVT::i32)};
100 MachineMemOperand *BaseMemOperand = MF.getMachineMemOperand(
101 DstPtrInfo.getWithOffset(OffsetSetwmi),
102 MachineMemOperand::MOStore | Volatile, SizeWords * 4, Align(4));
103 return DAG.getMemIntrinsicNode(RISCVISD::QC_SETWMI, dl,
104 DAG.getVTList(MVT::Other), Ops, MVT::i32,
105 BaseMemOperand);
106 };
107
108 // If i8 type and constant non-zero value.
109 if ((Src.getValueType() == MVT::i8) && !isNullConstant(Src))
110 // Replicate byte to word by multiplication with 0x01010101.
111 SrcValueReplicated =
112 DAG.getNode(ISD::MUL, dl, MVT::i32, SrcValueReplicated,
113 DAG.getConstant(0x01010101ul, dl, MVT::i32));
114
115 // We limit a QC_SETWMI to 16 words or less to improve interruptibility.
116 // So for 1-16 words we use a single QC_SETWMI:
117 //
118 // QC_SETWMI reg1, N, 0(reg2)
119 //
120 // For 17-32 words we use two QC_SETWMI's with the first as 16 words and the
121 // second for the remainder:
122 //
123 // QC_SETWMI reg1, 16, 0(reg2)
124 // QC_SETWMI reg1, N, 64(reg2)
125 //
126 // For 33-48 words, we would like to use (16, 16, n), but that means the last
127 // QC_SETWMI needs an offset of 128 which the instruction doesn't support.
128 // So in this case we use a length of 15 for the second instruction and we do
129 // the rest with the third instruction.
130 // This means the maximum inlined number of words is 47 (for now):
131 //
132 // QC_SETWMI R2, R0, 16, 0
133 // QC_SETWMI R2, R0, 15, 64
134 // QC_SETWMI R2, R0, N, 124
135 //
136 // For 48 words or more, call the target independent memset
137 if (NumberOfWords >= 48)
138 return SDValue();
139
140 if (NumberOfWords <= 16) {
141 // 1 - 16 words
142 return getSetwmiNode(NumberOfWords, 0);
143 }
144
145 if (NumberOfWords <= 32) {
146 // 17 - 32 words
147 OutChains.push_back(getSetwmiNode(NumberOfWords - 16, 64));
148 OutChains.push_back(getSetwmiNode(16, 0));
149 } else {
150 // 33 - 47 words
151 OutChains.push_back(getSetwmiNode(NumberOfWords - 31, 124));
152 OutChains.push_back(getSetwmiNode(15, 64));
153 OutChains.push_back(getSetwmiNode(16, 0));
154 }
155
156 return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains);
157}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
uint64_t Size
uint64_t getZExtValue() const
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, 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.
Proxy class that targets should inherit from if they wish to use the generated node descriptions.
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...
Definition: SelectionDAG.h:229
const TargetSubtargetInfo & getSubtarget() const
Definition: SelectionDAG.h:500
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)
Definition: SelectionDAG.h:707
MachineFunction & getMachineFunction() const
Definition: SelectionDAG.h:493
void push_back(const T &Elt)
Definition: SmallVector.h:414
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition: ISDOpcodes.h:832
@ TargetConstant
TargetConstant* - Like Constant*, but the DAG does not do any folding, simplification,...
Definition: ISDOpcodes.h:174
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
Definition: ISDOpcodes.h:53
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
#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
ElementCount getVectorElementCount() const
Definition: ValueTypes.h:345
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
Definition: ValueTypes.h:174
EVT getVectorElementType() const
Given a vector type, return the type of each element.
Definition: ValueTypes.h:323
This class contains a discriminated union of information about pointers in memory operands,...
MachinePointerInfo getWithOffset(int64_t O) const