https://github.com/BeMg updated https://github.com/llvm/llvm-project/pull/85786
>From 239b404203c66ab5336ffdfb45969a50c439a1c0 Mon Sep 17 00:00:00 2001 From: Piyou Chen <piyou.c...@sifive.com> Date: Tue, 19 Mar 2024 06:22:17 -0700 Subject: [PATCH 01/10] [RISCV][FMV] Support target_clones --- clang/include/clang/Basic/TargetInfo.h | 3 +- clang/lib/AST/ASTContext.cpp | 9 ++ clang/lib/Basic/Targets/RISCV.cpp | 10 +- clang/lib/Basic/Targets/RISCV.h | 2 + clang/lib/CodeGen/CodeGenFunction.cpp | 102 ++++++++++++- clang/lib/CodeGen/CodeGenFunction.h | 3 + clang/lib/CodeGen/CodeGenModule.cpp | 2 + clang/lib/CodeGen/Targets/RISCV.cpp | 23 +++ clang/lib/Sema/SemaDeclAttr.cpp | 22 +++ clang/test/CodeGen/attr-target-clones-riscv.c | 135 +++++++++++++++++ .../CodeGenCXX/attr-target-clones-riscv.cpp | 136 ++++++++++++++++++ .../test/SemaCXX/attr-target-clones-riscv.cpp | 19 +++ 12 files changed, 462 insertions(+), 4 deletions(-) create mode 100644 clang/test/CodeGen/attr-target-clones-riscv.c create mode 100644 clang/test/CodeGenCXX/attr-target-clones-riscv.cpp create mode 100644 clang/test/SemaCXX/attr-target-clones-riscv.cpp diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index 374595edd2ce4a..aa48596fbce07d 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -1445,7 +1445,8 @@ class TargetInfo : public TransferrableTargetInfo, /// Identify whether this target supports multiversioning of functions, /// which requires support for cpu_supports and cpu_is functionality. bool supportsMultiVersioning() const { - return getTriple().isX86() || getTriple().isAArch64(); + return getTriple().isX86() || getTriple().isAArch64() || + getTriple().isRISCV(); } /// Identify whether this target supports IFuncs. diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 5a8fae76a43a4d..0fd75e0b36b123 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -13636,6 +13636,15 @@ void ASTContext::getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap, Features.insert(Features.begin(), Target->getTargetOpts().FeaturesAsWritten.begin(), Target->getTargetOpts().FeaturesAsWritten.end()); + } else if (Target->getTriple().isRISCV()) { + if (VersionStr != "default") { + ParsedTargetAttr ParsedAttr = Target->parseTargetAttr(VersionStr); + Features.insert(Features.begin(), ParsedAttr.Features.begin(), + ParsedAttr.Features.end()); + } + Features.insert(Features.begin(), + Target->getTargetOpts().FeaturesAsWritten.begin(), + Target->getTargetOpts().FeaturesAsWritten.end()); } else { if (VersionStr.starts_with("arch=")) TargetCPU = VersionStr.drop_front(sizeof("arch=") - 1); diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp index a6d4af2b88111a..8e9132c9191a3c 100644 --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -257,7 +257,7 @@ bool RISCVTargetInfo::initFeatureMap( // If a target attribute specified a full arch string, override all the ISA // extension target features. - const auto I = llvm::find(FeaturesVec, "__RISCV_TargetAttrNeedOverride"); + const auto I = llvm::find(FeaturesVec, "+__RISCV_TargetAttrNeedOverride"); if (I != FeaturesVec.end()) { std::vector<std::string> OverrideFeatures(std::next(I), FeaturesVec.end()); @@ -366,6 +366,12 @@ bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, return true; } +bool RISCVTargetInfo::isValidFeatureName(StringRef Feature) const { + if (Feature.starts_with("__RISCV_TargetAttrNeedOverride")) + return true; + return llvm::RISCVISAInfo::isSupportedExtensionFeature(Feature); +} + bool RISCVTargetInfo::isValidCPUName(StringRef Name) const { bool Is64Bit = getTriple().isArch64Bit(); return llvm::RISCV::parseCPU(Name, Is64Bit); @@ -390,7 +396,7 @@ void RISCVTargetInfo::fillValidTuneCPUList( static void handleFullArchString(StringRef FullArchStr, std::vector<std::string> &Features) { - Features.push_back("__RISCV_TargetAttrNeedOverride"); + Features.push_back("+__RISCV_TargetAttrNeedOverride"); auto RII = llvm::RISCVISAInfo::parseArchString( FullArchStr, /* EnableExperimentalExtension */ true); if (llvm::errorToBool(RII.takeError())) { diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h index bfbdafb682c851..ef8f59185d753c 100644 --- a/clang/lib/Basic/Targets/RISCV.h +++ b/clang/lib/Basic/Targets/RISCV.h @@ -106,6 +106,8 @@ class RISCVTargetInfo : public TargetInfo { bool handleTargetFeatures(std::vector<std::string> &Features, DiagnosticsEngine &Diags) override; + bool isValidFeatureName(StringRef Feature) const override; + bool hasBitIntType() const override { return true; } bool hasBFloat16Type() const override { return true; } diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 4a3ff49b0007a3..544c696376cd89 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -2803,12 +2803,112 @@ void CodeGenFunction::EmitMultiVersionResolver( case llvm::Triple::aarch64: EmitAArch64MultiVersionResolver(Resolver, Options); return; + case llvm::Triple::riscv32: + case llvm::Triple::riscv64: + EmitRISCVMultiVersionResolver(Resolver, Options); + return; default: - assert(false && "Only implemented for x86 and AArch64 targets"); + assert(false && "Only implemented for x86, AArch64 and RISC-V targets"); } } +void CodeGenFunction::EmitRISCVMultiVersionResolver( + llvm::Function *Resolver, ArrayRef<MultiVersionResolverOption> Options) { + + auto EmitIFUNCFeatureCheckFunc = + [&](std::string CurrFeatStr) -> llvm::Value * { + llvm::Constant *FeatStr = Builder.CreateGlobalString(CurrFeatStr); + llvm::Type *Args[] = {Int8PtrTy}; + llvm::FunctionType *FTy = + llvm::FunctionType::get(Builder.getInt1Ty(), Args, /*Variadic*/ false); + llvm::FunctionCallee Func = + CGM.CreateRuntimeFunction(FTy, "__riscv_ifunc_select"); + cast<llvm::GlobalValue>(Func.getCallee())->setDSOLocal(true); + cast<llvm::GlobalValue>(Func.getCallee()) + ->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass); + return Builder.CreateCall(Func, FeatStr); + }; + + llvm::BasicBlock *CurBlock = createBasicBlock("resolver_entry", Resolver); + Builder.SetInsertPoint(CurBlock); + + bool SupportsIFunc = getContext().getTargetInfo().supportsIFunc(); + bool HasDefault = false; + int DefaultIndex = 0; + // Check the each candidate function. + for (unsigned Index = 0; Index < Options.size(); Index++) { + + if (Options[Index].Conditions.Features[0].starts_with("default")) { + HasDefault = true; + DefaultIndex = Index; + continue; + } + + Builder.SetInsertPoint(CurBlock); + + std::vector<std::string> TargetAttrFeats = + getContext() + .getTargetInfo() + .parseTargetAttr(Options[Index].Conditions.Features[0]) + .Features; + + if (!TargetAttrFeats.empty()) { + // If this function doens't need override, then merge with module level + // target features. Otherwise, remain the current target features. + auto I = llvm::find(TargetAttrFeats, "+__RISCV_TargetAttrNeedOverride"); + if (I == TargetAttrFeats.end()) + TargetAttrFeats.insert(TargetAttrFeats.begin(), + Target.getTargetOpts().FeaturesAsWritten.begin(), + Target.getTargetOpts().FeaturesAsWritten.end()); + else + TargetAttrFeats.erase(I); + + // Only consider +<extension-feature>. + std::vector<std::string> PlusTargetAttrFeats; + for (StringRef Feat : TargetAttrFeats) { + if (!getContext().getTargetInfo().isValidFeatureName( + Feat.substr(1).str())) + continue; + if (Feat.starts_with("+")) + PlusTargetAttrFeats.push_back(Feat.substr(1).str()); + } + + // Join with ';' delimiter + std::string CurrFeatStr = std::accumulate( + std::begin(PlusTargetAttrFeats), std::end(PlusTargetAttrFeats), + std::string(), [](const std::string &a, const std::string &b) { + return a.empty() ? b : a + ";" + b; + }); + + llvm::Value *Condition = EmitIFUNCFeatureCheckFunc(CurrFeatStr); + llvm::BasicBlock *RetBlock = + createBasicBlock("resolver_return", Resolver); + CGBuilderTy RetBuilder(*this, RetBlock); + CreateMultiVersionResolverReturn(CGM, Resolver, RetBuilder, + Options[Index].Function, SupportsIFunc); + CurBlock = createBasicBlock("resolver_else", Resolver); + Builder.CreateCondBr(Condition, RetBlock, CurBlock); + } + } + + // Finally, emit the default one. + if (HasDefault) { + Builder.SetInsertPoint(CurBlock); + CreateMultiVersionResolverReturn( + CGM, Resolver, Builder, Options[DefaultIndex].Function, SupportsIFunc); + return; + } + + // If no generic/default, emit an unreachable. + Builder.SetInsertPoint(CurBlock); + llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap); + TrapCall->setDoesNotReturn(); + TrapCall->setDoesNotThrow(); + Builder.CreateUnreachable(); + Builder.ClearInsertionPoint(); +} + void CodeGenFunction::EmitAArch64MultiVersionResolver( llvm::Function *Resolver, ArrayRef<MultiVersionResolverOption> Options) { assert(!Options.empty() && "No multiversion resolver options found"); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index e8f8aa601ed017..e62657de7b7323 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -5013,6 +5013,9 @@ class CodeGenFunction : public CodeGenTypeCache { void EmitAArch64MultiVersionResolver(llvm::Function *Resolver, ArrayRef<MultiVersionResolverOption> Options); + void + EmitRISCVMultiVersionResolver(llvm::Function *Resolver, + ArrayRef<MultiVersionResolverOption> Options); private: QualType getVarArgType(const Expr *Arg); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 8ceecff28cbc63..e571dbb384b78d 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -4161,6 +4161,8 @@ void CodeGenModule::emitMultiVersionFunctions() { for (auto &CurFeat : VerFeats) Feature.push_back(CurFeat.trim()); } + } else if (getTarget().getTriple().isRISCV()) { + Feature.push_back(Version); } else { if (Version.starts_with("arch=")) Architecture = Version.drop_front(sizeof("arch=") - 1); diff --git a/clang/lib/CodeGen/Targets/RISCV.cpp b/clang/lib/CodeGen/Targets/RISCV.cpp index 9a79424c4612ce..30c10c35133161 100644 --- a/clang/lib/CodeGen/Targets/RISCV.cpp +++ b/clang/lib/CodeGen/Targets/RISCV.cpp @@ -63,9 +63,32 @@ class RISCVABIInfo : public DefaultABIInfo { CharUnits Field2Off) const; ABIArgInfo coerceVLSVector(QualType Ty) const; + + using ABIInfo::appendAttributeMangling; + void appendAttributeMangling(TargetClonesAttr *Attr, unsigned Index, + raw_ostream &Out) const override; + void appendAttributeMangling(StringRef AttrStr, + raw_ostream &Out) const override; }; } // end anonymous namespace +void RISCVABIInfo::appendAttributeMangling(TargetClonesAttr *Attr, + unsigned Index, + raw_ostream &Out) const { + appendAttributeMangling(Attr->getFeatureStr(Index), Out); +} + +void RISCVABIInfo::appendAttributeMangling(StringRef AttrStr, + raw_ostream &Out) const { + if (AttrStr == "default") { + Out << ".default"; + return; + } + + Out << '.'; + Out << AttrStr; +} + void RISCVABIInfo::computeInfo(CGFunctionInfo &FI) const { QualType RetTy = FI.getReturnType(); if (!getCXXABI().classifyReturnType(FI)) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index ec00fdf3f88d9e..9e44e6a3b70734 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3626,6 +3626,28 @@ bool Sema::checkTargetClonesAttrString( if (hasArmStreamingInterface(cast<FunctionDecl>(D))) return Diag(LiteralLoc, diag::err_sme_streaming_cannot_be_multiversioned); + } else if (TInfo.getTriple().isRISCV()) { + if (Str.starts_with("arch=")) { + // parseTargetAttr will parse full version string, + // the following split Cur string is no longer interesting. + if ((!Cur.starts_with("arch="))) + continue; + + ParsedTargetAttr TargetAttr = + Context.getTargetInfo().parseTargetAttr(Str); + if (TargetAttr.Features.empty()) + return Diag(CurLoc, diag::warn_unsupported_target_attribute) + << Unsupported << None << Str << TargetClones; + } else if (Str == "default") { + DefaultIsDupe = HasDefault; + HasDefault = true; + } else { + return Diag(CurLoc, diag::warn_unsupported_target_attribute) + << Unsupported << None << Str << TargetClones; + } + if (llvm::is_contained(StringsBuffer, Str) || DefaultIsDupe) + Diag(CurLoc, diag::warn_target_clone_duplicate_options); + StringsBuffer.push_back(Str); } else { // Other targets ( currently X86 ) if (Cur.starts_with("arch=")) { diff --git a/clang/test/CodeGen/attr-target-clones-riscv.c b/clang/test/CodeGen/attr-target-clones-riscv.c new file mode 100644 index 00000000000000..70b74befb54ffb --- /dev/null +++ b/clang/test/CodeGen/attr-target-clones-riscv.c @@ -0,0 +1,135 @@ +// RUN: %clang_cc1 -triple riscv64-linux-gnu -target-feature +i -S -emit-llvm -o - %s | FileCheck %s + +__attribute__((target_clones("default", "arch=rv64gc"))) int foo1(void) { return 1; } +__attribute__((target_clones("default", "arch=+zbb"))) int foo2(void) { return 2; } +__attribute__((target_clones("default", "arch=+zbb,+c"))) int foo3(void) { return 3; } +__attribute__((target_clones("default", "arch=rv64gc", "arch=+zbb,+v"))) int foo4(void) { return 4; } +__attribute__((target_clones("default"))) int foo5(void) { return 5; } + +int bar() { + return foo1() + foo2() + foo3() + foo4(); +} + +//. +// CHECK: @[[GLOB0:[0-9]+]] = private unnamed_addr constant [25 x i8] c"m;a;f;d;c;zicsr;zifencei\00", align 1 +// CHECK: @[[GLOB1:[0-9]+]] = private unnamed_addr constant [6 x i8] c"i;zbb\00", align 1 +// CHECK: @[[GLOB2:[0-9]+]] = private unnamed_addr constant [8 x i8] c"i;zbb;c\00", align 1 +// CHECK: @[[GLOB3:[0-9]+]] = private unnamed_addr constant [25 x i8] c"m;a;f;d;c;zicsr;zifencei\00", align 1 +// CHECK: @[[GLOB4:[0-9]+]] = private unnamed_addr constant [8 x i8] c"i;zbb;v\00", align 1 +// CHECK: @foo1.ifunc = weak_odr alias i32 (), ptr @foo1 +// CHECK: @foo2.ifunc = weak_odr alias i32 (), ptr @foo2 +// CHECK: @foo3.ifunc = weak_odr alias i32 (), ptr @foo3 +// CHECK: @foo4.ifunc = weak_odr alias i32 (), ptr @foo4 +// CHECK: @foo5.ifunc = weak_odr alias i32 (), ptr @foo5 +// CHECK: @foo1 = weak_odr ifunc i32 (), ptr @foo1.resolver +// CHECK: @foo2 = weak_odr ifunc i32 (), ptr @foo2.resolver +// CHECK: @foo3 = weak_odr ifunc i32 (), ptr @foo3.resolver +// CHECK: @foo4 = weak_odr ifunc i32 (), ptr @foo4.resolver +// CHECK: @foo5 = weak_odr ifunc i32 (), ptr @foo5.resolver +//. +// CHECK-LABEL: define dso_local signext i32 @foo1.default( +// CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 1 +// +// +// CHECK-LABEL: define weak_odr ptr @foo1.resolver() comdat { +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(ptr @[[GLOB0]]) +// CHECK-NEXT: br i1 [[TMP0]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] +// CHECK: resolver_return: +// CHECK-NEXT: ret ptr @"foo1.arch=rv64gc" +// CHECK: resolver_else: +// CHECK-NEXT: ret ptr @foo1.default +// +// +// CHECK-LABEL: define dso_local signext i32 @foo2.default( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 2 +// +// +// CHECK-LABEL: define weak_odr ptr @foo2.resolver() comdat { +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(ptr @[[GLOB1]]) +// CHECK-NEXT: br i1 [[TMP0]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] +// CHECK: resolver_return: +// CHECK-NEXT: ret ptr @"foo2.arch=+zbb" +// CHECK: resolver_else: +// CHECK-NEXT: ret ptr @foo2.default +// +// +// CHECK-LABEL: define dso_local signext i32 @foo3.default( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 3 +// +// +// CHECK-LABEL: define weak_odr ptr @foo3.resolver() comdat { +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(ptr @[[GLOB2]]) +// CHECK-NEXT: br i1 [[TMP0]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] +// CHECK: resolver_return: +// CHECK-NEXT: ret ptr @"foo3.arch=+zbb,+c" +// CHECK: resolver_else: +// CHECK-NEXT: ret ptr @foo3.default +// +// +// CHECK-LABEL: define dso_local signext i32 @foo4.default( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 4 +// +// +// CHECK-LABEL: define weak_odr ptr @foo4.resolver() comdat { +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(ptr @[[GLOB3]]) +// CHECK-NEXT: br i1 [[TMP0]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] +// CHECK: resolver_return: +// CHECK-NEXT: ret ptr @"foo4.arch=rv64gc" +// CHECK: resolver_else: +// CHECK-NEXT: [[TMP1:%.*]] = call i1 @__riscv_ifunc_select(ptr @[[GLOB4]]) +// CHECK-NEXT: br i1 [[TMP1]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]] +// CHECK: resolver_return1: +// CHECK-NEXT: ret ptr @"foo4.arch=+zbb,+v" +// CHECK: resolver_else2: +// CHECK-NEXT: ret ptr @foo4.default +// +// +// CHECK-LABEL: define dso_local signext i32 @foo5.default( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 5 +// +// +// CHECK-LABEL: define weak_odr ptr @foo5.resolver() comdat { +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: ret ptr @foo5.default +// +// +// CHECK-LABEL: define dso_local signext i32 @bar( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[CALL:%.*]] = call signext i32 @foo1() +// CHECK-NEXT: [[CALL1:%.*]] = call signext i32 @foo2() +// CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CALL]], [[CALL1]] +// CHECK-NEXT: [[CALL2:%.*]] = call signext i32 @foo3() +// CHECK-NEXT: [[ADD3:%.*]] = add nsw i32 [[ADD]], [[CALL2]] +// CHECK-NEXT: [[CALL4:%.*]] = call signext i32 @foo4() +// CHECK-NEXT: [[ADD5:%.*]] = add nsw i32 [[ADD3]], [[CALL4]] +// CHECK-NEXT: ret i32 [[ADD5]] +// +//. +// CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+i" } +// CHECK: attributes #[[ATTR1:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+a,+c,+d,+f,+m,+zicsr,+zifencei,-e,-experimental-smmpm,-experimental-smnpm,-experimental-ssnpm,-experimental-sspm,-experimental-ssqosid,-experimental-supm,-experimental-zaamo,-experimental-zabha,-experimental-zalasr,-experimental-zalrsc,-experimental-zcmop,-experimental-zfbfmin,-experimental-zicfilp,-experimental-zicfiss,-experimental-zimop,-experimental-ztso,-experimental-zvfbfmin,-experimental-zvfbfwma,-h,-shcounterenw,-shgatpa,-shtvala,-shvsatpa,-shvstvala,-shvstvecd,-smaia,-smepmp,-ssaia,-ssccptr,-sscofpmf,-sscounterenw,-ssstateen,-ssstrict,-sstc,-sstvala,-sstvecd,-ssu64xl,-svade,-svadu,-svbare,-svinval,-svnapot,-svpbmt,-v,-xcvalu,-xcvbi,-xcvbitmanip,-xcvelw,-xcvmac,-xcvmem,-xcvsimd,-xsfcease,-xsfvcp,-xsfvfnrclipxfqf,-xsfvfwmaccqqq,-xsfvqmaccdod,-xsfvqmaccqoq,-xsifivecdiscarddlone,-xsifivecflushdlone,-xtheadba,-xtheadbb,-xtheadbs,-xtheadcmo,-xtheadcondmov,-xtheadfmemidx,-xtheadmac,-xtheadmemidx,-xtheadmempair,-xtheadsync,-xtheadvdot,-xventanacondops,-za128rs,-za64rs,-zacas,-zawrs,-zba,-zbb,-zbc,-zbkb,-zbkc,-zbkx,-zbs,-zca,-zcb,-zcd,-zce,-zcf,-zcmp,-zcmt,-zdinx,-zfa,-zfh,-zfhmin,-zfinx,-zhinx,-zhinxmin,-zic64b,-zicbom,-zicbop,-zicboz,-ziccamoa,-ziccif,-zicclsm,-ziccrse,-zicntr,-zicond,-zihintntl,-zihintpause,-zihpm,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-zmmul,-zvbb,-zvbc,-zve32f,-zve32x,-zve64d,-zve64f,-zve64x,-zvfh,-zvfhmin,-zvkb,-zvkg,-zvkn,-zvknc,-zvkned,-zvkng,-zvknha,-zvknhb,-zvks,-zvksc,-zvksed,-zvksg,-zvksh,-zvkt,-zvl1024b,-zvl128b,-zvl16384b,-zvl2048b,-zvl256b,-zvl32768b,-zvl32b,-zvl4096b,-zvl512b,-zvl64b,-zvl65536b,-zvl8192b" } +// CHECK: attributes #[[ATTR2:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+i,+zbb" } +// CHECK: attributes #[[ATTR3:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+c,+i,+zbb" } +// CHECK: attributes #[[ATTR4:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+d,+f,+i,+v,+zbb,+zicsr,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b" } +//. +// CHECK: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4} +// CHECK: [[META1:![0-9]+]] = !{i32 1, !"target-abi", !"lp64"} +// CHECK: [[META2:![0-9]+]] = !{i32 6, !"riscv-isa", [[META3:![0-9]+]]} +// CHECK: [[META3]] = !{!"rv64i2p1"} +// CHECK: [[META4:![0-9]+]] = !{i32 8, !"SmallDataLimit", i32 0} +// CHECK: [[META5:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"} +//. diff --git a/clang/test/CodeGenCXX/attr-target-clones-riscv.cpp b/clang/test/CodeGenCXX/attr-target-clones-riscv.cpp new file mode 100644 index 00000000000000..12f5d0284504bc --- /dev/null +++ b/clang/test/CodeGenCXX/attr-target-clones-riscv.cpp @@ -0,0 +1,136 @@ +// RUN: %clang_cc1 -std=c++11 -triple riscv64-linux-gnu -target-feature +i -target-feature +m -emit-llvm %s -o - | FileCheck %s + +__attribute__((target_clones("default", "arch=rv64gc"))) int foo1(void) { return 1; } +__attribute__((target_clones("default", "arch=+zbb"))) int foo2(void) { return 2; } +__attribute__((target_clones("default", "arch=+zbb,+c"))) int foo3(void) { return 3; } +__attribute__((target_clones("default", "arch=rv64gc", "arch=+zbb,+v"))) int foo4(void) { return 4; } +__attribute__((target_clones("default"))) int foo5(void) { return 5; } + +int bar() { + return foo1() + foo2() + foo3() + foo4(); +} + + +//. +// CHECK: @[[GLOB0:[0-9]+]] = private unnamed_addr constant [25 x i8] c"m;a;f;d;c;zicsr;zifencei\00", align 1 +// CHECK: @[[GLOB1:[0-9]+]] = private unnamed_addr constant [8 x i8] c"i;m;zbb\00", align 1 +// CHECK: @[[GLOB2:[0-9]+]] = private unnamed_addr constant [10 x i8] c"i;m;zbb;c\00", align 1 +// CHECK: @[[GLOB3:[0-9]+]] = private unnamed_addr constant [25 x i8] c"m;a;f;d;c;zicsr;zifencei\00", align 1 +// CHECK: @[[GLOB4:[0-9]+]] = private unnamed_addr constant [10 x i8] c"i;m;zbb;v\00", align 1 +// CHECK: @_Z4foo1v.ifunc = weak_odr alias i32 (), ptr @_Z4foo1v +// CHECK: @_Z4foo2v.ifunc = weak_odr alias i32 (), ptr @_Z4foo2v +// CHECK: @_Z4foo3v.ifunc = weak_odr alias i32 (), ptr @_Z4foo3v +// CHECK: @_Z4foo4v.ifunc = weak_odr alias i32 (), ptr @_Z4foo4v +// CHECK: @_Z4foo5v.ifunc = weak_odr alias i32 (), ptr @_Z4foo5v +// CHECK: @_Z4foo1v = weak_odr ifunc i32 (), ptr @_Z4foo1v.resolver +// CHECK: @_Z4foo2v = weak_odr ifunc i32 (), ptr @_Z4foo2v.resolver +// CHECK: @_Z4foo3v = weak_odr ifunc i32 (), ptr @_Z4foo3v.resolver +// CHECK: @_Z4foo4v = weak_odr ifunc i32 (), ptr @_Z4foo4v.resolver +// CHECK: @_Z4foo5v = weak_odr ifunc i32 (), ptr @_Z4foo5v.resolver +//. +// CHECK-LABEL: define dso_local noundef signext i32 @_Z4foo1v.default( +// CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 1 +// +// +// CHECK-LABEL: define weak_odr ptr @_Z4foo1v.resolver() comdat { +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(ptr @[[GLOB0]]) +// CHECK-NEXT: br i1 [[TMP0]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] +// CHECK: resolver_return: +// CHECK-NEXT: ret ptr @"_Z4foo1v.arch=rv64gc" +// CHECK: resolver_else: +// CHECK-NEXT: ret ptr @_Z4foo1v.default +// +// +// CHECK-LABEL: define dso_local noundef signext i32 @_Z4foo2v.default( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 2 +// +// +// CHECK-LABEL: define weak_odr ptr @_Z4foo2v.resolver() comdat { +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(ptr @[[GLOB1]]) +// CHECK-NEXT: br i1 [[TMP0]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] +// CHECK: resolver_return: +// CHECK-NEXT: ret ptr @"_Z4foo2v.arch=+zbb" +// CHECK: resolver_else: +// CHECK-NEXT: ret ptr @_Z4foo2v.default +// +// +// CHECK-LABEL: define dso_local noundef signext i32 @_Z4foo3v.default( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 3 +// +// +// CHECK-LABEL: define weak_odr ptr @_Z4foo3v.resolver() comdat { +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(ptr @[[GLOB2]]) +// CHECK-NEXT: br i1 [[TMP0]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] +// CHECK: resolver_return: +// CHECK-NEXT: ret ptr @"_Z4foo3v.arch=+zbb,+c" +// CHECK: resolver_else: +// CHECK-NEXT: ret ptr @_Z4foo3v.default +// +// +// CHECK-LABEL: define dso_local noundef signext i32 @_Z4foo4v.default( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 4 +// +// +// CHECK-LABEL: define weak_odr ptr @_Z4foo4v.resolver() comdat { +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(ptr @[[GLOB3]]) +// CHECK-NEXT: br i1 [[TMP0]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] +// CHECK: resolver_return: +// CHECK-NEXT: ret ptr @"_Z4foo4v.arch=rv64gc" +// CHECK: resolver_else: +// CHECK-NEXT: [[TMP1:%.*]] = call i1 @__riscv_ifunc_select(ptr @[[GLOB4]]) +// CHECK-NEXT: br i1 [[TMP1]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]] +// CHECK: resolver_return1: +// CHECK-NEXT: ret ptr @"_Z4foo4v.arch=+zbb,+v" +// CHECK: resolver_else2: +// CHECK-NEXT: ret ptr @_Z4foo4v.default +// +// +// CHECK-LABEL: define dso_local noundef signext i32 @_Z4foo5v.default( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 5 +// +// +// CHECK-LABEL: define weak_odr ptr @_Z4foo5v.resolver() comdat { +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: ret ptr @_Z4foo5v.default +// +// +// CHECK-LABEL: define dso_local noundef signext i32 @_Z3barv( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[CALL:%.*]] = call noundef signext i32 @_Z4foo1v() +// CHECK-NEXT: [[CALL1:%.*]] = call noundef signext i32 @_Z4foo2v() +// CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CALL]], [[CALL1]] +// CHECK-NEXT: [[CALL2:%.*]] = call noundef signext i32 @_Z4foo3v() +// CHECK-NEXT: [[ADD3:%.*]] = add nsw i32 [[ADD]], [[CALL2]] +// CHECK-NEXT: [[CALL4:%.*]] = call noundef signext i32 @_Z4foo4v() +// CHECK-NEXT: [[ADD5:%.*]] = add nsw i32 [[ADD3]], [[CALL4]] +// CHECK-NEXT: ret i32 [[ADD5]] +// +//. +// CHECK: attributes #[[ATTR0]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+i,+m" } +// CHECK: attributes #[[ATTR1:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+a,+c,+d,+f,+m,+zicsr,+zifencei,-e,-experimental-smmpm,-experimental-smnpm,-experimental-ssnpm,-experimental-sspm,-experimental-ssqosid,-experimental-supm,-experimental-zaamo,-experimental-zabha,-experimental-zalasr,-experimental-zalrsc,-experimental-zcmop,-experimental-zfbfmin,-experimental-zicfilp,-experimental-zicfiss,-experimental-zimop,-experimental-ztso,-experimental-zvfbfmin,-experimental-zvfbfwma,-h,-shcounterenw,-shgatpa,-shtvala,-shvsatpa,-shvstvala,-shvstvecd,-smaia,-smepmp,-ssaia,-ssccptr,-sscofpmf,-sscounterenw,-ssstateen,-ssstrict,-sstc,-sstvala,-sstvecd,-ssu64xl,-svade,-svadu,-svbare,-svinval,-svnapot,-svpbmt,-v,-xcvalu,-xcvbi,-xcvbitmanip,-xcvelw,-xcvmac,-xcvmem,-xcvsimd,-xsfcease,-xsfvcp,-xsfvfnrclipxfqf,-xsfvfwmaccqqq,-xsfvqmaccdod,-xsfvqmaccqoq,-xsifivecdiscarddlone,-xsifivecflushdlone,-xtheadba,-xtheadbb,-xtheadbs,-xtheadcmo,-xtheadcondmov,-xtheadfmemidx,-xtheadmac,-xtheadmemidx,-xtheadmempair,-xtheadsync,-xtheadvdot,-xventanacondops,-za128rs,-za64rs,-zacas,-zawrs,-zba,-zbb,-zbc,-zbkb,-zbkc,-zbkx,-zbs,-zca,-zcb,-zcd,-zce,-zcf,-zcmp,-zcmt,-zdinx,-zfa,-zfh,-zfhmin,-zfinx,-zhinx,-zhinxmin,-zic64b,-zicbom,-zicbop,-zicboz,-ziccamoa,-ziccif,-zicclsm,-ziccrse,-zicntr,-zicond,-zihintntl,-zihintpause,-zihpm,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-zmmul,-zvbb,-zvbc,-zve32f,-zve32x,-zve64d,-zve64f,-zve64x,-zvfh,-zvfhmin,-zvkb,-zvkg,-zvkn,-zvknc,-zvkned,-zvkng,-zvknha,-zvknhb,-zvks,-zvksc,-zvksed,-zvksg,-zvksh,-zvkt,-zvl1024b,-zvl128b,-zvl16384b,-zvl2048b,-zvl256b,-zvl32768b,-zvl32b,-zvl4096b,-zvl512b,-zvl64b,-zvl65536b,-zvl8192b" } +// CHECK: attributes #[[ATTR2:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+i,+m,+zbb" } +// CHECK: attributes #[[ATTR3:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+c,+i,+m,+zbb" } +// CHECK: attributes #[[ATTR4:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+d,+f,+i,+m,+v,+zbb,+zicsr,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b" } +//. +// CHECK: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4} +// CHECK: [[META1:![0-9]+]] = !{i32 1, !"target-abi", !"lp64"} +// CHECK: [[META2:![0-9]+]] = !{i32 6, !"riscv-isa", [[META3:![0-9]+]]} +// CHECK: [[META3]] = !{!"rv64i2p1_m2p0"} +// CHECK: [[META4:![0-9]+]] = !{i32 8, !"SmallDataLimit", i32 0} +// CHECK: [[META5:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"} +//. diff --git a/clang/test/SemaCXX/attr-target-clones-riscv.cpp b/clang/test/SemaCXX/attr-target-clones-riscv.cpp new file mode 100644 index 00000000000000..a1f7cfb47aee2f --- /dev/null +++ b/clang/test/SemaCXX/attr-target-clones-riscv.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -triple riscv64-linux-gnu -fsyntax-only -verify -fexceptions -fcxx-exceptions %s -std=c++14 + +// expected-warning@+1 {{unsupported 'mcpu=sifive-u74' in the 'target_clones' attribute string; 'target_clones' attribute ignored}} +void __attribute__((target_clones("default", "mcpu=sifive-u74"))) mcpu() {} + +// expected-warning@+1 {{unsupported 'mtune=sifive-u74' in the 'target_clones' attribute string; 'target_clones' attribute ignored}} +void __attribute__((target_clones("default", "mtune=sifive-u74"))) mtune() {} + +// expected-warning@+1 {{version list contains duplicate entries}} +void __attribute__((target_clones("default", "arch=+c", "arch=+c"))) dupVersion() {} + +void lambda() { + // expected-error@+1 {{attribute 'target_clones' multiversioned functions do not yet support lambdas}} + auto x = []() __attribute__((target_clones("default"))){}; + x(); + // expected-error@+1 {{attribute 'target_clones' multiversioned functions do not yet support lambdas}} + auto y = []() __attribute__((target_clones("arch=rv64gc", "default"))){}; + y(); +} >From f3e89fa28507c2e3ac9234a0add29a3c6742f1eb Mon Sep 17 00:00:00 2001 From: Piyou Chen <piyou.c...@sifive.com> Date: Wed, 20 Mar 2024 23:50:53 -0700 Subject: [PATCH 02/10] More Sema testcase --- clang/test/SemaCXX/attr-target-clones-riscv.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/clang/test/SemaCXX/attr-target-clones-riscv.cpp b/clang/test/SemaCXX/attr-target-clones-riscv.cpp index a1f7cfb47aee2f..4e5e8546e21f35 100644 --- a/clang/test/SemaCXX/attr-target-clones-riscv.cpp +++ b/clang/test/SemaCXX/attr-target-clones-riscv.cpp @@ -9,6 +9,15 @@ void __attribute__((target_clones("default", "mtune=sifive-u74"))) mtune() {} // expected-warning@+1 {{version list contains duplicate entries}} void __attribute__((target_clones("default", "arch=+c", "arch=+c"))) dupVersion() {} +// expected-warning@+1 {{unsupported '' in the 'target_clones' attribute string; 'target_clones' attribute ignored}} +void __attribute__((target_clones("default", ""))) emptyVersion() {} + +// expected-error@+1 {{'target_clones' multiversioning requires a default target}} +void __attribute__((target_clones("arch=+c"))) withoutDefault() {} + +// expected-warning@+1 {{unsupported '+c' in the 'target_clones' attribute string; 'target_clones' attribute ignored}} +void __attribute__((target_clones("default", "+c"))) invaildVersion() {} + void lambda() { // expected-error@+1 {{attribute 'target_clones' multiversioned functions do not yet support lambdas}} auto x = []() __attribute__((target_clones("default"))){}; >From 7b831fd93ebc424efe762b36e8ac77a25f517b3d Mon Sep 17 00:00:00 2001 From: Piyou Chen <piyou.c...@sifive.com> Date: Wed, 27 Mar 2024 23:15:21 -0700 Subject: [PATCH 03/10] Suppress warn_target_clone_mixed_values --- clang/lib/Sema/SemaDeclAttr.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 9e44e6a3b70734..314e161c622b63 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3627,6 +3627,9 @@ bool Sema::checkTargetClonesAttrString( return Diag(LiteralLoc, diag::err_sme_streaming_cannot_be_multiversioned); } else if (TInfo.getTriple().isRISCV()) { + // Suppress warn_target_clone_mixed_values + HasCommas = false; + if (Str.starts_with("arch=")) { // parseTargetAttr will parse full version string, // the following split Cur string is no longer interesting. >From dd80140cef3a71a67296b362d260290300ce4f44 Mon Sep 17 00:00:00 2001 From: Piyou Chen <piyou.c...@sifive.com> Date: Fri, 29 Mar 2024 00:03:40 -0700 Subject: [PATCH 04/10] Change __riscv_ifunc_select prototype __riscv_ifunc_select(char *) -> __riscv_ifunc_select(int, int) --- .../clang/Basic/DiagnosticFrontendKinds.td | 3 + clang/lib/CodeGen/CGBuiltin.cpp | 54 +++++++ clang/lib/CodeGen/CodeGenFunction.cpp | 24 ++- clang/lib/CodeGen/CodeGenFunction.h | 2 + .../attr-target-clones-riscv-invaild.c | 8 + clang/test/CodeGen/attr-target-clones-riscv.c | 42 ++--- .../CodeGenCXX/attr-target-clones-riscv.cpp | 43 +++--- llvm/include/llvm/Support/RISCVISAInfo.h | 1 + .../llvm/TargetParser/RISCVTargetParser.h | 4 + llvm/lib/Support/RISCVISAInfo.cpp | 12 ++ llvm/lib/TargetParser/RISCVTargetParser.cpp | 145 ++++++++++++++++++ 11 files changed, 283 insertions(+), 55 deletions(-) create mode 100644 clang/test/CodeGen/attr-target-clones-riscv-invaild.c diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td index 794a0a82be6d74..89a8702d4a6bb6 100644 --- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -360,4 +360,7 @@ def warn_profile_data_misexpect : Warning< def err_extract_api_ignores_file_not_found : Error<"file '%0' specified by '--extract-api-ignores=' not found">, DefaultFatal; +def err_extension_unsupport_riscv_hwprobe : Error< + "Unsupport '%0' for _riscv_hwprobe">; + } diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index e965df810add54..c8c2007967aa5f 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -60,6 +60,7 @@ #include "llvm/Support/MathExtras.h" #include "llvm/Support/ScopedPrinter.h" #include "llvm/TargetParser/AArch64TargetParser.h" +#include "llvm/TargetParser/RISCVTargetParser.h" #include "llvm/TargetParser/X86TargetParser.h" #include <optional> #include <sstream> @@ -14156,6 +14157,59 @@ CodeGenFunction::EmitAArch64CpuSupports(ArrayRef<StringRef> FeaturesStrs) { return Result; } +llvm::SmallVector<llvm::Value *> +CodeGenFunction::EmitRISCVExtSupports(ArrayRef<StringRef> FeaturesStrs) { + auto BaseExtKey = llvm::RISCV::getBaseExtensionKey(FeaturesStrs); + auto IMACompatibleExtKey = + llvm::RISCV::getIMACompatibleExtensionKey(FeaturesStrs); + + auto createConstVal = + [&](const std::vector<unsigned long long> &ExtKeys) -> llvm::Value * { + unsigned long long CurrKey = 0; + for (auto ExtKey : ExtKeys) { + if (ExtKey == 0) + continue; + CurrKey |= ExtKey; + } + return Builder.getInt64(CurrKey); + }; + + // check whether all FeatureStrs are available for hwprobe. + llvm::SmallVector<StringRef> UnsupportByHwprobe; + llvm::StringSet<> ImpliedExtBySupportExt; + for (unsigned Idx = 0; Idx < FeaturesStrs.size(); Idx++) { + if (BaseExtKey[Idx] == 0 && IMACompatibleExtKey[Idx] == 0) + UnsupportByHwprobe.push_back(FeaturesStrs[Idx]); + else + ImpliedExtBySupportExt.insert(FeaturesStrs[Idx].str()); + } + + // Repeatly find ImpliedExts until no longer found new. + bool Changed = true; + while (Changed) { + unsigned Size = ImpliedExtBySupportExt.size(); + for (auto Ext : ImpliedExtBySupportExt.keys()) { + auto ImpliedExts = llvm::RISCV::getImpliedExts(Ext); + for (auto ImpliedExt : ImpliedExts) + ImpliedExtBySupportExt.insert(ImpliedExt); + } + if (Size == ImpliedExtBySupportExt.size()) + Changed = false; + } + + // FIXME: Could hwprobe guarantee that the hardware will support the Implied + // extension? + for (unsigned Idx = 0; Idx < UnsupportByHwprobe.size(); Idx++) { + if (!llvm::is_contained(ImpliedExtBySupportExt, UnsupportByHwprobe[Idx])) + CGM.getDiags().Report(diag::err_extension_unsupport_riscv_hwprobe) + << UnsupportByHwprobe[Idx]; + } + + llvm::SmallVector<llvm::Value *> Vals = {createConstVal(BaseExtKey), + createConstVal(IMACompatibleExtKey)}; + return Vals; +} + Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, const CallExpr *E) { if (BuiltinID == Builtin::BI__builtin_cpu_is) diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 544c696376cd89..610c50c1b81d09 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -2817,9 +2817,12 @@ void CodeGenFunction::EmitRISCVMultiVersionResolver( llvm::Function *Resolver, ArrayRef<MultiVersionResolverOption> Options) { auto EmitIFUNCFeatureCheckFunc = - [&](std::string CurrFeatStr) -> llvm::Value * { - llvm::Constant *FeatStr = Builder.CreateGlobalString(CurrFeatStr); - llvm::Type *Args[] = {Int8PtrTy}; + [&](llvm::SmallVector<StringRef, 8> CurrFeatStrs) -> llvm::Value * { + llvm::SmallVector<llvm::Value *> FeatValue = + EmitRISCVExtSupports(CurrFeatStrs); + // Invoke `bool __riscv_ifunc_select(long long FeatsBaseKey, long long + // FeatsIMAKey)` + llvm::Type *Args[] = {FeatValue[0]->getType(), FeatValue[1]->getType()}; llvm::FunctionType *FTy = llvm::FunctionType::get(Builder.getInt1Ty(), Args, /*Variadic*/ false); llvm::FunctionCallee Func = @@ -2827,7 +2830,7 @@ void CodeGenFunction::EmitRISCVMultiVersionResolver( cast<llvm::GlobalValue>(Func.getCallee())->setDSOLocal(true); cast<llvm::GlobalValue>(Func.getCallee()) ->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass); - return Builder.CreateCall(Func, FeatStr); + return Builder.CreateCall(Func, {FeatValue[0], FeatValue[1]}); }; llvm::BasicBlock *CurBlock = createBasicBlock("resolver_entry", Resolver); @@ -2865,23 +2868,16 @@ void CodeGenFunction::EmitRISCVMultiVersionResolver( TargetAttrFeats.erase(I); // Only consider +<extension-feature>. - std::vector<std::string> PlusTargetAttrFeats; + llvm::SmallVector<StringRef, 8> PlusTargetAttrFeats; for (StringRef Feat : TargetAttrFeats) { if (!getContext().getTargetInfo().isValidFeatureName( Feat.substr(1).str())) continue; if (Feat.starts_with("+")) - PlusTargetAttrFeats.push_back(Feat.substr(1).str()); + PlusTargetAttrFeats.push_back(Feat.substr(1)); } - // Join with ';' delimiter - std::string CurrFeatStr = std::accumulate( - std::begin(PlusTargetAttrFeats), std::end(PlusTargetAttrFeats), - std::string(), [](const std::string &a, const std::string &b) { - return a.empty() ? b : a + ";" + b; - }); - - llvm::Value *Condition = EmitIFUNCFeatureCheckFunc(CurrFeatStr); + llvm::Value *Condition = EmitIFUNCFeatureCheckFunc(PlusTargetAttrFeats); llvm::BasicBlock *RetBlock = createBasicBlock("resolver_return", Resolver); CGBuilderTy RetBuilder(*this, RetBlock); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index e62657de7b7323..fddece85ec0a4d 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -5040,6 +5040,8 @@ class CodeGenFunction : public CodeGenTypeCache { FormAArch64ResolverCondition(const MultiVersionResolverOption &RO); llvm::Value *EmitAArch64CpuSupports(const CallExpr *E); llvm::Value *EmitAArch64CpuSupports(ArrayRef<StringRef> FeatureStrs); + llvm::SmallVector<llvm::Value *> + EmitRISCVExtSupports(ArrayRef<StringRef> FeatureStrs); }; inline DominatingLLVMValue::saved_type diff --git a/clang/test/CodeGen/attr-target-clones-riscv-invaild.c b/clang/test/CodeGen/attr-target-clones-riscv-invaild.c new file mode 100644 index 00000000000000..a88009ecc3d708 --- /dev/null +++ b/clang/test/CodeGen/attr-target-clones-riscv-invaild.c @@ -0,0 +1,8 @@ +// RUN: not %clang_cc1 -triple riscv64-linux-gnu -target-feature +i -S -emit-llvm -o - %s 2>&1 | FileCheck %s + +// CHECK: error: Unsupport 'zicsr' for _riscv_hwprobe +__attribute__((target_clones("default", "arch=+zicsr"))) int foo1(void) { + return 1; +} + +int bar() { return foo1(); } diff --git a/clang/test/CodeGen/attr-target-clones-riscv.c b/clang/test/CodeGen/attr-target-clones-riscv.c index 70b74befb54ffb..119c412f26b6ea 100644 --- a/clang/test/CodeGen/attr-target-clones-riscv.c +++ b/clang/test/CodeGen/attr-target-clones-riscv.c @@ -1,21 +1,20 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals all --include-generated-funcs --version 4 // RUN: %clang_cc1 -triple riscv64-linux-gnu -target-feature +i -S -emit-llvm -o - %s | FileCheck %s -__attribute__((target_clones("default", "arch=rv64gc"))) int foo1(void) { return 1; } +__attribute__((target_clones("default", "arch=rv64im"))) int foo1(void) { + return 1; +} __attribute__((target_clones("default", "arch=+zbb"))) int foo2(void) { return 2; } __attribute__((target_clones("default", "arch=+zbb,+c"))) int foo3(void) { return 3; } -__attribute__((target_clones("default", "arch=rv64gc", "arch=+zbb,+v"))) int foo4(void) { return 4; } +__attribute__((target_clones("default", "arch=rv64ima", "arch=+zbb,+v"))) int +foo4(void) { + return 4; +} __attribute__((target_clones("default"))) int foo5(void) { return 5; } -int bar() { - return foo1() + foo2() + foo3() + foo4(); -} +int bar() { return foo1() + foo2() + foo3() + foo4() + foo5(); } //. -// CHECK: @[[GLOB0:[0-9]+]] = private unnamed_addr constant [25 x i8] c"m;a;f;d;c;zicsr;zifencei\00", align 1 -// CHECK: @[[GLOB1:[0-9]+]] = private unnamed_addr constant [6 x i8] c"i;zbb\00", align 1 -// CHECK: @[[GLOB2:[0-9]+]] = private unnamed_addr constant [8 x i8] c"i;zbb;c\00", align 1 -// CHECK: @[[GLOB3:[0-9]+]] = private unnamed_addr constant [25 x i8] c"m;a;f;d;c;zicsr;zifencei\00", align 1 -// CHECK: @[[GLOB4:[0-9]+]] = private unnamed_addr constant [8 x i8] c"i;zbb;v\00", align 1 // CHECK: @foo1.ifunc = weak_odr alias i32 (), ptr @foo1 // CHECK: @foo2.ifunc = weak_odr alias i32 (), ptr @foo2 // CHECK: @foo3.ifunc = weak_odr alias i32 (), ptr @foo3 @@ -35,10 +34,10 @@ int bar() { // // CHECK-LABEL: define weak_odr ptr @foo1.resolver() comdat { // CHECK-NEXT: resolver_entry: -// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(ptr @[[GLOB0]]) +// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(i64 1, i64 0) // CHECK-NEXT: br i1 [[TMP0]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] // CHECK: resolver_return: -// CHECK-NEXT: ret ptr @"foo1.arch=rv64gc" +// CHECK-NEXT: ret ptr @"foo1.arch=rv64im" // CHECK: resolver_else: // CHECK-NEXT: ret ptr @foo1.default // @@ -51,7 +50,7 @@ int bar() { // // CHECK-LABEL: define weak_odr ptr @foo2.resolver() comdat { // CHECK-NEXT: resolver_entry: -// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(ptr @[[GLOB1]]) +// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(i64 1, i64 16) // CHECK-NEXT: br i1 [[TMP0]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] // CHECK: resolver_return: // CHECK-NEXT: ret ptr @"foo2.arch=+zbb" @@ -67,7 +66,7 @@ int bar() { // // CHECK-LABEL: define weak_odr ptr @foo3.resolver() comdat { // CHECK-NEXT: resolver_entry: -// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(ptr @[[GLOB2]]) +// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(i64 1, i64 18) // CHECK-NEXT: br i1 [[TMP0]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] // CHECK: resolver_return: // CHECK-NEXT: ret ptr @"foo3.arch=+zbb,+c" @@ -83,12 +82,12 @@ int bar() { // // CHECK-LABEL: define weak_odr ptr @foo4.resolver() comdat { // CHECK-NEXT: resolver_entry: -// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(ptr @[[GLOB3]]) +// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(i64 1, i64 0) // CHECK-NEXT: br i1 [[TMP0]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] // CHECK: resolver_return: -// CHECK-NEXT: ret ptr @"foo4.arch=rv64gc" +// CHECK-NEXT: ret ptr @"foo4.arch=rv64ima" // CHECK: resolver_else: -// CHECK-NEXT: [[TMP1:%.*]] = call i1 @__riscv_ifunc_select(ptr @[[GLOB4]]) +// CHECK-NEXT: [[TMP1:%.*]] = call i1 @__riscv_ifunc_select(i64 1, i64 20) // CHECK-NEXT: br i1 [[TMP1]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]] // CHECK: resolver_return1: // CHECK-NEXT: ret ptr @"foo4.arch=+zbb,+v" @@ -117,14 +116,17 @@ int bar() { // CHECK-NEXT: [[ADD3:%.*]] = add nsw i32 [[ADD]], [[CALL2]] // CHECK-NEXT: [[CALL4:%.*]] = call signext i32 @foo4() // CHECK-NEXT: [[ADD5:%.*]] = add nsw i32 [[ADD3]], [[CALL4]] -// CHECK-NEXT: ret i32 [[ADD5]] +// CHECK-NEXT: [[CALL6:%.*]] = call signext i32 @foo5() +// CHECK-NEXT: [[ADD7:%.*]] = add nsw i32 [[ADD5]], [[CALL6]] +// CHECK-NEXT: ret i32 [[ADD7]] // //. // CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+i" } -// CHECK: attributes #[[ATTR1:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+a,+c,+d,+f,+m,+zicsr,+zifencei,-e,-experimental-smmpm,-experimental-smnpm,-experimental-ssnpm,-experimental-sspm,-experimental-ssqosid,-experimental-supm,-experimental-zaamo,-experimental-zabha,-experimental-zalasr,-experimental-zalrsc,-experimental-zcmop,-experimental-zfbfmin,-experimental-zicfilp,-experimental-zicfiss,-experimental-zimop,-experimental-ztso,-experimental-zvfbfmin,-experimental-zvfbfwma,-h,-shcounterenw,-shgatpa,-shtvala,-shvsatpa,-shvstvala,-shvstvecd,-smaia,-smepmp,-ssaia,-ssccptr,-sscofpmf,-sscounterenw,-ssstateen,-ssstrict,-sstc,-sstvala,-sstvecd,-ssu64xl,-svade,-svadu,-svbare,-svinval,-svnapot,-svpbmt,-v,-xcvalu,-xcvbi,-xcvbitmanip,-xcvelw,-xcvmac,-xcvmem,-xcvsimd,-xsfcease,-xsfvcp,-xsfvfnrclipxfqf,-xsfvfwmaccqqq,-xsfvqmaccdod,-xsfvqmaccqoq,-xsifivecdiscarddlone,-xsifivecflushdlone,-xtheadba,-xtheadbb,-xtheadbs,-xtheadcmo,-xtheadcondmov,-xtheadfmemidx,-xtheadmac,-xtheadmemidx,-xtheadmempair,-xtheadsync,-xtheadvdot,-xventanacondops,-za128rs,-za64rs,-zacas,-zawrs,-zba,-zbb,-zbc,-zbkb,-zbkc,-zbkx,-zbs,-zca,-zcb,-zcd,-zce,-zcf,-zcmp,-zcmt,-zdinx,-zfa,-zfh,-zfhmin,-zfinx,-zhinx,-zhinxmin,-zic64b,-zicbom,-zicbop,-zicboz,-ziccamoa,-ziccif,-zicclsm,-ziccrse,-zicntr,-zicond,-zihintntl,-zihintpause,-zihpm,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-zmmul,-zvbb,-zvbc,-zve32f,-zve32x,-zve64d,-zve64f,-zve64x,-zvfh,-zvfhmin,-zvkb,-zvkg,-zvkn,-zvknc,-zvkned,-zvkng,-zvknha,-zvknhb,-zvks,-zvksc,-zvksed,-zvksg,-zvksh,-zvkt,-zvl1024b,-zvl128b,-zvl16384b,-zvl2048b,-zvl256b,-zvl32768b,-zvl32b,-zvl4096b,-zvl512b,-zvl64b,-zvl65536b,-zvl8192b" } +// CHECK: attributes #[[ATTR1:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+m,-a,-c,-d,-e,-experimental-smmpm,-experimental-smnpm,-experimental-ssnpm,-experimental-sspm,-experimental-ssqosid,-experimental-supm,-experimental-zaamo,-experimental-zabha,-experimental-zalasr,-experimental-zalrsc,-experimental-zcmop,-experimental-zfbfmin,-experimental-zicfilp,-experimental-zicfiss,-experimental-zimop,-experimental-ztso,-experimental-zvfbfmin,-experimental-zvfbfwma,-f,-h,-shcounterenw,-shgatpa,-shtvala,-shvsatpa,-shvstvala,-shvstvecd,-smaia,-smepmp,-ssaia,-ssccptr,-sscofpmf,-sscounterenw,-ssstateen,-ssstrict,-sstc,-sstvala,-sstvecd,-ssu64xl,-svade,-svadu,-svbare,-svinval,-svnapot,-svpbmt,-v,-xcvalu,-xcvbi,-xcvbitmanip,-xcvelw,-xcvmac,-xcvmem,-xcvsimd,-xsfcease,-xsfvcp,-xsfvfnrclipxfqf,-xsfvfwmaccqqq,-xsfvqmaccdod,-xsfvqmaccqoq,-xsifivecdiscarddlone,-xsifivecflushdlone,-xtheadba,-xtheadbb,-xtheadbs,-xtheadcmo,-xtheadcondmov,-xtheadfmemidx,-xtheadmac,-xtheadmemidx,-xtheadmempair,-xtheadsync,-xtheadvdot,-xventanacondops,-za128rs,-za64rs,-zacas,-zawrs,-zba,-zbb,-zbc,-zbkb,-zbkc,-zbkx,-zbs,-zca,-zcb,-zcd,-zce,-zcf,-zcmp,-zcmt,-zdinx,-zfa,-zfh,-zfhmin,-zfinx,-zhinx,-zhinxmin,-zic64b,-zicbom,-zicbop,-zicboz,-ziccamoa,-ziccif,-zicclsm,-ziccrse,-zicntr,-zicond,-zicsr,-zifencei,-zihintntl,-zihintpause,-zihpm,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-zmmul,-zvbb,-zvbc,-zve32f,-zve32x,-zve64d,-zve64f,-zve64x,-zvfh,-zvfhmin,-zvkb,-zvkg,-zvkn,-zvknc,-zvkned,-zvkng,-zvknha,-zvknhb,-zvks,-zvksc,-zvksed,-zvksg,-zvksh,-zvkt,-zvl1024b,-zvl128b,-zvl16384b,-zvl2048b,-zvl256b,-zvl32768b,-zvl32b,-zvl4096b,-zvl512b,-zvl64b,-zvl65536b,-zvl8192b" } // CHECK: attributes #[[ATTR2:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+i,+zbb" } // CHECK: attributes #[[ATTR3:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+c,+i,+zbb" } -// CHECK: attributes #[[ATTR4:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+d,+f,+i,+v,+zbb,+zicsr,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b" } +// CHECK: attributes #[[ATTR4:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+a,+m,-c,-d,-e,-experimental-smmpm,-experimental-smnpm,-experimental-ssnpm,-experimental-sspm,-experimental-ssqosid,-experimental-supm,-experimental-zaamo,-experimental-zabha,-experimental-zalasr,-experimental-zalrsc,-experimental-zcmop,-experimental-zfbfmin,-experimental-zicfilp,-experimental-zicfiss,-experimental-zimop,-experimental-ztso,-experimental-zvfbfmin,-experimental-zvfbfwma,-f,-h,-shcounterenw,-shgatpa,-shtvala,-shvsatpa,-shvstvala,-shvstvecd,-smaia,-smepmp,-ssaia,-ssccptr,-sscofpmf,-sscounterenw,-ssstateen,-ssstrict,-sstc,-sstvala,-sstvecd,-ssu64xl,-svade,-svadu,-svbare,-svinval,-svnapot,-svpbmt,-v,-xcvalu,-xcvbi,-xcvbitmanip,-xcvelw,-xcvmac,-xcvmem,-xcvsimd,-xsfcease,-xsfvcp,-xsfvfnrclipxfqf,-xsfvfwmaccqqq,-xsfvqmaccdod,-xsfvqmaccqoq,-xsifivecdiscarddlone,-xsifivecflushdlone,-xtheadba,-xtheadbb,-xtheadbs,-xtheadcmo,-xtheadcondmov,-xtheadfmemidx,-xtheadmac,-xtheadmemidx,-xtheadmempair,-xtheadsync,-xtheadvdot,-xventanacondops,-za128rs,-za64rs,-zacas,-zawrs,-zba,-zbb,-zbc,-zbkb,-zbkc,-zbkx,-zbs,-zca,-zcb,-zcd,-zce,-zcf,-zcmp,-zcmt,-zdinx,-zfa,-zfh,-zfhmin,-zfinx,-zhinx,-zhinxmin,-zic64b,-zicbom,-zicbop,-zicboz,-ziccamoa,-ziccif,-zicclsm,-ziccrse,-zicntr,-zicond,-zicsr,-zifencei,-zihintntl,-zihintpause,-zihpm,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-zmmul,-zvbb,-zvbc,-zve32f,-zve32x,-zve64d,-zve64f,-zve64x,-zvfh,-zvfhmin,-zvkb,-zvkg,-zvkn,-zvknc,-zvkned,-zvkng,-zvknha,-zvknhb,-zvks,-zvksc,-zvksed,-zvksg,-zvksh,-zvkt,-zvl1024b,-zvl128b,-zvl16384b,-zvl2048b,-zvl256b,-zvl32768b,-zvl32b,-zvl4096b,-zvl512b,-zvl64b,-zvl65536b,-zvl8192b" } +// CHECK: attributes #[[ATTR5:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+d,+f,+i,+v,+zbb,+zicsr,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b" } //. // CHECK: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4} // CHECK: [[META1:![0-9]+]] = !{i32 1, !"target-abi", !"lp64"} diff --git a/clang/test/CodeGenCXX/attr-target-clones-riscv.cpp b/clang/test/CodeGenCXX/attr-target-clones-riscv.cpp index 12f5d0284504bc..32b915f42213a6 100644 --- a/clang/test/CodeGenCXX/attr-target-clones-riscv.cpp +++ b/clang/test/CodeGenCXX/attr-target-clones-riscv.cpp @@ -1,22 +1,20 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals all --include-generated-funcs --version 4 // RUN: %clang_cc1 -std=c++11 -triple riscv64-linux-gnu -target-feature +i -target-feature +m -emit-llvm %s -o - | FileCheck %s -__attribute__((target_clones("default", "arch=rv64gc"))) int foo1(void) { return 1; } +__attribute__((target_clones("default", "arch=rv64im"))) int foo1(void) { + return 1; +} __attribute__((target_clones("default", "arch=+zbb"))) int foo2(void) { return 2; } __attribute__((target_clones("default", "arch=+zbb,+c"))) int foo3(void) { return 3; } -__attribute__((target_clones("default", "arch=rv64gc", "arch=+zbb,+v"))) int foo4(void) { return 4; } -__attribute__((target_clones("default"))) int foo5(void) { return 5; } - -int bar() { - return foo1() + foo2() + foo3() + foo4(); +__attribute__((target_clones("default", "arch=rv64ima", "arch=+zbb,+v"))) int +foo4(void) { + return 4; } +__attribute__((target_clones("default"))) int foo5(void) { return 5; } +int bar() { return foo1() + foo2() + foo3() + foo4() + foo5(); } //. -// CHECK: @[[GLOB0:[0-9]+]] = private unnamed_addr constant [25 x i8] c"m;a;f;d;c;zicsr;zifencei\00", align 1 -// CHECK: @[[GLOB1:[0-9]+]] = private unnamed_addr constant [8 x i8] c"i;m;zbb\00", align 1 -// CHECK: @[[GLOB2:[0-9]+]] = private unnamed_addr constant [10 x i8] c"i;m;zbb;c\00", align 1 -// CHECK: @[[GLOB3:[0-9]+]] = private unnamed_addr constant [25 x i8] c"m;a;f;d;c;zicsr;zifencei\00", align 1 -// CHECK: @[[GLOB4:[0-9]+]] = private unnamed_addr constant [10 x i8] c"i;m;zbb;v\00", align 1 // CHECK: @_Z4foo1v.ifunc = weak_odr alias i32 (), ptr @_Z4foo1v // CHECK: @_Z4foo2v.ifunc = weak_odr alias i32 (), ptr @_Z4foo2v // CHECK: @_Z4foo3v.ifunc = weak_odr alias i32 (), ptr @_Z4foo3v @@ -36,10 +34,10 @@ int bar() { // // CHECK-LABEL: define weak_odr ptr @_Z4foo1v.resolver() comdat { // CHECK-NEXT: resolver_entry: -// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(ptr @[[GLOB0]]) +// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(i64 1, i64 0) // CHECK-NEXT: br i1 [[TMP0]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] // CHECK: resolver_return: -// CHECK-NEXT: ret ptr @"_Z4foo1v.arch=rv64gc" +// CHECK-NEXT: ret ptr @"_Z4foo1v.arch=rv64im" // CHECK: resolver_else: // CHECK-NEXT: ret ptr @_Z4foo1v.default // @@ -52,7 +50,7 @@ int bar() { // // CHECK-LABEL: define weak_odr ptr @_Z4foo2v.resolver() comdat { // CHECK-NEXT: resolver_entry: -// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(ptr @[[GLOB1]]) +// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(i64 1, i64 16) // CHECK-NEXT: br i1 [[TMP0]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] // CHECK: resolver_return: // CHECK-NEXT: ret ptr @"_Z4foo2v.arch=+zbb" @@ -68,7 +66,7 @@ int bar() { // // CHECK-LABEL: define weak_odr ptr @_Z4foo3v.resolver() comdat { // CHECK-NEXT: resolver_entry: -// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(ptr @[[GLOB2]]) +// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(i64 1, i64 18) // CHECK-NEXT: br i1 [[TMP0]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] // CHECK: resolver_return: // CHECK-NEXT: ret ptr @"_Z4foo3v.arch=+zbb,+c" @@ -84,12 +82,12 @@ int bar() { // // CHECK-LABEL: define weak_odr ptr @_Z4foo4v.resolver() comdat { // CHECK-NEXT: resolver_entry: -// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(ptr @[[GLOB3]]) +// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(i64 1, i64 0) // CHECK-NEXT: br i1 [[TMP0]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] // CHECK: resolver_return: -// CHECK-NEXT: ret ptr @"_Z4foo4v.arch=rv64gc" +// CHECK-NEXT: ret ptr @"_Z4foo4v.arch=rv64ima" // CHECK: resolver_else: -// CHECK-NEXT: [[TMP1:%.*]] = call i1 @__riscv_ifunc_select(ptr @[[GLOB4]]) +// CHECK-NEXT: [[TMP1:%.*]] = call i1 @__riscv_ifunc_select(i64 1, i64 20) // CHECK-NEXT: br i1 [[TMP1]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]] // CHECK: resolver_return1: // CHECK-NEXT: ret ptr @"_Z4foo4v.arch=+zbb,+v" @@ -118,14 +116,17 @@ int bar() { // CHECK-NEXT: [[ADD3:%.*]] = add nsw i32 [[ADD]], [[CALL2]] // CHECK-NEXT: [[CALL4:%.*]] = call noundef signext i32 @_Z4foo4v() // CHECK-NEXT: [[ADD5:%.*]] = add nsw i32 [[ADD3]], [[CALL4]] -// CHECK-NEXT: ret i32 [[ADD5]] +// CHECK-NEXT: [[CALL6:%.*]] = call noundef signext i32 @_Z4foo5v() +// CHECK-NEXT: [[ADD7:%.*]] = add nsw i32 [[ADD5]], [[CALL6]] +// CHECK-NEXT: ret i32 [[ADD7]] // //. // CHECK: attributes #[[ATTR0]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+i,+m" } -// CHECK: attributes #[[ATTR1:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+a,+c,+d,+f,+m,+zicsr,+zifencei,-e,-experimental-smmpm,-experimental-smnpm,-experimental-ssnpm,-experimental-sspm,-experimental-ssqosid,-experimental-supm,-experimental-zaamo,-experimental-zabha,-experimental-zalasr,-experimental-zalrsc,-experimental-zcmop,-experimental-zfbfmin,-experimental-zicfilp,-experimental-zicfiss,-experimental-zimop,-experimental-ztso,-experimental-zvfbfmin,-experimental-zvfbfwma,-h,-shcounterenw,-shgatpa,-shtvala,-shvsatpa,-shvstvala,-shvstvecd,-smaia,-smepmp,-ssaia,-ssccptr,-sscofpmf,-sscounterenw,-ssstateen,-ssstrict,-sstc,-sstvala,-sstvecd,-ssu64xl,-svade,-svadu,-svbare,-svinval,-svnapot,-svpbmt,-v,-xcvalu,-xcvbi,-xcvbitmanip,-xcvelw,-xcvmac,-xcvmem,-xcvsimd,-xsfcease,-xsfvcp,-xsfvfnrclipxfqf,-xsfvfwmaccqqq,-xsfvqmaccdod,-xsfvqmaccqoq,-xsifivecdiscarddlone,-xsifivecflushdlone,-xtheadba,-xtheadbb,-xtheadbs,-xtheadcmo,-xtheadcondmov,-xtheadfmemidx,-xtheadmac,-xtheadmemidx,-xtheadmempair,-xtheadsync,-xtheadvdot,-xventanacondops,-za128rs,-za64rs,-zacas,-zawrs,-zba,-zbb,-zbc,-zbkb,-zbkc,-zbkx,-zbs,-zca,-zcb,-zcd,-zce,-zcf,-zcmp,-zcmt,-zdinx,-zfa,-zfh,-zfhmin,-zfinx,-zhinx,-zhinxmin,-zic64b,-zicbom,-zicbop,-zicboz,-ziccamoa,-ziccif,-zicclsm,-ziccrse,-zicntr,-zicond,-zihintntl,-zihintpause,-zihpm,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-zmmul,-zvbb,-zvbc,-zve32f,-zve32x,-zve64d,-zve64f,-zve64x,-zvfh,-zvfhmin,-zvkb,-zvkg,-zvkn,-zvknc,-zvkned,-zvkng,-zvknha,-zvknhb,-zvks,-zvksc,-zvksed,-zvksg,-zvksh,-zvkt,-zvl1024b,-zvl128b,-zvl16384b,-zvl2048b,-zvl256b,-zvl32768b,-zvl32b,-zvl4096b,-zvl512b,-zvl64b,-zvl65536b,-zvl8192b" } +// CHECK: attributes #[[ATTR1:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+m,-a,-c,-d,-e,-experimental-smmpm,-experimental-smnpm,-experimental-ssnpm,-experimental-sspm,-experimental-ssqosid,-experimental-supm,-experimental-zaamo,-experimental-zabha,-experimental-zalasr,-experimental-zalrsc,-experimental-zcmop,-experimental-zfbfmin,-experimental-zicfilp,-experimental-zicfiss,-experimental-zimop,-experimental-ztso,-experimental-zvfbfmin,-experimental-zvfbfwma,-f,-h,-shcounterenw,-shgatpa,-shtvala,-shvsatpa,-shvstvala,-shvstvecd,-smaia,-smepmp,-ssaia,-ssccptr,-sscofpmf,-sscounterenw,-ssstateen,-ssstrict,-sstc,-sstvala,-sstvecd,-ssu64xl,-svade,-svadu,-svbare,-svinval,-svnapot,-svpbmt,-v,-xcvalu,-xcvbi,-xcvbitmanip,-xcvelw,-xcvmac,-xcvmem,-xcvsimd,-xsfcease,-xsfvcp,-xsfvfnrclipxfqf,-xsfvfwmaccqqq,-xsfvqmaccdod,-xsfvqmaccqoq,-xsifivecdiscarddlone,-xsifivecflushdlone,-xtheadba,-xtheadbb,-xtheadbs,-xtheadcmo,-xtheadcondmov,-xtheadfmemidx,-xtheadmac,-xtheadmemidx,-xtheadmempair,-xtheadsync,-xtheadvdot,-xventanacondops,-za128rs,-za64rs,-zacas,-zawrs,-zba,-zbb,-zbc,-zbkb,-zbkc,-zbkx,-zbs,-zca,-zcb,-zcd,-zce,-zcf,-zcmp,-zcmt,-zdinx,-zfa,-zfh,-zfhmin,-zfinx,-zhinx,-zhinxmin,-zic64b,-zicbom,-zicbop,-zicboz,-ziccamoa,-ziccif,-zicclsm,-ziccrse,-zicntr,-zicond,-zicsr,-zifencei,-zihintntl,-zihintpause,-zihpm,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-zmmul,-zvbb,-zvbc,-zve32f,-zve32x,-zve64d,-zve64f,-zve64x,-zvfh,-zvfhmin,-zvkb,-zvkg,-zvkn,-zvknc,-zvkned,-zvkng,-zvknha,-zvknhb,-zvks,-zvksc,-zvksed,-zvksg,-zvksh,-zvkt,-zvl1024b,-zvl128b,-zvl16384b,-zvl2048b,-zvl256b,-zvl32768b,-zvl32b,-zvl4096b,-zvl512b,-zvl64b,-zvl65536b,-zvl8192b" } // CHECK: attributes #[[ATTR2:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+i,+m,+zbb" } // CHECK: attributes #[[ATTR3:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+c,+i,+m,+zbb" } -// CHECK: attributes #[[ATTR4:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+d,+f,+i,+m,+v,+zbb,+zicsr,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b" } +// CHECK: attributes #[[ATTR4:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+a,+m,-c,-d,-e,-experimental-smmpm,-experimental-smnpm,-experimental-ssnpm,-experimental-sspm,-experimental-ssqosid,-experimental-supm,-experimental-zaamo,-experimental-zabha,-experimental-zalasr,-experimental-zalrsc,-experimental-zcmop,-experimental-zfbfmin,-experimental-zicfilp,-experimental-zicfiss,-experimental-zimop,-experimental-ztso,-experimental-zvfbfmin,-experimental-zvfbfwma,-f,-h,-shcounterenw,-shgatpa,-shtvala,-shvsatpa,-shvstvala,-shvstvecd,-smaia,-smepmp,-ssaia,-ssccptr,-sscofpmf,-sscounterenw,-ssstateen,-ssstrict,-sstc,-sstvala,-sstvecd,-ssu64xl,-svade,-svadu,-svbare,-svinval,-svnapot,-svpbmt,-v,-xcvalu,-xcvbi,-xcvbitmanip,-xcvelw,-xcvmac,-xcvmem,-xcvsimd,-xsfcease,-xsfvcp,-xsfvfnrclipxfqf,-xsfvfwmaccqqq,-xsfvqmaccdod,-xsfvqmaccqoq,-xsifivecdiscarddlone,-xsifivecflushdlone,-xtheadba,-xtheadbb,-xtheadbs,-xtheadcmo,-xtheadcondmov,-xtheadfmemidx,-xtheadmac,-xtheadmemidx,-xtheadmempair,-xtheadsync,-xtheadvdot,-xventanacondops,-za128rs,-za64rs,-zacas,-zawrs,-zba,-zbb,-zbc,-zbkb,-zbkc,-zbkx,-zbs,-zca,-zcb,-zcd,-zce,-zcf,-zcmp,-zcmt,-zdinx,-zfa,-zfh,-zfhmin,-zfinx,-zhinx,-zhinxmin,-zic64b,-zicbom,-zicbop,-zicboz,-ziccamoa,-ziccif,-zicclsm,-ziccrse,-zicntr,-zicond,-zicsr,-zifencei,-zihintntl,-zihintpause,-zihpm,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-zmmul,-zvbb,-zvbc,-zve32f,-zve32x,-zve64d,-zve64f,-zve64x,-zvfh,-zvfhmin,-zvkb,-zvkg,-zvkn,-zvknc,-zvkned,-zvkng,-zvknha,-zvknhb,-zvks,-zvksc,-zvksed,-zvksg,-zvksh,-zvkt,-zvl1024b,-zvl128b,-zvl16384b,-zvl2048b,-zvl256b,-zvl32768b,-zvl32b,-zvl4096b,-zvl512b,-zvl64b,-zvl65536b,-zvl8192b" } +// CHECK: attributes #[[ATTR5:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+d,+f,+i,+m,+v,+zbb,+zicsr,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b" } //. // CHECK: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4} // CHECK: [[META1:![0-9]+]] = !{i32 1, !"target-abi", !"lp64"} diff --git a/llvm/include/llvm/Support/RISCVISAInfo.h b/llvm/include/llvm/Support/RISCVISAInfo.h index 46df93d7522602..2f86f99c267aca 100644 --- a/llvm/include/llvm/Support/RISCVISAInfo.h +++ b/llvm/include/llvm/Support/RISCVISAInfo.h @@ -93,6 +93,7 @@ class RISCVISAInfo { static llvm::Expected<std::unique_ptr<RISCVISAInfo>> postProcessAndChecking(std::unique_ptr<RISCVISAInfo> &&ISAInfo); static std::string getTargetFeatureForExtension(StringRef Ext); + static llvm::SmallVector<std::string> getImpliedExts(StringRef Ext); private: RISCVISAInfo(unsigned XLen) diff --git a/llvm/include/llvm/TargetParser/RISCVTargetParser.h b/llvm/include/llvm/TargetParser/RISCVTargetParser.h index cdd19189f8dc7d..f249ecd2e56733 100644 --- a/llvm/include/llvm/TargetParser/RISCVTargetParser.h +++ b/llvm/include/llvm/TargetParser/RISCVTargetParser.h @@ -36,6 +36,10 @@ StringRef getMArchFromMcpu(StringRef CPU); void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64); void fillValidTuneCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64); bool hasFastUnalignedAccess(StringRef CPU); +std::vector<unsigned long long> getBaseExtensionKey(ArrayRef<StringRef>); +std::vector<unsigned long long> + getIMACompatibleExtensionKey(ArrayRef<StringRef>); +llvm::SmallVector<std::string> getImpliedExts(StringRef Ext); } // namespace RISCV diff --git a/llvm/lib/Support/RISCVISAInfo.cpp b/llvm/lib/Support/RISCVISAInfo.cpp index 39235ace472483..d55c8eeed1f317 100644 --- a/llvm/lib/Support/RISCVISAInfo.cpp +++ b/llvm/lib/Support/RISCVISAInfo.cpp @@ -1388,3 +1388,15 @@ std::string RISCVISAInfo::getTargetFeatureForExtension(StringRef Ext) { return isExperimentalExtension(Name) ? "experimental-" + Name.str() : Name.str(); } + +llvm::SmallVector<std::string> RISCVISAInfo::getImpliedExts(StringRef Ext) { + auto *I = llvm::lower_bound(ImpliedExts, Ext); + if (I != std::end(ImpliedExts) && I->Name == Ext) { + llvm::SmallVector<std::string> Result; + for (auto ImpiledExt : ArrayRef(I->Exts)) { + Result.push_back(std::string(ImpiledExt)); + } + return Result; + } + return llvm::SmallVector<std::string>(); +} diff --git a/llvm/lib/TargetParser/RISCVTargetParser.cpp b/llvm/lib/TargetParser/RISCVTargetParser.cpp index 0d95e3a9b81962..b73861a5b8414b 100644 --- a/llvm/lib/TargetParser/RISCVTargetParser.cpp +++ b/llvm/lib/TargetParser/RISCVTargetParser.cpp @@ -119,6 +119,151 @@ void getFeaturesForCPU(StringRef CPU, else EnabledFeatures.push_back(F.substr(1)); } + +// Sync with https://docs.kernel.org/arch/riscv/hwprobe.html +// and compiler-rt/lib/builtins/riscv/ifunc_select.c +#define RISCV_HWPROBE_KEY_BASE_BEHAVIOR 3 +#define RISCV_HWPROBE_BASE_BEHAVIOR_IMA (1 << 0) +#define RISCV_HWPROBE_KEY_IMA_EXT_0 4 +#define RISCV_HWPROBE_IMA_FD (1 << 0) +#define RISCV_HWPROBE_IMA_C (1 << 1) +#define RISCV_HWPROBE_IMA_V (1 << 2) +#define RISCV_HWPROBE_EXT_ZBA (1 << 3) +#define RISCV_HWPROBE_EXT_ZBB (1 << 4) +#define RISCV_HWPROBE_EXT_ZBS (1 << 5) +#define RISCV_HWPROBE_EXT_ZICBOZ (1 << 6) +#define RISCV_HWPROBE_EXT_ZBC (1 << 7) +#define RISCV_HWPROBE_EXT_ZBKB (1 << 8) +#define RISCV_HWPROBE_EXT_ZBKC (1 << 9) +#define RISCV_HWPROBE_EXT_ZBKX (1 << 10) +#define RISCV_HWPROBE_EXT_ZKND (1 << 11) +#define RISCV_HWPROBE_EXT_ZKNE (1 << 12) +#define RISCV_HWPROBE_EXT_ZKNH (1 << 13) +#define RISCV_HWPROBE_EXT_ZKSED (1 << 14) +#define RISCV_HWPROBE_EXT_ZKSH (1 << 15) +#define RISCV_HWPROBE_EXT_ZKT (1 << 16) +#define RISCV_HWPROBE_EXT_ZVBB (1 << 17) +#define RISCV_HWPROBE_EXT_ZVBC (1 << 18) +#define RISCV_HWPROBE_EXT_ZVKB (1 << 19) +#define RISCV_HWPROBE_EXT_ZVKG (1 << 20) +#define RISCV_HWPROBE_EXT_ZVKNED (1 << 21) +#define RISCV_HWPROBE_EXT_ZVKNHA (1 << 22) +#define RISCV_HWPROBE_EXT_ZVKNHB (1 << 23) +#define RISCV_HWPROBE_EXT_ZVKSED (1 << 24) +#define RISCV_HWPROBE_EXT_ZVKSH (1 << 25) +#define RISCV_HWPROBE_EXT_ZVKT (1 << 26) +#define RISCV_HWPROBE_EXT_ZFH (1 << 27) +#define RISCV_HWPROBE_EXT_ZFHMIN (1 << 28) +#define RISCV_HWPROBE_EXT_ZIHINTNTL (1 << 29) +#define RISCV_HWPROBE_EXT_ZVFH (1 << 30) +#define RISCV_HWPROBE_EXT_ZVFHMIN (1 << 31) +#define RISCV_HWPROBE_EXT_ZFA (1ULL << 32) +#define RISCV_HWPROBE_EXT_ZTSO (1ULL << 33) +#define RISCV_HWPROBE_EXT_ZACAS (1ULL << 34) +#define RISCV_HWPROBE_EXT_ZICOND (1ULL << 35) + +std::vector<unsigned long long> getBaseExtensionKey(ArrayRef<StringRef> Exts) { + std::vector<unsigned long long> Result; + for (auto Ext : Exts) { + unsigned long long ExtKey = 0; + if (Ext.starts_with("i") || Ext.starts_with("m") || Ext.starts_with("a")) { + ExtKey = RISCV_HWPROBE_BASE_BEHAVIOR_IMA; + } + Result.push_back(ExtKey); + } + + return Result; +} + +std::vector<unsigned long long> +getIMACompatibleExtensionKey(ArrayRef<StringRef> Exts) { + std::vector<unsigned long long> Result; + + for (auto Ext : Exts) { + unsigned long long ExtKey = 0; + if (Ext.starts_with("f") || Ext.starts_with("d")) + ExtKey = RISCV_HWPROBE_IMA_FD; + if (Ext.starts_with("c")) + ExtKey = RISCV_HWPROBE_IMA_C; + if (Ext.starts_with("v")) + ExtKey = RISCV_HWPROBE_IMA_V; + if (Ext.starts_with("zba")) + ExtKey = RISCV_HWPROBE_EXT_ZBA; + if (Ext.starts_with("zbb")) + ExtKey = RISCV_HWPROBE_EXT_ZBB; + if (Ext.starts_with("zbs")) + ExtKey = RISCV_HWPROBE_EXT_ZBS; + if (Ext.starts_with("zicboz")) + ExtKey = RISCV_HWPROBE_EXT_ZICBOZ; + if (Ext.starts_with("zbc")) + ExtKey = RISCV_HWPROBE_EXT_ZBC; + if (Ext.starts_with("zbkb")) + ExtKey = RISCV_HWPROBE_EXT_ZBKB; + if (Ext.starts_with("zbkc")) + ExtKey = RISCV_HWPROBE_EXT_ZBKC; + if (Ext.starts_with("zbkk")) + ExtKey = RISCV_HWPROBE_EXT_ZBKX; + if (Ext.starts_with("zknd")) + ExtKey = RISCV_HWPROBE_EXT_ZKND; + if (Ext.starts_with("zkne")) + ExtKey = RISCV_HWPROBE_EXT_ZKNE; + if (Ext.starts_with("zknh")) + ExtKey = RISCV_HWPROBE_EXT_ZKNH; + if (Ext.starts_with("zksed")) + ExtKey = RISCV_HWPROBE_EXT_ZKSED; + if (Ext.starts_with("zksh")) + ExtKey = RISCV_HWPROBE_EXT_ZKSH; + if (Ext.starts_with("zkt")) + ExtKey = RISCV_HWPROBE_EXT_ZKT; + if (Ext.starts_with("zvbb")) + ExtKey = RISCV_HWPROBE_EXT_ZVBB; + if (Ext.starts_with("zvbc")) + ExtKey = RISCV_HWPROBE_EXT_ZVBC; + if (Ext.starts_with("zvkb")) + ExtKey = RISCV_HWPROBE_EXT_ZVKB; + if (Ext.starts_with("zvkg")) + ExtKey = RISCV_HWPROBE_EXT_ZVKG; + if (Ext.starts_with("zvkned")) + ExtKey = RISCV_HWPROBE_EXT_ZVKNED; + if (Ext.starts_with("zvknha")) + ExtKey = RISCV_HWPROBE_EXT_ZVKNHA; + if (Ext.starts_with("zvknhb")) + ExtKey = RISCV_HWPROBE_EXT_ZVKNHB; + if (Ext.starts_with("zvksed")) + ExtKey = RISCV_HWPROBE_EXT_ZVKSED; + if (Ext.starts_with("zvksh")) + ExtKey = RISCV_HWPROBE_EXT_ZVKSH; + if (Ext.starts_with("zvkt")) + ExtKey = RISCV_HWPROBE_EXT_ZVKT; + if (Ext.starts_with("zfh")) + ExtKey = RISCV_HWPROBE_EXT_ZFH; + if (Ext.starts_with("zfhmin")) + ExtKey = RISCV_HWPROBE_EXT_ZFHMIN; + if (Ext.starts_with("zihintntl")) + ExtKey = RISCV_HWPROBE_EXT_ZIHINTNTL; + if (Ext.starts_with("zvfh")) + ExtKey = RISCV_HWPROBE_EXT_ZVFH; + if (Ext.starts_with("zvfhmin")) + ExtKey = RISCV_HWPROBE_EXT_ZVFHMIN; + if (Ext.starts_with("zfa")) + ExtKey = RISCV_HWPROBE_EXT_ZFA; + if (Ext.starts_with("ztso")) + ExtKey = RISCV_HWPROBE_EXT_ZTSO; + if (Ext.starts_with("zacas")) + ExtKey = RISCV_HWPROBE_EXT_ZACAS; + if (Ext.starts_with("zicond")) + ExtKey = RISCV_HWPROBE_EXT_ZICOND; + + Result.push_back(ExtKey); + } + + return Result; +} + +llvm::SmallVector<std::string> getImpliedExts(StringRef Ext) { + return RISCVISAInfo::getImpliedExts(Ext); +} + } // namespace RISCV namespace RISCVVType { >From a26eb387f1a9ccf4874e7f97caa7d1ab61bca92d Mon Sep 17 00:00:00 2001 From: Piyou Chen <piyou.c...@sifive.com> Date: Wed, 3 Apr 2024 02:00:37 -0700 Subject: [PATCH 05/10] Make __riscv_ifunc_select accept a ptr and length of key __riscv_ifunc_select(unsigned long long, unsigned long long) -> struct hwprobe { long long key, unsigned long long value }; __riscv_ifunc_select(struct hwprobe *, unsigned) --- clang/lib/CodeGen/CGBuiltin.cpp | 57 +++++++++++++------ clang/lib/CodeGen/CodeGenFunction.cpp | 4 +- clang/test/CodeGen/attr-target-clones-riscv.c | 15 +++-- .../CodeGenCXX/attr-target-clones-riscv.cpp | 15 +++-- .../llvm/TargetParser/RISCVTargetParser.h | 47 +++++++++++++++ llvm/lib/TargetParser/RISCVTargetParser.cpp | 42 -------------- 6 files changed, 110 insertions(+), 70 deletions(-) diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index c8c2007967aa5f..cd8fc184b5bf56 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -14159,26 +14159,15 @@ CodeGenFunction::EmitAArch64CpuSupports(ArrayRef<StringRef> FeaturesStrs) { llvm::SmallVector<llvm::Value *> CodeGenFunction::EmitRISCVExtSupports(ArrayRef<StringRef> FeaturesStrs) { - auto BaseExtKey = llvm::RISCV::getBaseExtensionKey(FeaturesStrs); - auto IMACompatibleExtKey = + auto BaseExtReqs = llvm::RISCV::getBaseExtensionKey(FeaturesStrs); + auto IMACompatibleExtReqs = llvm::RISCV::getIMACompatibleExtensionKey(FeaturesStrs); - auto createConstVal = - [&](const std::vector<unsigned long long> &ExtKeys) -> llvm::Value * { - unsigned long long CurrKey = 0; - for (auto ExtKey : ExtKeys) { - if (ExtKey == 0) - continue; - CurrKey |= ExtKey; - } - return Builder.getInt64(CurrKey); - }; - // check whether all FeatureStrs are available for hwprobe. llvm::SmallVector<StringRef> UnsupportByHwprobe; llvm::StringSet<> ImpliedExtBySupportExt; for (unsigned Idx = 0; Idx < FeaturesStrs.size(); Idx++) { - if (BaseExtKey[Idx] == 0 && IMACompatibleExtKey[Idx] == 0) + if (BaseExtReqs[Idx] == 0 && IMACompatibleExtReqs[Idx] == 0) UnsupportByHwprobe.push_back(FeaturesStrs[Idx]); else ImpliedExtBySupportExt.insert(FeaturesStrs[Idx].str()); @@ -14205,8 +14194,44 @@ CodeGenFunction::EmitRISCVExtSupports(ArrayRef<StringRef> FeaturesStrs) { << UnsupportByHwprobe[Idx]; } - llvm::SmallVector<llvm::Value *> Vals = {createConstVal(BaseExtKey), - createConstVal(IMACompatibleExtKey)}; + StructType *structType = + StructType::create({llvm::Type::getInt64Ty(CGM.getLLVMContext()), + llvm::Type::getInt64Ty(CGM.getLLVMContext())}, + "riscv_hwprobe_pair"); + + auto *ATy = + llvm::ArrayType::get(structType, llvm::RISCV::RISCVHwprobeLengthOfKey); + + auto createConstant = [&](unsigned long long Value) -> Constant * { + return ConstantInt::get(llvm::Type::getInt64Ty(CGM.getLLVMContext()), + Value); + }; + + auto createHwprobeVal = [&](const std::vector<unsigned long long> &ExtReqs) + -> unsigned long long { + unsigned long long CurrVal = 0; + for (auto ExtReq : ExtReqs) { + if (ExtReq == 0) + continue; + CurrVal |= ExtReq; + } + return CurrVal; + }; + + SmallVector<Constant *> KeyValPairs; + KeyValPairs.push_back(ConstantStruct::get( + structType, {createConstant(llvm::RISCV::RISCVHwprobeKeyBase), + createConstant(createHwprobeVal(BaseExtReqs))})); + KeyValPairs.push_back(ConstantStruct::get( + structType, {createConstant(llvm::RISCV::RISCVHwprobeKeyIMA), + createConstant(createHwprobeVal(IMACompatibleExtReqs))})); + + GlobalVariable *KeyValuePairs = new GlobalVariable( + CGM.getModule(), ATy, false, GlobalValue::InternalLinkage, + ConstantArray::get(ATy, KeyValPairs), "__riscv_hwprobe_args"); + + llvm::SmallVector<llvm::Value *> Vals = { + KeyValuePairs, Builder.getInt32(llvm::RISCV::RISCVHwprobeLengthOfKey)}; return Vals; } diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 610c50c1b81d09..74b9b6860dec8d 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -2820,8 +2820,8 @@ void CodeGenFunction::EmitRISCVMultiVersionResolver( [&](llvm::SmallVector<StringRef, 8> CurrFeatStrs) -> llvm::Value * { llvm::SmallVector<llvm::Value *> FeatValue = EmitRISCVExtSupports(CurrFeatStrs); - // Invoke `bool __riscv_ifunc_select(long long FeatsBaseKey, long long - // FeatsIMAKey)` + // Invoke `bool __riscv_ifunc_select(struct riscv_hwprobe *ReqirePreKey, + // unsigned Length)` llvm::Type *Args[] = {FeatValue[0]->getType(), FeatValue[1]->getType()}; llvm::FunctionType *FTy = llvm::FunctionType::get(Builder.getInt1Ty(), Args, /*Variadic*/ false); diff --git a/clang/test/CodeGen/attr-target-clones-riscv.c b/clang/test/CodeGen/attr-target-clones-riscv.c index 119c412f26b6ea..721a4139853ad9 100644 --- a/clang/test/CodeGen/attr-target-clones-riscv.c +++ b/clang/test/CodeGen/attr-target-clones-riscv.c @@ -15,6 +15,11 @@ __attribute__((target_clones("default"))) int foo5(void) { return 5; } int bar() { return foo1() + foo2() + foo3() + foo4() + foo5(); } //. +// CHECK: @__riscv_hwprobe_args = internal global [2 x %riscv_hwprobe_pair] [%riscv_hwprobe_pair { i64 3, i64 1 }, %riscv_hwprobe_pair { i64 4, i64 0 }] +// CHECK: @__riscv_hwprobe_args.1 = internal global [2 x %riscv_hwprobe_pair.0] [%riscv_hwprobe_pair.0 { i64 3, i64 1 }, %riscv_hwprobe_pair.0 { i64 4, i64 16 }] +// CHECK: @__riscv_hwprobe_args.2 = internal global [2 x %riscv_hwprobe_pair.1] [%riscv_hwprobe_pair.1 { i64 3, i64 1 }, %riscv_hwprobe_pair.1 { i64 4, i64 18 }] +// CHECK: @__riscv_hwprobe_args.3 = internal global [2 x %riscv_hwprobe_pair.2] [%riscv_hwprobe_pair.2 { i64 3, i64 1 }, %riscv_hwprobe_pair.2 { i64 4, i64 0 }] +// CHECK: @__riscv_hwprobe_args.4 = internal global [2 x %riscv_hwprobe_pair.3] [%riscv_hwprobe_pair.3 { i64 3, i64 1 }, %riscv_hwprobe_pair.3 { i64 4, i64 20 }] // CHECK: @foo1.ifunc = weak_odr alias i32 (), ptr @foo1 // CHECK: @foo2.ifunc = weak_odr alias i32 (), ptr @foo2 // CHECK: @foo3.ifunc = weak_odr alias i32 (), ptr @foo3 @@ -34,7 +39,7 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5(); } // // CHECK-LABEL: define weak_odr ptr @foo1.resolver() comdat { // CHECK-NEXT: resolver_entry: -// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(i64 1, i64 0) +// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(ptr @__riscv_hwprobe_args, i32 2) // CHECK-NEXT: br i1 [[TMP0]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] // CHECK: resolver_return: // CHECK-NEXT: ret ptr @"foo1.arch=rv64im" @@ -50,7 +55,7 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5(); } // // CHECK-LABEL: define weak_odr ptr @foo2.resolver() comdat { // CHECK-NEXT: resolver_entry: -// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(i64 1, i64 16) +// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(ptr @__riscv_hwprobe_args.1, i32 2) // CHECK-NEXT: br i1 [[TMP0]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] // CHECK: resolver_return: // CHECK-NEXT: ret ptr @"foo2.arch=+zbb" @@ -66,7 +71,7 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5(); } // // CHECK-LABEL: define weak_odr ptr @foo3.resolver() comdat { // CHECK-NEXT: resolver_entry: -// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(i64 1, i64 18) +// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(ptr @__riscv_hwprobe_args.2, i32 2) // CHECK-NEXT: br i1 [[TMP0]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] // CHECK: resolver_return: // CHECK-NEXT: ret ptr @"foo3.arch=+zbb,+c" @@ -82,12 +87,12 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5(); } // // CHECK-LABEL: define weak_odr ptr @foo4.resolver() comdat { // CHECK-NEXT: resolver_entry: -// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(i64 1, i64 0) +// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(ptr @__riscv_hwprobe_args.3, i32 2) // CHECK-NEXT: br i1 [[TMP0]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] // CHECK: resolver_return: // CHECK-NEXT: ret ptr @"foo4.arch=rv64ima" // CHECK: resolver_else: -// CHECK-NEXT: [[TMP1:%.*]] = call i1 @__riscv_ifunc_select(i64 1, i64 20) +// CHECK-NEXT: [[TMP1:%.*]] = call i1 @__riscv_ifunc_select(ptr @__riscv_hwprobe_args.4, i32 2) // CHECK-NEXT: br i1 [[TMP1]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]] // CHECK: resolver_return1: // CHECK-NEXT: ret ptr @"foo4.arch=+zbb,+v" diff --git a/clang/test/CodeGenCXX/attr-target-clones-riscv.cpp b/clang/test/CodeGenCXX/attr-target-clones-riscv.cpp index 32b915f42213a6..b2e0687b12cc74 100644 --- a/clang/test/CodeGenCXX/attr-target-clones-riscv.cpp +++ b/clang/test/CodeGenCXX/attr-target-clones-riscv.cpp @@ -15,6 +15,11 @@ __attribute__((target_clones("default"))) int foo5(void) { return 5; } int bar() { return foo1() + foo2() + foo3() + foo4() + foo5(); } //. +// CHECK: @__riscv_hwprobe_args = internal global [2 x %riscv_hwprobe_pair] [%riscv_hwprobe_pair { i64 3, i64 1 }, %riscv_hwprobe_pair { i64 4, i64 0 }] +// CHECK: @__riscv_hwprobe_args.1 = internal global [2 x %riscv_hwprobe_pair.0] [%riscv_hwprobe_pair.0 { i64 3, i64 1 }, %riscv_hwprobe_pair.0 { i64 4, i64 16 }] +// CHECK: @__riscv_hwprobe_args.2 = internal global [2 x %riscv_hwprobe_pair.1] [%riscv_hwprobe_pair.1 { i64 3, i64 1 }, %riscv_hwprobe_pair.1 { i64 4, i64 18 }] +// CHECK: @__riscv_hwprobe_args.3 = internal global [2 x %riscv_hwprobe_pair.2] [%riscv_hwprobe_pair.2 { i64 3, i64 1 }, %riscv_hwprobe_pair.2 { i64 4, i64 0 }] +// CHECK: @__riscv_hwprobe_args.4 = internal global [2 x %riscv_hwprobe_pair.3] [%riscv_hwprobe_pair.3 { i64 3, i64 1 }, %riscv_hwprobe_pair.3 { i64 4, i64 20 }] // CHECK: @_Z4foo1v.ifunc = weak_odr alias i32 (), ptr @_Z4foo1v // CHECK: @_Z4foo2v.ifunc = weak_odr alias i32 (), ptr @_Z4foo2v // CHECK: @_Z4foo3v.ifunc = weak_odr alias i32 (), ptr @_Z4foo3v @@ -34,7 +39,7 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5(); } // // CHECK-LABEL: define weak_odr ptr @_Z4foo1v.resolver() comdat { // CHECK-NEXT: resolver_entry: -// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(i64 1, i64 0) +// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(ptr @__riscv_hwprobe_args, i32 2) // CHECK-NEXT: br i1 [[TMP0]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] // CHECK: resolver_return: // CHECK-NEXT: ret ptr @"_Z4foo1v.arch=rv64im" @@ -50,7 +55,7 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5(); } // // CHECK-LABEL: define weak_odr ptr @_Z4foo2v.resolver() comdat { // CHECK-NEXT: resolver_entry: -// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(i64 1, i64 16) +// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(ptr @__riscv_hwprobe_args.1, i32 2) // CHECK-NEXT: br i1 [[TMP0]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] // CHECK: resolver_return: // CHECK-NEXT: ret ptr @"_Z4foo2v.arch=+zbb" @@ -66,7 +71,7 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5(); } // // CHECK-LABEL: define weak_odr ptr @_Z4foo3v.resolver() comdat { // CHECK-NEXT: resolver_entry: -// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(i64 1, i64 18) +// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(ptr @__riscv_hwprobe_args.2, i32 2) // CHECK-NEXT: br i1 [[TMP0]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] // CHECK: resolver_return: // CHECK-NEXT: ret ptr @"_Z4foo3v.arch=+zbb,+c" @@ -82,12 +87,12 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5(); } // // CHECK-LABEL: define weak_odr ptr @_Z4foo4v.resolver() comdat { // CHECK-NEXT: resolver_entry: -// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(i64 1, i64 0) +// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(ptr @__riscv_hwprobe_args.3, i32 2) // CHECK-NEXT: br i1 [[TMP0]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] // CHECK: resolver_return: // CHECK-NEXT: ret ptr @"_Z4foo4v.arch=rv64ima" // CHECK: resolver_else: -// CHECK-NEXT: [[TMP1:%.*]] = call i1 @__riscv_ifunc_select(i64 1, i64 20) +// CHECK-NEXT: [[TMP1:%.*]] = call i1 @__riscv_ifunc_select(ptr @__riscv_hwprobe_args.4, i32 2) // CHECK-NEXT: br i1 [[TMP1]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]] // CHECK: resolver_return1: // CHECK-NEXT: ret ptr @"_Z4foo4v.arch=+zbb,+v" diff --git a/llvm/include/llvm/TargetParser/RISCVTargetParser.h b/llvm/include/llvm/TargetParser/RISCVTargetParser.h index f249ecd2e56733..43e393919e6033 100644 --- a/llvm/include/llvm/TargetParser/RISCVTargetParser.h +++ b/llvm/include/llvm/TargetParser/RISCVTargetParser.h @@ -18,6 +18,48 @@ #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" +// Sync with https://docs.kernel.org/arch/riscv/hwprobe.html +// and compiler-rt/lib/builtins/riscv/ifunc_select.c +#define RISCV_HWPROBE_KEY_BASE_BEHAVIOR 3 +#define RISCV_HWPROBE_BASE_BEHAVIOR_IMA (1 << 0) +#define RISCV_HWPROBE_KEY_IMA_EXT_0 4 +#define RISCV_HWPROBE_IMA_FD (1 << 0) +#define RISCV_HWPROBE_IMA_C (1 << 1) +#define RISCV_HWPROBE_IMA_V (1 << 2) +#define RISCV_HWPROBE_EXT_ZBA (1 << 3) +#define RISCV_HWPROBE_EXT_ZBB (1 << 4) +#define RISCV_HWPROBE_EXT_ZBS (1 << 5) +#define RISCV_HWPROBE_EXT_ZICBOZ (1 << 6) +#define RISCV_HWPROBE_EXT_ZBC (1 << 7) +#define RISCV_HWPROBE_EXT_ZBKB (1 << 8) +#define RISCV_HWPROBE_EXT_ZBKC (1 << 9) +#define RISCV_HWPROBE_EXT_ZBKX (1 << 10) +#define RISCV_HWPROBE_EXT_ZKND (1 << 11) +#define RISCV_HWPROBE_EXT_ZKNE (1 << 12) +#define RISCV_HWPROBE_EXT_ZKNH (1 << 13) +#define RISCV_HWPROBE_EXT_ZKSED (1 << 14) +#define RISCV_HWPROBE_EXT_ZKSH (1 << 15) +#define RISCV_HWPROBE_EXT_ZKT (1 << 16) +#define RISCV_HWPROBE_EXT_ZVBB (1 << 17) +#define RISCV_HWPROBE_EXT_ZVBC (1 << 18) +#define RISCV_HWPROBE_EXT_ZVKB (1 << 19) +#define RISCV_HWPROBE_EXT_ZVKG (1 << 20) +#define RISCV_HWPROBE_EXT_ZVKNED (1 << 21) +#define RISCV_HWPROBE_EXT_ZVKNHA (1 << 22) +#define RISCV_HWPROBE_EXT_ZVKNHB (1 << 23) +#define RISCV_HWPROBE_EXT_ZVKSED (1 << 24) +#define RISCV_HWPROBE_EXT_ZVKSH (1 << 25) +#define RISCV_HWPROBE_EXT_ZVKT (1 << 26) +#define RISCV_HWPROBE_EXT_ZFH (1 << 27) +#define RISCV_HWPROBE_EXT_ZFHMIN (1 << 28) +#define RISCV_HWPROBE_EXT_ZIHINTNTL (1 << 29) +#define RISCV_HWPROBE_EXT_ZVFH (1 << 30) +#define RISCV_HWPROBE_EXT_ZVFHMIN (1 << 31) +#define RISCV_HWPROBE_EXT_ZFA (1ULL << 32) +#define RISCV_HWPROBE_EXT_ZTSO (1ULL << 33) +#define RISCV_HWPROBE_EXT_ZACAS (1ULL << 34) +#define RISCV_HWPROBE_EXT_ZICOND (1ULL << 35) + namespace llvm { class Triple; @@ -27,6 +69,11 @@ namespace RISCV { // We use 64 bits as the known part in the scalable vector types. static constexpr unsigned RVVBitsPerBlock = 64; +// RISC-V Hwprobe +const unsigned RISCVHwprobeLengthOfKey = 2; +const unsigned RISCVHwprobeKeyBase = RISCV_HWPROBE_KEY_BASE_BEHAVIOR; +const unsigned RISCVHwprobeKeyIMA = RISCV_HWPROBE_KEY_IMA_EXT_0; + void getFeaturesForCPU(StringRef CPU, SmallVectorImpl<std::string> &EnabledFeatures, bool NeedPlus = false); diff --git a/llvm/lib/TargetParser/RISCVTargetParser.cpp b/llvm/lib/TargetParser/RISCVTargetParser.cpp index b73861a5b8414b..59f34947d97055 100644 --- a/llvm/lib/TargetParser/RISCVTargetParser.cpp +++ b/llvm/lib/TargetParser/RISCVTargetParser.cpp @@ -120,48 +120,6 @@ void getFeaturesForCPU(StringRef CPU, EnabledFeatures.push_back(F.substr(1)); } -// Sync with https://docs.kernel.org/arch/riscv/hwprobe.html -// and compiler-rt/lib/builtins/riscv/ifunc_select.c -#define RISCV_HWPROBE_KEY_BASE_BEHAVIOR 3 -#define RISCV_HWPROBE_BASE_BEHAVIOR_IMA (1 << 0) -#define RISCV_HWPROBE_KEY_IMA_EXT_0 4 -#define RISCV_HWPROBE_IMA_FD (1 << 0) -#define RISCV_HWPROBE_IMA_C (1 << 1) -#define RISCV_HWPROBE_IMA_V (1 << 2) -#define RISCV_HWPROBE_EXT_ZBA (1 << 3) -#define RISCV_HWPROBE_EXT_ZBB (1 << 4) -#define RISCV_HWPROBE_EXT_ZBS (1 << 5) -#define RISCV_HWPROBE_EXT_ZICBOZ (1 << 6) -#define RISCV_HWPROBE_EXT_ZBC (1 << 7) -#define RISCV_HWPROBE_EXT_ZBKB (1 << 8) -#define RISCV_HWPROBE_EXT_ZBKC (1 << 9) -#define RISCV_HWPROBE_EXT_ZBKX (1 << 10) -#define RISCV_HWPROBE_EXT_ZKND (1 << 11) -#define RISCV_HWPROBE_EXT_ZKNE (1 << 12) -#define RISCV_HWPROBE_EXT_ZKNH (1 << 13) -#define RISCV_HWPROBE_EXT_ZKSED (1 << 14) -#define RISCV_HWPROBE_EXT_ZKSH (1 << 15) -#define RISCV_HWPROBE_EXT_ZKT (1 << 16) -#define RISCV_HWPROBE_EXT_ZVBB (1 << 17) -#define RISCV_HWPROBE_EXT_ZVBC (1 << 18) -#define RISCV_HWPROBE_EXT_ZVKB (1 << 19) -#define RISCV_HWPROBE_EXT_ZVKG (1 << 20) -#define RISCV_HWPROBE_EXT_ZVKNED (1 << 21) -#define RISCV_HWPROBE_EXT_ZVKNHA (1 << 22) -#define RISCV_HWPROBE_EXT_ZVKNHB (1 << 23) -#define RISCV_HWPROBE_EXT_ZVKSED (1 << 24) -#define RISCV_HWPROBE_EXT_ZVKSH (1 << 25) -#define RISCV_HWPROBE_EXT_ZVKT (1 << 26) -#define RISCV_HWPROBE_EXT_ZFH (1 << 27) -#define RISCV_HWPROBE_EXT_ZFHMIN (1 << 28) -#define RISCV_HWPROBE_EXT_ZIHINTNTL (1 << 29) -#define RISCV_HWPROBE_EXT_ZVFH (1 << 30) -#define RISCV_HWPROBE_EXT_ZVFHMIN (1 << 31) -#define RISCV_HWPROBE_EXT_ZFA (1ULL << 32) -#define RISCV_HWPROBE_EXT_ZTSO (1ULL << 33) -#define RISCV_HWPROBE_EXT_ZACAS (1ULL << 34) -#define RISCV_HWPROBE_EXT_ZICOND (1ULL << 35) - std::vector<unsigned long long> getBaseExtensionKey(ArrayRef<StringRef> Exts) { std::vector<unsigned long long> Result; for (auto Ext : Exts) { >From 586510954c2260b71c94464d0461c77c26c19ff4 Mon Sep 17 00:00:00 2001 From: Piyou Chen <piyou.c...@sifive.com> Date: Sun, 7 Apr 2024 21:07:09 -0700 Subject: [PATCH 06/10] Deny non-linux use hwprobe-base FMV resolver --- clang/include/clang/Basic/DiagnosticFrontendKinds.td | 3 +++ clang/lib/CodeGen/CodeGenFunction.cpp | 6 ++++++ .../test/CodeGen/attr-target-clones-riscv-invaild.c | 12 +++++++++--- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td index 89a8702d4a6bb6..bb0c80db0c7d85 100644 --- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -363,4 +363,7 @@ def err_extract_api_ignores_file_not_found : def err_extension_unsupport_riscv_hwprobe : Error< "Unsupport '%0' for _riscv_hwprobe">; +def err_os_unsupport_riscv_hwprobe : Error< + "Only Linux support _riscv_hwprobe">; + } diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 74b9b6860dec8d..3f6c9cdc2fc4aa 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -2816,6 +2816,12 @@ void CodeGenFunction::EmitMultiVersionResolver( void CodeGenFunction::EmitRISCVMultiVersionResolver( llvm::Function *Resolver, ArrayRef<MultiVersionResolverOption> Options) { + if (getContext().getTargetInfo().getTriple().getOS() != + llvm::Triple::OSType::Linux) { + CGM.getDiags().Report(diag::err_os_unsupport_riscv_hwprobe); + return; + } + auto EmitIFUNCFeatureCheckFunc = [&](llvm::SmallVector<StringRef, 8> CurrFeatStrs) -> llvm::Value * { llvm::SmallVector<llvm::Value *> FeatValue = diff --git a/clang/test/CodeGen/attr-target-clones-riscv-invaild.c b/clang/test/CodeGen/attr-target-clones-riscv-invaild.c index a88009ecc3d708..97f427a727cf13 100644 --- a/clang/test/CodeGen/attr-target-clones-riscv-invaild.c +++ b/clang/test/CodeGen/attr-target-clones-riscv-invaild.c @@ -1,8 +1,14 @@ -// RUN: not %clang_cc1 -triple riscv64-linux-gnu -target-feature +i -S -emit-llvm -o - %s 2>&1 | FileCheck %s +// RUN: not %clang_cc1 -triple riscv64-linux-gnu -target-feature +i -S -emit-llvm -o - %s 2>&1 | FileCheck %s --check-prefix=CHECK-UNSUPPORT-EXT +// RUN: not %clang_cc1 -triple riscv64 -target-feature +i -S -emit-llvm -o - %s 2>&1 | FileCheck %s --check-prefix=CHECK-UNSUPPORT-OS -// CHECK: error: Unsupport 'zicsr' for _riscv_hwprobe +// CHECK-UNSUPPORT-EXT: error: Unsupport 'zicsr' for _riscv_hwprobe __attribute__((target_clones("default", "arch=+zicsr"))) int foo1(void) { return 1; } -int bar() { return foo1(); } +// CHECK-UNSUPPORT-OS: error: Only Linux support _riscv_hwprobe +__attribute__((target_clones("default", "arch=+c"))) int foo2(void) { + return 2; +} + +int bar() { return foo1()+foo2(); } >From 8ee12b85b00736f426f1558063f5f35bd3718d67 Mon Sep 17 00:00:00 2001 From: Piyou Chen <piyou.c...@sifive.com> Date: Tue, 9 Apr 2024 03:32:11 -0700 Subject: [PATCH 07/10] Make structType into StructType --- clang/lib/CodeGen/CGBuiltin.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index cd8fc184b5bf56..67b3c2ff9151c6 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -14194,13 +14194,13 @@ CodeGenFunction::EmitRISCVExtSupports(ArrayRef<StringRef> FeaturesStrs) { << UnsupportByHwprobe[Idx]; } - StructType *structType = + StructType *StructType = StructType::create({llvm::Type::getInt64Ty(CGM.getLLVMContext()), llvm::Type::getInt64Ty(CGM.getLLVMContext())}, "riscv_hwprobe_pair"); auto *ATy = - llvm::ArrayType::get(structType, llvm::RISCV::RISCVHwprobeLengthOfKey); + llvm::ArrayType::get(StructType, llvm::RISCV::RISCVHwprobeLengthOfKey); auto createConstant = [&](unsigned long long Value) -> Constant * { return ConstantInt::get(llvm::Type::getInt64Ty(CGM.getLLVMContext()), @@ -14220,10 +14220,10 @@ CodeGenFunction::EmitRISCVExtSupports(ArrayRef<StringRef> FeaturesStrs) { SmallVector<Constant *> KeyValPairs; KeyValPairs.push_back(ConstantStruct::get( - structType, {createConstant(llvm::RISCV::RISCVHwprobeKeyBase), + StructType, {createConstant(llvm::RISCV::RISCVHwprobeKeyBase), createConstant(createHwprobeVal(BaseExtReqs))})); KeyValPairs.push_back(ConstantStruct::get( - structType, {createConstant(llvm::RISCV::RISCVHwprobeKeyIMA), + StructType, {createConstant(llvm::RISCV::RISCVHwprobeKeyIMA), createConstant(createHwprobeVal(IMACompatibleExtReqs))})); GlobalVariable *KeyValuePairs = new GlobalVariable( >From aff22edff6cd0ce521a1fcaae0920458f0789b8b Mon Sep 17 00:00:00 2001 From: Piyou Chen <piyou.c...@sifive.com> Date: Tue, 9 Apr 2024 04:15:43 -0700 Subject: [PATCH 08/10] Make Found into find --- clang/lib/CodeGen/CGBuiltin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 67b3c2ff9151c6..014603ccc76b4b 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -14173,7 +14173,7 @@ CodeGenFunction::EmitRISCVExtSupports(ArrayRef<StringRef> FeaturesStrs) { ImpliedExtBySupportExt.insert(FeaturesStrs[Idx].str()); } - // Repeatly find ImpliedExts until no longer found new. + // Repeatly find ImpliedExts until no longer find new. bool Changed = true; while (Changed) { unsigned Size = ImpliedExtBySupportExt.size(); >From 6f80943069840e4e67785f8227b2af39676cf6cc Mon Sep 17 00:00:00 2001 From: Piyou Chen <piyou.c...@sifive.com> Date: Tue, 9 Apr 2024 05:59:53 -0700 Subject: [PATCH 09/10] Rewrite ImpliedExts searching --- clang/lib/CodeGen/CGBuiltin.cpp | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 014603ccc76b4b..f27f73ead65734 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -14165,31 +14165,30 @@ CodeGenFunction::EmitRISCVExtSupports(ArrayRef<StringRef> FeaturesStrs) { // check whether all FeatureStrs are available for hwprobe. llvm::SmallVector<StringRef> UnsupportByHwprobe; - llvm::StringSet<> ImpliedExtBySupportExt; + llvm::SmallVector<std::string> SupportByHwprobe; for (unsigned Idx = 0; Idx < FeaturesStrs.size(); Idx++) { if (BaseExtReqs[Idx] == 0 && IMACompatibleExtReqs[Idx] == 0) UnsupportByHwprobe.push_back(FeaturesStrs[Idx]); else - ImpliedExtBySupportExt.insert(FeaturesStrs[Idx].str()); + SupportByHwprobe.push_back(FeaturesStrs[Idx].str()); } // Repeatly find ImpliedExts until no longer find new. - bool Changed = true; - while (Changed) { - unsigned Size = ImpliedExtBySupportExt.size(); - for (auto Ext : ImpliedExtBySupportExt.keys()) { - auto ImpliedExts = llvm::RISCV::getImpliedExts(Ext); - for (auto ImpliedExt : ImpliedExts) - ImpliedExtBySupportExt.insert(ImpliedExt); - } - if (Size == ImpliedExtBySupportExt.size()) - Changed = false; + llvm::SmallVector<std::string> ImpliedExts; + + while (!SupportByHwprobe.empty()) { + std::string Ext = SupportByHwprobe.pop_back_val(); + if (llvm::is_contained(ImpliedExts, Ext)) + continue; + ImpliedExts.push_back(Ext); + for (auto ImpliedExt : llvm::RISCV::getImpliedExts(Ext)) + SupportByHwprobe.push_back(ImpliedExt); } // FIXME: Could hwprobe guarantee that the hardware will support the Implied // extension? for (unsigned Idx = 0; Idx < UnsupportByHwprobe.size(); Idx++) { - if (!llvm::is_contained(ImpliedExtBySupportExt, UnsupportByHwprobe[Idx])) + if (!llvm::is_contained(ImpliedExts, UnsupportByHwprobe[Idx])) CGM.getDiags().Report(diag::err_extension_unsupport_riscv_hwprobe) << UnsupportByHwprobe[Idx]; } >From e55270476b9448648993d8bc036ca40214bd419a Mon Sep 17 00:00:00 2001 From: Piyou Chen <piyou.c...@sifive.com> Date: Tue, 9 Apr 2024 06:24:25 -0700 Subject: [PATCH 10/10] Fix typo --- clang/lib/CodeGen/CGBuiltin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index f27f73ead65734..bea451ae7af3b8 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -14163,7 +14163,7 @@ CodeGenFunction::EmitRISCVExtSupports(ArrayRef<StringRef> FeaturesStrs) { auto IMACompatibleExtReqs = llvm::RISCV::getIMACompatibleExtensionKey(FeaturesStrs); - // check whether all FeatureStrs are available for hwprobe. + // Check whether all FeatureStrs are available for hwprobe. llvm::SmallVector<StringRef> UnsupportByHwprobe; llvm::SmallVector<std::string> SupportByHwprobe; for (unsigned Idx = 0; Idx < FeaturesStrs.size(); Idx++) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits