Skip to content

Commit fb87708

Browse files
authored
[RISCV] Support XSfmm C intrinsics (#143070)
In this version of intrinsics, users need to manage the life time of tiles on their own, compiler doesn't have tile type for variables not only for design simplicity but also preventing users to write bad performance code that could potentially having tile spills which are quite expensive in terms of cycles. Intrinsics are specified at the end of this document https://www.sifive.com/document-file/xsfmm-matrix-extensions-specification stack on: #143068 and #143069
1 parent 50eb865 commit fb87708

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+2255
-9
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13148,6 +13148,7 @@ def err_riscv_attribute_interrupt_requires_extension : Error<
1314813148
"RISC-V 'interrupt' attribute '%0' requires extension '%1'">;
1314913149
def err_riscv_attribute_interrupt_invalid_combination : Error<
1315013150
"RISC-V 'interrupt' attribute contains invalid combination of interrupt types">;
13151+
def err_riscv_builtin_invalid_twiden : Error<"RISC-V XSfmm twiden must be 1, 2 or 4">;
1315113152

1315213153
def err_std_source_location_impl_not_found : Error<
1315313154
"'std::source_location::__impl' was not found; it must be defined before '__builtin_source_location' is called">;

clang/include/clang/Basic/riscv_sifive_vector.td

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414

1515
include "riscv_vector_common.td"
1616

17+
class IsFloat<string type> {
18+
bit val = !or(!eq(type, "x"), !eq(type, "f"), !eq(type, "d"), !eq(type, "y"));
19+
}
20+
1721
//===----------------------------------------------------------------------===//
1822
// Instruction definitions
1923
//===----------------------------------------------------------------------===//
@@ -198,3 +202,169 @@ let ManualCodegen = [{
198202
defm sf_vfnrclip_xu_f_qf : RVVVFNRCLIPBuiltinSet<"Uv", "UvFqf", "c">;
199203
}
200204
}
205+
206+
multiclass RVVSFTileLoadStoreBuiltinSet<list<string> types,
207+
list<string> RequiredFeatures = []> {
208+
let OverloadedName = NAME,
209+
Name = NAME,
210+
IRName = NAME,
211+
Log2LMUL = [0],
212+
HasMasked = false,
213+
ManualCodegen = [{IntrinsicTypes = {Ops.back()->getType()};}] in
214+
foreach type = types in {
215+
let RequiredFeatures = !listconcat(RequiredFeatures,
216+
!cond(!eq(type, "x"): ["zvfhmin"],
217+
!eq(type, "y"): ["zvfbfmin"],
218+
true: []<string>)) in {
219+
def : RVVBuiltin<"e", "0zPCe", type>;
220+
if !not(IsFloat<type>.val) then
221+
def : RVVBuiltin<"Ue", "0zPCUe", type>;
222+
}
223+
}
224+
}
225+
226+
multiclass RVVSFTileMoveBuiltinSet<list<list<string>> suffixes_prototypes,
227+
list<int> intrinsic_types,
228+
string type,
229+
list<string> RequiredFeatures = []> {
230+
foreach sp = suffixes_prototypes in
231+
let RequiredFeatures = !listconcat(RequiredFeatures,
232+
!cond(!eq(type, "x"): ["zvfhmin"],
233+
!eq(type, "y"): ["zvfbfmin"],
234+
true: []<string>)),
235+
SupportOverloading = false,
236+
HasMasked = false,
237+
Name = NAME,
238+
IRName = NAME,
239+
HasVL = true,
240+
Log2LMUL = [3],
241+
IntrinsicTypes = intrinsic_types in
242+
def : RVVBuiltin<sp[0], sp[1], type>;
243+
}
244+
245+
multiclass RVVSFTileMoveVTBuiltinSet<list<string> RequiredFeatures = []> {
246+
foreach type = ["c", "s", "i", "l"] in
247+
defm NAME :
248+
RVVSFTileMoveBuiltinSet<[["v", "vz"], ["Uv", "Uvz"]], [-1], type,
249+
RequiredFeatures>;
250+
foreach type = ["x", "y", "f", "d"] in
251+
defm NAME :
252+
RVVSFTileMoveBuiltinSet<[["v", "vz"]], [-1], type, RequiredFeatures>;
253+
}
254+
255+
multiclass RVVSFTileMoveTVBuiltinSet<list<string> RequiredFeatures = []> {
256+
let SupportOverloading = true, OverloadedName = NAME in {
257+
foreach type = ["c", "s", "i", "l"] in
258+
defm NAME :
259+
RVVSFTileMoveBuiltinSet<[["v", "0zv"], ["Uv", "0zUv"]], [1], type,
260+
RequiredFeatures>;
261+
foreach type = ["x", "y", "f", "d"] in
262+
defm NAME :
263+
RVVSFTileMoveBuiltinSet<[["v", "0zv"]], [1], type, RequiredFeatures>;
264+
}
265+
}
266+
267+
multiclass RVVOp0Op1Op2BuiltinSet<string intrinsic_name, string type_range,
268+
list<list<string>> suffixes_prototypes>
269+
: RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [0, 1, 2]>;
270+
271+
multiclass RVVSFMatMulBuiltinSet<string prototype, string suffix,
272+
string type_range, list<int> widens> {
273+
foreach widen = widens in
274+
let OverloadedName = NAME,
275+
TWiden = widen,
276+
HasVL = false,
277+
Log2LMUL = [3],
278+
HasMasked = false in
279+
defm NAME : RVVOp0Op1Op2BuiltinSet<NAME, type_range,
280+
[[!strconcat("w", !cast<string>(widen)), suffix, prototype]]>;
281+
}
282+
283+
multiclass RVVSFMatMulFloatBuiltinSet<string name, string prototype, string suffix,
284+
list<string> type_range, int widen> {
285+
// Currently the XSfmm spec doesn't support w8.
286+
foreach type = type_range in
287+
let OverloadedName = name # !strconcat("_w", !cast<string>(widen)),
288+
TWiden = widen,
289+
HasVL = false,
290+
Log2LMUL = [3],
291+
Name = name # "_" # !strconcat("w", !cast<string>(widen)),
292+
HasMasked = false in
293+
defm : RVVOp0Op1BuiltinSet<name, type, [["", suffix, prototype]]>;
294+
}
295+
296+
multiclass RVVSFVTZeroBuiltinSet {
297+
let SupportOverloading = false,
298+
HasVL = false,
299+
HasMasked = false,
300+
Name = NAME,
301+
IRName = NAME,
302+
Log2LMUL = [0] in
303+
defm : RVVOp0BuiltinSet<NAME, "i", [["", "", "0Kzzzzz"]]>;
304+
}
305+
306+
multiclass RVVSFVTDiscardBuiltinSet {
307+
let SupportOverloading = false,
308+
HasVL = false,
309+
HasMasked = false,
310+
Name = NAME,
311+
IRName = NAME,
312+
Log2LMUL = [0] in
313+
defm : RVVBuiltinSet<NAME, "i", [["", "", "0"]], []>;
314+
}
315+
316+
let RequiredFeatures = ["xsfmmbase"] in {
317+
let SupportOverloading = false,
318+
HasVL = false,
319+
HasMasked = false,
320+
Log2LMUL = [0],
321+
ManualCodegen = [{IntrinsicTypes = {ResultType};}] in // Set XLEN type
322+
{
323+
// let HasBuiltinAlias = false in
324+
def sf_vsettnt : RVVBuiltin<"", "zzKzKz", "i">;
325+
def sf_vsettm : RVVBuiltin<"", "zzKzKz", "i">;
326+
let IRName = "sf_vsettnt" in
327+
def sf_vsettn : RVVBuiltin<"", "zzKzKz", "i">;
328+
def sf_vsettk : RVVBuiltin<"", "zzKzKz", "i">;
329+
}
330+
defm sf_vtzero_t : RVVSFVTZeroBuiltinSet;
331+
defm sf_vtdiscard : RVVSFVTDiscardBuiltinSet;
332+
}
333+
334+
defm sf_vtmv_v_t : RVVSFTileMoveVTBuiltinSet<["xsfmmbase"]>;
335+
defm sf_vtmv_t_v : RVVSFTileMoveTVBuiltinSet<["xsfmmbase"]>;
336+
337+
defm sf_vlte8 : RVVSFTileLoadStoreBuiltinSet<["c"], ["xsfmmbase"]>;
338+
defm sf_vlte16 : RVVSFTileLoadStoreBuiltinSet<["s", "x", "y"], ["xsfmmbase"]>;
339+
defm sf_vlte32 : RVVSFTileLoadStoreBuiltinSet<["i", "f"], ["xsfmmbase"]>;
340+
defm sf_vlte64 : RVVSFTileLoadStoreBuiltinSet<["l", "d"], ["xsfmmbase"]>;
341+
342+
defm sf_vste8 : RVVSFTileLoadStoreBuiltinSet<["c"], ["xsfmmbase"]>;
343+
defm sf_vste16 : RVVSFTileLoadStoreBuiltinSet<["s", "x", "y"], ["xsfmmbase"]>;
344+
defm sf_vste32 : RVVSFTileLoadStoreBuiltinSet<["i", "f"], ["xsfmmbase"]>;
345+
defm sf_vste64 : RVVSFTileLoadStoreBuiltinSet<["l", "d"], ["xsfmmbase"]>;
346+
347+
let RequiredFeatures = ["xsfmm32a8i"] in {
348+
defm sf_mm_u_u : RVVSFMatMulBuiltinSet<"0KzUvUvzzz", "UvUv", "c", [4]>;
349+
defm sf_mm_s_u : RVVSFMatMulBuiltinSet<"0KzvUvzzz", "vUv", "c", [4]>;
350+
defm sf_mm_u_s : RVVSFMatMulBuiltinSet<"0KzUvvzzz", "Uvv", "c", [4]>;
351+
defm sf_mm_s_s : RVVSFMatMulBuiltinSet<"0Kzvvzzz", "vv", "c", [4]>;
352+
353+
}
354+
355+
let RequiredFeatures = ["xsfmm32a16f"] in
356+
defm : RVVSFMatMulFloatBuiltinSet<"sf_mm_f_f", "0Kzvvzzz", "v", ["x", "y"], 2>;
357+
358+
let RequiredFeatures = ["xsfmm32a32f"] in
359+
defm : RVVSFMatMulFloatBuiltinSet<"sf_mm_f_f", "0Kzvvzzz", "v", ["f"], 1>;
360+
361+
let RequiredFeatures = ["xsfmm32a8f"] in
362+
foreach e1 = [5, 4] in
363+
foreach e2 = [5, 4] in
364+
let OverloadedName = "sf_mm_e" # e1 # "m" # !sub(7, e1) # "_e" # e2 # "m" # !sub(7, e2) in
365+
defm : RVVSFMatMulFloatBuiltinSet<
366+
"sf_mm_e" # e1 # "m" # !sub(7, e1) # "_e" # e2 # "m" # !sub(7, e2),
367+
"0KzUvUvzzz", "UvUv", ["c"], 4>;
368+
369+
let RequiredFeatures = ["xsfmm64a64f"] in
370+
defm : RVVSFMatMulFloatBuiltinSet<"sf_mm_f_f", "0Kzvvzzz", "v", ["d"], 1>;

clang/include/clang/Basic/riscv_vector_common.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,9 @@ class RVVBuiltin<string suffix, string prototype, string type_range,
247247
// Set to true if the builtin has a parameter that models floating-point
248248
// rounding mode control
249249
bit HasFRMRoundModeOp = false;
250+
251+
// TWiden for XSfmm.
252+
int TWiden = 0;
250253
}
251254

