Skip to content

Commit 2a05a52

Browse files
committed
[RISCV] Support vector crypto extension C intrinsics
Depends on D141672, D138809 Differential Revision: https://reviews.llvm.org/D138810
1 parent 61709bb commit 2a05a52

Some content is hidden

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

122 files changed

+45627
-1
lines changed

clang/include/clang/Basic/riscv_vector.td

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@ multiclass RVVOutOp1Op2BuiltinSet<string intrinsic_name, string type_range,
8585
list<list<string>> suffixes_prototypes>
8686
: RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [-1, 1, 2]>;
8787

88+
// IntrinsicTypes is output, op2 [-1, 2]
89+
multiclass RVVOutOp2BuiltinSet<string intrinsic_name, string type_range,
90+
list<list<string>> suffixes_prototypes>
91+
: RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [-1, 2]>;
92+
8893
multiclass RVVSignedBinBuiltinSet
8994
: RVVOutOp1BuiltinSet<NAME, "csil",
9095
[["vv", "v", "vvv"],
@@ -109,6 +114,14 @@ multiclass RVVIntBinBuiltinSet
109114
: RVVSignedBinBuiltinSet,
110115
RVVUnsignedBinBuiltinSet;
111116

117+
multiclass RVVInt64BinBuiltinSet
118+
: RVVOutOp1BuiltinSet<NAME, "l",
119+
[["vv", "v", "vvv"],
120+
["vx", "v", "vve"]]>,
121+
RVVOutOp1BuiltinSet<NAME, "l",
122+
[["vv", "Uv", "UvUvUv"],
123+
["vx", "Uv", "UvUvUe"]]>;
124+
112125
multiclass RVVSlideOneBuiltinSet
113126
: RVVOutOp1BuiltinSet<NAME, "csil",
114127
[["vx", "v", "vve"],
@@ -2818,3 +2831,94 @@ let HasMasked = false, HasVL = false, IRName = "" in {
28182831
}
28192832
}
28202833
}
2834+
2835+
multiclass RVVOutBuiltinSetZvbb {
2836+
let OverloadedName = NAME in
2837+
defm "" : RVVOutBuiltinSet<NAME, "csil", [["v", "v", "vv"],
2838+
["v", "Uv", "UvUv"]]>;
2839+
}
2840+
2841+
multiclass RVVOutBuiltinSetZvk<bit HasVV = 1, bit HasVS = 1> {
2842+
// vaesz only has 'vs' and vgmul only has 'vv' and they do not have ambiguous
2843+
// prototypes like other zvkned instructions (e.g. vaesdf), so we don't
2844+
// need to encode the operand mnemonics into its intrinsic function name.
2845+
if HasVV then {
2846+
defvar name = NAME # !if(!eq(NAME, "vgmul"), "", "_vv");
2847+
let OverloadedName = name in
2848+
defm "" : RVVOutBuiltinSet<NAME # "_vv", "i",
2849+
[["vv", "Uv", "UvUvUv"]]>;
2850+
}
2851+
2852+
if HasVS then {
2853+
foreach vs2_lmul = ["(SEFixedLog2LMUL:-1)", "(SEFixedLog2LMUL:0)",
2854+
"(SEFixedLog2LMUL:1)", "(SEFixedLog2LMUL:2)",
2855+
"(SEFixedLog2LMUL:3)"] in {
2856+
defvar name = NAME # !if(!eq(NAME, "vaesz"), "", "_vs");
2857+
let OverloadedName = name, IRName = NAME # "_vs", Name = NAME # "_vs",
2858+
IntrinsicTypes = [-1, 1] in
2859+
def NAME # vs2_lmul
2860+
: RVVBuiltin<vs2_lmul # "UvUv", "UvUv" # vs2_lmul # "Uv", "i">;
2861+
}
2862+
}
2863+
}
2864+
2865+
multiclass RVVOutOp2BuiltinSetVVZvk<string type_range = "i">
2866+
: RVVOutOp2BuiltinSet<NAME, type_range, [["vv", "Uv", "UvUvUvUv"]]>;
2867+
2868+
multiclass RVVOutOp2BuiltinSetVIZvk<string type_range = "i">
2869+
: RVVOutOp2BuiltinSet<NAME, type_range, [["vi", "Uv", "UvUvUvKz"]]>;
2870+
2871+
multiclass RVVSignedWidenBinBuiltinSetVwsll
2872+
: RVVWidenBuiltinSet<NAME, "csi",
2873+
[["vv", "Uw", "UwUvUv"],
2874+
["vx", "Uw", "UwUvz"]]>;
2875+
2876+
let UnMaskedPolicyScheme = HasPassthruOperand in {
2877+
// zvbb
2878+
defm vandn : RVVUnsignedBinBuiltinSet;
2879+
defm vbrev : RVVOutBuiltinSetZvbb;
2880+
defm vbrev8 : RVVOutBuiltinSetZvbb;
2881+
defm vrev8 : RVVOutBuiltinSetZvbb;
2882+
defm vclz : RVVOutBuiltinSetZvbb;
2883+
defm vctz : RVVOutBuiltinSetZvbb;
2884+
defm vcpopv : RVVOutBuiltinSetZvbb;
2885+
defm vrol : RVVUnsignedShiftBuiltinSet;
2886+
defm vror : RVVUnsignedShiftBuiltinSet;
2887+
let OverloadedName = "vwsll" in
2888+
defm vwsll : RVVSignedWidenBinBuiltinSetVwsll;
2889+
2890+
// zvbc
2891+
defm vclmul : RVVInt64BinBuiltinSet;
2892+
defm vclmulh : RVVInt64BinBuiltinSet;
2893+
}
2894+
2895+
let UnMaskedPolicyScheme = HasPolicyOperand, HasMasked = false in {
2896+
// zvkg
2897+
defm vghsh : RVVOutOp2BuiltinSetVVZvk;
2898+
defm vgmul : RVVOutBuiltinSetZvk</*HasVV*/1, /*HasVS*/0>;
2899+
2900+
// zvkned
2901+
defm vaesdf : RVVOutBuiltinSetZvk;
2902+
defm vaesdm : RVVOutBuiltinSetZvk;
2903+
defm vaesef : RVVOutBuiltinSetZvk;
2904+
defm vaesem : RVVOutBuiltinSetZvk;
2905+
let UnMaskedPolicyScheme = HasPassthruOperand in
2906+
defm vaeskf1 : RVVOutOp1BuiltinSet<"vaeskf1", "i", [["vi", "Uv", "UvUvKz"]]>;
2907+
defm vaeskf2 : RVVOutOp2BuiltinSetVIZvk;
2908+
defm vaesz : RVVOutBuiltinSetZvk</*HasVV*/0>;
2909+
2910+
// zvknha or zvknhb
2911+
defm vsha2ch : RVVOutOp2BuiltinSetVVZvk<"il">;
2912+
defm vsha2cl : RVVOutOp2BuiltinSetVVZvk<"il">;
2913+
defm vsha2ms : RVVOutOp2BuiltinSetVVZvk<"il">;
2914+
2915+
// zvksed
2916+
let UnMaskedPolicyScheme = HasPassthruOperand in
2917+
defm vsm4k : RVVOutOp1BuiltinSet<"vsm4k", "i", [["vi", "Uv", "UvUvKz"]]>;
2918+
defm vsm4r : RVVOutBuiltinSetZvk;
2919+
2920+
// zvksh
2921+
defm vsm3c : RVVOutOp2BuiltinSetVIZvk;
2922+
let UnMaskedPolicyScheme = HasPassthruOperand in
2923+
defm vsm3me : RVVOutOp1BuiltinSet<"vsm3me", "i", [["vv", "Uv", "UvUvUv"]]>;
2924+
}

