aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--clang/lib/Basic/Targets/RISCV.cpp7
-rw-r--r--clang/lib/Basic/Targets/RISCV.h2
-rw-r--r--clang/lib/CodeGen/CGBuiltin.cpp44
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h2
-rw-r--r--clang/test/CodeGen/RISCV/builtin-cpu-is.c39
-rw-r--r--llvm/include/llvm/TargetParser/RISCVTargetParser.h17
-rw-r--r--llvm/lib/Target/RISCV/RISCVProcessors.td15
-rw-r--r--llvm/lib/TargetParser/RISCVTargetParser.cpp33
-rw-r--r--llvm/test/TableGen/riscv-target-def.td13
-rw-r--r--llvm/utils/TableGen/RISCVTargetDefEmitter.cpp14
10 files changed, 166 insertions, 20 deletions
diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp
index eaaba76..88b9ca0 100644
--- a/clang/lib/Basic/Targets/RISCV.cpp
+++ b/clang/lib/Basic/Targets/RISCV.cpp
@@ -508,3 +508,10 @@ bool RISCVTargetInfo::validateGlobalRegisterVariable(
}
return false;
}
+
+bool RISCVTargetInfo::validateCpuIs(StringRef CPUName) const {
+ assert(getTriple().isOSLinux() &&
+ "__builtin_cpu_is() is only supported for Linux.");
+
+ return llvm::RISCV::hasValidCPUModel(CPUName);
+}
diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h
index 3b41858..3544ea6 100644
--- a/clang/lib/Basic/Targets/RISCV.h
+++ b/clang/lib/Basic/Targets/RISCV.h
@@ -128,8 +128,10 @@ public:
}
bool supportsCpuSupports() const override { return getTriple().isOSLinux(); }
+ bool supportsCpuIs() const override { return getTriple().isOSLinux(); }
bool supportsCpuInit() const override { return getTriple().isOSLinux(); }
bool validateCpuSupports(StringRef Feature) const override;
+ bool validateCpuIs(StringRef CPUName) const override;
bool isValidFeatureName(StringRef Name) const override;
bool validateGlobalRegisterVariable(StringRef RegName, unsigned RegSize,
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 9e0c0bf..24f6209 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -67,6 +67,7 @@
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/TargetParser/AArch64TargetParser.h"
#include "llvm/TargetParser/RISCVISAInfo.h"
+#include "llvm/TargetParser/RISCVTargetParser.h"
#include "llvm/TargetParser/X86TargetParser.h"
#include <optional>
#include <sstream>
@@ -22505,6 +22506,47 @@ Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID,
return nullptr;
}
+Value *CodeGenFunction::EmitRISCVCpuIs(const CallExpr *E) {
+ const Expr *CPUExpr = E->getArg(0)->IgnoreParenCasts();
+ StringRef CPUStr = cast<clang::StringLiteral>(CPUExpr)->getString();
+ return EmitRISCVCpuIs(CPUStr);
+}
+
+Value *CodeGenFunction::EmitRISCVCpuIs(StringRef CPUStr) {
+ llvm::Type *Int32Ty = Builder.getInt32Ty();
+ llvm::Type *Int64Ty = Builder.getInt64Ty();
+ llvm::StructType *StructTy = llvm::StructType::get(Int32Ty, Int64Ty, Int64Ty);
+ llvm::Constant *RISCVCPUModel =
+ CGM.CreateRuntimeVariable(StructTy, "__riscv_cpu_model");
+ cast<llvm::GlobalValue>(RISCVCPUModel)->setDSOLocal(true);
+
+ auto loadRISCVCPUID = [&](unsigned Index) {
+ Value *Ptr = Builder.CreateStructGEP(StructTy, RISCVCPUModel, Index);
+ Value *CPUID = Builder.CreateAlignedLoad(StructTy->getTypeAtIndex(Index),
+ Ptr, llvm::MaybeAlign());
+ return CPUID;
+ };
+
+ const llvm::RISCV::CPUModel CPUModel = llvm::RISCV::getCPUModel(CPUStr);
+
+ // Compare mvendorid.
+ Value *VendorID = loadRISCVCPUID(0);
+ Value *Result =
+ Builder.CreateICmpEQ(VendorID, Builder.getInt32(CPUModel.MVendorID));
+
+ // Compare marchid.
+ Value *ArchID = loadRISCVCPUID(1);
+ Result = Builder.CreateAnd(
+ Result, Builder.CreateICmpEQ(ArchID, Builder.getInt64(CPUModel.MArchID)));
+
+ // Compare mimplid.
+ Value *ImplID = loadRISCVCPUID(2);
+ Result = Builder.CreateAnd(
+ Result, Builder.CreateICmpEQ(ImplID, Builder.getInt64(CPUModel.MImpID)));
+
+ return Result;
+}
+
Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
const CallExpr *E,
ReturnValueSlot ReturnValue) {
@@ -22513,6 +22555,8 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
return EmitRISCVCpuSupports(E);
if (BuiltinID == Builtin::BI__builtin_cpu_init)
return EmitRISCVCpuInit();
+ if (BuiltinID == Builtin::BI__builtin_cpu_is)
+ return EmitRISCVCpuIs(E);
SmallVector<Value *, 4> Ops;
llvm::Type *ResultType = ConvertType(E->getType());
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index fcc1013..5c4d76c 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -4730,6 +4730,8 @@ public:
llvm::Value *EmitRISCVCpuSupports(const CallExpr *E);
llvm::Value *EmitRISCVCpuSupports(ArrayRef<StringRef> FeaturesStrs);
llvm::Value *EmitRISCVCpuInit();
+ llvm::Value *EmitRISCVCpuIs(const CallExpr *E);
+ llvm::Value *EmitRISCVCpuIs(StringRef CPUStr);
void AddAMDGPUFenceAddressSpaceMMRA(llvm::Instruction *Inst,
const CallExpr *E);
diff --git a/clang/test/CodeGen/RISCV/builtin-cpu-is.c b/clang/test/CodeGen/RISCV/builtin-cpu-is.c
new file mode 100644
index 0000000..3cb3558
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/builtin-cpu-is.c
@@ -0,0 +1,39 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
+// RUN: %clang_cc1 -triple riscv64-unknown-linux-gnu -disable-O0-optnone -emit-llvm %s -o - \
+// RUN: | opt -S -passes=mem2reg | FileCheck %s --check-prefix=CHECK-RV64
+
+// CHECK-RV64-LABEL: define dso_local signext i32 @test_cpu_is_veyron_v1(
+// CHECK-RV64-SAME: ) #[[ATTR0:[0-9]+]] {
+// CHECK-RV64-NEXT: [[ENTRY:.*:]]
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i32, ptr @__riscv_cpu_model, align 4
+// CHECK-RV64-NEXT: [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 1567
+// CHECK-RV64-NEXT: [[TMP2:%.*]] = load i64, ptr getelementptr inbounds nuw ({ i32, i64, i64 }, ptr @__riscv_cpu_model, i32 0, i32 1), align 8
+// CHECK-RV64-NEXT: [[TMP3:%.*]] = icmp eq i64 [[TMP2]], -9223372036854710272
+// CHECK-RV64-NEXT: [[TMP4:%.*]] = and i1 [[TMP1]], [[TMP3]]
+// CHECK-RV64-NEXT: [[TMP5:%.*]] = load i64, ptr getelementptr inbounds nuw ({ i32, i64, i64 }, ptr @__riscv_cpu_model, i32 0, i32 2), align 8
+// CHECK-RV64-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 273
+// CHECK-RV64-NEXT: [[TMP7:%.*]] = and i1 [[TMP4]], [[TMP6]]
+// CHECK-RV64-NEXT: [[CONV:%.*]] = zext i1 [[TMP7]] to i32
+// CHECK-RV64-NEXT: ret i32 [[CONV]]
+//
+int test_cpu_is_veyron_v1() {
+ return __builtin_cpu_is("veyron-v1");
+}
+
+// CHECK-RV64-LABEL: define dso_local signext i32 @test_cpu_is_spacemit_x60(
+// CHECK-RV64-SAME: ) #[[ATTR0]] {
+// CHECK-RV64-NEXT: [[ENTRY:.*:]]
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i32, ptr @__riscv_cpu_model, align 4
+// CHECK-RV64-NEXT: [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 1808
+// CHECK-RV64-NEXT: [[TMP2:%.*]] = load i64, ptr getelementptr inbounds nuw ({ i32, i64, i64 }, ptr @__riscv_cpu_model, i32 0, i32 1), align 8
+// CHECK-RV64-NEXT: [[TMP3:%.*]] = icmp eq i64 [[TMP2]], -9223372035378380799
+// CHECK-RV64-NEXT: [[TMP4:%.*]] = and i1 [[TMP1]], [[TMP3]]
+// CHECK-RV64-NEXT: [[TMP5:%.*]] = load i64, ptr getelementptr inbounds nuw ({ i32, i64, i64 }, ptr @__riscv_cpu_model, i32 0, i32 2), align 8
+// CHECK-RV64-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 1152921505839391232
+// CHECK-RV64-NEXT: [[TMP7:%.*]] = and i1 [[TMP4]], [[TMP6]]
+// CHECK-RV64-NEXT: [[CONV:%.*]] = zext i1 [[TMP7]] to i32
+// CHECK-RV64-NEXT: ret i32 [[CONV]]
+//
+int test_cpu_is_spacemit_x60() {
+ return __builtin_cpu_is("spacemit-x60");
+}
diff --git a/llvm/include/llvm/TargetParser/RISCVTargetParser.h b/llvm/include/llvm/TargetParser/RISCVTargetParser.h
index c757789..71035db 100644
--- a/llvm/include/llvm/TargetParser/RISCVTargetParser.h
+++ b/llvm/include/llvm/TargetParser/RISCVTargetParser.h
@@ -32,6 +32,21 @@ struct RISCVExtensionBitmask {
};
} // namespace RISCVExtensionBitmaskTable
+struct CPUModel {
+ uint32_t MVendorID;
+ uint64_t MArchID;
+ uint64_t MImpID;
+};
+
+struct CPUInfo {
+ StringLiteral Name;
+ StringLiteral DefaultMarch;
+ bool FastScalarUnalignedAccess;
+ bool FastVectorUnalignedAccess;
+ CPUModel CPUModel;
+ bool is64Bit() const { return DefaultMarch.starts_with("rv64"); }
+};
+
// We use 64 bits as the known part in the scalable vector types.
static constexpr unsigned RVVBitsPerBlock = 64;
@@ -45,6 +60,8 @@ void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64);
void fillValidTuneCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64);
bool hasFastScalarUnalignedAccess(StringRef CPU);
bool hasFastVectorUnalignedAccess(StringRef CPU);
+bool hasValidCPUModel(StringRef CPU);
+CPUModel getCPUModel(StringRef CPU);
} // namespace RISCV
diff --git a/llvm/lib/Target/RISCV/RISCVProcessors.td b/llvm/lib/Target/RISCV/RISCVProcessors.td
index e52a856..af8fbc9 100644
--- a/llvm/lib/Target/RISCV/RISCVProcessors.td
+++ b/llvm/lib/Target/RISCV/RISCVProcessors.td
@@ -49,6 +49,9 @@ class RISCVProcessorModel<string n,
string default_march = "">
: ProcessorModel<n, m, f, tunef> {
string DefaultMarch = default_march;
+ int MVendorID = 0;
+ int MArchID = 0;
+ int MImpID = 0;
}
class RISCVTuneProcessorModel<string n,
@@ -435,7 +438,11 @@ def VENTANA_VEYRON_V1 : RISCVProcessorModel<"veyron-v1",
TuneZExtHFusion,
TuneZExtWFusion,
TuneShiftedZExtWFusion,
- TuneLDADDFusion]>;
+ TuneLDADDFusion]> {
+ let MVendorID = 0x61f;
+ let MArchID = 0x8000000000010000;
+ let MImpID = 0x111;
+}
def XIANGSHAN_NANHU : RISCVProcessorModel<"xiangshan-nanhu",
XiangShanNanHuModel,
@@ -481,7 +488,11 @@ def SPACEMIT_X60 : RISCVProcessorModel<"spacemit-x60",
[TuneDLenFactor2,
TuneOptimizedNF2SegmentLoadStore,
TuneOptimizedNF3SegmentLoadStore,
- TuneOptimizedNF4SegmentLoadStore]>;
+ TuneOptimizedNF4SegmentLoadStore]> {
+ let MVendorID = 0x710;
+ let MArchID = 0x8000000058000001;
+ let MImpID = 0x1000000049772200;
+}
def RP2350_HAZARD3 : RISCVProcessorModel<"rp2350-hazard3",
NoSchedModel,
diff --git a/llvm/lib/TargetParser/RISCVTargetParser.cpp b/llvm/lib/TargetParser/RISCVTargetParser.cpp
index 49a35bf..2d407f6 100644
--- a/llvm/lib/TargetParser/RISCVTargetParser.cpp
+++ b/llvm/lib/TargetParser/RISCVTargetParser.cpp
@@ -22,24 +22,22 @@ namespace RISCV {
enum CPUKind : unsigned {
#define PROC(ENUM, NAME, DEFAULT_MARCH, FAST_SCALAR_UNALIGN, \
- FAST_VECTOR_UNALIGN) \
+ FAST_VECTOR_UNALIGN, MVENDORID, MARCHID, MIMPID) \
CK_##ENUM,
#define TUNE_PROC(ENUM, NAME) CK_##ENUM,
#include "llvm/TargetParser/RISCVTargetParserDef.inc"
};
-struct CPUInfo {
- StringLiteral Name;
- StringLiteral DefaultMarch;
- bool FastScalarUnalignedAccess;
- bool FastVectorUnalignedAccess;
- bool is64Bit() const { return DefaultMarch.starts_with("rv64"); }
-};
-
constexpr CPUInfo RISCVCPUInfo[] = {
#define PROC(ENUM, NAME, DEFAULT_MARCH, FAST_SCALAR_UNALIGN, \
- FAST_VECTOR_UNALIGN) \
- {NAME, DEFAULT_MARCH, FAST_SCALAR_UNALIGN, FAST_VECTOR_UNALIGN},
+ FAST_VECTOR_UNALIGN, MVENDORID, MARCHID, MIMPID) \
+ { \
+ NAME, \
+ DEFAULT_MARCH, \
+ FAST_SCALAR_UNALIGN, \
+ FAST_VECTOR_UNALIGN, \
+ {MVENDORID, MARCHID, MIMPID}, \
+ },
#include "llvm/TargetParser/RISCVTargetParserDef.inc"
};
@@ -60,6 +58,19 @@ bool hasFastVectorUnalignedAccess(StringRef CPU) {
return Info && Info->FastVectorUnalignedAccess;
}
+bool hasValidCPUModel(StringRef CPU) {
+ const CPUModel CPUModel = getCPUModel(CPU);
+ return CPUModel.MVendorID != 0 && CPUModel.MArchID != 0 &&
+ CPUModel.MImpID != 0;
+}
+
+CPUModel getCPUModel(StringRef CPU) {
+ const CPUInfo *Info = getCPUInfoByName(CPU);
+ if (!Info)
+ return {0, 0, 0};
+ return Info->CPUModel;
+}
+
bool parseCPU(StringRef CPU, bool IsRV64) {
const CPUInfo *Info = getCPUInfoByName(CPU);
diff --git a/llvm/test/TableGen/riscv-target-def.td b/llvm/test/TableGen/riscv-target-def.td
index c071cfd..7917873 100644
--- a/llvm/test/TableGen/riscv-target-def.td
+++ b/llvm/test/TableGen/riscv-target-def.td
@@ -81,6 +81,9 @@ class RISCVProcessorModel<string n,
string default_march = "">
: ProcessorModel<n, m, f, tunef> {
string DefaultMarch = default_march;
+ int MVendorID = 0;
+ int MArchID = 0;
+ int MImpID = 0;
}
class RISCVTuneProcessorModel<string n,
@@ -160,13 +163,13 @@ def ROCKET : RISCVTuneProcessorModel<"rocket",
// CHECK: #endif // GET_SUPPORTED_PROFILES
// CHECK: #ifndef PROC
-// CHECK-NEXT: #define PROC(ENUM, NAME, DEFAULT_MARCH, FAST_SCALAR_UNALIGN, FAST_VECTOR_UNALIGN)
+// CHECK-NEXT: #define PROC(ENUM, NAME, DEFAULT_MARCH, FAST_SCALAR_UNALIGN, FAST_VECTOR_UNALIGN, MVENDORID, MARCHID, MIMPID)
// CHECK-NEXT: #endif
-// CHECK: PROC(GENERIC_RV32, {"generic-rv32"}, {"rv32i2p1"}, 0, 0)
-// CHECK-NEXT: PROC(GENERIC_RV64, {"generic-rv64"}, {"rv64i2p1"}, 0, 0)
-// CHECK-NEXT: PROC(ROCKET_RV32, {"rocket-rv32"}, {"rv32i2p1_zicsr2p0_zidummy0p1_zifencei2p0"}, 0, 0)
-// CHECK-NEXT: PROC(ROCKET_RV64, {"rocket-rv64"}, {"rv64i2p1_zicsr2p0_zidummy0p1_zifencei2p0"}, 0, 0)
+// CHECK: PROC(GENERIC_RV32, {"generic-rv32"}, {"rv32i2p1"}, 0, 0, 0x00000000, 0x0000000000000000, 0x0000000000000000)
+// CHECK-NEXT: PROC(GENERIC_RV64, {"generic-rv64"}, {"rv64i2p1"}, 0, 0, 0x00000000, 0x0000000000000000, 0x0000000000000000)
+// CHECK-NEXT: PROC(ROCKET_RV32, {"rocket-rv32"}, {"rv32i2p1_zicsr2p0_zidummy0p1_zifencei2p0"}, 0, 0, 0x00000000, 0x0000000000000000, 0x0000000000000000)
+// CHECK-NEXT: PROC(ROCKET_RV64, {"rocket-rv64"}, {"rv64i2p1_zicsr2p0_zidummy0p1_zifencei2p0"}, 0, 0, 0x00000000, 0x0000000000000000, 0x0000000000000000)
// CHECK: #undef PROC
diff --git a/llvm/utils/TableGen/RISCVTargetDefEmitter.cpp b/llvm/utils/TableGen/RISCVTargetDefEmitter.cpp
index 39211aa..723f1d7 100644
--- a/llvm/utils/TableGen/RISCVTargetDefEmitter.cpp
+++ b/llvm/utils/TableGen/RISCVTargetDefEmitter.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/ADT/DenseSet.h"
+#include "llvm/Support/Format.h"
#include "llvm/Support/RISCVISAUtils.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
@@ -166,7 +167,7 @@ static void emitRISCVProfiles(const RecordKeeper &Records, raw_ostream &OS) {
static void emitRISCVProcs(const RecordKeeper &RK, raw_ostream &OS) {
OS << "#ifndef PROC\n"
<< "#define PROC(ENUM, NAME, DEFAULT_MARCH, FAST_SCALAR_UNALIGN"
- << ", FAST_VECTOR_UNALIGN)\n"
+ << ", FAST_VECTOR_UNALIGN, MVENDORID, MARCHID, MIMPID)\n"
<< "#endif\n\n";
// Iterate on all definition records.
@@ -192,8 +193,17 @@ static void emitRISCVProcs(const RecordKeeper &RK, raw_ostream &OS) {
printMArch(OS, Features);
else
OS << MArch;
+
+ uint32_t MVendorID = Rec->getValueAsInt("MVendorID");
+ uint64_t MArchID = Rec->getValueAsInt("MArchID");
+ uint64_t MImpID = Rec->getValueAsInt("MImpID");
+
OS << "\"}, " << FastScalarUnalignedAccess << ", "
- << FastVectorUnalignedAccess << ")\n";
+ << FastVectorUnalignedAccess;
+ OS << ", " << format_hex(MVendorID, 10);
+ OS << ", " << format_hex(MArchID, 18);
+ OS << ", " << format_hex(MImpID, 18);
+ OS << ")\n";
}
OS << "\n#undef PROC\n";
OS << "\n";