252255
// This is the code emitted in the header.

clang/include/clang/Support/RISCVVIntrinsicUtils.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,7 @@ class RVVIntrinsic {
402402
std::vector<int64_t> IntrinsicTypes;
403403
unsigned NF = 1;
404404
Policy PolicyAttrs;
405+
unsigned TWiden = 0;
405406

406407
public:
407408
RVVIntrinsic(llvm::StringRef Name, llvm::StringRef Suffix,
@@ -410,8 +411,8 @@ class RVVIntrinsic {
410411
bool HasVL, PolicyScheme Scheme, bool SupportOverloading,
411412
bool HasBuiltinAlias, llvm::StringRef ManualCodegen,
412413
const RVVTypes &Types,
413-
const std::vector<int64_t> &IntrinsicTypes,
414-
unsigned NF, Policy PolicyAttrs, bool HasFRMRoundModeOp);
414+
const std::vector<int64_t> &IntrinsicTypes, unsigned NF,
415+
Policy PolicyAttrs, bool HasFRMRoundModeOp, unsigned TWiden);
415416
~RVVIntrinsic() = default;
416417

417418
RVVTypePtr getOutputType() const { return OutputType; }
@@ -435,6 +436,7 @@ class RVVIntrinsic {
435436
llvm::StringRef getManualCodegen() const { return ManualCodegen; }
436437
PolicyScheme getPolicyScheme() const { return Scheme; }
437438
unsigned getNF() const { return NF; }
439+
unsigned getTWiden() const { return TWiden; }
438440
const std::vector<int64_t> &getIntrinsicTypes() const {
439441
return IntrinsicTypes;
440442
}

clang/lib/CodeGen/TargetBuiltins/RISCV.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,6 +1121,8 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
11211121
bool IsMasked = false;
11221122
// This is used by segment load/store to determine it's llvm type.
11231123
unsigned SegInstSEW = 8;
1124+
// This is used by XSfmm.
1125+
unsigned TWiden = 0;
11241126

11251127
// Required for overloaded intrinsics.
11261128
llvm::SmallVector<llvm::Type *, 2> IntrinsicTypes;

clang/lib/Headers/sifive_vector.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,4 +115,60 @@
115115
#endif
116116
#endif
117117

118+
#define __riscv_sf_vsettnt_e8w1(atn) __riscv_sf_vsettnt(atn, 0, 1);
119+
#define __riscv_sf_vsettnt_e8w2(atn) __riscv_sf_vsettnt(atn, 0, 2);
120+
#define __riscv_sf_vsettnt_e8w4(atn) __riscv_sf_vsettnt(atn, 0, 3);
121+
#define __riscv_sf_vsettnt_e16w1(atn) __riscv_sf_vsettnt(atn, 1, 1);
122+
#define __riscv_sf_vsettnt_e16w2(atn) __riscv_sf_vsettnt(atn, 1, 2);
123+
#define __riscv_sf_vsettnt_e16w4(atn) __riscv_sf_vsettnt(atn, 1, 3);
124+
#define __riscv_sf_vsettnt_e32w1(atn) __riscv_sf_vsettnt(atn, 2, 1);
125+
#define __riscv_sf_vsettnt_e32w2(atn) __riscv_sf_vsettnt(atn, 2, 2);
126+
#define __riscv_sf_vsettm_e8w1(atm) __riscv_sf_vsettm(atm, 0, 1);
127+
#define __riscv_sf_vsettm_e8w2(atm) __riscv_sf_vsettm(atm, 0, 2);
128+
#define __riscv_sf_vsettm_e8w4(atm) __riscv_sf_vsettm(atm, 0, 3);
129+
#define __riscv_sf_vsettm_e16w1(atm) __riscv_sf_vsettm(atm, 1, 1);
130+
#define __riscv_sf_vsettm_e16w2(atm) __riscv_sf_vsettm(atm, 1, 2);
131+
#define __riscv_sf_vsettm_e16w4(atm) __riscv_sf_vsettm(atm, 1, 3);
132+
#define __riscv_sf_vsettm_e32w1(atm) __riscv_sf_vsettm(atm, 2, 1);
133+
#define __riscv_sf_vsettm_e32w2(atm) __riscv_sf_vsettm(atm, 2, 2);
134+
#define __riscv_sf_vsettn_e8w1(atn) __riscv_sf_vsettn(atn, 0, 1);
135+
#define __riscv_sf_vsettn_e8w2(atn) __riscv_sf_vsettn(atn, 0, 2);
136+
#define __riscv_sf_vsettn_e8w4(atn) __riscv_sf_vsettn(atn, 0, 3);
137+
#define __riscv_sf_vsettn_e16w1(atn) __riscv_sf_vsettn(atn, 1, 1);
138+
#define __riscv_sf_vsettn_e16w2(atn) __riscv_sf_vsettn(atn, 1, 2);
139+
#define __riscv_sf_vsettn_e16w4(atn) __riscv_sf_vsettn(atn, 1, 3);
140+
#define __riscv_sf_vsettn_e32w1(atn) __riscv_sf_vsettn(atn, 2, 1);
141+
#define __riscv_sf_vsettn_e32w2(atn) __riscv_sf_vsettn(atn, 2, 2);
142+
#define __riscv_sf_vsettk_e8w1(atk) __riscv_sf_vsettk(atk, 0, 1);
143+
#define __riscv_sf_vsettk_e8w2(atk) __riscv_sf_vsettk(atk, 0, 2);
144+
#define __riscv_sf_vsettk_e8w4(atk) __riscv_sf_vsettk(atk, 0, 3);
145+
#define __riscv_sf_vsettk_e16w1(atk) __riscv_sf_vsettk(atk, 1, 1);
146+
#define __riscv_sf_vsettk_e16w2(atk) __riscv_sf_vsettk(atk, 1, 2);
147+
#define __riscv_sf_vsettk_e16w4(atk) __riscv_sf_vsettk(atk, 1, 3);
148+
#define __riscv_sf_vsettk_e32w1(atk) __riscv_sf_vsettk(atk, 2, 1);
149+
#define __riscv_sf_vsettk_e32w2(atk) __riscv_sf_vsettk(atk, 2, 2);
150+
#define __riscv_sf_vtzero_t_e8w1(tile, atm, atn) \
151+
__riscv_sf_vtzero_t(tile, atm, atn, 3, 1);
152+
#define __riscv_sf_vtzero_t_e8w2(tile, atm, atn) \
153+
__riscv_sf_vtzero_t(tile, atm, atn, 3, 2);
154+
#define __riscv_sf_vtzero_t_e8w4(tile, atm, atn) \
155+
__riscv_sf_vtzero_t(tile, atm, atn, 3, 4);
156+
#define __riscv_sf_vtzero_t_e16w1(tile, atm, atn) \
157+
__riscv_sf_vtzero_t(tile, atm, atn, 4, 1);
158+
#define __riscv_sf_vtzero_t_e16w2(tile, atm, atn) \
159+
__riscv_sf_vtzero_t(tile, atm, atn, 4, 2);
160+
#define __riscv_sf_vtzero_t_e16w4(tile, atm, atn) \
161+
__riscv_sf_vtzero_t(tile, atm, atn, 4, 4);
162+
#define __riscv_sf_vtzero_t_e32w1(tile, atm, atn) \
163+
__riscv_sf_vtzero_t(tile, atm, atn, 5, 1);
164+
#define __riscv_sf_vtzero_t_e32w2(tile, atm, atn) \
165+
__riscv_sf_vtzero_t(tile, atm, atn, 5, 2);
166+
#if __riscv_v_elen >= 64
167+
#define __riscv_sf_vsettnt_e64w1(atn) __riscv_sf_vsettnt(atn, 3, 1);
168+
#define __riscv_sf_vsettm_e64w1(atm) __riscv_sf_vsettm(atm, 3, 1);
169+
#define __riscv_sf_vsettn_e64w1(atn) __riscv_sf_vsettn(atn, 3, 1);
170+
#define __riscv_sf_vsettk_e64w1(atk) __riscv_sf_vsettk(atk, 3, 1);
171+
#define __riscv_sf_vtzero_t_e64w1(tile, atm, atn) \
172+
__riscv_sf_vtzero_t(tile, atm, atn, 6, 1);
173+
#endif
118174
#endif //_SIFIVE_VECTOR_H_

clang/lib/Sema/SemaRISCV.cpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,80 @@ bool SemaRISCV::CheckBuiltinFunctionCall(const TargetInfo &TI,
664664
return CheckVSetVL(1, 2);
665665
case RISCVVector::BI__builtin_rvv_vsetvlimax:
666666
return CheckVSetVL(0, 1);
667+
case RISCVVector::BI__builtin_rvv_sf_vsettnt:
668+
case RISCVVector::BI__builtin_rvv_sf_vsettm:
669+
case RISCVVector::BI__builtin_rvv_sf_vsettn:
670+
case RISCVVector::BI__builtin_rvv_sf_vsettk:
671+
return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 3) ||
672+
SemaRef.BuiltinConstantArgRange(TheCall, 2, 1, 3);
673+
case RISCVVector::BI__builtin_rvv_sf_mm_f_f_w1:
674+
case RISCVVector::BI__builtin_rvv_sf_mm_f_f_w2:
675+
case RISCVVector::BI__builtin_rvv_sf_mm_e5m2_e4m3_w4:
676+
case RISCVVector::BI__builtin_rvv_sf_mm_e5m2_e5m2_w4:
677+
case RISCVVector::BI__builtin_rvv_sf_mm_e4m3_e4m3_w4:
678+
case RISCVVector::BI__builtin_rvv_sf_mm_e4m3_e5m2_w4:
679+
case RISCVVector::BI__builtin_rvv_sf_mm_u_u_w4:
680+
case RISCVVector::BI__builtin_rvv_sf_mm_u_s_w4:
681+
case RISCVVector::BI__builtin_rvv_sf_mm_s_u_w4:
682+
case RISCVVector::BI__builtin_rvv_sf_mm_s_s_w4: {
683+
QualType Arg1Type = TheCall->getArg(1)->getType();
684+
ASTContext::BuiltinVectorTypeInfo Info =
685+
SemaRef.Context.getBuiltinVectorTypeInfo(
686+
Arg1Type->castAs<BuiltinType>());
687+
unsigned EltSize = SemaRef.Context.getTypeSize(Info.ElementType);
688+
llvm::APSInt Result;
689+
690+
// We can't check the value of a dependent argument.
691+
Expr *Arg = TheCall->getArg(0);
692+
if (Arg->isTypeDependent() || Arg->isValueDependent())
693+
return false;
694+
695+
// Check constant-ness first.
696+
if (SemaRef.BuiltinConstantArg(TheCall, 0, Result))
697+
return true;
698+
699+
// For TEW = 32, mtd can only be 0, 4, 8, 12.
700+
// For TEW = 64, mtd can only be 0, 2, 4, 6, 8, 10, 12, 14.
701+
// Only `sf_mm_f_f_w1` and `sf_mm_f_f_w2` might have TEW = 64.
702+
if ((BuiltinID == RISCVVector::BI__builtin_rvv_sf_mm_f_f_w1 &&
703+
EltSize == 64) ||
704+
(BuiltinID == RISCVVector::BI__builtin_rvv_sf_mm_f_f_w2 &&
705+
EltSize == 32))
706+
return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 15) ||
707+
SemaRef.BuiltinConstantArgMultiple(TheCall, 0, 2);
708+
return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 15) ||
709+
SemaRef.BuiltinConstantArgMultiple(TheCall, 0, 4);
710+
}
711+
case RISCVVector::BI__builtin_rvv_sf_vtzero_t: {
712+
llvm::APSInt Log2SEWResult;
713+
llvm::APSInt TWidenResult;
714+
if (SemaRef.BuiltinConstantArg(TheCall, 3, Log2SEWResult) ||
715+
SemaRef.BuiltinConstantArg(TheCall, 4, TWidenResult))
716+
return true;
717+
718+
int Log2SEW = Log2SEWResult.getSExtValue();
719+
int TWiden = TWidenResult.getSExtValue();
720+
721+
// 3 <= LogSEW <= 6
722+
if (SemaRef.BuiltinConstantArgRange(TheCall, 3, 3, 6))
723+
return true;
724+
725+
// TWiden
726+
if (TWiden != 1 && TWiden != 2 && TWiden != 4)
727+
return Diag(TheCall->getBeginLoc(),
728+
diag::err_riscv_builtin_invalid_twiden);
729+
730+
int TEW = (1 << Log2SEW) * TWiden;
731+
732+
// For TEW = 8, mtd can be 0~15.
733+
// For TEW = 16 or 64, mtd can only be 0, 2, 4, 6, 8, 10, 12, 14.
734+
// For TEW = 32, mtd can only be 0, 4, 8, 12.
735+
if (SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 15))
736+
return true;
737+
if (TEW == 16 || TEW == 64)
738+
return SemaRef.BuiltinConstantArgMultiple(TheCall, 0, 2);
739+
return SemaRef.BuiltinConstantArgMultiple(TheCall, 0, 4);
740+
}
667741
case RISCVVector::BI__builtin_rvv_vget_v: {
668742
ASTContext::BuiltinVectorTypeInfo ResVecInfo =
669743
Context.getBuiltinVectorTypeInfo(cast<BuiltinType>(

clang/lib/Support/RISCVVIntrinsicUtils.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -980,11 +980,12 @@ RVVIntrinsic::RVVIntrinsic(
980980
bool HasMaskedOffOperand, bool HasVL, PolicyScheme Scheme,
981981
bool SupportOverloading, bool HasBuiltinAlias, StringRef ManualCodegen,
982982
const RVVTypes &OutInTypes, const std::vector<int64_t> &NewIntrinsicTypes,
983-
unsigned NF, Policy NewPolicyAttrs, bool HasFRMRoundModeOp)
983+
unsigned NF, Policy NewPolicyAttrs, bool HasFRMRoundModeOp, unsigned TWiden)
984984
: IRName(IRName), IsMasked(IsMasked),
985985
HasMaskedOffOperand(HasMaskedOffOperand), HasVL(HasVL), Scheme(Scheme),
986986
SupportOverloading(SupportOverloading), HasBuiltinAlias(HasBuiltinAlias),
987-
ManualCodegen(ManualCodegen.str()), NF(NF), PolicyAttrs(NewPolicyAttrs) {
987+
ManualCodegen(ManualCodegen.str()), NF(NF), PolicyAttrs(NewPolicyAttrs),
988+
TWiden(TWiden) {
988989

989990
// Init BuiltinName, Name and OverloadedName
990991
BuiltinName = NewName.str();

0 commit comments

Comments
 (0)