Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/riscv_vector_common.td
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,9 @@ class RVVBuiltin<string suffix, string prototype, string type_range,
// This builtin has a masked form.
bit HasMasked = true;

// This is used by intrinsics that need vtype.altfmt
bit AltFmt = false;

// If HasMasked, this flag states that this builtin has a maskedoff operand. It
// is always the first operand in builtin and IR intrinsic.
bit HasMaskedOffOperand = true;
Expand Down
19 changes: 13 additions & 6 deletions clang/include/clang/Support/RISCVVIntrinsicUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ llvm::SmallVector<PrototypeDescriptor>
parsePrototypes(llvm::StringRef Prototypes);

// Basic type of vector type.
enum class BasicType : uint8_t {
enum class BasicType : uint16_t {
Unknown = 0,
Int8 = 1 << 0,
Int16 = 1 << 1,
Expand All @@ -212,8 +212,10 @@ enum class BasicType : uint8_t {
Float16 = 1 << 5,
Float32 = 1 << 6,
Float64 = 1 << 7,
MaxOffset = 7,
LLVM_MARK_AS_BITMASK_ENUM(Float64),
F8E4M3 = 1 << 8,
F8E5M2 = 1 << 9,
MaxOffset = 9,
LLVM_MARK_AS_BITMASK_ENUM(F8E5M2),
};

// Type of vector type.
Expand All @@ -228,6 +230,8 @@ enum ScalarTypeKind : uint8_t {
UnsignedInteger,
Float,
BFloat,
FloatE4M3,
FloatE5M2,
Invalid,
Undefined,
};
Expand Down Expand Up @@ -412,7 +416,8 @@ class RVVIntrinsic {
bool HasBuiltinAlias, llvm::StringRef ManualCodegen,
const RVVTypes &Types,
const std::vector<int64_t> &IntrinsicTypes, unsigned NF,
Policy PolicyAttrs, bool HasFRMRoundModeOp, unsigned TWiden);
Policy PolicyAttrs, bool HasFRMRoundModeOp, unsigned TWiden,
bool AltFmt);
~RVVIntrinsic() = default;

RVVTypePtr getOutputType() const { return OutputType; }
Expand Down Expand Up @@ -482,7 +487,8 @@ class RVVIntrinsic {
static void updateNamesAndPolicy(bool IsMasked, bool HasPolicy,
std::string &Name, std::string &BuiltinName,
std::string &OverloadedName,
Policy &PolicyAttrs, bool HasFRMRoundModeOp);
Policy &PolicyAttrs, bool HasFRMRoundModeOp,
bool AltFmt);
};

