https://github.com/preames updated https://github.com/llvm/llvm-project/pull/99700
>From ddf2c58a864576586b89cc611e2bea15b8cf18ba Mon Sep 17 00:00:00 2001 From: Philip Reames <prea...@rivosinc.com> Date: Fri, 19 Jul 2024 10:46:19 -0700 Subject: [PATCH 1/3] [WIP][RISCV] Support __builtin_cpu_init and __builtin_cpu_supports This implements the __builtin_cpu_init and __builtin_cpu_supports builtin routines based on the compiler runtime changes in https://github.com/llvm/llvm-project/pull/85790. This is inspired by https://github.com/llvm/llvm-project/pull/85786. Major changes are a) a restriction in scope to only the builtins (which have a much narrower user interface), and the avoidance of false generality. This change deliberately only handles group 0 extensions (which happen to be all defined ones today), and avoids the tblgen changes from that review. This is still a WIP. It is posted for initial feedback on whether this makes sense to try to get into 19.x release. Major items left undone: * Updating clang tests to exercise this logic. * Actually running it at all. I did not build compiler-rt, and thus all my checking was of generated asm/IR. * Investigate claims from gcc docs that __builtin_cpu_init is called early in process lifetime with high priority constructor. I did not find this with some quick searching. --- clang/lib/Basic/Targets/RISCV.cpp | 6 ++ clang/lib/Basic/Targets/RISCV.h | 4 ++ clang/lib/CodeGen/CGBuiltin.cpp | 55 +++++++++++++++++ clang/lib/CodeGen/CodeGenFunction.h | 3 + llvm/include/llvm/TargetParser/RISCVISAInfo.h | 4 ++ llvm/lib/TargetParser/RISCVISAInfo.cpp | 61 +++++++++++++++++++ 6 files changed, 133 insertions(+) diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp index 9159162f01d1b..41d836330b38c 100644 --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -479,3 +479,9 @@ RISCVTargetInfo::checkCallingConvention(CallingConv CC) const { return CCCR_OK; } } + +bool RISCVTargetInfo::validateCpuSupports(StringRef Feature) const { + // Only allow extensions we have a known bit position for in the + // __riscv_feature_bits structure. + return -1 != llvm::RISCVISAInfo::getRISCVFeaturesBitPosition(Feature); +} diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h index d5df6344bedc0..626274b8fc437 100644 --- a/clang/lib/Basic/Targets/RISCV.h +++ b/clang/lib/Basic/Targets/RISCV.h @@ -126,6 +126,10 @@ class RISCVTargetInfo : public TargetInfo { std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override { return std::make_pair(32, 32); } + + bool supportsCpuSupports() const override { return getTriple().isOSLinux(); } + bool supportsCpuInit() const override { return getTriple().isOSLinux(); } + bool validateCpuSupports(StringRef Feature) const override; }; class LLVM_LIBRARY_VISIBILITY RISCV32TargetInfo : public RISCVTargetInfo { public: diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 2ad62d6ee0bb2..71c947776adf2 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -62,6 +62,8 @@ #include "llvm/Support/MathExtras.h" #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> @@ -14215,6 +14217,16 @@ Value *CodeGenFunction::EmitAArch64CpuInit() { return Builder.CreateCall(Func); } +Value *CodeGenFunction::EmitRISCVCpuInit() { + llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false); + llvm::FunctionCallee Func = + CGM.CreateRuntimeFunction(FTy, "__init_riscv_feature_bits"); + auto *CalleeGV = cast<llvm::GlobalValue>(Func.getCallee()); + CalleeGV->setDSOLocal(true); + CalleeGV->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass); + return Builder.CreateCall(Func); +} + Value *CodeGenFunction::EmitX86CpuInit() { llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, /*Variadic*/ false); @@ -14267,6 +14279,43 @@ CodeGenFunction::EmitAArch64CpuSupports(ArrayRef<StringRef> FeaturesStrs) { return Result; } +Value *CodeGenFunction::EmitRISCVCpuSupports(const CallExpr *E) { + + const Expr *FeatureExpr = E->getArg(0)->IgnoreParenCasts(); + StringRef FeatureStr = cast<StringLiteral>(FeatureExpr)->getString(); + if (!getContext().getTargetInfo().validateCpuSupports(FeatureStr)) + return Builder.getFalse(); + + // Note: We are making an unchecked assumption that the size of the + // feature array is >= 1. This holds for any version of compiler-rt + // which defines this interface. + llvm::ArrayType *ArrayOfInt64Ty = + llvm::ArrayType::get(Int64Ty, 1); + llvm::Type *StructTy = llvm::StructType::get(Int32Ty, ArrayOfInt64Ty); + llvm::Constant *RISCVFeaturesBits = + CGM.CreateRuntimeVariable(StructTy, "__riscv_feature_bits"); + auto *GV = cast<llvm::GlobalValue>(RISCVFeaturesBits); + GV->setDSOLocal(true); + + auto LoadFeatureBit = [&](unsigned Index) { + // Create GEP then load. + Value *IndexVal = llvm::ConstantInt::get(Int32Ty, Index); + llvm::Value *GEPIndices[] = {Builder.getInt32(0), Builder.getInt32(1), + IndexVal}; + Value *Ptr = + Builder.CreateInBoundsGEP(StructTy, RISCVFeaturesBits, GEPIndices); + Value *FeaturesBit = + Builder.CreateAlignedLoad(Int64Ty, Ptr, CharUnits::fromQuantity(8)); + return FeaturesBit; + }; + + int BitPos = RISCVISAInfo::getRISCVFeaturesBitPosition(FeatureStr); + assert(BitPos != -1 && "validation should have rejected this feature"); + Value *MaskV = Builder.getInt64(1ULL << BitPos); + Value *Bitset = Builder.CreateAnd(LoadFeatureBit(0), MaskV); + return Builder.CreateICmpEQ(Bitset, MaskV); +} + Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, const CallExpr *E) { if (BuiltinID == Builtin::BI__builtin_cpu_is) @@ -21728,6 +21777,12 @@ Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID, Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID, const CallExpr *E, ReturnValueSlot ReturnValue) { + + if (BuiltinID == Builtin::BI__builtin_cpu_supports) + return EmitRISCVCpuSupports(E); + if (BuiltinID == Builtin::BI__builtin_cpu_init) + return EmitRISCVCpuInit(); + 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 d83e38cab8e2d..1ee45a1f1f99d 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -4695,6 +4695,9 @@ class CodeGenFunction : public CodeGenTypeCache { llvm::Value *EmitRISCVBuiltinExpr(unsigned BuiltinID, const CallExpr *E, ReturnValueSlot ReturnValue); + llvm::Value *EmitRISCVCpuSupports(const CallExpr *E); + llvm::Value *EmitRISCVCpuInit(); + void AddAMDGPUFenceAddressSpaceMMRA(llvm::Instruction *Inst, const CallExpr *E); void ProcessOrderScopeAMDGCN(llvm::Value *Order, llvm::Value *Scope, diff --git a/llvm/include/llvm/TargetParser/RISCVISAInfo.h b/llvm/include/llvm/TargetParser/RISCVISAInfo.h index d7a08013fa6ac..d71ff174bf0d2 100644 --- a/llvm/include/llvm/TargetParser/RISCVISAInfo.h +++ b/llvm/include/llvm/TargetParser/RISCVISAInfo.h @@ -80,6 +80,10 @@ class RISCVISAInfo { std::set<StringRef> &EnabledFeatureNames, StringMap<StringRef> &DescMap); + /// Return the bit position (in group 0) of __riscv_feature_bits. Returns + /// -1 if not supported. + static int getRISCVFeaturesBitPosition(StringRef Ext); + private: RISCVISAInfo(unsigned XLen) : XLen(XLen) {} diff --git a/llvm/lib/TargetParser/RISCVISAInfo.cpp b/llvm/lib/TargetParser/RISCVISAInfo.cpp index e6ddbb4dc28d5..3ff1b325793e6 100644 --- a/llvm/lib/TargetParser/RISCVISAInfo.cpp +++ b/llvm/lib/TargetParser/RISCVISAInfo.cpp @@ -1020,3 +1020,64 @@ std::string RISCVISAInfo::getTargetFeatureForExtension(StringRef Ext) { return isExperimentalExtension(Name) ? "experimental-" + Name.str() : Name.str(); } + +struct RISCVExtBit { + const StringRef ext; + uint64_t bitpos; +}; + +/// Maps extensions with assigned bit positions within group 0 of +/// __riscv_features_bits to their respective bit position. At the +/// moment all extensions are within group 0. +static RISCVExtBit RISCVGroup0BitPositions[] = { + {"a", 0}, + {"c", 2}, + {"d", 3}, + {"f", 5}, + {"i", 8}, + {"m", 12}, + {"v", 21}, + {"zacas", 26}, + {"zba", 27}, + {"zbb", 28}, + {"zbc", 29}, + {"zbkb", 30}, + {"zbkc", 31}, + {"zbkx", 32}, + {"zbs", 33}, + {"zfa", 34}, + {"zfh", 35}, + {"zfhmin", 36}, + {"zicboz", 37}, + {"zicond", 38}, + {"zihintntl", 39}, + {"zihintpause", 40}, + {"zknd", 41}, + {"zkne", 42}, + {"zknh", 43}, + {"zksed", 44}, + {"zksh", 45}, + {"zkt", 46}, + {"ztso", 47}, + {"zvbb", 48}, + {"zvbc", 49}, + {"zvfh", 50}, + {"zvfhmin", 51}, + {"zvkb", 52}, + {"zvkg", 53}, + {"zvkned", 54}, + {"zvknha", 55}, + {"zvknhb", 56}, + {"zvksed", 57}, + {"zvksh", 58}, + {"zvkt", 59} +}; +int RISCVISAInfo::getRISCVFeaturesBitPosition(StringRef Ext) { + // Note that this code currently accepts mixed case extension names, but + // does not handle extension versions at all. That's probably fine because + // there's only one extension version in the __riscv_feature_bits vector. + for (auto E : RISCVGroup0BitPositions) + if (E.ext.equals_insensitive(Ext)) + return E.bitpos; + return -1; +} >From 1be1e5e3fb4b191de78a3d9176036b066476129c Mon Sep 17 00:00:00 2001 From: Philip Reames <prea...@rivosinc.com> Date: Fri, 19 Jul 2024 13:32:29 -0700 Subject: [PATCH 2/3] Clang format fix --- clang/lib/CodeGen/CGBuiltin.cpp | 3 +- llvm/lib/TargetParser/RISCVISAInfo.cpp | 63 +++++++++----------------- 2 files changed, 22 insertions(+), 44 deletions(-) diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 71c947776adf2..25dbe221325cc 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -14289,8 +14289,7 @@ Value *CodeGenFunction::EmitRISCVCpuSupports(const CallExpr *E) { // Note: We are making an unchecked assumption that the size of the // feature array is >= 1. This holds for any version of compiler-rt // which defines this interface. - llvm::ArrayType *ArrayOfInt64Ty = - llvm::ArrayType::get(Int64Ty, 1); + llvm::ArrayType *ArrayOfInt64Ty = llvm::ArrayType::get(Int64Ty, 1); llvm::Type *StructTy = llvm::StructType::get(Int32Ty, ArrayOfInt64Ty); llvm::Constant *RISCVFeaturesBits = CGM.CreateRuntimeVariable(StructTy, "__riscv_feature_bits"); diff --git a/llvm/lib/TargetParser/RISCVISAInfo.cpp b/llvm/lib/TargetParser/RISCVISAInfo.cpp index 3ff1b325793e6..7a5b10a877ebe 100644 --- a/llvm/lib/TargetParser/RISCVISAInfo.cpp +++ b/llvm/lib/TargetParser/RISCVISAInfo.cpp @@ -1030,48 +1030,27 @@ struct RISCVExtBit { /// __riscv_features_bits to their respective bit position. At the /// moment all extensions are within group 0. static RISCVExtBit RISCVGroup0BitPositions[] = { - {"a", 0}, - {"c", 2}, - {"d", 3}, - {"f", 5}, - {"i", 8}, - {"m", 12}, - {"v", 21}, - {"zacas", 26}, - {"zba", 27}, - {"zbb", 28}, - {"zbc", 29}, - {"zbkb", 30}, - {"zbkc", 31}, - {"zbkx", 32}, - {"zbs", 33}, - {"zfa", 34}, - {"zfh", 35}, - {"zfhmin", 36}, - {"zicboz", 37}, - {"zicond", 38}, - {"zihintntl", 39}, - {"zihintpause", 40}, - {"zknd", 41}, - {"zkne", 42}, - {"zknh", 43}, - {"zksed", 44}, - {"zksh", 45}, - {"zkt", 46}, - {"ztso", 47}, - {"zvbb", 48}, - {"zvbc", 49}, - {"zvfh", 50}, - {"zvfhmin", 51}, - {"zvkb", 52}, - {"zvkg", 53}, - {"zvkned", 54}, - {"zvknha", 55}, - {"zvknhb", 56}, - {"zvksed", 57}, - {"zvksh", 58}, - {"zvkt", 59} -}; + {"a", 0}, {"c", 2}, + {"d", 3}, {"f", 5}, + {"i", 8}, {"m", 12}, + {"v", 21}, {"zacas", 26}, + {"zba", 27}, {"zbb", 28}, + {"zbc", 29}, {"zbkb", 30}, + {"zbkc", 31}, {"zbkx", 32}, + {"zbs", 33}, {"zfa", 34}, + {"zfh", 35}, {"zfhmin", 36}, + {"zicboz", 37}, {"zicond", 38}, + {"zihintntl", 39}, {"zihintpause", 40}, + {"zknd", 41}, {"zkne", 42}, + {"zknh", 43}, {"zksed", 44}, + {"zksh", 45}, {"zkt", 46}, + {"ztso", 47}, {"zvbb", 48}, + {"zvbc", 49}, {"zvfh", 50}, + {"zvfhmin", 51}, {"zvkb", 52}, + {"zvkg", 53}, {"zvkned", 54}, + {"zvknha", 55}, {"zvknhb", 56}, + {"zvksed", 57}, {"zvksh", 58}, + {"zvkt", 59}}; int RISCVISAInfo::getRISCVFeaturesBitPosition(StringRef Ext) { // Note that this code currently accepts mixed case extension names, but // does not handle extension versions at all. That's probably fine because >From 2f261105201bae7166eefd3fc67e3e864cd7df31 Mon Sep 17 00:00:00 2001 From: Philip Reames <prea...@rivosinc.com> Date: Mon, 22 Jul 2024 07:29:31 -0700 Subject: [PATCH 3/3] Address review comments --- clang/lib/CodeGen/CGBuiltin.cpp | 1 - llvm/lib/TargetParser/RISCVISAInfo.cpp | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 25dbe221325cc..96a0887284c21 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -63,7 +63,6 @@ #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> diff --git a/llvm/lib/TargetParser/RISCVISAInfo.cpp b/llvm/lib/TargetParser/RISCVISAInfo.cpp index 7a5b10a877ebe..48b0536f3b886 100644 --- a/llvm/lib/TargetParser/RISCVISAInfo.cpp +++ b/llvm/lib/TargetParser/RISCVISAInfo.cpp @@ -1023,7 +1023,7 @@ std::string RISCVISAInfo::getTargetFeatureForExtension(StringRef Ext) { struct RISCVExtBit { const StringRef ext; - uint64_t bitpos; + uint8_t bitpos; }; /// Maps extensions with assigned bit positions within group 0 of _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits