Skip to content

Commit

Permalink
[RISCV] Decouple Zve* extensions and the V extension.
Browse files Browse the repository at this point in the history
According to the spec, there are some difference between V and Zve64d. For example, the vmulh integer multiply variants that return the high word of the product (vmulh.vv, vmulh.vx, vmulhu.vv, vmulhu.vx, vmulhsu.vv, vmulhsu.vx) are not included for EEW=64 in Zve64*, but V extension does support these instructions. So we should decouple Zve* extensions and the V extension.

Differential Revision: https://reviews.llvm.org/D117854
  • Loading branch information
jacquesguan authored and jacquesguan committed Jan 24, 2022
1 parent bf039a8 commit ba16e3c
Show file tree
Hide file tree
Showing 11 changed files with 101 additions and 48 deletions.
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/DiagnosticSemaKinds.td
Expand Up @@ -11471,7 +11471,7 @@ def warn_tcb_enforcement_violation : Warning<

// RISC-V builtin required extension warning
def err_riscv_builtin_requires_extension : Error<
"builtin requires '%0' extension support to be enabled">;
"builtin requires at least one of the following extensions support to be enabled : %0">;
def err_riscv_builtin_invalid_lmul : Error<
"LMUL argument must be in the range [0,3] or [5,7]">;
} // end of sema component.
2 changes: 1 addition & 1 deletion clang/lib/Basic/Targets/RISCV.cpp
Expand Up @@ -188,7 +188,7 @@ void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,
if (ISAInfo->hasExtension("c"))
Builder.defineMacro("__riscv_compressed");

if (ISAInfo->hasExtension("zve32x"))
if (ISAInfo->hasExtension("zve32x") || ISAInfo->hasExtension("v"))
Builder.defineMacro("__riscv_vector");
}