// Raw RVV intrinsic info, used to expand later.
Expand Down Expand Up @@ -517,7 +523,7 @@ struct RVVIntrinsicRecord {
uint8_t OverloadedSuffixSize;

// Supported type, mask of BasicType.
uint8_t TypeRangeMask;
uint16_t TypeRangeMask;

// Supported LMUL.
uint8_t Log2LMULMask;
Expand All @@ -531,6 +537,7 @@ struct RVVIntrinsicRecord {
bool HasTailPolicy : 1;
bool HasMaskPolicy : 1;
bool HasFRMRoundModeOp : 1;
bool AltFmt : 1;
bool IsTuple : 1;
LLVM_PREFERRED_TYPE(PolicyScheme)
uint8_t UnMaskedPolicyScheme : 2;
Expand Down
6 changes: 5 additions & 1 deletion clang/lib/Sema/SemaRISCV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@ static QualType RVVType2Qual(ASTContext &Context, const RVVType *Type) {
case ScalarTypeKind::UnsignedInteger:
QT = Context.getIntTypeForBitwidth(Type->getElementBitwidth(), false);
break;
case ScalarTypeKind::FloatE4M3:
case ScalarTypeKind::FloatE5M2:
QT = Context.getIntTypeForBitwidth(8, false);
break;
case ScalarTypeKind::BFloat:
QT = Context.BFloat16Ty;
break;
Expand Down Expand Up @@ -379,7 +383,7 @@ void RISCVIntrinsicManagerImpl::InitRVVIntrinsic(

RVVIntrinsic::updateNamesAndPolicy(IsMasked, HasPolicy, Name, BuiltinName,
OverloadedName, PolicyAttrs,
Record.HasFRMRoundModeOp);
Record.HasFRMRoundModeOp, Record.AltFmt);

// Put into IntrinsicList.
uint32_t Index = IntrinsicList.size();
Expand Down
72 changes: 56 additions & 16 deletions clang/lib/Support/RISCVVIntrinsicUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,12 @@ void RVVType::initBuiltinStr() {
case ScalarTypeKind::BFloat:
BuiltinStr += "y";
break;
case ScalarTypeKind::FloatE4M3:
BuiltinStr += "a";
break;
case ScalarTypeKind::FloatE5M2:
BuiltinStr += "b";
break;
default:
llvm_unreachable("ScalarType is invalid!");
}
Expand Down Expand Up @@ -244,6 +250,8 @@ void RVVType::initClangBuiltinStr() {
ClangBuiltinStr += "int";
break;
case ScalarTypeKind::UnsignedInteger:
case ScalarTypeKind::FloatE4M3:
case ScalarTypeKind::FloatE5M2:
ClangBuiltinStr += "uint";
break;
default:
Expand Down Expand Up @@ -319,6 +327,8 @@ void RVVType::initTypeStr() {
Str += getTypeString("int");
break;
case ScalarTypeKind::UnsignedInteger:
case ScalarTypeKind::FloatE4M3:
case ScalarTypeKind::FloatE5M2:
Str += getTypeString("uint");
break;
default:
Expand Down Expand Up @@ -346,6 +356,12 @@ void RVVType::initShortStr() {
case ScalarTypeKind::UnsignedInteger:
ShortStr = "u" + utostr(ElementBitwidth);
break;
case ScalarTypeKind::FloatE4M3:
ShortStr = "f8e4m3";
break;
case ScalarTypeKind::FloatE5M2:
ShortStr = "f8e5m2";
break;
default:
llvm_unreachable("Unhandled case!");
}
Expand Down Expand Up @@ -395,6 +411,14 @@ void RVVType::applyBasicType() {
ElementBitwidth = 16;
ScalarType = ScalarTypeKind::BFloat;
break;
case BasicType::F8E4M3:
ElementBitwidth = 8;
ScalarType = ScalarTypeKind::FloatE4M3;
break;
case BasicType::F8E5M2:
ElementBitwidth = 8;
ScalarType = ScalarTypeKind::FloatE5M2;
break;
default:
llvm_unreachable("Unhandled type code!");
}
Expand Down Expand Up @@ -709,11 +733,17 @@ void RVVType::applyModifier(const PrototypeDescriptor &Transformer) {
Scale = LMUL.getScale(ElementBitwidth);
if (ScalarType == ScalarTypeKind::BFloat)
ScalarType = ScalarTypeKind::Float;
if (ScalarType == ScalarTypeKind::FloatE4M3 ||
ScalarType == ScalarTypeKind::FloatE5M2)
ScalarType = ScalarTypeKind::BFloat;
break;
case VectorTypeModifier::Widening4XVector:
ElementBitwidth *= 4;
LMUL.MulLog2LMUL(2);
Scale = LMUL.getScale(ElementBitwidth);
if (ScalarType == ScalarTypeKind::FloatE4M3 ||
ScalarType == ScalarTypeKind::FloatE5M2)
ScalarType = ScalarTypeKind::Float;
break;
case VectorTypeModifier::Widening8XVector:
ElementBitwidth *= 8;
Expand Down Expand Up @@ -938,13 +968,13 @@ RVVTypeCache::computeTypes(BasicType BT, int Log2LMUL, unsigned NF,
static uint64_t computeRVVTypeHashValue(BasicType BT, int Log2LMUL,
PrototypeDescriptor Proto) {
// Layout of hash value:
// 0 8 16 24 32 40
// 0 8 24 32 40 48
// | 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);
return (Log2LMUL + 3) | (static_cast<uint64_t>(BT) & 0xffff) << 8 |
((uint64_t)(Proto.PT & 0xff) << 24) |
((uint64_t)(Proto.TM & 0xff) << 32) |
((uint64_t)(Proto.VTM & 0xff) << 40);
}

std::optional<RVVTypePtr> RVVTypeCache::computeType(BasicType BT, int Log2LMUL,
Expand Down Expand Up @@ -974,13 +1004,16 @@ std::optional<RVVTypePtr> RVVTypeCache::computeType(BasicType BT, int Log2LMUL,
//===----------------------------------------------------------------------===//
// RVVIntrinsic implementation
//===----------------------------------------------------------------------===//
RVVIntrinsic::RVVIntrinsic(
StringRef NewName, StringRef Suffix, StringRef NewOverloadedName,
StringRef OverloadedSuffix, StringRef IRName, bool IsMasked,
bool HasMaskedOffOperand, bool HasVL, PolicyScheme Scheme,
bool SupportOverloading, bool HasBuiltinAlias, StringRef ManualCodegen,
const RVVTypes &OutInTypes, const std::vector<int64_t> &NewIntrinsicTypes,
unsigned NF, Policy NewPolicyAttrs, bool HasFRMRoundModeOp, unsigned TWiden)
RVVIntrinsic::RVVIntrinsic(StringRef NewName, StringRef Suffix,
StringRef NewOverloadedName,
StringRef OverloadedSuffix, StringRef IRName,
bool IsMasked, bool HasMaskedOffOperand, bool HasVL,
PolicyScheme Scheme, bool SupportOverloading,
bool HasBuiltinAlias, StringRef ManualCodegen,
const RVVTypes &OutInTypes,
const std::vector<int64_t> &NewIntrinsicTypes,
unsigned NF, Policy NewPolicyAttrs,
bool HasFRMRoundModeOp, unsigned TWiden, bool AltFmt)
: IRName(IRName), IsMasked(IsMasked),
HasMaskedOffOperand(HasMaskedOffOperand), HasVL(HasVL), Scheme(Scheme),
SupportOverloading(SupportOverloading), HasBuiltinAlias(HasBuiltinAlias),
Expand All @@ -1000,7 +1033,7 @@ RVVIntrinsic::RVVIntrinsic(
OverloadedName += "_" + OverloadedSuffix.str();

updateNamesAndPolicy(IsMasked, hasPolicy(), Name, BuiltinName, OverloadedName,
PolicyAttrs, HasFRMRoundModeOp);
PolicyAttrs, HasFRMRoundModeOp, AltFmt);

// Init OutputType and InputTypes
OutputType = OutInTypes[0];
Expand Down Expand Up @@ -1141,9 +1174,12 @@ RVVIntrinsic::getSupportedMaskedPolicies(bool HasTailPolicy,
"and mask policy");
}

void RVVIntrinsic::updateNamesAndPolicy(
bool IsMasked, bool HasPolicy, std::string &Name, std::string &BuiltinName,
std::string &OverloadedName, Policy &PolicyAttrs, bool HasFRMRoundModeOp) {
void RVVIntrinsic::updateNamesAndPolicy(bool IsMasked, bool HasPolicy,
std::string &Name,
std::string &BuiltinName,
std::string &OverloadedName,
Policy &PolicyAttrs,
bool HasFRMRoundModeOp, bool AltFmt) {

auto appendPolicySuffix = [&](const std::string &suffix) {
Name += suffix;
Expand All @@ -1156,6 +1192,9 @@ void RVVIntrinsic::updateNamesAndPolicy(
BuiltinName += "_rm";
}

if (AltFmt)
BuiltinName += "_alt";

if (IsMasked) {
if (PolicyAttrs.isTUMUPolicy())
appendPolicySuffix("_tumu");
Expand Down Expand Up @@ -1239,6 +1278,7 @@ raw_ostream &operator<<(raw_ostream &OS, const RVVIntrinsicRecord &Record) {
OS << "/*HasTailPolicy=*/" << (int)Record.HasTailPolicy << ", ";
OS << "/*HasMaskPolicy=*/" << (int)Record.HasMaskPolicy << ", ";
OS << "/*HasFRMRoundModeOp=*/" << (int)Record.HasFRMRoundModeOp << ", ";
OS << "/*AltFmt=*/" << (int)Record.AltFmt << ",";
OS << "/*IsTuple=*/" << (int)Record.IsTuple << ", ";
OS << "/*UnMaskedPolicyScheme=*/" << (PolicyScheme)Record.UnMaskedPolicyScheme
<< ", ";
Expand Down
17 changes: 13 additions & 4 deletions clang/utils/TableGen/RISCVVEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ struct SemaRecord {
bool HasTailPolicy : 1;
bool HasMaskPolicy : 1;
bool HasFRMRoundModeOp : 1;
bool AltFmt : 1;
bool IsTuple : 1;
LLVM_PREFERRED_TYPE(PolicyScheme)
uint8_t UnMaskedPolicyScheme : 2;
Expand Down Expand Up @@ -147,6 +148,10 @@ static BasicType ParseBasicType(char c) {
return BasicType::Float64;
case 'y':
return BasicType::BFloat16;
case 'a':
return BasicType::F8E4M3;
case 'b':
return BasicType::F8E5M2;
default:
return BasicType::Unknown;
}
Expand Down Expand Up @@ -641,6 +646,7 @@ void RVVEmitter::createRVVIntrinsics(
std::vector<int64_t> Log2LMULList = R->getValueAsListOfInts("Log2LMUL");
bool HasTailPolicy = R->getValueAsBit("HasTailPolicy");
bool HasMaskPolicy = R->getValueAsBit("HasMaskPolicy");
bool AltFmt = R->getValueAsBit("AltFmt");
bool SupportOverloading = R->getValueAsBit("SupportOverloading");
bool HasBuiltinAlias = R->getValueAsBit("HasBuiltinAlias");
StringRef ManualCodegen = R->getValueAsString("ManualCodegen");
Expand Down Expand Up @@ -701,7 +707,7 @@ void RVVEmitter::createRVVIntrinsics(
/*IsMasked=*/false, /*HasMaskedOffOperand=*/false, HasVL,
UnMaskedPolicyScheme, SupportOverloading, HasBuiltinAlias,
ManualCodegen, *Types, IntrinsicTypes, NF, DefaultPolicy,
HasFRMRoundModeOp, TWiden));
HasFRMRoundModeOp, TWiden, AltFmt));
if (UnMaskedPolicyScheme != PolicyScheme::SchemeNone)
for (auto P : SupportedUnMaskedPolicies) {
SmallVector<PrototypeDescriptor> PolicyPrototype =
Expand All @@ -716,7 +722,7 @@ void RVVEmitter::createRVVIntrinsics(
/*IsMask=*/false, /*HasMaskedOffOperand=*/false, HasVL,
UnMaskedPolicyScheme, SupportOverloading, HasBuiltinAlias,
ManualCodegen, *PolicyTypes, IntrinsicTypes, NF, P,
HasFRMRoundModeOp, TWiden));
HasFRMRoundModeOp, TWiden, AltFmt));
}
if (!HasMasked)
continue;
Expand All @@ -727,7 +733,8 @@ void RVVEmitter::createRVVIntrinsics(
Name, SuffixStr, OverloadedName, OverloadedSuffixStr, MaskedIRName,
/*IsMasked=*/true, HasMaskedOffOperand, HasVL, MaskedPolicyScheme,
SupportOverloading, HasBuiltinAlias, ManualCodegen, *MaskTypes,
IntrinsicTypes, NF, DefaultPolicy, HasFRMRoundModeOp, TWiden));
IntrinsicTypes, NF, DefaultPolicy, HasFRMRoundModeOp, TWiden,
AltFmt));
if (MaskedPolicyScheme == PolicyScheme::SchemeNone)
continue;
for (auto P : SupportedMaskedPolicies) {
Expand All @@ -742,7 +749,7 @@ void RVVEmitter::createRVVIntrinsics(
MaskedIRName, /*IsMasked=*/true, HasMaskedOffOperand, HasVL,
MaskedPolicyScheme, SupportOverloading, HasBuiltinAlias,
ManualCodegen, *PolicyTypes, IntrinsicTypes, NF, P,
HasFRMRoundModeOp, TWiden));
HasFRMRoundModeOp, TWiden, AltFmt));
}
} // End for Log2LMULList
} // End for TypeRange
Expand Down Expand Up @@ -780,6 +787,7 @@ void RVVEmitter::createRVVIntrinsics(
SR.HasMaskedOffOperand = HasMaskedOffOperand;
SR.HasTailPolicy = HasTailPolicy;
SR.HasMaskPolicy = HasMaskPolicy;
SR.AltFmt = AltFmt;
SR.UnMaskedPolicyScheme = static_cast<uint8_t>(UnMaskedPolicyScheme);
SR.MaskedPolicyScheme = static_cast<uint8_t>(MaskedPolicyScheme);
SR.Prototype = std::move(BasicPrototype);
Expand Down Expand Up @@ -824,6 +832,7 @@ void RVVEmitter::createRVVIntrinsicRecords(std::vector<RVVIntrinsicRecord> &Out,
R.HasMaskedOffOperand = SR.HasMaskedOffOperand;
R.HasTailPolicy = SR.HasTailPolicy;
R.HasMaskPolicy = SR.HasMaskPolicy;
R.AltFmt = SR.AltFmt;
R.UnMaskedPolicyScheme = SR.UnMaskedPolicyScheme;
R.MaskedPolicyScheme = SR.MaskedPolicyScheme;
R.IsTuple = SR.IsTuple;
Expand Down
20 changes: 20 additions & 0 deletions llvm/include/llvm/IR/IntrinsicsRISCV.td
Original file line number Diff line number Diff line change
Expand Up @@ -1958,6 +1958,26 @@ let TargetPrefix = "riscv" in {
let TargetPrefix = "riscv" in
def int_riscv_pause : DefaultAttrsIntrinsic<[], [], [IntrNoMem, IntrHasSideEffects]>;


//===----------------------------------------------------------------------===//
// Zvfofp8min - OFP8 conversion extension
// The Zvfofp8min extension provides basic support for the two 8-bit
// floating-point formats defined in the Open Compute Project OFP8
// specification, OFP8 E4M3 and OFP8 E5M2.
let TargetPrefix = "riscv" in {
// OFP8 to BF16 conversion instructions
defm vfwcvt_f_f_v_alt : RISCVConversion;
// BF16 to OFP8 conversion instructions
defm vfncvt_sat_f_f_w : RISCVConversionRoundingMode;
defm vfncvt_f_f_w_alt : RISCVConversionRoundingMode;
defm vfncvt_sat_f_f_w_alt : RISCVConversionRoundingMode;
// FP32 to OFP8 conversion instructions
defm vfncvt_f_f_q : RISCVConversionRoundingMode;
defm vfncvt_f_f_q_alt : RISCVConversionRoundingMode;
defm vfncvt_sat_f_f_q : RISCVConversionRoundingMode;
defm vfncvt_sat_f_f_q_alt : RISCVConversionRoundingMode;
} // TargetPrefix = "riscv"

// Vendor extensions
//===----------------------------------------------------------------------===//
include "llvm/IR/IntrinsicsRISCVXTHead.td"
Expand Down
4 changes: 3 additions & 1 deletion llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,11 +216,13 @@ void RISCVInstPrinter::printVTypeI(const MCInst *MI, unsigned OpNo,
const MCSubtargetInfo &STI, raw_ostream &O) {
unsigned Imm = MI->getOperand(OpNo).getImm();
// Print the raw immediate for reserved values: vlmul[2:0]=4, vsew[2:0]=0b1xx,
// altfmt=1 without zvfbfa extension, or non-zero in bits 9 and above.
// altfmt=1 without zvfbfa or zvfofp8min extension, or non-zero in bits 9 and
// above.
if (RISCVVType::getVLMUL(Imm) == RISCVVType::VLMUL::LMUL_RESERVED ||
RISCVVType::getSEW(Imm) > 64 ||
(RISCVVType::isAltFmt(Imm) &&
!(STI.hasFeature(RISCV::FeatureStdExtZvfbfa) ||
STI.hasFeature(RISCV::FeatureStdExtZvfofp8min) ||
STI.hasFeature(RISCV::FeatureVendorXSfvfbfexp16e))) ||
(Imm >> 9) != 0) {
O << formatImm(Imm);
Expand Down
Loading