Skip to content

Commit

Permalink
[RISCV][POC] Model frm control for vfadd
Browse files Browse the repository at this point in the history
Depends on D152879.

Specification PR: riscv-non-isa/rvv-intrinsic-doc#226

This patch adds variant of `vfadd` that models the rounding mode control.
The added variant has suffix `_rm` appended to differentiate from the
existing ones that does not alternate `frm` and uses whatever is inside.

The value `7` is used to indicate no rounding mode change. Reusing the
semantic from the rounding mode encoding for scalar floating-point
instructions.

Additional data member `HasFRMRoundModeOp` is added so we can append
`_rm` suffix for the fadd variants that models rounding mode control.

Additional data member `IsRVVFixedPoint` is added so we can define
pseudo instructions with rounding mode operand and distinguish the
instructions between fixed-point and floating-point.

Reviewed By: craig.topper, kito-cheng

Differential Revision: https://reviews.llvm.org/D152996
  • Loading branch information
eopXD committed Jul 13, 2023
1 parent 503b3ab commit 7648207
Show file tree
Hide file tree
Showing 35 changed files with 4,758 additions and 616 deletions.
69 changes: 68 additions & 1 deletion clang/include/clang/Basic/riscv_vector.td
Expand Up @@ -226,6 +226,11 @@ multiclass RVVFloatingBinBuiltinSet
[["vv", "v", "vvv"],
["vf", "v", "vve"]]>;

multiclass RVVFloatingBinBuiltinSetRoundingMode
: RVVOutOp1BuiltinSet<NAME, "xfd",
[["vv", "v", "vvvu"],
["vf", "v", "vveu"]]>;

multiclass RVVFloatingBinVFBuiltinSet
: RVVOutOp1BuiltinSet<NAME, "xfd",
[["vf", "v", "vve"]]>;
Expand Down Expand Up @@ -1856,10 +1861,72 @@ let ManualCodegen = [{
defm vnclipu : RVVUnsignedNShiftBuiltinSetRoundingMode;
defm vnclip : RVVSignedNShiftBuiltinSetRoundingMode;
}
}

// 14. Vector Floating-Point Instructions
let HeaderCode =
[{
enum __RISCV_FRM {
__RISCV_FRM_RNE = 0,
__RISCV_FRM_RTZ = 1,
__RISCV_FRM_RDN = 2,
__RISCV_FRM_RUP = 3,
__RISCV_FRM_RMM = 4,
};
}] in def frm_enum : RVVHeader;

let UnMaskedPolicyScheme = HasPassthruOperand in {
// 14.2. Vector Single-Width Floating-Point Add/Subtract Instructions
defm vfadd : RVVFloatingBinBuiltinSet;
let ManualCodegen = [{
{
// LLVM intrinsic
// Unmasked: (passthru, op0, op1, round_mode, vl)
// Masked: (passthru, vector_in, vector_in/scalar_in, mask, frm, vl, policy)

SmallVector<llvm::Value*, 7> Operands;
bool HasMaskedOff = !(
(IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) ||
(!IsMasked && PolicyAttrs & RVV_VTA));
bool HasRoundModeOp = IsMasked ?
(HasMaskedOff ? Ops.size() == 6 : Ops.size() == 5) :
(HasMaskedOff ? Ops.size() == 5 : Ops.size() == 4);

unsigned Offset = IsMasked ?
(HasMaskedOff ? 2 : 1) : (HasMaskedOff ? 1 : 0);

if (!HasMaskedOff)
Operands.push_back(llvm::PoisonValue::get(ResultType));
else
Operands.push_back(Ops[IsMasked ? 1 : 0]);

Operands.push_back(Ops[Offset]); // op0
Operands.push_back(Ops[Offset + 1]); // op1

if (IsMasked)
Operands.push_back(Ops[0]); // mask

if (HasRoundModeOp) {
Operands.push_back(Ops[Offset + 2]); // frm
Operands.push_back(Ops[Offset + 3]); // vl
} else {
Operands.push_back(ConstantInt::get(Ops[Offset + 2]->getType(), 7)); // frm
Operands.push_back(Ops[Offset + 2]); // vl
}

if (IsMasked)
Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));

IntrinsicTypes = {ResultType, Ops[Offset + 1]->getType(),
Operands.back()->getType()};
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
return Builder.CreateCall(F, Operands, "");
}
}] in {
let HasFRMRoundModeOp = true in {
defm vfadd : RVVFloatingBinBuiltinSetRoundingMode;
}
defm vfadd : RVVFloatingBinBuiltinSet;
}
defm vfsub : RVVFloatingBinBuiltinSet;
defm vfrsub : RVVFloatingBinVFBuiltinSet;

Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Basic/riscv_vector_common.td
Expand Up @@ -234,6 +234,10 @@ class RVVBuiltin<string suffix, string prototype, string type_range,

