Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
1 change: 1 addition & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -13139,6 +13139,7 @@ def err_riscv_attribute_interrupt_requires_extension : Error<
"RISC-V 'interrupt' attribute '%0' requires extension '%1'">;
def err_riscv_attribute_interrupt_invalid_combination : Error<
"RISC-V 'interrupt' attribute contains invalid combination of interrupt types">;
def err_riscv_builtin_invalid_twiden : Error<"RISC-V XSfmm twiden must be 1, 2 or 4">;

def err_std_source_location_impl_not_found : Error<
"'std::source_location::__impl' was not found; it must be defined before '__builtin_source_location' is called">;
Expand Down
170 changes: 170 additions & 0 deletions clang/include/clang/Basic/riscv_sifive_vector.td
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@

include "riscv_vector_common.td"

class IsFloat<string type> {
bit val = !or(!eq(type, "x"), !eq(type, "f"), !eq(type, "d"), !eq(type, "y"));
}

//===----------------------------------------------------------------------===//
// Instruction definitions
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -198,3 +202,169 @@ let ManualCodegen = [{
defm sf_vfnrclip_xu_f_qf : RVVVFNRCLIPBuiltinSet<"Uv", "UvFqf", "c">;
}
}

multiclass RVVSFTileLoadStoreBuiltinSet<list<string> types,
list<string> RequiredFeatures = []> {
let OverloadedName = NAME,
Name = NAME,
IRName = NAME,
Log2LMUL = [0],
HasMasked = false,
ManualCodegen = [{IntrinsicTypes = {Ops.back()->getType()};}] in
foreach type = types in {
let RequiredFeatures = !listconcat(RequiredFeatures,
!cond(!eq(type, "x"): ["zvfhmin"],
!eq(type, "y"): ["zvfbfmin"],
true: []<string>)) in {
def : RVVBuiltin<"e", "0zPCe", type>;
if !not(IsFloat<type>.val) then
def : RVVBuiltin<"Ue", "0zPCUe", type>;
}
}
}

multiclass RVVSFTileMoveBuiltinSet<list<list<string>> suffixes_prototypes,
list<int> intrinsic_types,
string type,
list<string> RequiredFeatures = []> {
foreach sp = suffixes_prototypes in
let RequiredFeatures = !listconcat(RequiredFeatures,
!cond(!eq(type, "x"): ["zvfhmin"],
!eq(type, "y"): ["zvfbfmin"],
true: []<string>)),
SupportOverloading = false,
HasMasked = false,
Name = NAME,
IRName = NAME,
HasVL = true,
Log2LMUL = [3],
IntrinsicTypes = intrinsic_types in
def : RVVBuiltin<sp[0], sp[1], type>;
}

multiclass RVVSFTileMoveVTBuiltinSet<list<string> RequiredFeatures = []> {
foreach type = ["c", "s", "i", "l"] in
defm NAME :
RVVSFTileMoveBuiltinSet<[["v", "vz"], ["Uv", "Uvz"]], [-1], type,
RequiredFeatures>;
foreach type = ["x", "y", "f", "d"] in
defm NAME :
RVVSFTileMoveBuiltinSet<[["v", "vz"]], [-1], type, RequiredFeatures>;
}

multiclass RVVSFTileMoveTVBuiltinSet<list<string> RequiredFeatures = []> {
let SupportOverloading = true, OverloadedName = NAME in {
foreach type = ["c", "s", "i", "l"] in
defm NAME :
RVVSFTileMoveBuiltinSet<[["v", "0zv"], ["Uv", "0zUv"]], [1], type,
RequiredFeatures>;
foreach type = ["x", "y", "f", "d"] in
defm NAME :
RVVSFTileMoveBuiltinSet<[["v", "0zv"]], [1], type, RequiredFeatures>;
}
}

multiclass RVVOp0Op1Op2BuiltinSet<string intrinsic_name, string type_range,
list<list<string>> suffixes_prototypes>
: RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [0, 1, 2]>;

multiclass RVVSFMatMulBuiltinSet<string prototype, string suffix,
string type_range, list<int> widens> {
foreach widen = widens in
let OverloadedName = NAME,
TWiden = widen,
HasVL = false,
Log2LMUL = [3],
HasMasked = false in
defm NAME : RVVOp0Op1Op2BuiltinSet<NAME, type_range,
[[!strconcat("w", !cast<string>(widen)), suffix, prototype]]>;
}

