llvm-project/llvm/lib/Target/VE/VECustomDAG.cpp
Simon Moll 7d926b7177 [VE] LEGALAVL and staged VVP legalization
The new LEGALAVL node annotates that the AVL refers to packs of 64bit.
We use a two-stage lowering approach with LEGALAVL:

First, standard SDNodes are translated into illegal VVP layer nodes.
Regardless of source (VP or standard), all VVP nodes have a mask and AVL
parameter. The AVL parameter refers to the element position (just as in
VP intrinsics).

Second, we legalize the AVL usage in VVP layer nodes. If the element
size is < 64bit, the EVL parameter has to be adjusted to refer to packs
of 64bits.  We wrap the legalized AVL in a LEGALAVL node to track this.

Reviewed By: kaz7

Differential Revision: https://reviews.llvm.org/D118321
2022-02-02 09:11:41 +01:00

152 lines
4.2 KiB
C++

//===-- 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 interfaces that VE uses to lower LLVM code into a
// selection DAG.
//
//===----------------------------------------------------------------------===//
#include "VECustomDAG.h"
#ifndef DEBUG_TYPE
#define DEBUG_TYPE "vecustomdag"
#endif
namespace llvm {
static const int StandardVectorWidth = 256;
bool isPackedVectorType(EVT SomeVT) {
if (!SomeVT.isVector())
return false;
return SomeVT.getVectorNumElements() > StandardVectorWidth;
}
/// \returns the VVP_* SDNode opcode corresponsing to \p OC.
Optional<unsigned> getVVPOpcode(unsigned Opcode) {
switch (Opcode) {
#define HANDLE_VP_TO_VVP(VPOPC, VVPNAME) \
case ISD::VPOPC: \
return VEISD::VVPNAME;
#define ADD_VVP_OP(VVPNAME, SDNAME) \
case VEISD::VVPNAME: \
case ISD::SDNAME: \
return VEISD::VVPNAME;
#include "VVPNodes.def"
}
return None;
}
bool maySafelyIgnoreMask(SDValue Op) {
auto VVPOpc = getVVPOpcode(Op->getOpcode());
auto Opc = VVPOpc.getValueOr(Op->getOpcode());
switch (Opc) {
case VEISD::VVP_SDIV:
case VEISD::VVP_UDIV:
case VEISD::VVP_FDIV:
case VEISD::VVP_SELECT:
return false;
default:
return true;
}
}
bool isVVPOrVEC(unsigned Opcode) {
switch (Opcode) {
case VEISD::VEC_BROADCAST:
#define ADD_VVP_OP(VVPNAME, ...) case VEISD::VVPNAME:
#include "VVPNodes.def"
return true;
}
return false;
}
bool isVVPBinaryOp(unsigned VVPOpcode) {
switch (VVPOpcode) {
#define ADD_BINARY_VVP_OP(VVPNAME, ...) \
case VEISD::VVPNAME: \
return true;
#include "VVPNodes.def"
}
return false;
}
// Return the AVL operand position for this VVP or VEC Op.
Optional<int> getAVLPos(unsigned Opc) {
// This is only available for VP SDNodes
auto PosOpt = ISD::getVPExplicitVectorLengthIdx(Opc);
if (PosOpt)
return *PosOpt;
// VVP Opcodes.
if (isVVPBinaryOp(Opc))
return 3;
// VM Opcodes.
switch (Opc) {
case VEISD::VEC_BROADCAST:
return 1;
case VEISD::VVP_SELECT:
return 3;
}
return None;
}
bool isLegalAVL(SDValue AVL) { return AVL->getOpcode() == VEISD::LEGALAVL; }
SDValue getNodeAVL(SDValue Op) {
auto PosOpt = getAVLPos(Op->getOpcode());
return PosOpt ? Op->getOperand(*PosOpt) : SDValue();
}
std::pair<SDValue, bool> getAnnotatedNodeAVL(SDValue Op) {
SDValue AVL = getNodeAVL(Op);
if (!AVL)
return {SDValue(), true};
if (isLegalAVL(AVL))
return {AVL->getOperand(0), true};
return {AVL, false};
}
SDValue VECustomDAG::getConstant(uint64_t Val, EVT VT, bool IsTarget,
bool IsOpaque) const {
return DAG.getConstant(Val, DL, VT, IsTarget, IsOpaque);
}
SDValue VECustomDAG::getBroadcast(EVT ResultVT, SDValue Scalar,
SDValue AVL) const {
assert(ResultVT.isVector());
auto ScaVT = Scalar.getValueType();
assert(ScaVT != MVT::i1 && "TODO: Mask broadcasts");
if (isPackedVectorType(ResultVT)) {
// v512x packed mode broadcast
// Replicate the scalar reg (f32 or i32) onto the opposing half of the full
// scalar register. If it's an I64 type, assume that this has already
// happened.
if (ScaVT == MVT::f32) {
Scalar = getNode(VEISD::REPL_F32, MVT::i64, Scalar);
} else if (ScaVT == MVT::i32) {
Scalar = getNode(VEISD::REPL_I32, MVT::i64, Scalar);
}
}
return getNode(VEISD::VEC_BROADCAST, ResultVT, {Scalar, AVL});
}
SDValue VECustomDAG::annotateLegalAVL(SDValue AVL) const {
if (isLegalAVL(AVL))
return AVL;
return getNode(VEISD::LEGALAVL, AVL.getValueType(), AVL);
}
} // namespace llvm