clang/include/clang/Basic/riscv_vector_common.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@
9797
// and LMUL), and computes another vector type which only changed LMUL as
9898
// given value. The new LMUL should be smaller than the old one. Ignore to
9999
// define a new builtin if its equivalent type has illegal lmul.
100+
// (SEFixedLog2LMUL:Value): Smaller or Equal Fixed Log2LMUL. Given a vector
101+
// type (SEW and LMUL), and computes another vector type which only
102+
// changed LMUL as given value. The new LMUL should be smaller than or
103+
// equal to the old one. Ignore to define a new builtin if its equivalent
104+
// type has illegal lmul.
100105
// (LFixedLog2LMUL:Value): Larger Fixed Log2LMUL. Given a vector type (SEW
101106
// and LMUL), and computes another vector type which only changed LMUL as
102107
// given value. The new LMUL should be larger than the old one. Ignore to

clang/include/clang/Support/RISCVVIntrinsicUtils.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,13 @@ enum class VectorTypeModifier : uint8_t {
5858
SFixedLog2LMUL1,
5959
SFixedLog2LMUL2,
6060
SFixedLog2LMUL3,
61+
SEFixedLog2LMULN3,
62+
SEFixedLog2LMULN2,
63+
SEFixedLog2LMULN1,
64+
SEFixedLog2LMUL0,
65+
SEFixedLog2LMUL1,
66+
SEFixedLog2LMUL2,
67+
SEFixedLog2LMUL3,
6168
Tuple2,
6269
Tuple3,
6370
Tuple4,
@@ -259,7 +266,7 @@ class RVVType {
259266
std::string Str;
260267
std::string ShortStr;
261268

262-
enum class FixedLMULType { LargerThan, SmallerThan };
269+
enum class FixedLMULType { LargerThan, SmallerThan, SmallerOrEqual };
263270

264271
RVVType(BasicType BT, int Log2LMUL, const PrototypeDescriptor &Profile);
265272

clang/lib/Sema/SemaChecking.cpp

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
#include "llvm/Support/MathExtras.h"
8787
#include "llvm/Support/SaveAndRestore.h"
8888
#include "llvm/Support/raw_ostream.h"
89+
#include "llvm/TargetParser/RISCVTargetParser.h"
8990
#include "llvm/TargetParser/Triple.h"
9091
#include <algorithm>
9192
#include <bitset>
@@ -4513,6 +4514,27 @@ bool Sema::CheckRISCVLMUL(CallExpr *TheCall, unsigned ArgNum) {
45134514
<< Arg->getSourceRange();
45144515
}
45154516

4517+
static bool CheckInvalidVLENandLMUL(const TargetInfo &TI, CallExpr *TheCall,
4518+
Sema &S, QualType Type, int EGW) {
4519+
assert((EGW == 128 || EGW == 256) && "EGW can only be 128 or 256 bits");
4520+
4521+
// LMUL * VLEN >= EGW
4522+
uint64_t ElemSize = Type->isRVVType(32, false) ? 32 : 64;
4523+
uint64_t ElemCount = Type->isRVVType(1) ? 1 :
4524+
Type->isRVVType(2) ? 2 :
4525+
Type->isRVVType(4) ? 4 :
4526+
Type->isRVVType(8) ? 8 :
4527+
16;
4528+
float Lmul = (float)(ElemSize * ElemCount) / llvm::RISCV::RVVBitsPerBlock;
4529+
uint64_t MinRequiredVLEN = std::max(EGW / Lmul, (float)ElemSize);
4530+
std::string RequiredExt = "zvl" + std::to_string(MinRequiredVLEN) + "b";
4531+
if (!TI.hasFeature(RequiredExt))
4532+
return S.Diag(TheCall->getBeginLoc(),
4533+
diag::err_riscv_type_requires_extension) << Type << RequiredExt;
4534+
4535+
return false;
4536+
}
4537+
45164538
bool Sema::CheckRISCVBuiltinFunctionCall(const TargetInfo &TI,
45174539
unsigned BuiltinID,
45184540
CallExpr *TheCall) {
@@ -4671,6 +4693,76 @@ bool Sema::CheckRISCVBuiltinFunctionCall(const TargetInfo &TI,
46714693
(VecInfo.EC.getKnownMinValue() * VecInfo.NumVectors);
46724694
return SemaBuiltinConstantArgRange(TheCall, 1, 0, MaxIndex - 1);
46734695
}
4696+
// Vector Crypto
4697+
case RISCVVector::BI__builtin_rvv_vaeskf1_vi_tu:
4698+
case RISCVVector::BI__builtin_rvv_vaeskf2_vi_tu:
4699+
case RISCVVector::BI__builtin_rvv_vaeskf2_vi:
4700+
case RISCVVector::BI__builtin_rvv_vsm4k_vi_tu: {
4701+
QualType Op1Type = TheCall->getArg(0)->getType();
4702+
QualType Op2Type = TheCall->getArg(1)->getType();
4703+
return CheckInvalidVLENandLMUL(TI, TheCall, *this, Op1Type, 128) ||
4704+
CheckInvalidVLENandLMUL(TI, TheCall, *this, Op2Type, 128) ||
4705+
SemaBuiltinConstantArgRange(TheCall, 2, 0, 31);
4706+
}
4707+
case RISCVVector::BI__builtin_rvv_vsm3c_vi_tu:
4708+
case RISCVVector::BI__builtin_rvv_vsm3c_vi: {
4709+
QualType Op1Type = TheCall->getArg(0)->getType();
4710+
return CheckInvalidVLENandLMUL(TI, TheCall, *this, Op1Type, 256) ||
4711+
SemaBuiltinConstantArgRange(TheCall, 2, 0, 31);
4712+
}
4713+
case RISCVVector::BI__builtin_rvv_vaeskf1_vi:
4714+
case RISCVVector::BI__builtin_rvv_vsm4k_vi: {
4715+
QualType Op1Type = TheCall->getArg(0)->getType();
4716+
return CheckInvalidVLENandLMUL(TI, TheCall, *this, Op1Type, 128) ||
4717+
SemaBuiltinConstantArgRange(TheCall, 1, 0, 31);
4718+
}
4719+
case RISCVVector::BI__builtin_rvv_vaesdf_vv:
4720+
case RISCVVector::BI__builtin_rvv_vaesdf_vs:
4721+
case RISCVVector::BI__builtin_rvv_vaesdm_vv:
4722+
case RISCVVector::BI__builtin_rvv_vaesdm_vs:
4723+
case RISCVVector::BI__builtin_rvv_vaesef_vv:
4724+
case RISCVVector::BI__builtin_rvv_vaesef_vs:
4725+
case RISCVVector::BI__builtin_rvv_vaesem_vv:
4726+
case RISCVVector::BI__builtin_rvv_vaesem_vs:
4727+
case RISCVVector::BI__builtin_rvv_vaesz_vs:
4728+
case RISCVVector::BI__builtin_rvv_vsm4r_vv:
4729+
case RISCVVector::BI__builtin_rvv_vsm4r_vs:
4730+
case RISCVVector::BI__builtin_rvv_vaesdf_vv_tu:
4731+
case RISCVVector::BI__builtin_rvv_vaesdf_vs_tu:
4732+
case RISCVVector::BI__builtin_rvv_vaesdm_vv_tu:
4733+
case RISCVVector::BI__builtin_rvv_vaesdm_vs_tu:
4734+
case RISCVVector::BI__builtin_rvv_vaesef_vv_tu:
4735+
case RISCVVector::BI__builtin_rvv_vaesef_vs_tu:
4736+
case RISCVVector::BI__builtin_rvv_vaesem_vv_tu:
4737+
case RISCVVector::BI__builtin_rvv_vaesem_vs_tu:
4738+
case RISCVVector::BI__builtin_rvv_vaesz_vs_tu:
4739+
case RISCVVector::BI__builtin_rvv_vsm4r_vv_tu:
4740+
case RISCVVector::BI__builtin_rvv_vsm4r_vs_tu: {
4741+
QualType Op1Type = TheCall->getArg(0)->getType();
4742+
QualType Op2Type = TheCall->getArg(1)->getType();
4743+
return CheckInvalidVLENandLMUL(TI, TheCall, *this, Op1Type, 128) ||
4744+
CheckInvalidVLENandLMUL(TI, TheCall, *this, Op2Type, 128);
4745+
}
4746+
case RISCVVector::BI__builtin_rvv_vsha2ch_vv:
4747+
case RISCVVector::BI__builtin_rvv_vsha2cl_vv:
4748+
case RISCVVector::BI__builtin_rvv_vsha2ms_vv:
4749+
case RISCVVector::BI__builtin_rvv_vsha2ch_vv_tu:
4750+
case RISCVVector::BI__builtin_rvv_vsha2cl_vv_tu:
4751+
case RISCVVector::BI__builtin_rvv_vsha2ms_vv_tu: {
4752+
QualType Op1Type = TheCall->getArg(0)->getType();
4753+
QualType Op2Type = TheCall->getArg(1)->getType();
4754+
QualType Op3Type = TheCall->getArg(2)->getType();
4755+
uint64_t ElemSize = Op1Type->isRVVType(32, false) ? 32 : 64;
4756+
if (ElemSize == 64 && !TI.hasFeature("experimental-zvknhb"))
4757+
return
4758+
Diag(TheCall->getBeginLoc(), diag::err_riscv_type_requires_extension)
4759+
<< Op1Type << "experimental-zvknhb";
4760+
4761+
return CheckInvalidVLENandLMUL(TI, TheCall, *this, Op1Type, ElemSize << 2) ||
4762+
CheckInvalidVLENandLMUL(TI, TheCall, *this, Op2Type, ElemSize << 2) ||
4763+
CheckInvalidVLENandLMUL(TI, TheCall, *this, Op3Type, ElemSize << 2);
4764+
}
4765+
46744766
case RISCVVector::BI__builtin_rvv_sf_vc_i_se_u8mf8:
46754767
case RISCVVector::BI__builtin_rvv_sf_vc_i_se_u8mf4:
46764768
case RISCVVector::BI__builtin_rvv_sf_vc_i_se_u8mf2:

clang/lib/Support/RISCVVIntrinsicUtils.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,38 @@ PrototypeDescriptor::parsePrototypeDescriptor(
559559
return std::nullopt;
560560
}
561561

562+
} else if (ComplexTT.first == "SEFixedLog2LMUL") {
563+
int32_t Log2LMUL;
564+
if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
565+
llvm_unreachable("Invalid SEFixedLog2LMUL value!");
566+
return std::nullopt;
567+
}
568+
switch (Log2LMUL) {
569+
case -3:
570+
VTM = VectorTypeModifier::SEFixedLog2LMULN3;
571+
break;
572+
case -2:
573+
VTM = VectorTypeModifier::SEFixedLog2LMULN2;
574+
break;
575+
case -1:
576+
VTM = VectorTypeModifier::SEFixedLog2LMULN1;
577+
break;
578+
case 0:
579+
VTM = VectorTypeModifier::SEFixedLog2LMUL0;
580+
break;
581+
case 1:
582+
VTM = VectorTypeModifier::SEFixedLog2LMUL1;
583+
break;
584+
case 2:
585+
VTM = VectorTypeModifier::SEFixedLog2LMUL2;
586+
break;
587+
case 3:
588+
VTM = VectorTypeModifier::SEFixedLog2LMUL3;
589+
break;
590+
default:
591+
llvm_unreachable("Invalid LFixedLog2LMUL value, should be [-3, 3]");
592+
return std::nullopt;
593+
}
562594
} else if (ComplexTT.first == "Tuple") {
563595
unsigned NF = 0;
564596
if (ComplexTT.second.getAsInteger(10, NF)) {
@@ -726,6 +758,27 @@ void RVVType::applyModifier(const PrototypeDescriptor &Transformer) {
726758
case VectorTypeModifier::SFixedLog2LMUL3:
727759
applyFixedLog2LMUL(3, FixedLMULType::SmallerThan);
728760
break;
761+
case VectorTypeModifier::SEFixedLog2LMULN3:
762+
applyFixedLog2LMUL(-3, FixedLMULType::SmallerOrEqual);
763+
break;
764+
case VectorTypeModifier::SEFixedLog2LMULN2:
765+
applyFixedLog2LMUL(-2, FixedLMULType::SmallerOrEqual);
766+
break;
767+
case VectorTypeModifier::SEFixedLog2LMULN1:
768+
applyFixedLog2LMUL(-1, FixedLMULType::SmallerOrEqual);
769+
break;
770+
case VectorTypeModifier::SEFixedLog2LMUL0:
771+
applyFixedLog2LMUL(0, FixedLMULType::SmallerOrEqual);
772+
break;
773+
case VectorTypeModifier::SEFixedLog2LMUL1:
774+
applyFixedLog2LMUL(1, FixedLMULType::SmallerOrEqual);
775+
break;
776+
case VectorTypeModifier::SEFixedLog2LMUL2:
777+
applyFixedLog2LMUL(2, FixedLMULType::SmallerOrEqual);
778+
break;
779+
case VectorTypeModifier::SEFixedLog2LMUL3:
780+
applyFixedLog2LMUL(3, FixedLMULType::SmallerOrEqual);
781+
break;
729782
case VectorTypeModifier::Tuple2:
730783
case VectorTypeModifier::Tuple3:
731784
case VectorTypeModifier::Tuple4:
@@ -818,6 +871,12 @@ void RVVType::applyFixedLog2LMUL(int Log2LMUL, enum FixedLMULType Type) {
818871
return;
819872
}
820873
break;
874+
case FixedLMULType::SmallerOrEqual:
875+
if (Log2LMUL > LMUL.Log2LMUL) {
876+
ScalarType = ScalarTypeKind::Invalid;
877+
return;
878+
}
879+
break;
821880
}
822881

823882
// Update new LMUL

0 commit comments

Comments
 (0)