multiclass RVVSFMatMulFloatBuiltinSet<string name, string prototype, string suffix,
list<string> type_range, int widen> {
// Currently the XSfmm spec doesn't support w8.
foreach type = type_range in
let OverloadedName = name # !strconcat("_w", !cast<string>(widen)),
TWiden = widen,
HasVL = false,
Log2LMUL = [3],
Name = name # "_" # !strconcat("w", !cast<string>(widen)),
HasMasked = false in
defm : RVVOp0Op1BuiltinSet<name, type, [["", suffix, prototype]]>;
}

multiclass RVVSFVTZeroBuiltinSet {
let SupportOverloading = false,
HasVL = false,
HasMasked = false,
Name = NAME,
IRName = NAME,
Log2LMUL = [0] in
defm : RVVOp0BuiltinSet<NAME, "i", [["", "", "0Kzzzzz"]]>;
}

multiclass RVVSFVTDiscardBuiltinSet {
let SupportOverloading = false,
HasVL = false,
HasMasked = false,
Name = NAME,
IRName = NAME,
Log2LMUL = [0] in
defm : RVVBuiltinSet<NAME, "i", [["", "", "0"]], []>;
}

let RequiredFeatures = ["xsfmmbase"] in {
let SupportOverloading = false,
HasVL = false,
HasMasked = false,
Log2LMUL = [0],
ManualCodegen = [{IntrinsicTypes = {ResultType};}] in // Set XLEN type
{
// let HasBuiltinAlias = false in
def sf_vsettnt : RVVBuiltin<"", "zzKzKz", "i">;
def sf_vsettm : RVVBuiltin<"", "zzKzKz", "i">;
let IRName = "sf_vsettnt" in
def sf_vsettn : RVVBuiltin<"", "zzKzKz", "i">;
def sf_vsettk : RVVBuiltin<"", "zzKzKz", "i">;
}
defm sf_vtzero_t : RVVSFVTZeroBuiltinSet;
defm sf_vtdiscard : RVVSFVTDiscardBuiltinSet;
}

defm sf_vtmv_v_t : RVVSFTileMoveVTBuiltinSet<["xsfmmbase"]>;
defm sf_vtmv_t_v : RVVSFTileMoveTVBuiltinSet<["xsfmmbase"]>;

defm sf_vlte8 : RVVSFTileLoadStoreBuiltinSet<["c"], ["xsfmmbase"]>;
defm sf_vlte16 : RVVSFTileLoadStoreBuiltinSet<["s", "x", "y"], ["xsfmmbase"]>;
defm sf_vlte32 : RVVSFTileLoadStoreBuiltinSet<["i", "f"], ["xsfmmbase"]>;
defm sf_vlte64 : RVVSFTileLoadStoreBuiltinSet<["l", "d"], ["xsfmmbase"]>;

defm sf_vste8 : RVVSFTileLoadStoreBuiltinSet<["c"], ["xsfmmbase"]>;
defm sf_vste16 : RVVSFTileLoadStoreBuiltinSet<["s", "x", "y"], ["xsfmmbase"]>;
defm sf_vste32 : RVVSFTileLoadStoreBuiltinSet<["i", "f"], ["xsfmmbase"]>;
defm sf_vste64 : RVVSFTileLoadStoreBuiltinSet<["l", "d"], ["xsfmmbase"]>;

let RequiredFeatures = ["xsfmm32a8i"] in {
defm sf_mm_u_u : RVVSFMatMulBuiltinSet<"0KzUvUvzzz", "UvUv", "c", [4]>;
defm sf_mm_s_u : RVVSFMatMulBuiltinSet<"0KzvUvzzz", "vUv", "c", [4]>;
defm sf_mm_u_s : RVVSFMatMulBuiltinSet<"0KzUvvzzz", "Uvv", "c", [4]>;
defm sf_mm_s_s : RVVSFMatMulBuiltinSet<"0Kzvvzzz", "vv", "c", [4]>;

}

let RequiredFeatures = ["xsfmm32a16f"] in
defm : RVVSFMatMulFloatBuiltinSet<"sf_mm_f_f", "0Kzvvzzz", "v", ["x", "y"], 2>;

let RequiredFeatures = ["xsfmm32a32f"] in
defm : RVVSFMatMulFloatBuiltinSet<"sf_mm_f_f", "0Kzvvzzz", "v", ["f"], 1>;

let RequiredFeatures = ["xsfmm32a8f"] in
foreach e1 = [5, 4] in
foreach e2 = [5, 4] in
let OverloadedName = "sf_mm_e" # e1 # "m" # !sub(7, e1) # "_e" # e2 # "m" # !sub(7, e2) in
defm : RVVSFMatMulFloatBuiltinSet<
"sf_mm_e" # e1 # "m" # !sub(7, e1) # "_e" # e2 # "m" # !sub(7, e2),
"0KzUvUvzzz", "UvUv", ["c"], 4>;