// Set to true if the builtin is associated with tuple types.
bit IsTuple = false;

// Set to true if the builtin has a parameter that models floating-point
// rounding mode control
bit HasFRMRoundModeOp = false;
}

// This is the code emitted in the header.
Expand Down
6 changes: 4 additions & 2 deletions clang/include/clang/Support/RISCVVIntrinsicUtils.h
Expand Up @@ -387,6 +387,7 @@ class RVVIntrinsic {
std::vector<int64_t> IntrinsicTypes;
unsigned NF = 1;
Policy PolicyAttrs;
bool HasFRMRoundModeOp;

public:
RVVIntrinsic(llvm::StringRef Name, llvm::StringRef Suffix,
Expand All @@ -397,7 +398,7 @@ class RVVIntrinsic {
const RVVTypes &Types,
const std::vector<int64_t> &IntrinsicTypes,
const std::vector<llvm::StringRef> &RequiredFeatures,
unsigned NF, Policy PolicyAttrs);
unsigned NF, Policy PolicyAttrs, bool HasFRMRoundModeOp);
~RVVIntrinsic() = default;

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

// RVVRequire should be sync'ed with target features, but only
Expand Down Expand Up @@ -526,6 +527,7 @@ struct RVVIntrinsicRecord {
bool HasMaskedOffOperand : 1;
bool HasTailPolicy : 1;
bool HasMaskPolicy : 1;
bool HasFRMRoundModeOp : 1;
bool IsTuple : 1;
uint8_t UnMaskedPolicyScheme : 2;
uint8_t MaskedPolicyScheme : 2;
Expand Down
15 changes: 15 additions & 0 deletions clang/lib/Sema/SemaChecking.cpp
Expand Up @@ -4808,6 +4808,21 @@ bool Sema::CheckRISCVBuiltinFunctionCall(const TargetInfo &TI,
case RISCVVector::BI__builtin_rvv_vnclipu_wv_tumu:
case RISCVVector::BI__builtin_rvv_vnclipu_wx_tumu:
return SemaBuiltinConstantArgRange(TheCall, 4, 0, 3);
case RISCVVector::BI__builtin_rvv_vfadd_vv_rm:
case RISCVVector::BI__builtin_rvv_vfadd_vf_rm:
return SemaBuiltinConstantArgRange(TheCall, 2, 0, 4);
case RISCVVector::BI__builtin_rvv_vfadd_vv_rm_tu:
case RISCVVector::BI__builtin_rvv_vfadd_vf_rm_tu:
case RISCVVector::BI__builtin_rvv_vfadd_vv_rm_tama:
case RISCVVector::BI__builtin_rvv_vfadd_vf_rm_tama:
return SemaBuiltinConstantArgRange(TheCall, 3, 0, 4);
case RISCVVector::BI__builtin_rvv_vfadd_vv_rm_tum:
case RISCVVector::BI__builtin_rvv_vfadd_vf_rm_tum:
case RISCVVector::BI__builtin_rvv_vfadd_vv_rm_tumu:
case RISCVVector::BI__builtin_rvv_vfadd_vf_rm_tumu:
case RISCVVector::BI__builtin_rvv_vfadd_vv_rm_mu:
case RISCVVector::BI__builtin_rvv_vfadd_vf_rm_mu:
return SemaBuiltinConstantArgRange(TheCall, 4, 0, 4);
case RISCV::BI__builtin_riscv_ntl_load:
case RISCV::BI__builtin_riscv_ntl_store:
DeclRefExpr *DRE =
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Sema/SemaRISCVVectorLookup.cpp
Expand Up @@ -362,7 +362,8 @@ void RISCVIntrinsicManagerImpl::InitRVVIntrinsic(
std::string BuiltinName = "__builtin_rvv_" + std::string(Record.Name);

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

// Put into IntrinsicList.
size_t Index = IntrinsicList.size();
Expand Down
37 changes: 20 additions & 17 deletions clang/lib/Support/RISCVVIntrinsicUtils.cpp
Expand Up @@ -875,20 +875,19 @@ 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,
const std::vector<StringRef> &RequiredFeatures,
unsigned NF, Policy NewPolicyAttrs)
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,
const std::vector<StringRef> &RequiredFeatures, unsigned NF,
Policy NewPolicyAttrs, bool HasFRMRoundModeOp)
: IRName(IRName), IsMasked(IsMasked),
HasMaskedOffOperand(HasMaskedOffOperand), HasVL(HasVL), Scheme(Scheme),
SupportOverloading(SupportOverloading), HasBuiltinAlias(HasBuiltinAlias),
ManualCodegen(ManualCodegen.str()), NF(NF), PolicyAttrs(NewPolicyAttrs) {
ManualCodegen(ManualCodegen.str()), NF(NF), PolicyAttrs(NewPolicyAttrs),
HasFRMRoundModeOp(HasFRMRoundModeOp) {

// Init BuiltinName, Name and OverloadedName
BuiltinName = NewName.str();
Expand All @@ -903,7 +902,7 @@ RVVIntrinsic::RVVIntrinsic(StringRef NewName, StringRef Suffix,
OverloadedName += "_" + OverloadedSuffix.str();

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

// Init OutputType and InputTypes
OutputType = OutInTypes[0];
Expand Down Expand Up @@ -1045,11 +1044,9 @@ 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) {
void RVVIntrinsic::updateNamesAndPolicy(
bool IsMasked, bool HasPolicy, std::string &Name, std::string &BuiltinName,
std::string &OverloadedName, Policy &PolicyAttrs, bool HasFRMRoundModeOp) {

auto appendPolicySuffix = [&](const std::string &suffix) {
Name += suffix;
Expand All @@ -1062,6 +1059,11 @@ void RVVIntrinsic::updateNamesAndPolicy(bool IsMasked, bool HasPolicy,
Name = "__riscv_" + Name;
OverloadedName = "__riscv_" + OverloadedName;

if (HasFRMRoundModeOp) {
Name += "_rm";
BuiltinName += "_rm";
}

if (IsMasked) {
if (PolicyAttrs.isTUMUPolicy())
appendPolicySuffix("_tumu");
Expand Down Expand Up @@ -1131,6 +1133,7 @@ raw_ostream &operator<<(raw_ostream &OS, const RVVIntrinsicRecord &Record) {
OS << (int)Record.HasMaskedOffOperand << ",";
OS << (int)Record.HasTailPolicy << ",";
OS << (int)Record.HasMaskPolicy << ",";
OS << (int)Record.HasFRMRoundModeOp << ",";
OS << (int)Record.IsTuple << ",";
OS << (int)Record.UnMaskedPolicyScheme << ",";
OS << (int)Record.MaskedPolicyScheme << ",";
Expand Down

0 comments on commit 7648207

Please sign in to comment.