Expand Down
48 changes: 32 additions & 16 deletions clang/lib/Sema/SemaChecking.cpp
Expand Up @@ -3976,23 +3976,39 @@ bool Sema::CheckRISCVBuiltinFunctionCall(const TargetInfo &TI,

// Check if each required feature is included
for (StringRef F : ReqFeatures) {
if (TI.hasFeature(F))
continue;

// If the feature is 64bit, alter the string so it will print better in
// the diagnostic.
if (F == "64bit")
F = "RV64";

// Convert features like "zbr" and "experimental-zbr" to "Zbr".
F.consume_front("experimental-");
std::string FeatureStr = F.str();
FeatureStr[0] = std::toupper(FeatureStr[0]);
SmallVector<StringRef> ReqOpFeatures;
F.split(ReqOpFeatures, '|');
bool HasFeature = false;
for (StringRef OF : ReqOpFeatures) {
if (TI.hasFeature(OF)) {
HasFeature = true;
continue;
}
}

// Error message
FeatureMissing = true;
Diag(TheCall->getBeginLoc(), diag::err_riscv_builtin_requires_extension)
<< TheCall->getSourceRange() << StringRef(FeatureStr);
if (!HasFeature) {
std::string FeatureStrs = "";
for (StringRef OF : ReqOpFeatures) {
// If the feature is 64bit, alter the string so it will print better in
// the diagnostic.
if (OF == "64bit")
OF = "RV64";

// Convert features like "zbr" and "experimental-zbr" to "Zbr".
OF.consume_front("experimental-");
std::string FeatureStr = OF.str();
FeatureStr[0] = std::toupper(FeatureStr[0]);
// Combine strings.
FeatureStrs += FeatureStrs == "" ? "" : ", ";
FeatureStrs += "'";
FeatureStrs += FeatureStr;
FeatureStrs += "'";
}
// Error message
FeatureMissing = true;
Diag(TheCall->getBeginLoc(), diag::err_riscv_builtin_requires_extension)
<< TheCall->getSourceRange() << StringRef(FeatureStrs);
}
}

if (FeatureMissing)
Expand Down
Expand Up @@ -2,5 +2,5 @@
// RUN: %clang_cc1 -triple riscv32 -target-feature +zbb -verify %s -o -

int orc_b_64(int a) {
return __builtin_riscv_orc_b_64(a); // expected-error {{builtin requires 'RV64' extension support to be enabled}}
return __builtin_riscv_orc_b_64(a); // expected-error {{builtin requires at least one of the following extensions support to be enabled : 'RV64'}}
}
18 changes: 18 additions & 0 deletions clang/test/CodeGen/RISCV/rvv-intrinsics/rvv-error.c
@@ -0,0 +1,18 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
// REQUIRES: riscv-registered-target
// RUN: %clang_cc1 -triple riscv64 -target-feature +v -disable-O0-optnone -emit-llvm %s -o - | opt -S -mem2reg | FileCheck --check-prefix=CHECK-RV64V %s
// RUN: %clang_cc1 -triple riscv64 -target-feature +zve64x -disable-O0-optnone -emit-llvm %s -o - | opt -S -mem2reg | FileCheck --check-prefix=CHECK-RV64V %s
// RUN: not %clang_cc1 -triple riscv64 -emit-llvm-only %s 2>&1 | FileCheck %s --check-prefix=CHECK-RV64-ERR

// CHECK-RV64V-LABEL: @test(
// CHECK-RV64V-NEXT: entry:
// CHECK-RV64V-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 1, i64 0, i64 0)
// CHECK-RV64V-NEXT: [[CONV:%.*]] = trunc i64 [[TMP0]] to i32
// CHECK-RV64V-NEXT: ret i32 [[CONV]]
//

// CHECK-RV64-ERR: error: builtin requires at least one of the following extensions support to be enabled : 'Zve32x', 'V'

int test() {
return __builtin_rvv_vsetvli(1, 0, 0);
}
2 changes: 1 addition & 1 deletion clang/utils/TableGen/RISCVVEmitter.cpp
Expand Up @@ -1034,7 +1034,7 @@ void RVVEmitter::createBuiltins(raw_ostream &OS) {

OS << "#if defined(TARGET_BUILTIN) && !defined(RISCVV_BUILTIN)\n";
OS << "#define RISCVV_BUILTIN(ID, TYPE, ATTRS) TARGET_BUILTIN(ID, TYPE, "
"ATTRS, \"zve32x\")\n";
"ATTRS, \"zve32x|v\")\n";
OS << "#endif\n";
for (auto &Def : Defs) {
auto P =
Expand Down
17 changes: 15 additions & 2 deletions llvm/lib/Support/RISCVISAInfo.cpp
Expand Up @@ -701,9 +701,11 @@ Error RISCVISAInfo::checkDependency() {
bool HasE = Exts.count("e") == 1;
bool HasD = Exts.count("d") == 1;
bool HasF = Exts.count("f") == 1;
bool HasVector = Exts.count("zve32x") == 1;
bool HasZve32x = Exts.count("zve32x") == 1;
bool HasZve32f = Exts.count("zve32f") == 1;
bool HasZve64d = Exts.count("zve64d") == 1;
bool HasV = Exts.count("v") == 1;
bool HasVector = HasZve32x || HasV;
bool HasZvl = MinVLen != 0;

if (HasE && !IsRv32)
Expand Down Expand Up @@ -736,14 +738,20 @@ Error RISCVISAInfo::checkDependency() {
errc::invalid_argument,
"zvl*b requires v or zve* extension to also be specified");

// Could not implement Zve* extension and the V extension at the same time.
if (HasZve32x && HasV)
return createStringError(
errc::invalid_argument,
"It is illegal to specify the v extension with zve* extensions");

// Additional dependency checks.
// TODO: The 'q' extension requires rv64.
// TODO: It is illegal to specify 'e' extensions with 'f' and 'd'.

return Error::success();
}

static const char *ImpliedExtsV[] = {"zvl128b", "zve64d", "f", "d"};
static const char *ImpliedExtsV[] = {"zvl128b", "f", "d"};
static const char *ImpliedExtsZfh[] = {"zfhmin"};
static const char *ImpliedExtsZve64d[] = {"zve64f"};
static const char *ImpliedExtsZve64f[] = {"zve64x", "zve32f"};
Expand Down Expand Up @@ -872,6 +880,11 @@ void RISCVISAInfo::updateMaxELen() {
ExtName.getAsInteger(10, ZveELen);
MaxELen = std::max(MaxELen, ZveELen);
}
if (ExtName == "v") {
MaxELenFp = 64;
MaxELen = 64;
return;
}
}
}

Expand Down
8 changes: 4 additions & 4 deletions llvm/lib/Target/RISCV/RISCV.td
Expand Up @@ -306,21 +306,21 @@ def FeatureStdExtZve64d
def FeatureStdExtV
: SubtargetFeature<"v", "HasStdExtV", "true",
"'V' (Vector Extension for Application Processors)",
[FeatureStdExtZvl128b, FeatureStdExtZve64d, FeatureStdExtF, FeatureStdExtD]>;
[FeatureStdExtZvl128b, FeatureStdExtF, FeatureStdExtD]>;

def HasVInstructions : Predicate<"Subtarget->hasVInstructions()">,
AssemblerPredicate<
(any_of FeatureStdExtZve32x),
(any_of FeatureStdExtZve32x, FeatureStdExtV),
"'V' (Vector Extension for Application Processors), 'Zve32x' or "
"'Zve64x' (Vector Extensions for Embedded Processors)">;
def HasVInstructionsI64 : Predicate<"Subtarget->hasVInstructionsI64()">,
AssemblerPredicate<
(any_of FeatureStdExtZve64x),
(any_of FeatureStdExtZve64x, FeatureStdExtV),
"'V' (Vector Extension for Application Processors) or 'Zve64x' "
"(Vector Extensions for Embedded Processors)">;
def HasVInstructionsAnyF : Predicate<"Subtarget->hasVInstructionsAnyF()">,
AssemblerPredicate<
(any_of FeatureStdExtZve32f),
(any_of FeatureStdExtZve32f, FeatureStdExtV),
"'V' (Vector Extension for Application Processors), 'Zve32f', "
"'Zve64f' or 'Zve64d' (Vector Extensions for Embedded Processors)">;

Expand Down
16 changes: 11 additions & 5 deletions llvm/lib/Target/RISCV/RISCVSubtarget.h
Expand Up @@ -199,13 +199,19 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo {
}

// Vector codegen related methods.
bool hasVInstructions() const { return HasStdExtZve32x; }
bool hasVInstructionsI64() const { return HasStdExtZve64x; }
bool hasVInstructionsF16() const { return HasStdExtZve32f && HasStdExtZfh; }
bool hasVInstructions() const { return HasStdExtV || HasStdExtZve32x; }
bool hasVInstructionsI64() const { return HasStdExtV || HasStdExtZve64x; }
bool hasVInstructionsF16() const {
return (HasStdExtV || HasStdExtZve32f) && HasStdExtZfh;
}
// FIXME: Consider Zfinx in the future
bool hasVInstructionsF32() const { return HasStdExtZve32f && HasStdExtF; }
bool hasVInstructionsF32() const {
return HasStdExtV || (HasStdExtZve32f && HasStdExtF);
}
// FIXME: Consider Zdinx in the future
bool hasVInstructionsF64() const { return HasStdExtZve64d && HasStdExtD; }
bool hasVInstructionsF64() const {
return HasStdExtV || (HasStdExtZve64d && HasStdExtD);
}
// F16 and F64 both require F32.
bool hasVInstructionsAnyF() const { return hasVInstructionsF32(); }
unsigned getMaxInterleaveFactor() const {
Expand Down
8 changes: 4 additions & 4 deletions llvm/test/CodeGen/RISCV/attributes.ll
Expand Up @@ -80,8 +80,8 @@
; RV32ZBR: .attribute 5, "rv32i2p0_zbr0p93"
; RV32ZBS: .attribute 5, "rv32i2p0_zbs1p0"
; RV32ZBT: .attribute 5, "rv32i2p0_zbt0p93"
; RV32V: .attribute 5, "rv32i2p0_f2p0_d2p0_v1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0"
; RV32COMBINED: .attribute 5, "rv32i2p0_f2p0_d2p0_v1p0_zfh1p0_zfhmin1p0_zbb1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0"
; RV32V: .attribute 5, "rv32i2p0_f2p0_d2p0_v1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0"
; RV32COMBINED: .attribute 5, "rv32i2p0_f2p0_d2p0_v1p0_zfh1p0_zfhmin1p0_zbb1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0"
; RV32ZBKB: .attribute 5, "rv32i2p0_zbkb1p0"
; RV32ZBKC: .attribute 5, "rv32i2p0_zbkc1p0"
; RV32ZKND: .attribute 5, "rv32i2p0_zknd1p0"
Expand Down Expand Up @@ -112,8 +112,8 @@
; RV64ZBR: .attribute 5, "rv64i2p0_zbr0p93"
; RV64ZBS: .attribute 5, "rv64i2p0_zbs1p0"
; RV64ZBT: .attribute 5, "rv64i2p0_zbt0p93"
; RV64V: .attribute 5, "rv64i2p0_f2p0_d2p0_v1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0"
; RV64COMBINED: .attribute 5, "rv64i2p0_f2p0_d2p0_v1p0_zfh1p0_zfhmin1p0_zbb1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0"
; RV64V: .attribute 5, "rv64i2p0_f2p0_d2p0_v1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0"
; RV64COMBINED: .attribute 5, "rv64i2p0_f2p0_d2p0_v1p0_zfh1p0_zfhmin1p0_zbb1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0"
; RV64ZBKB: .attribute 5, "rv64i2p0_zbkb1p0"
; RV64ZBKC: .attribute 5, "rv64i2p0_zbkc1p0"
; RV64ZKND: .attribute 5, "rv64i2p0_zknd1p0"
Expand Down
26 changes: 13 additions & 13 deletions llvm/test/MC/RISCV/attribute-arch.s
Expand Up @@ -34,43 +34,43 @@
# CHECK: attribute 5, "rv32i2p0_m2p0_a2p0_f2p0_d2p0_c2p0"

.attribute arch, "rv32iv"
# CHECK: attribute 5, "rv32i2p0_f2p0_d2p0_v1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0"
# CHECK: attribute 5, "rv32i2p0_f2p0_d2p0_v1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0"

.attribute arch, "rv32ivzvl32b"
# CHECK: attribute 5, "rv32i2p0_f2p0_d2p0_v1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0"
# CHECK: attribute 5, "rv32i2p0_f2p0_d2p0_v1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0"

.attribute arch, "rv32ivzvl64b"
# CHECK: attribute 5, "rv32i2p0_f2p0_d2p0_v1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0"
# CHECK: attribute 5, "rv32i2p0_f2p0_d2p0_v1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0"

.attribute arch, "rv32ivzvl128b"
# CHECK: attribute 5, "rv32i2p0_f2p0_d2p0_v1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0"
# CHECK: attribute 5, "rv32i2p0_f2p0_d2p0_v1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0"

.attribute arch, "rv32ivzvl256b"
# CHECK: attribute 5, "rv32i2p0_f2p0_d2p0_v1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl256b1p0_zvl32b1p0_zvl64b1p0"
# CHECK: attribute 5, "rv32i2p0_f2p0_d2p0_v1p0_zvl128b1p0_zvl256b1p0_zvl32b1p0_zvl64b1p0"

.attribute arch, "rv32ivzvl512b"
# CHECK: attribute 5, "rv32i2p0_f2p0_d2p0_v1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl256b1p0_zvl32b1p0_zvl512b1p0_zvl64b1p0"
# CHECK: attribute 5, "rv32i2p0_f2p0_d2p0_v1p0_zvl128b1p0_zvl256b1p0_zvl32b1p0_zvl512b1p0_zvl64b1p0"

.attribute arch, "rv32ivzvl1024b"
# CHECK: attribute 5, "rv32i2p0_f2p0_d2p0_v1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl1024b1p0_zvl128b1p0_zvl256b1p0_zvl32b1p0_zvl512b1p0_zvl64b1p0"
# CHECK: attribute 5, "rv32i2p0_f2p0_d2p0_v1p0_zvl1024b1p0_zvl128b1p0_zvl256b1p0_zvl32b1p0_zvl512b1p0_zvl64b1p0"

.attribute arch, "rv32ivzvl2048b"
# CHECK: attribute 5, "rv32i2p0_f2p0_d2p0_v1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl1024b1p0_zvl128b1p0_zvl2048b1p0_zvl256b1p0_zvl32b1p0_zvl512b1p0_zvl64b1p0"
# CHECK: attribute 5, "rv32i2p0_f2p0_d2p0_v1p0_zvl1024b1p0_zvl128b1p0_zvl2048b1p0_zvl256b1p0_zvl32b1p0_zvl512b1p0_zvl64b1p0"

.attribute arch, "rv32ivzvl4096b"
# CHECK: attribute 5, "rv32i2p0_f2p0_d2p0_v1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl1024b1p0_zvl128b1p0_zvl2048b1p0_zvl256b1p0_zvl32b1p0_zvl4096b1p0_zvl512b1p0_zvl64b1p0"
# CHECK: attribute 5, "rv32i2p0_f2p0_d2p0_v1p0_zvl1024b1p0_zvl128b1p0_zvl2048b1p0_zvl256b1p0_zvl32b1p0_zvl4096b1p0_zvl512b1p0_zvl64b1p0"

.attribute arch, "rv32ivzvl8192b"
# CHECK: attribute 5, "rv32i2p0_f2p0_d2p0_v1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl1024b1p0_zvl128b1p0_zvl2048b1p0_zvl256b1p0_zvl32b1p0_zvl4096b1p0_zvl512b1p0_zvl64b1p0_zvl8192b1p0"
# CHECK: attribute 5, "rv32i2p0_f2p0_d2p0_v1p0_zvl1024b1p0_zvl128b1p0_zvl2048b1p0_zvl256b1p0_zvl32b1p0_zvl4096b1p0_zvl512b1p0_zvl64b1p0_zvl8192b1p0"

.attribute arch, "rv32ivzvl16384b"
# CHECK: attribute 5, "rv32i2p0_f2p0_d2p0_v1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl1024b1p0_zvl128b1p0_zvl16384b1p0_zvl2048b1p0_zvl256b1p0_zvl32b1p0_zvl4096b1p0_zvl512b1p0_zvl64b1p0_zvl8192b1p0"
# CHECK: attribute 5, "rv32i2p0_f2p0_d2p0_v1p0_zvl1024b1p0_zvl128b1p0_zvl16384b1p0_zvl2048b1p0_zvl256b1p0_zvl32b1p0_zvl4096b1p0_zvl512b1p0_zvl64b1p0_zvl8192b1p0"

.attribute arch, "rv32ivzvl32768b"
# CHECK: attribute 5, "rv32i2p0_f2p0_d2p0_v1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl1024b1p0_zvl128b1p0_zvl16384b1p0_zvl2048b1p0_zvl256b1p0_zvl32768b1p0_zvl32b1p0_zvl4096b1p0_zvl512b1p0_zvl64b1p0_zvl8192b1p0"
# CHECK: attribute 5, "rv32i2p0_f2p0_d2p0_v1p0_zvl1024b1p0_zvl128b1p0_zvl16384b1p0_zvl2048b1p0_zvl256b1p0_zvl32768b1p0_zvl32b1p0_zvl4096b1p0_zvl512b1p0_zvl64b1p0_zvl8192b1p0"

.attribute arch, "rv32ivzvl65536b"
# CHECK: attribute 5, "rv32i2p0_f2p0_d2p0_v1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl1024b1p0_zvl128b1p0_zvl16384b1p0_zvl2048b1p0_zvl256b1p0_zvl32768b1p0_zvl32b1p0_zvl4096b1p0_zvl512b1p0_zvl64b1p0_zvl65536b1p0_zvl8192b1p0"
# CHECK: attribute 5, "rv32i2p0_f2p0_d2p0_v1p0_zvl1024b1p0_zvl128b1p0_zvl16384b1p0_zvl2048b1p0_zvl256b1p0_zvl32768b1p0_zvl32b1p0_zvl4096b1p0_zvl512b1p0_zvl64b1p0_zvl65536b1p0_zvl8192b1p0"

.attribute arch, "rv32izve32x"
# CHECK: attribute 5, "rv32i2p0_zve32x1p0_zvl32b1p0"
Expand Down

0 comments on commit ba16e3c

Please sign in to comment.