let RequiredFeatures = ["xsfmm64a64f"] in
defm : RVVSFMatMulFloatBuiltinSet<"sf_mm_f_f", "0Kzvvzzz", "v", ["d"], 1>;
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 @@ -245,6 +245,9 @@ class RVVBuiltin<string suffix, string prototype, string type_range,
// Set to true if the builtin has a parameter that models floating-point
// rounding mode control
bit HasFRMRoundModeOp = false;

// TWiden for XSfmm.
int TWiden = 0;
}

// This is the code emitted in the header.
Expand Down
6 changes: 4 additions & 2 deletions clang/include/clang/Support/RISCVVIntrinsicUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,7 @@ class RVVIntrinsic {
std::vector<int64_t> IntrinsicTypes;
unsigned NF = 1;
Policy PolicyAttrs;
unsigned TWiden = 0;

public:
RVVIntrinsic(llvm::StringRef Name, llvm::StringRef Suffix,
Expand All @@ -410,8 +411,8 @@ class RVVIntrinsic {
bool HasVL, PolicyScheme Scheme, bool SupportOverloading,
bool HasBuiltinAlias, llvm::StringRef ManualCodegen,
const RVVTypes &Types,
const std::vector<int64_t> &IntrinsicTypes,
unsigned NF, Policy PolicyAttrs, bool HasFRMRoundModeOp);
const std::vector<int64_t> &IntrinsicTypes, unsigned NF,
Policy PolicyAttrs, bool HasFRMRoundModeOp, unsigned TWiden);
~RVVIntrinsic() = default;

RVVTypePtr getOutputType() const { return OutputType; }
Expand All @@ -435,6 +436,7 @@ class RVVIntrinsic {
llvm::StringRef getManualCodegen() const { return ManualCodegen; }
PolicyScheme getPolicyScheme() const { return Scheme; }
unsigned getNF() const { return NF; }
unsigned getTWiden() const { return TWiden; }
const std::vector<int64_t> &getIntrinsicTypes() const {
return IntrinsicTypes;
}
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1121,6 +1121,8 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
bool IsMasked = false;
// This is used by segment load/store to determine it's llvm type.
unsigned SegInstSEW = 8;
// This is used by XSfmm.
unsigned TWiden = 0;

// Required for overloaded intrinsics.
llvm::SmallVector<llvm::Type *, 2> IntrinsicTypes;
Expand Down
56 changes: 56 additions & 0 deletions clang/lib/Headers/sifive_vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,60 @@
#endif
#endif

#define __riscv_sf_vsettnt_e8w1(atn) __riscv_sf_vsettnt(atn, 0, 1);
#define __riscv_sf_vsettnt_e8w2(atn) __riscv_sf_vsettnt(atn, 0, 2);
#define __riscv_sf_vsettnt_e8w4(atn) __riscv_sf_vsettnt(atn, 0, 3);
#define __riscv_sf_vsettnt_e16w1(atn) __riscv_sf_vsettnt(atn, 1, 1);
#define __riscv_sf_vsettnt_e16w2(atn) __riscv_sf_vsettnt(atn, 1, 2);
#define __riscv_sf_vsettnt_e16w4(atn) __riscv_sf_vsettnt(atn, 1, 3);
#define __riscv_sf_vsettnt_e32w1(atn) __riscv_sf_vsettnt(atn, 2, 1);
#define __riscv_sf_vsettnt_e32w2(atn) __riscv_sf_vsettnt(atn, 2, 2);
#define __riscv_sf_vsettm_e8w1(atm) __riscv_sf_vsettm(atm, 0, 1);
#define __riscv_sf_vsettm_e8w2(atm) __riscv_sf_vsettm(atm, 0, 2);
#define __riscv_sf_vsettm_e8w4(atm) __riscv_sf_vsettm(atm, 0, 3);
#define __riscv_sf_vsettm_e16w1(atm) __riscv_sf_vsettm(atm, 1, 1);
#define __riscv_sf_vsettm_e16w2(atm) __riscv_sf_vsettm(atm, 1, 2);
#define __riscv_sf_vsettm_e16w4(atm) __riscv_sf_vsettm(atm, 1, 3);
#define __riscv_sf_vsettm_e32w1(atm) __riscv_sf_vsettm(atm, 2, 1);
#define __riscv_sf_vsettm_e32w2(atm) __riscv_sf_vsettm(atm, 2, 2);
#define __riscv_sf_vsettn_e8w1(atn) __riscv_sf_vsettn(atn, 0, 1);
#define __riscv_sf_vsettn_e8w2(atn) __riscv_sf_vsettn(atn, 0, 2);
#define __riscv_sf_vsettn_e8w4(atn) __riscv_sf_vsettn(atn, 0, 3);
#define __riscv_sf_vsettn_e16w1(atn) __riscv_sf_vsettn(atn, 1, 1);
#define __riscv_sf_vsettn_e16w2(atn) __riscv_sf_vsettn(atn, 1, 2);
#define __riscv_sf_vsettn_e16w4(atn) __riscv_sf_vsettn(atn, 1, 3);
#define __riscv_sf_vsettn_e32w1(atn) __riscv_sf_vsettn(atn, 2, 1);
#define __riscv_sf_vsettn_e32w2(atn) __riscv_sf_vsettn(atn, 2, 2);
#define __riscv_sf_vsettk_e8w1(atk) __riscv_sf_vsettk(atk, 0, 1);
#define __riscv_sf_vsettk_e8w2(atk) __riscv_sf_vsettk(atk, 0, 2);
#define __riscv_sf_vsettk_e8w4(atk) __riscv_sf_vsettk(atk, 0, 3);
#define __riscv_sf_vsettk_e16w1(atk) __riscv_sf_vsettk(atk, 1, 1);
#define __riscv_sf_vsettk_e16w2(atk) __riscv_sf_vsettk(atk, 1, 2);
#define __riscv_sf_vsettk_e16w4(atk) __riscv_sf_vsettk(atk, 1, 3);
#define __riscv_sf_vsettk_e32w1(atk) __riscv_sf_vsettk(atk, 2, 1);
#define __riscv_sf_vsettk_e32w2(atk) __riscv_sf_vsettk(atk, 2, 2);
#define __riscv_sf_vtzero_t_e8w1(tile, atm, atn) \
__riscv_sf_vtzero_t(tile, atm, atn, 3, 1);
#define __riscv_sf_vtzero_t_e8w2(tile, atm, atn) \
__riscv_sf_vtzero_t(tile, atm, atn, 3, 2);
#define __riscv_sf_vtzero_t_e8w4(tile, atm, atn) \
__riscv_sf_vtzero_t(tile, atm, atn, 3, 4);
#define __riscv_sf_vtzero_t_e16w1(tile, atm, atn) \
__riscv_sf_vtzero_t(tile, atm, atn, 4, 1);
#define __riscv_sf_vtzero_t_e16w2(tile, atm, atn) \
__riscv_sf_vtzero_t(tile, atm, atn, 4, 2);
#define __riscv_sf_vtzero_t_e16w4(tile, atm, atn) \
__riscv_sf_vtzero_t(tile, atm, atn, 4, 4);
#define __riscv_sf_vtzero_t_e32w1(tile, atm, atn) \
__riscv_sf_vtzero_t(tile, atm, atn, 5, 1);
#define __riscv_sf_vtzero_t_e32w2(tile, atm, atn) \
__riscv_sf_vtzero_t(tile, atm, atn, 5, 2);
#if __riscv_v_elen >= 64
#define __riscv_sf_vsettnt_e64w1(atn) __riscv_sf_vsettnt(atn, 3, 1);
#define __riscv_sf_vsettm_e64w1(atm) __riscv_sf_vsettm(atm, 3, 1);
#define __riscv_sf_vsettn_e64w1(atn) __riscv_sf_vsettn(atn, 3, 1);
#define __riscv_sf_vsettk_e64w1(atk) __riscv_sf_vsettk(atk, 3, 1);
#define __riscv_sf_vtzero_t_e64w1(tile, atm, atn) \
__riscv_sf_vtzero_t(tile, atm, atn, 6, 1);
#endif
#endif //_SIFIVE_VECTOR_H_
75 changes: 75 additions & 0 deletions clang/lib/Sema/SemaRISCV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,81 @@ bool SemaRISCV::CheckBuiltinFunctionCall(const TargetInfo &TI,
return CheckVSetVL(1, 2);
case RISCVVector::BI__builtin_rvv_vsetvlimax:
return CheckVSetVL(0, 1);
case RISCVVector::BI__builtin_rvv_sf_vsettnt:
case RISCVVector::BI__builtin_rvv_sf_vsettm:
case RISCVVector::BI__builtin_rvv_sf_vsettn:
case RISCVVector::BI__builtin_rvv_sf_vsettk:
return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 3) ||
SemaRef.BuiltinConstantArgRange(TheCall, 2, 1, 3);
case RISCVVector::BI__builtin_rvv_sf_mm_f_f_w1:
case RISCVVector::BI__builtin_rvv_sf_mm_f_f_w2:
case RISCVVector::BI__builtin_rvv_sf_mm_e5m2_e4m3_w4:
case RISCVVector::BI__builtin_rvv_sf_mm_e5m2_e5m2_w4:
case RISCVVector::BI__builtin_rvv_sf_mm_e4m3_e4m3_w4:
case RISCVVector::BI__builtin_rvv_sf_mm_e4m3_e5m2_w4:
case RISCVVector::BI__builtin_rvv_sf_mm_u_u_w4:
case RISCVVector::BI__builtin_rvv_sf_mm_u_s_w4:
case RISCVVector::BI__builtin_rvv_sf_mm_s_u_w4:
case RISCVVector::BI__builtin_rvv_sf_mm_s_s_w4: {
QualType Arg1Type = TheCall->getArg(1)->getType();
ASTContext::BuiltinVectorTypeInfo Info =
SemaRef.Context.getBuiltinVectorTypeInfo(
Arg1Type->castAs<BuiltinType>());
unsigned EltSize = SemaRef.Context.getTypeSize(Info.ElementType);
llvm::APSInt Result;

// We can't check the value of a dependent argument.
Expr *Arg = TheCall->getArg(0);
if (Arg->isTypeDependent() || Arg->isValueDependent())
return false;

// Check constant-ness first.
if (SemaRef.BuiltinConstantArg(TheCall, 0, Result))
return true;

// For TEW = 32, mtd can only be 0, 4, 8, 12.
// For TEW = 64, mtd can only be 0, 2, 4, 6, 8, 10, 12, 14.
// Only `sf_mm_f_f_w1` and `sf_mm_f_f_w2` might have TEW = 64.
if ((BuiltinID == RISCVVector::BI__builtin_rvv_sf_mm_f_f_w1 &&
EltSize == 64) ||
(BuiltinID == RISCVVector::BI__builtin_rvv_sf_mm_f_f_w2 &&
EltSize == 32))
return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 15) ||
SemaRef.BuiltinConstantArgMultiple(TheCall, 0, 2);
return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 15) ||
SemaRef.BuiltinConstantArgMultiple(TheCall, 0, 4);
}
case RISCVVector::BI__builtin_rvv_sf_vtzero_t: {
llvm::APSInt Log2SEWResult;
llvm::APSInt TWidenResult;
if (SemaRef.BuiltinConstantArg(TheCall, 3, Log2SEWResult) ||
SemaRef.BuiltinConstantArg(TheCall, 4, TWidenResult))
return true;

int Log2SEW = Log2SEWResult.getSExtValue();
int TWiden = TWidenResult.getSExtValue();
int TEW = (1 << Log2SEW) * TWiden;

// 3 <= LogSEW <= 6
if (SemaRef.BuiltinConstantArgRange(TheCall, 3, 3, 6))
return true;

// TWiden
if (TWiden != 1 && TWiden != 2 && TWiden != 4)
return Diag(TheCall->getBeginLoc(),
diag::err_riscv_builtin_invalid_twiden);

// For TEW = 8, mtd can be 0~15.
// For TEW = 16 or 64, mtd can only be 0, 2, 4, 6, 8, 10, 12, 14.
// For TEW = 32, mtd can only be 0, 4, 8, 12.
if (TEW == 8)
return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 15);
if (TEW == 16 || TEW == 64)
return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 15) ||
SemaRef.BuiltinConstantArgMultiple(TheCall, 0, 2);
return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 15) ||
SemaRef.BuiltinConstantArgMultiple(TheCall, 0, 4);
}
case RISCVVector::BI__builtin_rvv_vget_v: {
ASTContext::BuiltinVectorTypeInfo ResVecInfo =
Context.getBuiltinVectorTypeInfo(cast<BuiltinType>(
Expand Down
5 changes: 3 additions & 2 deletions clang/lib/Support/RISCVVIntrinsicUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -975,11 +975,12 @@ RVVIntrinsic::RVVIntrinsic(
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 NF, Policy NewPolicyAttrs, bool HasFRMRoundModeOp, unsigned TWiden)
: 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),
TWiden(TWiden) {

// Init BuiltinName, Name and OverloadedName
BuiltinName = NewName.str();
Expand Down
Loading
Loading