Author: Pengcheng Wang Date: 2024-11-22T22:58:54+08:00 New Revision: 875b10f7d0888ca7e53f527f4c30531bd6b50bfb
URL: https://github.com/llvm/llvm-project/commit/875b10f7d0888ca7e53f527f4c30531bd6b50bfb DIFF: https://github.com/llvm/llvm-project/commit/875b10f7d0888ca7e53f527f4c30531bd6b50bfb.diff LOG: [RISCV] Support __builtin_cpu_is We have defined `__riscv_cpu_model` variable in #101449. It contains `mvendorid`, `marchid` and `mimpid` fields which are read via system call `sys_riscv_hwprobe`. We can support `__builtin_cpu_is` via comparing values in compiler's CPU definitions and `__riscv_cpu_model`. This depends on #116202. Reviewers: lenary, BeMg, kito-cheng, preames, lukel97 Reviewed By: lenary Pull Request: https://github.com/llvm/llvm-project/pull/116231 Added: clang/test/CodeGen/RISCV/builtin-cpu-is-error.c clang/test/CodeGen/RISCV/builtin-cpu-is.c Modified: clang/lib/Basic/Targets/RISCV.cpp clang/lib/Basic/Targets/RISCV.h clang/lib/CodeGen/CGBuiltin.cpp clang/lib/CodeGen/CodeGenFunction.h clang/test/Preprocessor/has_builtin_cpuid.c llvm/include/llvm/TargetParser/RISCVTargetParser.h llvm/lib/TargetParser/RISCVTargetParser.cpp Removed: ################################################################################ diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp index c61ee7ee203923..2384b322c50f92 100644 --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -512,3 +512,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 3b418585ab4a39..3544ea64cb5e77 100644 --- a/clang/lib/Basic/Targets/RISCV.h +++ b/clang/lib/Basic/Targets/RISCV.h @@ -128,8 +128,10 @@ class RISCVTargetInfo : public TargetInfo { } 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 ff7132fd8bc1e7..4b96bdb709c777 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -66,6 +66,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 <utility> @@ -22693,6 +22694,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 Model = llvm::RISCV::getCPUModel(CPUStr); + + // Compare mvendorid. + Value *VendorID = loadRISCVCPUID(0); + Value *Result = + Builder.CreateICmpEQ(VendorID, Builder.getInt32(Model.MVendorID)); + + // Compare marchid. + Value *ArchID = loadRISCVCPUID(1); + Result = Builder.CreateAnd( + Result, Builder.CreateICmpEQ(ArchID, Builder.getInt64(Model.MArchID))); + + // Compare mimpid. + Value *ImpID = loadRISCVCPUID(2); + Result = Builder.CreateAnd( + Result, Builder.CreateICmpEQ(ImpID, Builder.getInt64(Model.MImpID))); + + return Result; +} + Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID, const CallExpr *E, ReturnValueSlot ReturnValue) { @@ -22701,6 +22743,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 fcc1013d7361ec..5c4d76c2267a77 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -4730,6 +4730,8 @@ class CodeGenFunction : public CodeGenTypeCache { 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-error.c b/clang/test/CodeGen/RISCV/builtin-cpu-is-error.c new file mode 100644 index 00000000000000..ce5e1420f7f456 --- /dev/null +++ b/clang/test/CodeGen/RISCV/builtin-cpu-is-error.c @@ -0,0 +1,7 @@ +// RUN: not %clang_cc1 -triple riscv64-unknown-linux-gnu -emit-llvm %s -o - 2>&1 \ +// RUN: | FileCheck %s + +// CHECK: error: invalid cpu name for builtin +int test_cpu_is_invalid_cpu() { + return __builtin_cpu_is("generic-rv64"); +} 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 00000000000000..3cb3558a751ae3 --- /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/clang/test/Preprocessor/has_builtin_cpuid.c b/clang/test/Preprocessor/has_builtin_cpuid.c index e69f912ce688dd..86cbc6d378a074 100644 --- a/clang/test/Preprocessor/has_builtin_cpuid.c +++ b/clang/test/Preprocessor/has_builtin_cpuid.c @@ -8,8 +8,8 @@ // RUN: -verify %s // expected-no-diagnostics #if __has_builtin(__builtin_cpu_is) -# if defined(ARM) || defined(RISCV) -# error "ARM/RISCV shouldn't have __builtin_cpu_is" +# if defined(ARM) +# error "ARM shouldn't have __builtin_cpu_is" # endif #endif diff --git a/llvm/include/llvm/TargetParser/RISCVTargetParser.h b/llvm/include/llvm/TargetParser/RISCVTargetParser.h index 4a0a602fd80e20..c237e1ddd6b381 100644 --- a/llvm/include/llvm/TargetParser/RISCVTargetParser.h +++ b/llvm/include/llvm/TargetParser/RISCVTargetParser.h @@ -60,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/TargetParser/RISCVTargetParser.cpp b/llvm/lib/TargetParser/RISCVTargetParser.cpp index f4d09d1e302408..625645a99e12fc 100644 --- a/llvm/lib/TargetParser/RISCVTargetParser.cpp +++ b/llvm/lib/TargetParser/RISCVTargetParser.cpp @@ -57,6 +57,18 @@ bool hasFastVectorUnalignedAccess(StringRef CPU) { return Info && Info->FastVectorUnalignedAccess; } +bool hasValidCPUModel(StringRef CPU) { + const CPUModel Model = getCPUModel(CPU); + return Model.MVendorID != 0 && Model.MArchID != 0 && Model.MImpID != 0; +} + +CPUModel getCPUModel(StringRef CPU) { + const CPUInfo *Info = getCPUInfoByName(CPU); + if (!Info) + return {0, 0, 0}; + return Info->Model; +} + bool parseCPU(StringRef CPU, bool IsRV64) { const CPUInfo *Info = getCPUInfoByName(CPU); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits