1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
|
//===------------ VECustomDAG.h - VE Custom DAG Nodes -----------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines the helper functions that VE uses to lower LLVM code into a
// selection DAG. For example, hiding SDLoc, and easy to use SDNodeFlags.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TARGET_VE_VECUSTOMDAG_H
#define LLVM_LIB_TARGET_VE_VECUSTOMDAG_H
#include "VE.h"
#include "VEISelLowering.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/TargetLowering.h"
namespace llvm {
std::optional<unsigned> getVVPOpcode(unsigned Opcode);
bool isVVPUnaryOp(unsigned Opcode);
bool isVVPBinaryOp(unsigned Opcode);
bool isVVPReductionOp(unsigned Opcode);
MVT splitVectorType(MVT VT);
bool isPackedVectorType(EVT SomeVT);
bool isMaskType(EVT SomeVT);
bool isMaskArithmetic(SDValue Op);
bool isVVPOrVEC(unsigned);
bool supportsPackedMode(unsigned Opcode, EVT IdiomVT);
bool isPackingSupportOpcode(unsigned Opc);
bool maySafelyIgnoreMask(SDValue Op);
/// The VE backend uses a two-staged process to lower and legalize vector
/// instructions:
//
/// 1. VP and standard vector SDNodes are lowered to SDNodes of the VVP_* layer.
//
// All VVP nodes have a mask and an Active Vector Length (AVL) parameter.
// The AVL parameters refers to the element position in the vector the VVP
// node operates on.
//
//
// 2. The VVP SDNodes are legalized. The AVL in a legal VVP node refers to
// chunks of 64bit. We track this by wrapping the AVL in a LEGALAVL node.
//
// The AVL mechanism in the VE architecture always refers to chunks of
// 64bit, regardless of the actual element type vector instructions are
// operating on. For vector types v256.32 or v256.64 nothing needs to be
// legalized since each element occupies a 64bit chunk - there is no
// difference between counting 64bit chunks or element positions. However,
// all vector types with > 256 elements store more than one logical element
// per 64bit chunk and need to be transformed.
// However legalization is performed, the resulting legal VVP SDNodes will
// have a LEGALAVL node as their AVL operand. The LEGALAVL nodes wraps
// around an AVL that refers to 64 bit chunks just as the architecture
// demands - that is, the wrapped AVL is the correct setting for the VL
// register for this VVP operation to get the desired behavior.
//
/// AVL Functions {
// The AVL operand position of this node.
std::optional<int> getAVLPos(unsigned);
// Whether this is a LEGALAVL node.
bool isLegalAVL(SDValue AVL);
// The AVL operand of this node.
SDValue getNodeAVL(SDValue);
// Mask position of this node.
std::optional<int> getMaskPos(unsigned);
SDValue getNodeMask(SDValue);
// Return the AVL operand of this node. If it is a LEGALAVL node, unwrap it.
// Return with the boolean whether unwrapping happened.
std::pair<SDValue, bool> getAnnotatedNodeAVL(SDValue);
/// } AVL Functions
/// Node Properties {
std::optional<EVT> getIdiomaticVectorType(SDNode *Op);
SDValue getLoadStoreStride(SDValue Op, VECustomDAG &CDAG);
SDValue getMemoryPtr(SDValue Op);
SDValue getNodeChain(SDValue Op);
SDValue getStoredValue(SDValue Op);
SDValue getNodePassthru(SDValue Op);
SDValue getGatherScatterIndex(SDValue Op);
SDValue getGatherScatterScale(SDValue Op);
unsigned getScalarReductionOpcode(unsigned VVPOC, bool IsMask);
// Whether this VP_REDUCE_*/ VECREDUCE_*/VVP_REDUCE_* SDNode has a start
// parameter.
bool hasReductionStartParam(unsigned VVPOC);
/// } Node Properties
enum class Packing {
Normal = 0, // 256 element standard mode.
Dense = 1 // 512 element packed mode.
};
// Get the vector or mask register type for this packing and element type.
MVT getLegalVectorType(Packing P, MVT ElemVT);
// Whether this type belongs to a packed mask or vector register.
Packing getTypePacking(EVT);
enum class PackElem : int8_t {
Lo = 0, // Integer (63, 32]
Hi = 1 // Float (32, 0]
};
struct VETargetMasks {
SDValue Mask;
SDValue AVL;
VETargetMasks(SDValue Mask = SDValue(), SDValue AVL = SDValue())
: Mask(Mask), AVL(AVL) {}
};
class VECustomDAG {
SelectionDAG &DAG;
SDLoc DL;
public:
SelectionDAG *getDAG() const { return &DAG; }
VECustomDAG(SelectionDAG &DAG, SDLoc DL) : DAG(DAG), DL(DL) {}
VECustomDAG(SelectionDAG &DAG, SDValue WhereOp) : DAG(DAG), DL(WhereOp) {}
VECustomDAG(SelectionDAG &DAG, const SDNode *WhereN) : DAG(DAG), DL(WhereN) {}
/// getNode {
SDValue getNode(unsigned OC, SDVTList VTL, ArrayRef<SDValue> OpV,
std::optional<SDNodeFlags> Flags = std::nullopt) const {
auto N = DAG.getNode(OC, DL, VTL, OpV);
if (Flags)
N->setFlags(*Flags);
return N;
}
SDValue getNode(unsigned OC, ArrayRef<EVT> ResVT, ArrayRef<SDValue> OpV,
std::optional<SDNodeFlags> Flags = std::nullopt) const {
auto N = DAG.getNode(OC, DL, ResVT, OpV);
if (Flags)
N->setFlags(*Flags);
return N;
}
SDValue getNode(unsigned OC, EVT ResVT, ArrayRef<SDValue> OpV,
std::optional<SDNodeFlags> Flags = std::nullopt) const {
auto N = DAG.getNode(OC, DL, ResVT, OpV);
if (Flags)
N->setFlags(*Flags);
return N;
}
SDValue getUNDEF(EVT VT) const { return DAG.getUNDEF(VT); }
/// } getNode
/// Legalizing getNode {
SDValue getLegalReductionOpVVP(unsigned VVPOpcode, EVT ResVT, SDValue StartV,
SDValue VectorV, SDValue Mask, SDValue AVL,
SDNodeFlags Flags) const;
/// } Legalizing getNode
/// Packing {
SDValue getUnpack(EVT DestVT, SDValue Vec, PackElem Part, SDValue AVL) const;
SDValue getPack(EVT DestVT, SDValue LoVec, SDValue HiVec, SDValue AVL) const;
/// } Packing
SDValue getMergeValues(ArrayRef<SDValue> Values) const {
return DAG.getMergeValues(Values, DL);
}
SDValue getConstant(uint64_t Val, EVT VT, bool IsTarget = false,
bool IsOpaque = false) const;
SDValue getConstantMask(Packing Packing, bool AllTrue) const;
SDValue getMaskBroadcast(EVT ResultVT, SDValue Scalar, SDValue AVL) const;
SDValue getBroadcast(EVT ResultVT, SDValue Scalar, SDValue AVL) const;
// Wrap AVL in a LEGALAVL node (unless it is one already).
SDValue annotateLegalAVL(SDValue AVL) const;
VETargetMasks getTargetSplitMask(SDValue RawMask, SDValue RawAVL,
PackElem Part) const;
// Splitting support
SDValue getSplitPtrOffset(SDValue Ptr, SDValue ByteStride,
PackElem Part) const;
SDValue getSplitPtrStride(SDValue PackStride) const;
SDValue getGatherScatterAddress(SDValue BasePtr, SDValue Scale, SDValue Index,
SDValue Mask, SDValue AVL) const;
EVT getVectorVT(EVT ElemVT, unsigned NumElems) const {
return EVT::getVectorVT(*DAG.getContext(), ElemVT, NumElems);
}
};
} // namespace llvm
#endif // LLVM_LIB_TARGET_VE_VECUSTOMDAG_H
|