2022-04-14 17:35:58 +08:00
|
|
|
//===- RISCVVIntrinsicUtils.cpp - RISC-V Vector Intrinsic Utils -*- 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
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "clang/Support/RISCVVIntrinsicUtils.h"
|
|
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
|
|
#include "llvm/ADT/Optional.h"
|
|
|
|
#include "llvm/ADT/SmallSet.h"
|
|
|
|
#include "llvm/ADT/StringExtras.h"
|
|
|
|
#include "llvm/ADT/StringMap.h"
|
|
|
|
#include "llvm/ADT/StringSet.h"
|
|
|
|
#include "llvm/ADT/Twine.h"
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
#include <numeric>
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
namespace clang {
|
|
|
|
namespace RISCV {
|
|
|
|
|
2022-05-11 23:39:13 +08:00
|
|
|
const PrototypeDescriptor PrototypeDescriptor::Mask = PrototypeDescriptor(
|
|
|
|
BaseTypeModifier::Vector, VectorTypeModifier::MaskVector);
|
|
|
|
const PrototypeDescriptor PrototypeDescriptor::VL =
|
|
|
|
PrototypeDescriptor(BaseTypeModifier::SizeT);
|
|
|
|
const PrototypeDescriptor PrototypeDescriptor::Vector =
|
|
|
|
PrototypeDescriptor(BaseTypeModifier::Vector);
|
|
|
|
|
2022-04-14 17:35:58 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Type implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
LMULType::LMULType(int NewLog2LMUL) {
|
|
|
|
// Check Log2LMUL is -3, -2, -1, 0, 1, 2, 3
|
|
|
|
assert(NewLog2LMUL <= 3 && NewLog2LMUL >= -3 && "Bad LMUL number!");
|
|
|
|
Log2LMUL = NewLog2LMUL;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string LMULType::str() const {
|
|
|
|
if (Log2LMUL < 0)
|
|
|
|
return "mf" + utostr(1ULL << (-Log2LMUL));
|
|
|
|
return "m" + utostr(1ULL << Log2LMUL);
|
|
|
|
}
|
|
|
|
|
|
|
|
VScaleVal LMULType::getScale(unsigned ElementBitwidth) const {
|
|
|
|
int Log2ScaleResult = 0;
|
|
|
|
switch (ElementBitwidth) {
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
Log2ScaleResult = Log2LMUL + 3;
|
|
|
|
break;
|
|
|
|
case 16:
|
|
|
|
Log2ScaleResult = Log2LMUL + 2;
|
|
|
|
break;
|
|
|
|
case 32:
|
|
|
|
Log2ScaleResult = Log2LMUL + 1;
|
|
|
|
break;
|
|
|
|
case 64:
|
|
|
|
Log2ScaleResult = Log2LMUL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Illegal vscale result would be less than 1
|
|
|
|
if (Log2ScaleResult < 0)
|
2022-12-03 11:54:46 -08:00
|
|
|
return std::nullopt;
|
2022-04-14 17:35:58 +08:00
|
|
|
return 1 << Log2ScaleResult;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LMULType::MulLog2LMUL(int log2LMUL) { Log2LMUL += log2LMUL; }
|
|
|
|
|
2022-05-11 23:39:13 +08:00
|
|
|
RVVType::RVVType(BasicType BT, int Log2LMUL,
|
|
|
|
const PrototypeDescriptor &prototype)
|
2022-04-14 17:35:58 +08:00
|
|
|
: BT(BT), LMUL(LMULType(Log2LMUL)) {
|
|
|
|
applyBasicType();
|
|
|
|
applyModifier(prototype);
|
|
|
|
Valid = verifyType();
|
|
|
|
if (Valid) {
|
|
|
|
initBuiltinStr();
|
|
|
|
initTypeStr();
|
|
|
|
if (isVector()) {
|
|
|
|
initClangBuiltinStr();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// clang-format off
|
|
|
|
// boolean type are encoded the ratio of n (SEW/LMUL)
|
|
|
|
// SEW/LMUL | 1 | 2 | 4 | 8 | 16 | 32 | 64
|
|
|
|
// c type | vbool64_t | vbool32_t | vbool16_t | vbool8_t | vbool4_t | vbool2_t | vbool1_t
|
|
|
|
// IR type | nxv1i1 | nxv2i1 | nxv4i1 | nxv8i1 | nxv16i1 | nxv32i1 | nxv64i1
|
|
|
|
|
|
|
|
// type\lmul | 1/8 | 1/4 | 1/2 | 1 | 2 | 4 | 8
|
|
|
|
// -------- |------ | -------- | ------- | ------- | -------- | -------- | --------
|
|
|
|
// i64 | N/A | N/A | N/A | nxv1i64 | nxv2i64 | nxv4i64 | nxv8i64
|
|
|
|
// i32 | N/A | N/A | nxv1i32 | nxv2i32 | nxv4i32 | nxv8i32 | nxv16i32
|
|
|
|
// i16 | N/A | nxv1i16 | nxv2i16 | nxv4i16 | nxv8i16 | nxv16i16 | nxv32i16
|
|
|
|
// i8 | nxv1i8 | nxv2i8 | nxv4i8 | nxv8i8 | nxv16i8 | nxv32i8 | nxv64i8
|
|
|
|
// double | N/A | N/A | N/A | nxv1f64 | nxv2f64 | nxv4f64 | nxv8f64
|
|
|
|
// float | N/A | N/A | nxv1f32 | nxv2f32 | nxv4f32 | nxv8f32 | nxv16f32
|
|
|
|
// half | N/A | nxv1f16 | nxv2f16 | nxv4f16 | nxv8f16 | nxv16f16 | nxv32f16
|
|
|
|
// clang-format on
|
|
|
|
|
|
|
|
bool RVVType::verifyType() const {
|
|
|
|
if (ScalarType == Invalid)
|
|
|
|
return false;
|
|
|
|
if (isScalar())
|
|
|
|
return true;
|
2022-06-25 22:26:24 -07:00
|
|
|
if (!Scale)
|
2022-04-14 17:35:58 +08:00
|
|
|
return false;
|
|
|
|
if (isFloat() && ElementBitwidth == 8)
|
|
|
|
return false;
|
2022-12-17 04:45:11 +00:00
|
|
|
unsigned V = *Scale;
|
2022-04-14 17:35:58 +08:00
|
|
|
switch (ElementBitwidth) {
|
|
|
|
case 1:
|
|
|
|
case 8:
|
|
|
|
// Check Scale is 1,2,4,8,16,32,64
|
|
|
|
return (V <= 64 && isPowerOf2_32(V));
|
|
|
|
case 16:
|
|
|
|
// Check Scale is 1,2,4,8,16,32
|
|
|
|
return (V <= 32 && isPowerOf2_32(V));
|
|
|
|
case 32:
|
|
|
|
// Check Scale is 1,2,4,8,16
|
|
|
|
return (V <= 16 && isPowerOf2_32(V));
|
|
|
|
case 64:
|
|
|
|
// Check Scale is 1,2,4,8
|
|
|
|
return (V <= 8 && isPowerOf2_32(V));
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RVVType::initBuiltinStr() {
|
|
|
|
assert(isValid() && "RVVType is invalid");
|
|
|
|
switch (ScalarType) {
|
|
|
|
case ScalarTypeKind::Void:
|
|
|
|
BuiltinStr = "v";
|
|
|
|
return;
|
|
|
|
case ScalarTypeKind::Size_t:
|
|
|
|
BuiltinStr = "z";
|
|
|
|
if (IsImmediate)
|
|
|
|
BuiltinStr = "I" + BuiltinStr;
|
|
|
|
if (IsPointer)
|
|
|
|
BuiltinStr += "*";
|
|
|
|
return;
|
|
|
|
case ScalarTypeKind::Ptrdiff_t:
|
|
|
|
BuiltinStr = "Y";
|
|
|
|
return;
|
|
|
|
case ScalarTypeKind::UnsignedLong:
|
|
|
|
BuiltinStr = "ULi";
|
|
|
|
return;
|
|
|
|
case ScalarTypeKind::SignedLong:
|
|
|
|
BuiltinStr = "Li";
|
|
|
|
return;
|
|
|
|
case ScalarTypeKind::Boolean:
|
|
|
|
assert(ElementBitwidth == 1);
|
|
|
|
BuiltinStr += "b";
|
|
|
|
break;
|
|
|
|
case ScalarTypeKind::SignedInteger:
|
|
|
|
case ScalarTypeKind::UnsignedInteger:
|
|
|
|
switch (ElementBitwidth) {
|
|
|
|
case 8:
|
|
|
|
BuiltinStr += "c";
|
|
|
|
break;
|
|
|
|
case 16:
|
|
|
|
BuiltinStr += "s";
|
|
|
|
break;
|
|
|
|
case 32:
|
|
|
|
BuiltinStr += "i";
|
|
|
|
break;
|
|
|
|
case 64:
|
|
|
|
BuiltinStr += "Wi";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
llvm_unreachable("Unhandled ElementBitwidth!");
|
|
|
|
}
|
|
|
|
if (isSignedInteger())
|
|
|
|
BuiltinStr = "S" + BuiltinStr;
|
|
|
|
else
|
|
|
|
BuiltinStr = "U" + BuiltinStr;
|
|
|
|
break;
|
|
|
|
case ScalarTypeKind::Float:
|
|
|
|
switch (ElementBitwidth) {
|
|
|
|
case 16:
|
|
|
|
BuiltinStr += "x";
|
|
|
|
break;
|
|
|
|
case 32:
|
|
|
|
BuiltinStr += "f";
|
|
|
|
break;
|
|
|
|
case 64:
|
|
|
|
BuiltinStr += "d";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
llvm_unreachable("Unhandled ElementBitwidth!");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
llvm_unreachable("ScalarType is invalid!");
|
|
|
|
}
|
|
|
|
if (IsImmediate)
|
|
|
|
BuiltinStr = "I" + BuiltinStr;
|
|
|
|
if (isScalar()) {
|
|
|
|
if (IsConstant)
|
|
|
|
BuiltinStr += "C";
|
|
|
|
if (IsPointer)
|
|
|
|
BuiltinStr += "*";
|
|
|
|
return;
|
|
|
|
}
|
2022-06-20 22:59:26 -07:00
|
|
|
BuiltinStr = "q" + utostr(*Scale) + BuiltinStr;
|
2022-04-14 17:35:58 +08:00
|
|
|
// Pointer to vector types. Defined for segment load intrinsics.
|
|
|
|
// segment load intrinsics have pointer type arguments to store the loaded
|
|
|
|
// vector values.
|
|
|
|
if (IsPointer)
|
|
|
|
BuiltinStr += "*";
|
|
|
|
}
|
|
|
|
|
|
|
|
void RVVType::initClangBuiltinStr() {
|
|
|
|
assert(isValid() && "RVVType is invalid");
|
|
|
|
assert(isVector() && "Handle Vector type only");
|
|
|
|
|
|
|
|
ClangBuiltinStr = "__rvv_";
|
|
|
|
switch (ScalarType) {
|
|
|
|
case ScalarTypeKind::Boolean:
|
2022-06-20 22:59:26 -07:00
|
|
|
ClangBuiltinStr += "bool" + utostr(64 / *Scale) + "_t";
|
2022-04-14 17:35:58 +08:00
|
|
|
return;
|
|
|
|
case ScalarTypeKind::Float:
|
|
|
|
ClangBuiltinStr += "float";
|
|
|
|
break;
|
|
|
|
case ScalarTypeKind::SignedInteger:
|
|
|
|
ClangBuiltinStr += "int";
|
|
|
|
break;
|
|
|
|
case ScalarTypeKind::UnsignedInteger:
|
|
|
|
ClangBuiltinStr += "uint";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
llvm_unreachable("ScalarTypeKind is invalid");
|
|
|
|
}
|
|
|
|
ClangBuiltinStr += utostr(ElementBitwidth) + LMUL.str() + "_t";
|
|
|
|
}
|
|
|
|
|
|
|
|
void RVVType::initTypeStr() {
|
|
|
|
assert(isValid() && "RVVType is invalid");
|
|
|
|
|
|
|
|
if (IsConstant)
|
|
|
|
Str += "const ";
|
|
|
|
|
|
|
|
auto getTypeString = [&](StringRef TypeStr) {
|
|
|
|
if (isScalar())
|
|
|
|
return Twine(TypeStr + Twine(ElementBitwidth) + "_t").str();
|
|
|
|
return Twine("v" + TypeStr + Twine(ElementBitwidth) + LMUL.str() + "_t")
|
|
|
|
.str();
|
|
|
|
};
|
|
|
|
|
|
|
|
switch (ScalarType) {
|
|
|
|
case ScalarTypeKind::Void:
|
|
|
|
Str = "void";
|
|
|
|
return;
|
|
|
|
case ScalarTypeKind::Size_t:
|
|
|
|
Str = "size_t";
|
|
|
|
if (IsPointer)
|
|
|
|
Str += " *";
|
|
|
|
return;
|
|
|
|
case ScalarTypeKind::Ptrdiff_t:
|
|
|
|
Str = "ptrdiff_t";
|
|
|
|
return;
|
|
|
|
case ScalarTypeKind::UnsignedLong:
|
|
|
|
Str = "unsigned long";
|
|
|
|
return;
|
|
|
|
case ScalarTypeKind::SignedLong:
|
|
|
|
Str = "long";
|
|
|
|
return;
|
|
|
|
case ScalarTypeKind::Boolean:
|
|
|
|
if (isScalar())
|
|
|
|
Str += "bool";
|
|
|
|
else
|
|
|
|
// Vector bool is special case, the formulate is
|
|
|
|
// `vbool<N>_t = MVT::nxv<64/N>i1` ex. vbool16_t = MVT::4i1
|
2022-06-20 22:59:26 -07:00
|
|
|
Str += "vbool" + utostr(64 / *Scale) + "_t";
|
2022-04-14 17:35:58 +08:00
|
|
|
break;
|
|
|
|
case ScalarTypeKind::Float:
|
|
|
|
if (isScalar()) {
|
|
|
|
if (ElementBitwidth == 64)
|
|
|
|
Str += "double";
|
|
|
|
else if (ElementBitwidth == 32)
|
|
|
|
Str += "float";
|
|
|
|
else if (ElementBitwidth == 16)
|
|
|
|
Str += "_Float16";
|
|
|
|
else
|
|
|
|
llvm_unreachable("Unhandled floating type.");
|
|
|
|
} else
|
|
|
|
Str += getTypeString("float");
|
|
|
|
break;
|
|
|
|
case ScalarTypeKind::SignedInteger:
|
|
|
|
Str += getTypeString("int");
|
|
|
|
break;
|
|
|
|
case ScalarTypeKind::UnsignedInteger:
|
|
|
|
Str += getTypeString("uint");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
llvm_unreachable("ScalarType is invalid!");
|
|
|
|
}
|
|
|
|
if (IsPointer)
|
|
|
|
Str += " *";
|
|
|
|
}
|
|
|
|
|
|
|
|
void RVVType::initShortStr() {
|
|
|
|
switch (ScalarType) {
|
|
|
|
case ScalarTypeKind::Boolean:
|
|
|
|
assert(isVector());
|
2022-06-20 22:59:26 -07:00
|
|
|
ShortStr = "b" + utostr(64 / *Scale);
|
2022-04-14 17:35:58 +08:00
|
|
|
return;
|
|
|
|
case ScalarTypeKind::Float:
|
|
|
|
ShortStr = "f" + utostr(ElementBitwidth);
|
|
|
|
break;
|
|
|
|
case ScalarTypeKind::SignedInteger:
|
|
|
|
ShortStr = "i" + utostr(ElementBitwidth);
|
|
|
|
break;
|
|
|
|
case ScalarTypeKind::UnsignedInteger:
|
|
|
|
ShortStr = "u" + utostr(ElementBitwidth);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
llvm_unreachable("Unhandled case!");
|
|
|
|
}
|
|
|
|
if (isVector())
|
|
|
|
ShortStr += LMUL.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
void RVVType::applyBasicType() {
|
|
|
|
switch (BT) {
|
2022-05-11 23:39:13 +08:00
|
|
|
case BasicType::Int8:
|
2022-04-14 17:35:58 +08:00
|
|
|
ElementBitwidth = 8;
|
|
|
|
ScalarType = ScalarTypeKind::SignedInteger;
|
|
|
|
break;
|
2022-05-11 23:39:13 +08:00
|
|
|
case BasicType::Int16:
|
2022-04-14 17:35:58 +08:00
|
|
|
ElementBitwidth = 16;
|
|
|
|
ScalarType = ScalarTypeKind::SignedInteger;
|
|
|
|
break;
|
2022-05-11 23:39:13 +08:00
|
|
|
case BasicType::Int32:
|
2022-04-14 17:35:58 +08:00
|
|
|
ElementBitwidth = 32;
|
|
|
|
ScalarType = ScalarTypeKind::SignedInteger;
|
|
|
|
break;
|
2022-05-11 23:39:13 +08:00
|
|
|
case BasicType::Int64:
|
2022-04-14 17:35:58 +08:00
|
|
|
ElementBitwidth = 64;
|
|
|
|
ScalarType = ScalarTypeKind::SignedInteger;
|
|
|
|
break;
|
2022-05-11 23:39:13 +08:00
|
|
|
case BasicType::Float16:
|
2022-04-14 17:35:58 +08:00
|
|
|
ElementBitwidth = 16;
|
|
|
|
ScalarType = ScalarTypeKind::Float;
|
|
|
|
break;
|
2022-05-11 23:39:13 +08:00
|
|
|
case BasicType::Float32:
|
2022-04-14 17:35:58 +08:00
|
|
|
ElementBitwidth = 32;
|
|
|
|
ScalarType = ScalarTypeKind::Float;
|
|
|
|
break;
|
2022-05-11 23:39:13 +08:00
|
|
|
case BasicType::Float64:
|
2022-04-14 17:35:58 +08:00
|
|
|
ElementBitwidth = 64;
|
|
|
|
ScalarType = ScalarTypeKind::Float;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
llvm_unreachable("Unhandled type code!");
|
|
|
|
}
|
|
|
|
assert(ElementBitwidth != 0 && "Bad element bitwidth!");
|
|
|
|
}
|
|
|
|
|
2022-05-11 23:39:13 +08:00
|
|
|
Optional<PrototypeDescriptor> PrototypeDescriptor::parsePrototypeDescriptor(
|
|
|
|
llvm::StringRef PrototypeDescriptorStr) {
|
|
|
|
PrototypeDescriptor PD;
|
|
|
|
BaseTypeModifier PT = BaseTypeModifier::Invalid;
|
|
|
|
VectorTypeModifier VTM = VectorTypeModifier::NoModifier;
|
|
|
|
|
|
|
|
if (PrototypeDescriptorStr.empty())
|
|
|
|
return PD;
|
|
|
|
|
|
|
|
// Handle base type modifier
|
|
|
|
auto PType = PrototypeDescriptorStr.back();
|
2022-04-14 17:35:58 +08:00
|
|
|
switch (PType) {
|
|
|
|
case 'e':
|
2022-05-11 23:39:13 +08:00
|
|
|
PT = BaseTypeModifier::Scalar;
|
2022-04-14 17:35:58 +08:00
|
|
|
break;
|
|
|
|
case 'v':
|
2022-05-11 23:39:13 +08:00
|
|
|
PT = BaseTypeModifier::Vector;
|
2022-04-14 17:35:58 +08:00
|
|
|
break;
|
|
|
|
case 'w':
|
2022-05-11 23:39:13 +08:00
|
|
|
PT = BaseTypeModifier::Vector;
|
|
|
|
VTM = VectorTypeModifier::Widening2XVector;
|
2022-04-14 17:35:58 +08:00
|
|
|
break;
|
|
|
|
case 'q':
|
2022-05-11 23:39:13 +08:00
|
|
|
PT = BaseTypeModifier::Vector;
|
|
|
|
VTM = VectorTypeModifier::Widening4XVector;
|
2022-04-14 17:35:58 +08:00
|
|
|
break;
|
|
|
|
case 'o':
|
2022-05-11 23:39:13 +08:00
|
|
|
PT = BaseTypeModifier::Vector;
|
|
|
|
VTM = VectorTypeModifier::Widening8XVector;
|
2022-04-14 17:35:58 +08:00
|
|
|
break;
|
|
|
|
case 'm':
|
2022-05-11 23:39:13 +08:00
|
|
|
PT = BaseTypeModifier::Vector;
|
|
|
|
VTM = VectorTypeModifier::MaskVector;
|
2022-04-14 17:35:58 +08:00
|
|
|
break;
|
|
|
|
case '0':
|
2022-05-11 23:39:13 +08:00
|
|
|
PT = BaseTypeModifier::Void;
|
2022-04-14 17:35:58 +08:00
|
|
|
break;
|
|
|
|
case 'z':
|
2022-05-11 23:39:13 +08:00
|
|
|
PT = BaseTypeModifier::SizeT;
|
2022-04-14 17:35:58 +08:00
|
|
|
break;
|
|
|
|
case 't':
|
2022-05-11 23:39:13 +08:00
|
|
|
PT = BaseTypeModifier::Ptrdiff;
|
2022-04-14 17:35:58 +08:00
|
|
|
break;
|
|
|
|
case 'u':
|
2022-05-11 23:39:13 +08:00
|
|
|
PT = BaseTypeModifier::UnsignedLong;
|
2022-04-14 17:35:58 +08:00
|
|
|
break;
|
|
|
|
case 'l':
|
2022-05-11 23:39:13 +08:00
|
|
|
PT = BaseTypeModifier::SignedLong;
|
2022-04-14 17:35:58 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
llvm_unreachable("Illegal primitive type transformers!");
|
|
|
|
}
|
2022-05-11 23:39:13 +08:00
|
|
|
PD.PT = static_cast<uint8_t>(PT);
|
|
|
|
PrototypeDescriptorStr = PrototypeDescriptorStr.drop_back();
|
|
|
|
|
|
|
|
// Compute the vector type transformers, it can only appear one time.
|
|
|
|
if (PrototypeDescriptorStr.startswith("(")) {
|
|
|
|
assert(VTM == VectorTypeModifier::NoModifier &&
|
|
|
|
"VectorTypeModifier should only have one modifier");
|
|
|
|
size_t Idx = PrototypeDescriptorStr.find(')');
|
2022-04-14 17:35:58 +08:00
|
|
|
assert(Idx != StringRef::npos);
|
2022-05-11 23:39:13 +08:00
|
|
|
StringRef ComplexType = PrototypeDescriptorStr.slice(1, Idx);
|
|
|
|
PrototypeDescriptorStr = PrototypeDescriptorStr.drop_front(Idx + 1);
|
|
|
|
assert(!PrototypeDescriptorStr.contains('(') &&
|
|
|
|
"Only allow one vector type modifier");
|
2022-04-14 17:35:58 +08:00
|
|
|
|
|
|
|
auto ComplexTT = ComplexType.split(":");
|
|
|
|
if (ComplexTT.first == "Log2EEW") {
|
|
|
|
uint32_t Log2EEW;
|
2022-05-11 23:39:13 +08:00
|
|
|
if (ComplexTT.second.getAsInteger(10, Log2EEW)) {
|
|
|
|
llvm_unreachable("Invalid Log2EEW value!");
|
2022-12-03 11:54:46 -08:00
|
|
|
return std::nullopt;
|
2022-05-11 23:39:13 +08:00
|
|
|
}
|
|
|
|
switch (Log2EEW) {
|
|
|
|
case 3:
|
|
|
|
VTM = VectorTypeModifier::Log2EEW3;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
VTM = VectorTypeModifier::Log2EEW4;
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
VTM = VectorTypeModifier::Log2EEW5;
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
VTM = VectorTypeModifier::Log2EEW6;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
llvm_unreachable("Invalid Log2EEW value, should be [3-6]");
|
2022-12-03 11:54:46 -08:00
|
|
|
return std::nullopt;
|
2022-05-11 23:39:13 +08:00
|
|
|
}
|
2022-04-14 17:35:58 +08:00
|
|
|
} else if (ComplexTT.first == "FixedSEW") {
|
|
|
|
uint32_t NewSEW;
|
2022-05-11 23:39:13 +08:00
|
|
|
if (ComplexTT.second.getAsInteger(10, NewSEW)) {
|
|
|
|
llvm_unreachable("Invalid FixedSEW value!");
|
2022-12-03 11:54:46 -08:00
|
|
|
return std::nullopt;
|
2022-05-11 23:39:13 +08:00
|
|
|
}
|
|
|
|
switch (NewSEW) {
|
|
|
|
case 8:
|
|
|
|
VTM = VectorTypeModifier::FixedSEW8;
|
|
|
|
break;
|
|
|
|
case 16:
|
|
|
|
VTM = VectorTypeModifier::FixedSEW16;
|
|
|
|
break;
|
|
|
|
case 32:
|
|
|
|
VTM = VectorTypeModifier::FixedSEW32;
|
|
|
|
break;
|
|
|
|
case 64:
|
|
|
|
VTM = VectorTypeModifier::FixedSEW64;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
llvm_unreachable("Invalid FixedSEW value, should be 8, 16, 32 or 64");
|
2022-12-03 11:54:46 -08:00
|
|
|
return std::nullopt;
|
2022-04-14 17:35:58 +08:00
|
|
|
}
|
|
|
|
} else if (ComplexTT.first == "LFixedLog2LMUL") {
|
2022-05-11 23:39:13 +08:00
|
|
|
int32_t Log2LMUL;
|
|
|
|
if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
|
|
|
|
llvm_unreachable("Invalid LFixedLog2LMUL value!");
|
2022-12-03 11:54:46 -08:00
|
|
|
return std::nullopt;
|
2022-05-11 23:39:13 +08:00
|
|
|
}
|
|
|
|
switch (Log2LMUL) {
|
|
|
|
case -3:
|
|
|
|
VTM = VectorTypeModifier::LFixedLog2LMULN3;
|
|
|
|
break;
|
|
|
|
case -2:
|
|
|
|
VTM = VectorTypeModifier::LFixedLog2LMULN2;
|
|
|
|
break;
|
|
|
|
case -1:
|
|
|
|
VTM = VectorTypeModifier::LFixedLog2LMULN1;
|
|
|
|
break;
|
|
|
|
case 0:
|
|
|
|
VTM = VectorTypeModifier::LFixedLog2LMUL0;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
VTM = VectorTypeModifier::LFixedLog2LMUL1;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
VTM = VectorTypeModifier::LFixedLog2LMUL2;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
VTM = VectorTypeModifier::LFixedLog2LMUL3;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
llvm_unreachable("Invalid LFixedLog2LMUL value, should be [-3, 3]");
|
2022-12-03 11:54:46 -08:00
|
|
|
return std::nullopt;
|
2022-05-11 23:39:13 +08:00
|
|
|
}
|
2022-04-14 17:35:58 +08:00
|
|
|
} else if (ComplexTT.first == "SFixedLog2LMUL") {
|
2022-05-11 23:39:13 +08:00
|
|
|
int32_t Log2LMUL;
|
|
|
|
if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
|
|
|
|
llvm_unreachable("Invalid SFixedLog2LMUL value!");
|
2022-12-03 11:54:46 -08:00
|
|
|
return std::nullopt;
|
2022-05-11 23:39:13 +08:00
|
|
|
}
|
|
|
|
switch (Log2LMUL) {
|
|
|
|
case -3:
|
|
|
|
VTM = VectorTypeModifier::SFixedLog2LMULN3;
|
|
|
|
break;
|
|
|
|
case -2:
|
|
|
|
VTM = VectorTypeModifier::SFixedLog2LMULN2;
|
|
|
|
break;
|
|
|
|
case -1:
|
|
|
|
VTM = VectorTypeModifier::SFixedLog2LMULN1;
|
|
|
|
break;
|
|
|
|
case 0:
|
|
|
|
VTM = VectorTypeModifier::SFixedLog2LMUL0;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
VTM = VectorTypeModifier::SFixedLog2LMUL1;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
VTM = VectorTypeModifier::SFixedLog2LMUL2;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
VTM = VectorTypeModifier::SFixedLog2LMUL3;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
llvm_unreachable("Invalid LFixedLog2LMUL value, should be [-3, 3]");
|
2022-12-03 11:54:46 -08:00
|
|
|
return std::nullopt;
|
2022-05-11 23:39:13 +08:00
|
|
|
}
|
|
|
|
|
2022-04-14 17:35:58 +08:00
|
|
|
} else {
|
|
|
|
llvm_unreachable("Illegal complex type transformers!");
|
|
|
|
}
|
|
|
|
}
|
2022-05-11 23:39:13 +08:00
|
|
|
PD.VTM = static_cast<uint8_t>(VTM);
|
2022-04-14 17:35:58 +08:00
|
|
|
|
|
|
|
// Compute the remain type transformers
|
2022-05-11 23:39:13 +08:00
|
|
|
TypeModifier TM = TypeModifier::NoModifier;
|
|
|
|
for (char I : PrototypeDescriptorStr) {
|
2022-04-14 17:35:58 +08:00
|
|
|
switch (I) {
|
|
|
|
case 'P':
|
2022-05-11 23:39:13 +08:00
|
|
|
if ((TM & TypeModifier::Const) == TypeModifier::Const)
|
2022-04-14 17:35:58 +08:00
|
|
|
llvm_unreachable("'P' transformer cannot be used after 'C'");
|
2022-05-11 23:39:13 +08:00
|
|
|
if ((TM & TypeModifier::Pointer) == TypeModifier::Pointer)
|
2022-04-14 17:35:58 +08:00
|
|
|
llvm_unreachable("'P' transformer cannot be used twice");
|
2022-05-11 23:39:13 +08:00
|
|
|
TM |= TypeModifier::Pointer;
|
2022-04-14 17:35:58 +08:00
|
|
|
break;
|
|
|
|
case 'C':
|
2022-05-11 23:39:13 +08:00
|
|
|
TM |= TypeModifier::Const;
|
2022-04-14 17:35:58 +08:00
|
|
|
break;
|
|
|
|
case 'K':
|
2022-05-11 23:39:13 +08:00
|
|
|
TM |= TypeModifier::Immediate;
|
2022-04-14 17:35:58 +08:00
|
|
|
break;
|
|
|
|
case 'U':
|
2022-05-11 23:39:13 +08:00
|
|
|
TM |= TypeModifier::UnsignedInteger;
|
2022-04-14 17:35:58 +08:00
|
|
|
break;
|
|
|
|
case 'I':
|
2022-05-11 23:39:13 +08:00
|
|
|
TM |= TypeModifier::SignedInteger;
|
2022-04-14 17:35:58 +08:00
|
|
|
break;
|
|
|
|
case 'F':
|
2022-05-11 23:39:13 +08:00
|
|
|
TM |= TypeModifier::Float;
|
2022-04-14 17:35:58 +08:00
|
|
|
break;
|
|
|
|
case 'S':
|
2022-05-11 23:39:13 +08:00
|
|
|
TM |= TypeModifier::LMUL1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
llvm_unreachable("Illegal non-primitive type transformer!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
PD.TM = static_cast<uint8_t>(TM);
|
|
|
|
|
|
|
|
return PD;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RVVType::applyModifier(const PrototypeDescriptor &Transformer) {
|
|
|
|
// Handle primitive type transformer
|
|
|
|
switch (static_cast<BaseTypeModifier>(Transformer.PT)) {
|
|
|
|
case BaseTypeModifier::Scalar:
|
|
|
|
Scale = 0;
|
|
|
|
break;
|
|
|
|
case BaseTypeModifier::Vector:
|
|
|
|
Scale = LMUL.getScale(ElementBitwidth);
|
|
|
|
break;
|
|
|
|
case BaseTypeModifier::Void:
|
|
|
|
ScalarType = ScalarTypeKind::Void;
|
|
|
|
break;
|
|
|
|
case BaseTypeModifier::SizeT:
|
|
|
|
ScalarType = ScalarTypeKind::Size_t;
|
|
|
|
break;
|
|
|
|
case BaseTypeModifier::Ptrdiff:
|
|
|
|
ScalarType = ScalarTypeKind::Ptrdiff_t;
|
|
|
|
break;
|
|
|
|
case BaseTypeModifier::UnsignedLong:
|
|
|
|
ScalarType = ScalarTypeKind::UnsignedLong;
|
|
|
|
break;
|
|
|
|
case BaseTypeModifier::SignedLong:
|
|
|
|
ScalarType = ScalarTypeKind::SignedLong;
|
|
|
|
break;
|
|
|
|
case BaseTypeModifier::Invalid:
|
|
|
|
ScalarType = ScalarTypeKind::Invalid;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (static_cast<VectorTypeModifier>(Transformer.VTM)) {
|
|
|
|
case VectorTypeModifier::Widening2XVector:
|
|
|
|
ElementBitwidth *= 2;
|
2022-05-19 23:23:34 -07:00
|
|
|
LMUL.MulLog2LMUL(1);
|
2022-05-11 23:39:13 +08:00
|
|
|
Scale = LMUL.getScale(ElementBitwidth);
|
|
|
|
break;
|
|
|
|
case VectorTypeModifier::Widening4XVector:
|
|
|
|
ElementBitwidth *= 4;
|
2022-05-19 23:23:34 -07:00
|
|
|
LMUL.MulLog2LMUL(2);
|
2022-05-11 23:39:13 +08:00
|
|
|
Scale = LMUL.getScale(ElementBitwidth);
|
|
|
|
break;
|
|
|
|
case VectorTypeModifier::Widening8XVector:
|
|
|
|
ElementBitwidth *= 8;
|
2022-05-19 23:23:34 -07:00
|
|
|
LMUL.MulLog2LMUL(3);
|
2022-05-11 23:39:13 +08:00
|
|
|
Scale = LMUL.getScale(ElementBitwidth);
|
|
|
|
break;
|
|
|
|
case VectorTypeModifier::MaskVector:
|
|
|
|
ScalarType = ScalarTypeKind::Boolean;
|
|
|
|
Scale = LMUL.getScale(ElementBitwidth);
|
|
|
|
ElementBitwidth = 1;
|
|
|
|
break;
|
|
|
|
case VectorTypeModifier::Log2EEW3:
|
|
|
|
applyLog2EEW(3);
|
|
|
|
break;
|
|
|
|
case VectorTypeModifier::Log2EEW4:
|
|
|
|
applyLog2EEW(4);
|
|
|
|
break;
|
|
|
|
case VectorTypeModifier::Log2EEW5:
|
|
|
|
applyLog2EEW(5);
|
|
|
|
break;
|
|
|
|
case VectorTypeModifier::Log2EEW6:
|
|
|
|
applyLog2EEW(6);
|
|
|
|
break;
|
|
|
|
case VectorTypeModifier::FixedSEW8:
|
|
|
|
applyFixedSEW(8);
|
|
|
|
break;
|
|
|
|
case VectorTypeModifier::FixedSEW16:
|
|
|
|
applyFixedSEW(16);
|
|
|
|
break;
|
|
|
|
case VectorTypeModifier::FixedSEW32:
|
|
|
|
applyFixedSEW(32);
|
|
|
|
break;
|
|
|
|
case VectorTypeModifier::FixedSEW64:
|
|
|
|
applyFixedSEW(64);
|
|
|
|
break;
|
|
|
|
case VectorTypeModifier::LFixedLog2LMULN3:
|
|
|
|
applyFixedLog2LMUL(-3, FixedLMULType::LargerThan);
|
|
|
|
break;
|
|
|
|
case VectorTypeModifier::LFixedLog2LMULN2:
|
|
|
|
applyFixedLog2LMUL(-2, FixedLMULType::LargerThan);
|
|
|
|
break;
|
|
|
|
case VectorTypeModifier::LFixedLog2LMULN1:
|
|
|
|
applyFixedLog2LMUL(-1, FixedLMULType::LargerThan);
|
|
|
|
break;
|
|
|
|
case VectorTypeModifier::LFixedLog2LMUL0:
|
|
|
|
applyFixedLog2LMUL(0, FixedLMULType::LargerThan);
|
|
|
|
break;
|
|
|
|
case VectorTypeModifier::LFixedLog2LMUL1:
|
|
|
|
applyFixedLog2LMUL(1, FixedLMULType::LargerThan);
|
|
|
|
break;
|
|
|
|
case VectorTypeModifier::LFixedLog2LMUL2:
|
|
|
|
applyFixedLog2LMUL(2, FixedLMULType::LargerThan);
|
|
|
|
break;
|
|
|
|
case VectorTypeModifier::LFixedLog2LMUL3:
|
|
|
|
applyFixedLog2LMUL(3, FixedLMULType::LargerThan);
|
|
|
|
break;
|
|
|
|
case VectorTypeModifier::SFixedLog2LMULN3:
|
|
|
|
applyFixedLog2LMUL(-3, FixedLMULType::SmallerThan);
|
|
|
|
break;
|
|
|
|
case VectorTypeModifier::SFixedLog2LMULN2:
|
|
|
|
applyFixedLog2LMUL(-2, FixedLMULType::SmallerThan);
|
|
|
|
break;
|
|
|
|
case VectorTypeModifier::SFixedLog2LMULN1:
|
|
|
|
applyFixedLog2LMUL(-1, FixedLMULType::SmallerThan);
|
|
|
|
break;
|
|
|
|
case VectorTypeModifier::SFixedLog2LMUL0:
|
|
|
|
applyFixedLog2LMUL(0, FixedLMULType::SmallerThan);
|
|
|
|
break;
|
|
|
|
case VectorTypeModifier::SFixedLog2LMUL1:
|
|
|
|
applyFixedLog2LMUL(1, FixedLMULType::SmallerThan);
|
|
|
|
break;
|
|
|
|
case VectorTypeModifier::SFixedLog2LMUL2:
|
|
|
|
applyFixedLog2LMUL(2, FixedLMULType::SmallerThan);
|
|
|
|
break;
|
|
|
|
case VectorTypeModifier::SFixedLog2LMUL3:
|
|
|
|
applyFixedLog2LMUL(3, FixedLMULType::SmallerThan);
|
|
|
|
break;
|
|
|
|
case VectorTypeModifier::NoModifier:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (unsigned TypeModifierMaskShift = 0;
|
|
|
|
TypeModifierMaskShift <= static_cast<unsigned>(TypeModifier::MaxOffset);
|
|
|
|
++TypeModifierMaskShift) {
|
|
|
|
unsigned TypeModifierMask = 1 << TypeModifierMaskShift;
|
|
|
|
if ((static_cast<unsigned>(Transformer.TM) & TypeModifierMask) !=
|
|
|
|
TypeModifierMask)
|
|
|
|
continue;
|
|
|
|
switch (static_cast<TypeModifier>(TypeModifierMask)) {
|
|
|
|
case TypeModifier::Pointer:
|
|
|
|
IsPointer = true;
|
|
|
|
break;
|
|
|
|
case TypeModifier::Const:
|
|
|
|
IsConstant = true;
|
|
|
|
break;
|
|
|
|
case TypeModifier::Immediate:
|
|
|
|
IsImmediate = true;
|
|
|
|
IsConstant = true;
|
|
|
|
break;
|
|
|
|
case TypeModifier::UnsignedInteger:
|
|
|
|
ScalarType = ScalarTypeKind::UnsignedInteger;
|
|
|
|
break;
|
|
|
|
case TypeModifier::SignedInteger:
|
|
|
|
ScalarType = ScalarTypeKind::SignedInteger;
|
|
|
|
break;
|
|
|
|
case TypeModifier::Float:
|
|
|
|
ScalarType = ScalarTypeKind::Float;
|
|
|
|
break;
|
|
|
|
case TypeModifier::LMUL1:
|
2022-04-14 17:35:58 +08:00
|
|
|
LMUL = LMULType(0);
|
|
|
|
// Update ElementBitwidth need to update Scale too.
|
|
|
|
Scale = LMUL.getScale(ElementBitwidth);
|
|
|
|
break;
|
|
|
|
default:
|
2022-05-11 23:39:13 +08:00
|
|
|
llvm_unreachable("Unknown type modifier mask!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void RVVType::applyLog2EEW(unsigned Log2EEW) {
|
|
|
|
// update new elmul = (eew/sew) * lmul
|
|
|
|
LMUL.MulLog2LMUL(Log2EEW - Log2_32(ElementBitwidth));
|
|
|
|
// update new eew
|
|
|
|
ElementBitwidth = 1 << Log2EEW;
|
|
|
|
ScalarType = ScalarTypeKind::SignedInteger;
|
|
|
|
Scale = LMUL.getScale(ElementBitwidth);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RVVType::applyFixedSEW(unsigned NewSEW) {
|
|
|
|
// Set invalid type if src and dst SEW are same.
|
|
|
|
if (ElementBitwidth == NewSEW) {
|
|
|
|
ScalarType = ScalarTypeKind::Invalid;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Update new SEW
|
|
|
|
ElementBitwidth = NewSEW;
|
|
|
|
Scale = LMUL.getScale(ElementBitwidth);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RVVType::applyFixedLog2LMUL(int Log2LMUL, enum FixedLMULType Type) {
|
|
|
|
switch (Type) {
|
|
|
|
case FixedLMULType::LargerThan:
|
|
|
|
if (Log2LMUL < LMUL.Log2LMUL) {
|
|
|
|
ScalarType = ScalarTypeKind::Invalid;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case FixedLMULType::SmallerThan:
|
|
|
|
if (Log2LMUL > LMUL.Log2LMUL) {
|
|
|
|
ScalarType = ScalarTypeKind::Invalid;
|
|
|
|
return;
|
2022-04-14 17:35:58 +08:00
|
|
|
}
|
2022-05-11 23:39:13 +08:00
|
|
|
break;
|
2022-04-14 17:35:58 +08:00
|
|
|
}
|
2022-05-11 23:39:13 +08:00
|
|
|
|
|
|
|
// Update new LMUL
|
|
|
|
LMUL = LMULType(Log2LMUL);
|
|
|
|
Scale = LMUL.getScale(ElementBitwidth);
|
|
|
|
}
|
|
|
|
|
|
|
|
Optional<RVVTypes>
|
2022-11-21 22:18:54 +08:00
|
|
|
RVVTypeCache::computeTypes(BasicType BT, int Log2LMUL, unsigned NF,
|
|
|
|
ArrayRef<PrototypeDescriptor> Prototype) {
|
2022-05-11 23:39:13 +08:00
|
|
|
// LMUL x NF must be less than or equal to 8.
|
|
|
|
if ((Log2LMUL >= 1) && (1 << Log2LMUL) * NF > 8)
|
2022-12-03 11:54:46 -08:00
|
|
|
return std::nullopt;
|
2022-05-11 23:39:13 +08:00
|
|
|
|
|
|
|
RVVTypes Types;
|
2022-05-29 22:31:12 -07:00
|
|
|
for (const PrototypeDescriptor &Proto : Prototype) {
|
2022-05-11 23:39:13 +08:00
|
|
|
auto T = computeType(BT, Log2LMUL, Proto);
|
2022-06-25 22:26:24 -07:00
|
|
|
if (!T)
|
2022-12-03 11:54:46 -08:00
|
|
|
return std::nullopt;
|
2022-05-11 23:39:13 +08:00
|
|
|
// Record legal type index
|
2022-12-17 05:15:07 +00:00
|
|
|
Types.push_back(*T);
|
2022-05-11 23:39:13 +08:00
|
|
|
}
|
|
|
|
return Types;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compute the hash value of RVVType, used for cache the result of computeType.
|
|
|
|
static uint64_t computeRVVTypeHashValue(BasicType BT, int Log2LMUL,
|
|
|
|
PrototypeDescriptor Proto) {
|
|
|
|
// Layout of hash value:
|
|
|
|
// 0 8 16 24 32 40
|
|
|
|
// | Log2LMUL + 3 | BT | Proto.PT | Proto.TM | Proto.VTM |
|
|
|
|
assert(Log2LMUL >= -3 && Log2LMUL <= 3);
|
|
|
|
return (Log2LMUL + 3) | (static_cast<uint64_t>(BT) & 0xff) << 8 |
|
|
|
|
((uint64_t)(Proto.PT & 0xff) << 16) |
|
|
|
|
((uint64_t)(Proto.TM & 0xff) << 24) |
|
|
|
|
((uint64_t)(Proto.VTM & 0xff) << 32);
|
|
|
|
}
|
|
|
|
|
2022-11-21 22:18:54 +08:00
|
|
|
Optional<RVVTypePtr> RVVTypeCache::computeType(BasicType BT, int Log2LMUL,
|
|
|
|
PrototypeDescriptor Proto) {
|
2022-05-11 23:39:13 +08:00
|
|
|
uint64_t Idx = computeRVVTypeHashValue(BT, Log2LMUL, Proto);
|
|
|
|
// Search first
|
|
|
|
auto It = LegalTypes.find(Idx);
|
|
|
|
if (It != LegalTypes.end())
|
|
|
|
return &(It->second);
|
|
|
|
|
|
|
|
if (IllegalTypes.count(Idx))
|
2022-12-03 11:54:46 -08:00
|
|
|
return std::nullopt;
|
2022-05-11 23:39:13 +08:00
|
|
|
|
|
|
|
// Compute type and record the result.
|
|
|
|
RVVType T(BT, Log2LMUL, Proto);
|
|
|
|
if (T.isValid()) {
|
|
|
|
// Record legal type index and value.
|
2022-11-21 22:18:54 +08:00
|
|
|
std::pair<std::unordered_map<uint64_t, RVVType>::iterator, bool>
|
|
|
|
InsertResult = LegalTypes.insert({Idx, T});
|
|
|
|
return &(InsertResult.first->second);
|
2022-05-11 23:39:13 +08:00
|
|
|
}
|
|
|
|
// Record illegal type index.
|
|
|
|
IllegalTypes.insert(Idx);
|
2022-12-03 11:54:46 -08:00
|
|
|
return std::nullopt;
|
2022-04-14 17:35:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// RVVIntrinsic implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
RVVIntrinsic::RVVIntrinsic(
|
2022-05-29 22:31:12 -07:00
|
|
|
StringRef NewName, StringRef Suffix, StringRef NewOverloadedName,
|
|
|
|
StringRef OverloadedSuffix, StringRef IRName, bool IsMasked,
|
2022-04-14 17:35:58 +08:00
|
|
|
bool HasMaskedOffOperand, bool HasVL, PolicyScheme Scheme,
|
2022-05-26 17:19:50 -07:00
|
|
|
bool SupportOverloading, bool HasBuiltinAlias, StringRef ManualCodegen,
|
2022-04-14 17:35:58 +08:00
|
|
|
const RVVTypes &OutInTypes, const std::vector<int64_t> &NewIntrinsicTypes,
|
2022-05-26 17:19:50 -07:00
|
|
|
const std::vector<StringRef> &RequiredFeatures, unsigned NF,
|
|
|
|
Policy NewDefaultPolicy, bool IsPrototypeDefaultTU)
|
|
|
|
: IRName(IRName), IsMasked(IsMasked),
|
|
|
|
HasMaskedOffOperand(HasMaskedOffOperand), HasVL(HasVL), Scheme(Scheme),
|
|
|
|
SupportOverloading(SupportOverloading), HasBuiltinAlias(HasBuiltinAlias),
|
|
|
|
ManualCodegen(ManualCodegen.str()), NF(NF),
|
|
|
|
DefaultPolicy(NewDefaultPolicy) {
|
2022-04-14 17:35:58 +08:00
|
|
|
|
2022-05-29 22:31:12 -07:00
|
|
|
// Init BuiltinName, Name and OverloadedName
|
2022-04-14 17:35:58 +08:00
|
|
|
BuiltinName = NewName.str();
|
|
|
|
Name = BuiltinName;
|
2022-05-29 22:31:12 -07:00
|
|
|
if (NewOverloadedName.empty())
|
|
|
|
OverloadedName = NewName.split("_").first.str();
|
2022-04-14 17:35:58 +08:00
|
|
|
else
|
2022-05-29 22:31:12 -07:00
|
|
|
OverloadedName = NewOverloadedName.str();
|
2022-04-14 17:35:58 +08:00
|
|
|
if (!Suffix.empty())
|
|
|
|
Name += "_" + Suffix.str();
|
2022-05-29 22:31:12 -07:00
|
|
|
if (!OverloadedSuffix.empty())
|
|
|
|
OverloadedName += "_" + OverloadedSuffix.str();
|
2022-05-26 17:19:50 -07:00
|
|
|
|
|
|
|
updateNamesAndPolicy(IsMasked, hasPolicy(), IsPrototypeDefaultTU, Name,
|
|
|
|
BuiltinName, OverloadedName, DefaultPolicy);
|
2022-04-14 17:35:58 +08:00
|
|
|
|
|
|
|
// Init OutputType and InputTypes
|
|
|
|
OutputType = OutInTypes[0];
|
|
|
|
InputTypes.assign(OutInTypes.begin() + 1, OutInTypes.end());
|
|
|
|
|
|
|
|
// IntrinsicTypes is unmasked TA version index. Need to update it
|
|
|
|
// if there is merge operand (It is always in first operand).
|
|
|
|
IntrinsicTypes = NewIntrinsicTypes;
|
2022-05-26 17:19:50 -07:00
|
|
|
if ((IsMasked && hasMaskedOffOperand()) ||
|
|
|
|
(!IsMasked && hasPassthruOperand() && !IsPrototypeDefaultTU)) {
|
2022-04-14 17:35:58 +08:00
|
|
|
for (auto &I : IntrinsicTypes) {
|
|
|
|
if (I >= 0)
|
|
|
|
I += NF;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string RVVIntrinsic::getBuiltinTypeStr() const {
|
|
|
|
std::string S;
|
|
|
|
S += OutputType->getBuiltinStr();
|
|
|
|
for (const auto &T : InputTypes) {
|
|
|
|
S += T->getBuiltinStr();
|
|
|
|
}
|
|
|
|
return S;
|
|
|
|
}
|
|
|
|
|
2022-05-11 23:39:13 +08:00
|
|
|
std::string RVVIntrinsic::getSuffixStr(
|
2022-11-21 22:18:54 +08:00
|
|
|
RVVTypeCache &TypeCache, BasicType Type, int Log2LMUL,
|
2022-05-20 16:24:37 +08:00
|
|
|
llvm::ArrayRef<PrototypeDescriptor> PrototypeDescriptors) {
|
2022-05-11 23:39:13 +08:00
|
|
|
SmallVector<std::string> SuffixStrs;
|
|
|
|
for (auto PD : PrototypeDescriptors) {
|
2022-11-21 22:18:54 +08:00
|
|
|
auto T = TypeCache.computeType(Type, Log2LMUL, PD);
|
2022-06-20 22:59:26 -07:00
|
|
|
SuffixStrs.push_back((*T)->getShortStr());
|
2022-05-11 23:39:13 +08:00
|
|
|
}
|
|
|
|
return join(SuffixStrs, "_");
|
|
|
|
}
|
|
|
|
|
2022-05-26 17:19:50 -07:00
|
|
|
llvm::SmallVector<PrototypeDescriptor> RVVIntrinsic::computeBuiltinTypes(
|
|
|
|
llvm::ArrayRef<PrototypeDescriptor> Prototype, bool IsMasked,
|
|
|
|
bool HasMaskedOffOperand, bool HasVL, unsigned NF,
|
|
|
|
bool IsPrototypeDefaultTU, PolicyScheme DefaultScheme,
|
|
|
|
Policy DefaultPolicy) {
|
2022-07-26 09:12:32 +00:00
|
|
|
SmallVector<PrototypeDescriptor> NewPrototype(Prototype.begin(),
|
|
|
|
Prototype.end());
|
2022-05-26 17:19:50 -07:00
|
|
|
// Update DefaultPolicy if need (TA or TAMA) for compute builtin types.
|
[RISCV] Refactor RVV Policy by structure
RVV intrinsic function has several policy variants.
Include TU, TA, TAMU, TAMA, TUMU, TUMA, MU, MA, TUM, TAM
Currently, the clang side enumerates these policies, but it's hard to add a new policy.
This patch use structure to replace the origin policy enumeration, and enhance some policy transform logic.
This is a clean-up job that will not affect the RVV intrinsic functionality and make sure riscv_vector_builtin_cg.inc is the same as the original one.
Reviewed By: kito-cheng
Differential Revision: https://reviews.llvm.org/D139995
2022-12-20 01:12:57 -08:00
|
|
|
if (DefaultPolicy.isMAPolicy())
|
|
|
|
DefaultPolicy.TailPolicy = Policy::PolicyType::Agnostic; // TAMA
|
|
|
|
if (DefaultPolicy.isPolicyNonePolicy()) {
|
2022-05-26 17:19:50 -07:00
|
|
|
if (!IsMasked) {
|
[RISCV] Refactor RVV Policy by structure
RVV intrinsic function has several policy variants.
Include TU, TA, TAMU, TAMA, TUMU, TUMA, MU, MA, TUM, TAM
Currently, the clang side enumerates these policies, but it's hard to add a new policy.
This patch use structure to replace the origin policy enumeration, and enhance some policy transform logic.
This is a clean-up job that will not affect the RVV intrinsic functionality and make sure riscv_vector_builtin_cg.inc is the same as the original one.
Reviewed By: kito-cheng
Differential Revision: https://reviews.llvm.org/D139995
2022-12-20 01:12:57 -08:00
|
|
|
DefaultPolicy.PolicyNone = false;
|
2022-05-26 17:19:50 -07:00
|
|
|
if (IsPrototypeDefaultTU)
|
[RISCV] Refactor RVV Policy by structure
RVV intrinsic function has several policy variants.
Include TU, TA, TAMU, TAMA, TUMU, TUMA, MU, MA, TUM, TAM
Currently, the clang side enumerates these policies, but it's hard to add a new policy.
This patch use structure to replace the origin policy enumeration, and enhance some policy transform logic.
This is a clean-up job that will not affect the RVV intrinsic functionality and make sure riscv_vector_builtin_cg.inc is the same as the original one.
Reviewed By: kito-cheng
Differential Revision: https://reviews.llvm.org/D139995
2022-12-20 01:12:57 -08:00
|
|
|
DefaultPolicy.TailPolicy = Policy::PolicyType::Undisturbed; // TU
|
2022-05-26 17:19:50 -07:00
|
|
|
else
|
[RISCV] Refactor RVV Policy by structure
RVV intrinsic function has several policy variants.
Include TU, TA, TAMU, TAMA, TUMU, TUMA, MU, MA, TUM, TAM
Currently, the clang side enumerates these policies, but it's hard to add a new policy.
This patch use structure to replace the origin policy enumeration, and enhance some policy transform logic.
This is a clean-up job that will not affect the RVV intrinsic functionality and make sure riscv_vector_builtin_cg.inc is the same as the original one.
Reviewed By: kito-cheng
Differential Revision: https://reviews.llvm.org/D139995
2022-12-20 01:12:57 -08:00
|
|
|
DefaultPolicy.TailPolicy = Policy::PolicyType::Agnostic; // TA
|
2022-05-26 17:19:50 -07:00
|
|
|
}
|
|
|
|
}
|
2022-08-02 16:39:17 +00:00
|
|
|
bool HasPassthruOp = DefaultScheme == PolicyScheme::HasPassthruOperand;
|
2022-07-26 09:12:32 +00:00
|
|
|
if (IsMasked) {
|
2022-05-26 17:19:50 -07:00
|
|
|
// If HasMaskedOffOperand, insert result type as first input operand if
|
|
|
|
// need.
|
[RISCV] Refactor RVV Policy by structure
RVV intrinsic function has several policy variants.
Include TU, TA, TAMU, TAMA, TUMU, TUMA, MU, MA, TUM, TAM
Currently, the clang side enumerates these policies, but it's hard to add a new policy.
This patch use structure to replace the origin policy enumeration, and enhance some policy transform logic.
This is a clean-up job that will not affect the RVV intrinsic functionality and make sure riscv_vector_builtin_cg.inc is the same as the original one.
Reviewed By: kito-cheng
Differential Revision: https://reviews.llvm.org/D139995
2022-12-20 01:12:57 -08:00
|
|
|
if (HasMaskedOffOperand && !DefaultPolicy.isTAMAPolicy()) {
|
2022-08-04 17:34:05 +00:00
|
|
|
if (NF == 1) {
|
2022-07-26 09:12:32 +00:00
|
|
|
NewPrototype.insert(NewPrototype.begin() + 1, NewPrototype[0]);
|
2022-05-26 17:19:50 -07:00
|
|
|
} else if (NF > 1) {
|
2022-07-26 09:12:32 +00:00
|
|
|
// Convert
|
|
|
|
// (void, op0 address, op1 address, ...)
|
|
|
|
// to
|
|
|
|
// (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...)
|
|
|
|
PrototypeDescriptor MaskoffType = NewPrototype[1];
|
|
|
|
MaskoffType.TM &= ~static_cast<uint8_t>(TypeModifier::Pointer);
|
2022-12-25 07:38:01 -08:00
|
|
|
NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType);
|
2022-07-26 09:12:32 +00:00
|
|
|
}
|
|
|
|
}
|
2022-08-02 16:39:17 +00:00
|
|
|
// Erase passthru operand for TAM
|
[RISCV] Refactor RVV Policy by structure
RVV intrinsic function has several policy variants.
Include TU, TA, TAMU, TAMA, TUMU, TUMA, MU, MA, TUM, TAM
Currently, the clang side enumerates these policies, but it's hard to add a new policy.
This patch use structure to replace the origin policy enumeration, and enhance some policy transform logic.
This is a clean-up job that will not affect the RVV intrinsic functionality and make sure riscv_vector_builtin_cg.inc is the same as the original one.
Reviewed By: kito-cheng
Differential Revision: https://reviews.llvm.org/D139995
2022-12-20 01:12:57 -08:00
|
|
|
if (NF == 1 && IsPrototypeDefaultTU && DefaultPolicy.isTAMAPolicy() &&
|
2022-08-02 16:39:17 +00:00
|
|
|
HasPassthruOp && !HasMaskedOffOperand)
|
|
|
|
NewPrototype.erase(NewPrototype.begin() + 1);
|
2022-07-26 09:12:32 +00:00
|
|
|
if (HasMaskedOffOperand && NF > 1) {
|
|
|
|
// Convert
|
|
|
|
// (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...)
|
|
|
|
// to
|
|
|
|
// (void, op0 address, op1 address, ..., mask, maskedoff0, maskedoff1,
|
|
|
|
// ...)
|
|
|
|
NewPrototype.insert(NewPrototype.begin() + NF + 1,
|
|
|
|
PrototypeDescriptor::Mask);
|
|
|
|
} else {
|
|
|
|
// If IsMasked, insert PrototypeDescriptor:Mask as first input operand.
|
|
|
|
NewPrototype.insert(NewPrototype.begin() + 1, PrototypeDescriptor::Mask);
|
|
|
|
}
|
2022-08-04 17:34:05 +00:00
|
|
|
} else {
|
|
|
|
if (NF == 1) {
|
[RISCV] Refactor RVV Policy by structure
RVV intrinsic function has several policy variants.
Include TU, TA, TAMU, TAMA, TUMU, TUMA, MU, MA, TUM, TAM
Currently, the clang side enumerates these policies, but it's hard to add a new policy.
This patch use structure to replace the origin policy enumeration, and enhance some policy transform logic.
This is a clean-up job that will not affect the RVV intrinsic functionality and make sure riscv_vector_builtin_cg.inc is the same as the original one.
Reviewed By: kito-cheng
Differential Revision: https://reviews.llvm.org/D139995
2022-12-20 01:12:57 -08:00
|
|
|
if (DefaultPolicy.isTUPolicy() && HasPassthruOp && !IsPrototypeDefaultTU)
|
2022-08-04 17:34:05 +00:00
|
|
|
NewPrototype.insert(NewPrototype.begin(), NewPrototype[0]);
|
[RISCV] Refactor RVV Policy by structure
RVV intrinsic function has several policy variants.
Include TU, TA, TAMU, TAMA, TUMU, TUMA, MU, MA, TUM, TAM
Currently, the clang side enumerates these policies, but it's hard to add a new policy.
This patch use structure to replace the origin policy enumeration, and enhance some policy transform logic.
This is a clean-up job that will not affect the RVV intrinsic functionality and make sure riscv_vector_builtin_cg.inc is the same as the original one.
Reviewed By: kito-cheng
Differential Revision: https://reviews.llvm.org/D139995
2022-12-20 01:12:57 -08:00
|
|
|
else if (DefaultPolicy.isTAPolicy() && HasPassthruOp &&
|
2022-08-04 17:34:05 +00:00
|
|
|
IsPrototypeDefaultTU)
|
|
|
|
NewPrototype.erase(NewPrototype.begin() + 1);
|
|
|
|
if (DefaultScheme == PolicyScheme::HasPassthruOperandAtIdx1) {
|
[RISCV] Refactor RVV Policy by structure
RVV intrinsic function has several policy variants.
Include TU, TA, TAMU, TAMA, TUMU, TUMA, MU, MA, TUM, TAM
Currently, the clang side enumerates these policies, but it's hard to add a new policy.
This patch use structure to replace the origin policy enumeration, and enhance some policy transform logic.
This is a clean-up job that will not affect the RVV intrinsic functionality and make sure riscv_vector_builtin_cg.inc is the same as the original one.
Reviewed By: kito-cheng
Differential Revision: https://reviews.llvm.org/D139995
2022-12-20 01:12:57 -08:00
|
|
|
if (DefaultPolicy.isTUPolicy() && !IsPrototypeDefaultTU) {
|
2022-08-04 17:34:05 +00:00
|
|
|
// Insert undisturbed output to index 1
|
|
|
|
NewPrototype.insert(NewPrototype.begin() + 2, NewPrototype[0]);
|
[RISCV] Refactor RVV Policy by structure
RVV intrinsic function has several policy variants.
Include TU, TA, TAMU, TAMA, TUMU, TUMA, MU, MA, TUM, TAM
Currently, the clang side enumerates these policies, but it's hard to add a new policy.
This patch use structure to replace the origin policy enumeration, and enhance some policy transform logic.
This is a clean-up job that will not affect the RVV intrinsic functionality and make sure riscv_vector_builtin_cg.inc is the same as the original one.
Reviewed By: kito-cheng
Differential Revision: https://reviews.llvm.org/D139995
2022-12-20 01:12:57 -08:00
|
|
|
} else if (DefaultPolicy.isTAPolicy() && IsPrototypeDefaultTU) {
|
2022-08-04 17:34:05 +00:00
|
|
|
// Erase passthru for TA policy
|
|
|
|
NewPrototype.erase(NewPrototype.begin() + 2);
|
|
|
|
}
|
2022-08-01 17:59:53 +00:00
|
|
|
}
|
[RISCV] Refactor RVV Policy by structure
RVV intrinsic function has several policy variants.
Include TU, TA, TAMU, TAMA, TUMU, TUMA, MU, MA, TUM, TAM
Currently, the clang side enumerates these policies, but it's hard to add a new policy.
This patch use structure to replace the origin policy enumeration, and enhance some policy transform logic.
This is a clean-up job that will not affect the RVV intrinsic functionality and make sure riscv_vector_builtin_cg.inc is the same as the original one.
Reviewed By: kito-cheng
Differential Revision: https://reviews.llvm.org/D139995
2022-12-20 01:12:57 -08:00
|
|
|
} else if (DefaultPolicy.isTUPolicy() && HasPassthruOp) {
|
2022-08-04 17:34:05 +00:00
|
|
|
// NF > 1 cases for segment load operations.
|
|
|
|
// Convert
|
|
|
|
// (void, op0 address, op1 address, ...)
|
|
|
|
// to
|
|
|
|
// (void, op0 address, op1 address, maskedoff0, maskedoff1, ...)
|
|
|
|
PrototypeDescriptor MaskoffType = Prototype[1];
|
|
|
|
MaskoffType.TM &= ~static_cast<uint8_t>(TypeModifier::Pointer);
|
2022-12-25 07:38:01 -08:00
|
|
|
NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType);
|
2022-08-01 17:59:53 +00:00
|
|
|
}
|
2022-08-04 17:34:05 +00:00
|
|
|
}
|
2022-07-26 09:12:32 +00:00
|
|
|
|
|
|
|
// If HasVL, append PrototypeDescriptor:VL to last operand
|
|
|
|
if (HasVL)
|
|
|
|
NewPrototype.push_back(PrototypeDescriptor::VL);
|
|
|
|
return NewPrototype;
|
|
|
|
}
|
|
|
|
|
2022-05-26 17:19:50 -07:00
|
|
|
llvm::SmallVector<Policy>
|
|
|
|
RVVIntrinsic::getSupportedMaskedPolicies(bool HasTailPolicy,
|
|
|
|
bool HasMaskPolicy) {
|
|
|
|
if (HasTailPolicy && HasMaskPolicy)
|
[RISCV] Refactor RVV Policy by structure
RVV intrinsic function has several policy variants.
Include TU, TA, TAMU, TAMA, TUMU, TUMA, MU, MA, TUM, TAM
Currently, the clang side enumerates these policies, but it's hard to add a new policy.
This patch use structure to replace the origin policy enumeration, and enhance some policy transform logic.
This is a clean-up job that will not affect the RVV intrinsic functionality and make sure riscv_vector_builtin_cg.inc is the same as the original one.
Reviewed By: kito-cheng
Differential Revision: https://reviews.llvm.org/D139995
2022-12-20 01:12:57 -08:00
|
|
|
return {Policy(Policy::PolicyType::Undisturbed,
|
|
|
|
Policy::PolicyType::Agnostic), // TUMA
|
|
|
|
Policy(Policy::PolicyType::Agnostic,
|
|
|
|
Policy::PolicyType::Agnostic), // TAMA
|
|
|
|
Policy(Policy::PolicyType::Undisturbed,
|
|
|
|
Policy::PolicyType::Undisturbed), // TUMU
|
|
|
|
Policy(Policy::PolicyType::Agnostic,
|
|
|
|
Policy::PolicyType::Undisturbed)}; // TAMU
|
|
|
|
|
|
|
|
if (HasTailPolicy)
|
|
|
|
return {Policy(Policy::PolicyType::Undisturbed,
|
|
|
|
Policy::PolicyType::Agnostic, true), // TUM
|
|
|
|
Policy(Policy::PolicyType::Agnostic, Policy::PolicyType::Agnostic,
|
|
|
|
true)}; // TAM
|
|
|
|
|
|
|
|
return {
|
|
|
|
Policy(Policy::PolicyType::Omit, Policy::PolicyType::Agnostic), // MA
|
|
|
|
Policy(Policy::PolicyType::Omit, Policy::PolicyType::Undisturbed)}; // MU
|
2022-05-26 17:19:50 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void RVVIntrinsic::updateNamesAndPolicy(bool IsMasked, bool HasPolicy,
|
|
|
|
bool IsPrototypeDefaultTU,
|
|
|
|
std::string &Name,
|
|
|
|
std::string &BuiltinName,
|
|
|
|
std::string &OverloadedName,
|
|
|
|
Policy &DefaultPolicy) {
|
|
|
|
|
|
|
|
auto appendPolicySuffix = [&](const std::string &suffix) {
|
|
|
|
Name += suffix;
|
|
|
|
BuiltinName += suffix;
|
|
|
|
OverloadedName += suffix;
|
|
|
|
};
|
|
|
|
|
[RISCV] Refactor RVV Policy by structure
RVV intrinsic function has several policy variants.
Include TU, TA, TAMU, TAMA, TUMU, TUMA, MU, MA, TUM, TAM
Currently, the clang side enumerates these policies, but it's hard to add a new policy.
This patch use structure to replace the origin policy enumeration, and enhance some policy transform logic.
This is a clean-up job that will not affect the RVV intrinsic functionality and make sure riscv_vector_builtin_cg.inc is the same as the original one.
Reviewed By: kito-cheng
Differential Revision: https://reviews.llvm.org/D139995
2022-12-20 01:12:57 -08:00
|
|
|
if (DefaultPolicy.isPolicyNonePolicy()) {
|
|
|
|
DefaultPolicy.PolicyNone = false;
|
2022-05-26 17:19:50 -07:00
|
|
|
if (IsMasked) {
|
|
|
|
Name += "_m";
|
|
|
|
// FIXME: Currently _m default policy implementation is different with
|
|
|
|
// RVV intrinsic spec (TUMA)
|
[RISCV] Refactor RVV Policy by structure
RVV intrinsic function has several policy variants.
Include TU, TA, TAMU, TAMA, TUMU, TUMA, MU, MA, TUM, TAM
Currently, the clang side enumerates these policies, but it's hard to add a new policy.
This patch use structure to replace the origin policy enumeration, and enhance some policy transform logic.
This is a clean-up job that will not affect the RVV intrinsic functionality and make sure riscv_vector_builtin_cg.inc is the same as the original one.
Reviewed By: kito-cheng
Differential Revision: https://reviews.llvm.org/D139995
2022-12-20 01:12:57 -08:00
|
|
|
DefaultPolicy.TailPolicy = Policy::PolicyType::Undisturbed;
|
|
|
|
DefaultPolicy.MaskPolicy = Policy::PolicyType::Undisturbed;
|
2022-05-26 17:19:50 -07:00
|
|
|
if (HasPolicy)
|
|
|
|
BuiltinName += "_tumu";
|
|
|
|
else
|
|
|
|
BuiltinName += "_m";
|
|
|
|
} else if (IsPrototypeDefaultTU) {
|
[RISCV] Refactor RVV Policy by structure
RVV intrinsic function has several policy variants.
Include TU, TA, TAMU, TAMA, TUMU, TUMA, MU, MA, TUM, TAM
Currently, the clang side enumerates these policies, but it's hard to add a new policy.
This patch use structure to replace the origin policy enumeration, and enhance some policy transform logic.
This is a clean-up job that will not affect the RVV intrinsic functionality and make sure riscv_vector_builtin_cg.inc is the same as the original one.
Reviewed By: kito-cheng
Differential Revision: https://reviews.llvm.org/D139995
2022-12-20 01:12:57 -08:00
|
|
|
DefaultPolicy.TailPolicy = Policy::PolicyType::Undisturbed;
|
2022-05-26 17:19:50 -07:00
|
|
|
if (HasPolicy)
|
|
|
|
BuiltinName += "_tu";
|
|
|
|
} else {
|
[RISCV] Refactor RVV Policy by structure
RVV intrinsic function has several policy variants.
Include TU, TA, TAMU, TAMA, TUMU, TUMA, MU, MA, TUM, TAM
Currently, the clang side enumerates these policies, but it's hard to add a new policy.
This patch use structure to replace the origin policy enumeration, and enhance some policy transform logic.
This is a clean-up job that will not affect the RVV intrinsic functionality and make sure riscv_vector_builtin_cg.inc is the same as the original one.
Reviewed By: kito-cheng
Differential Revision: https://reviews.llvm.org/D139995
2022-12-20 01:12:57 -08:00
|
|
|
DefaultPolicy.TailPolicy = Policy::PolicyType::Agnostic;
|
2022-05-26 17:19:50 -07:00
|
|
|
if (HasPolicy)
|
|
|
|
BuiltinName += "_ta";
|
|
|
|
}
|
[RISCV] Refactor RVV Policy by structure
RVV intrinsic function has several policy variants.
Include TU, TA, TAMU, TAMA, TUMU, TUMA, MU, MA, TUM, TAM
Currently, the clang side enumerates these policies, but it's hard to add a new policy.
This patch use structure to replace the origin policy enumeration, and enhance some policy transform logic.
This is a clean-up job that will not affect the RVV intrinsic functionality and make sure riscv_vector_builtin_cg.inc is the same as the original one.
Reviewed By: kito-cheng
Differential Revision: https://reviews.llvm.org/D139995
2022-12-20 01:12:57 -08:00
|
|
|
} else {
|
|
|
|
if (DefaultPolicy.isTUMPolicy())
|
|
|
|
appendPolicySuffix("_tum");
|
|
|
|
else if (DefaultPolicy.isTAMPolicy())
|
|
|
|
appendPolicySuffix("_tam");
|
|
|
|
else if (DefaultPolicy.isTUMUPolicy())
|
|
|
|
appendPolicySuffix("_tumu");
|
|
|
|
else if (DefaultPolicy.isTAMUPolicy())
|
|
|
|
appendPolicySuffix("_tamu");
|
|
|
|
else if (DefaultPolicy.isTUMAPolicy())
|
|
|
|
appendPolicySuffix("_tuma");
|
|
|
|
else if (DefaultPolicy.isTAMAPolicy())
|
|
|
|
appendPolicySuffix("_tama");
|
|
|
|
else if (DefaultPolicy.isTUPolicy())
|
|
|
|
appendPolicySuffix("_tu");
|
|
|
|
else if (DefaultPolicy.isTAPolicy())
|
|
|
|
appendPolicySuffix("_ta");
|
|
|
|
else if (DefaultPolicy.isMUPolicy()) {
|
|
|
|
appendPolicySuffix("_mu");
|
|
|
|
DefaultPolicy.TailPolicy = Policy::PolicyType::Agnostic;
|
|
|
|
} else if (DefaultPolicy.isMAPolicy()) {
|
|
|
|
appendPolicySuffix("_ma");
|
|
|
|
DefaultPolicy.TailPolicy = Policy::PolicyType::Agnostic;
|
|
|
|
}
|
2022-05-26 17:19:50 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-11 23:39:13 +08:00
|
|
|
SmallVector<PrototypeDescriptor> parsePrototypes(StringRef Prototypes) {
|
|
|
|
SmallVector<PrototypeDescriptor> PrototypeDescriptors;
|
|
|
|
const StringRef Primaries("evwqom0ztul");
|
|
|
|
while (!Prototypes.empty()) {
|
|
|
|
size_t Idx = 0;
|
|
|
|
// Skip over complex prototype because it could contain primitive type
|
|
|
|
// character.
|
|
|
|
if (Prototypes[0] == '(')
|
|
|
|
Idx = Prototypes.find_first_of(')');
|
|
|
|
Idx = Prototypes.find_first_of(Primaries, Idx);
|
|
|
|
assert(Idx != StringRef::npos);
|
|
|
|
auto PD = PrototypeDescriptor::parsePrototypeDescriptor(
|
|
|
|
Prototypes.slice(0, Idx + 1));
|
|
|
|
if (!PD)
|
|
|
|
llvm_unreachable("Error during parsing prototype.");
|
|
|
|
PrototypeDescriptors.push_back(*PD);
|
|
|
|
Prototypes = Prototypes.drop_front(Idx + 1);
|
|
|
|
}
|
|
|
|
return PrototypeDescriptors;
|
|
|
|
}
|
|
|
|
|
[RISCV] Lazily add RVV C intrinsics.
Leverage the method OpenCL uses that adds C intrinsics when the lookup
failed. There is no need to define C intrinsics in the header file any
more. It could help to avoid the large header file to speed up the
compilation of RVV source code. Besides that, only the C intrinsics used
by the users will be added into the declaration table.
This patch is based on https://reviews.llvm.org/D103228 and inspired by
OpenCL implementation.
### Experimental Results
#### TL;DR:
- Binary size of clang increase ~200k, which is +0.07% for debug build and +0.13% for release build.
- Single file compilation speed up ~33x for debug build and ~8.5x for release build
- Regression time reduce ~10% (`ninja check-all`, enable all targets)
#### Header size change
```
| size | LoC |
------------------------------
Before | 4,434,725 | 69,749 |
After | 6,140 | 162 |
```
#### Single File Compilation Time
Testcase:
```
#include <riscv_vector.h>
vint32m1_t test_vadd_vv_vfloat32m1_t(vint32m1_t op1, vint32m1_t op2, size_t vl) {
return vadd(op1, op2, vl);
}
```
##### Debug build:
Before:
```
real 0m19.352s
user 0m19.252s
sys 0m0.092s
```
After:
```
real 0m0.576s
user 0m0.552s
sys 0m0.024s
```
~33x speed up for debug build
##### Release build:
Before:
```
real 0m0.773s
user 0m0.741s
sys 0m0.032s
```
After:
```
real 0m0.092s
user 0m0.080s
sys 0m0.012s
```
~8.5x speed up for release build
#### Regression time
Note: the failed case is `tools/llvm-debuginfod-find/debuginfod.test` which is unrelated to this patch.
##### Debug build
Before:
```
Testing Time: 1358.38s
Skipped : 11
Unsupported : 446
Passed : 75767
Expectedly Failed: 190
Failed : 1
```
After
```
Testing Time: 1220.29s
Skipped : 11
Unsupported : 446
Passed : 75767
Expectedly Failed: 190
Failed : 1
```
##### Release build
Before:
```
Testing Time: 381.98s
Skipped : 12
Unsupported : 1407
Passed : 74765
Expectedly Failed: 176
Failed : 1
```
After:
```
Testing Time: 346.25s
Skipped : 12
Unsupported : 1407
Passed : 74765
Expectedly Failed: 176
Failed : 1
```
#### Binary size of clang
##### Debug build
Before
```
text data bss dec hex filename
335261851 12726004 552812 348540667 14c64efb bin/clang
```
After
```
text data bss dec hex filename
335442803 12798708 552940 348794451 14ca2e53 bin/clang
```
+253K, +0.07% code size
##### Release build
Before
```
text data bss dec hex filename
144123975 8374648 483140 152981763 91e5103 bin/clang
```
After
```
text data bss dec hex filename
144255762 8447296 483268 153186326 9217016 bin/clang
```
+204K, +0.13%
Authored-by: Kito Cheng <kito.cheng@sifive.com>
Co-Authored-by: Hsiangkai Wang <kai.wang@sifive.com>
Reviewed By: khchen, aaron.ballman
Differential Revision: https://reviews.llvm.org/D111617
2022-07-13 15:52:17 +08:00
|
|
|
raw_ostream &operator<<(raw_ostream &OS, const RVVIntrinsicRecord &Record) {
|
|
|
|
OS << "{";
|
|
|
|
OS << "\"" << Record.Name << "\",";
|
|
|
|
if (Record.OverloadedName == nullptr ||
|
|
|
|
StringRef(Record.OverloadedName).empty())
|
|
|
|
OS << "nullptr,";
|
|
|
|
else
|
|
|
|
OS << "\"" << Record.OverloadedName << "\",";
|
|
|
|
OS << Record.PrototypeIndex << ",";
|
|
|
|
OS << Record.SuffixIndex << ",";
|
|
|
|
OS << Record.OverloadedSuffixIndex << ",";
|
|
|
|
OS << (int)Record.PrototypeLength << ",";
|
|
|
|
OS << (int)Record.SuffixLength << ",";
|
|
|
|
OS << (int)Record.OverloadedSuffixSize << ",";
|
|
|
|
OS << (int)Record.RequiredExtensions << ",";
|
|
|
|
OS << (int)Record.TypeRangeMask << ",";
|
|
|
|
OS << (int)Record.Log2LMULMask << ",";
|
|
|
|
OS << (int)Record.NF << ",";
|
2022-07-26 10:14:03 +00:00
|
|
|
OS << (int)Record.HasMasked << ",";
|
|
|
|
OS << (int)Record.HasVL << ",";
|
|
|
|
OS << (int)Record.HasMaskedOffOperand << ",";
|
2022-05-26 17:19:50 -07:00
|
|
|
OS << (int)Record.IsPrototypeDefaultTU << ",";
|
|
|
|
OS << (int)Record.HasTailPolicy << ",";
|
|
|
|
OS << (int)Record.HasMaskPolicy << ",";
|
|
|
|
OS << (int)Record.UnMaskedPolicyScheme << ",";
|
|
|
|
OS << (int)Record.MaskedPolicyScheme << ",";
|
[RISCV] Lazily add RVV C intrinsics.
Leverage the method OpenCL uses that adds C intrinsics when the lookup
failed. There is no need to define C intrinsics in the header file any
more. It could help to avoid the large header file to speed up the
compilation of RVV source code. Besides that, only the C intrinsics used
by the users will be added into the declaration table.
This patch is based on https://reviews.llvm.org/D103228 and inspired by
OpenCL implementation.
### Experimental Results
#### TL;DR:
- Binary size of clang increase ~200k, which is +0.07% for debug build and +0.13% for release build.
- Single file compilation speed up ~33x for debug build and ~8.5x for release build
- Regression time reduce ~10% (`ninja check-all`, enable all targets)
#### Header size change
```
| size | LoC |
------------------------------
Before | 4,434,725 | 69,749 |
After | 6,140 | 162 |
```
#### Single File Compilation Time
Testcase:
```
#include <riscv_vector.h>
vint32m1_t test_vadd_vv_vfloat32m1_t(vint32m1_t op1, vint32m1_t op2, size_t vl) {
return vadd(op1, op2, vl);
}
```
##### Debug build:
Before:
```
real 0m19.352s
user 0m19.252s
sys 0m0.092s
```
After:
```
real 0m0.576s
user 0m0.552s
sys 0m0.024s
```
~33x speed up for debug build
##### Release build:
Before:
```
real 0m0.773s
user 0m0.741s
sys 0m0.032s
```
After:
```
real 0m0.092s
user 0m0.080s
sys 0m0.012s
```
~8.5x speed up for release build
#### Regression time
Note: the failed case is `tools/llvm-debuginfod-find/debuginfod.test` which is unrelated to this patch.
##### Debug build
Before:
```
Testing Time: 1358.38s
Skipped : 11
Unsupported : 446
Passed : 75767
Expectedly Failed: 190
Failed : 1
```
After
```
Testing Time: 1220.29s
Skipped : 11
Unsupported : 446
Passed : 75767
Expectedly Failed: 190
Failed : 1
```
##### Release build
Before:
```
Testing Time: 381.98s
Skipped : 12
Unsupported : 1407
Passed : 74765
Expectedly Failed: 176
Failed : 1
```
After:
```
Testing Time: 346.25s
Skipped : 12
Unsupported : 1407
Passed : 74765
Expectedly Failed: 176
Failed : 1
```
#### Binary size of clang
##### Debug build
Before
```
text data bss dec hex filename
335261851 12726004 552812 348540667 14c64efb bin/clang
```
After
```
text data bss dec hex filename
335442803 12798708 552940 348794451 14ca2e53 bin/clang
```
+253K, +0.07% code size
##### Release build
Before
```
text data bss dec hex filename
144123975 8374648 483140 152981763 91e5103 bin/clang
```
After
```
text data bss dec hex filename
144255762 8447296 483268 153186326 9217016 bin/clang
```
+204K, +0.13%
Authored-by: Kito Cheng <kito.cheng@sifive.com>
Co-Authored-by: Hsiangkai Wang <kai.wang@sifive.com>
Reviewed By: khchen, aaron.ballman
Differential Revision: https://reviews.llvm.org/D111617
2022-07-13 15:52:17 +08:00
|
|
|
OS << "},\n";
|
|
|
|
return OS;
|
|
|
|
}
|
|
|
|
|
2022-04-14 17:35:58 +08:00
|
|
|
} // end namespace RISCV
|
|
|
|
} // end namespace clang
|