BeMg updated this revision to Diff 557995. BeMg added a comment. 1. remain else if by removing continue 2. Keep NonISAExtFeature after override 3. Update testcase with -target-feature +save-restore 4. Improve resolveTargetOverride function
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D151730/new/ https://reviews.llvm.org/D151730 Files: clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Basic/Targets/RISCV.cpp clang/lib/Basic/Targets/RISCV.h clang/lib/Sema/SemaDeclAttr.cpp clang/test/CodeGen/RISCV/riscv-func-attr-target-err.c clang/test/CodeGen/RISCV/riscv-func-attr-target.c
Index: clang/test/CodeGen/RISCV/riscv-func-attr-target.c =================================================================== --- /dev/null +++ clang/test/CodeGen/RISCV/riscv-func-attr-target.c @@ -0,0 +1,46 @@ +// REQUIRES: riscv-registered-target +// RUN: %clang_cc1 -triple riscv64 -target-feature +zifencei -target-feature +m \ +// RUN: -target-feature +a -target-feature +save-restore \ +// RUN: -emit-llvm %s -o - | FileCheck %s + +// CHECK-LABEL: define dso_local void @testDefault +// CHECK-SAME: () #0 { +void testDefault() {} +// CHECK-LABEL: define dso_local void @testMultiAttrStr +// CHECK-SAME: () #1 { +__attribute__((target("cpu=rocket-rv64;tune=generic-rv64;arch=+v"))) void +testMultiAttrStr() {} +// CHECK-LABEL: define dso_local void @testSingleExtension +// CHECK-SAME: () #2 { +__attribute__((target("arch=+zbb"))) void testSingleExtension() {} +// CHECK-LABEL: define dso_local void @testMultiExtension +// CHECK-SAME: () #3 { +__attribute__((target("arch=+zbb,+v,+zicond"))) void testMultiExtension() {} +// CHECK-LABEL: define dso_local void @testFullArch +// CHECK-SAME: () #4 { +__attribute__((target("arch=rv64gc_zbb"))) void testFullArch() {} +// CHECK-LABEL: define dso_local void @testFullArchButSmallThanCmdArch +// CHECK-SAME: () #5 { +__attribute__((target("arch=rv64im"))) void testFullArchButSmallThanCmdArch() {} +// CHECK-LABEL: define dso_local void @testAttrArchAndAttrCpu +// CHECK-SAME: () #6 { +__attribute__((target("cpu=sifive-u54;arch=+zbb"))) void +testAttrArchAndAttrCpu() {} +// CHECK-LABEL: define dso_local void @testAttrFullArchAndAttrCpu +// CHECK-SAME: () #7 { +__attribute__((target("cpu=sifive-u54;arch=rv64im"))) void +testAttrFullArchAndAttrCpu() {} +// CHECK-LABEL: define dso_local void @testAttrCpuOnly +// CHECK-SAME: () #8 { +__attribute__((target("cpu=sifive-u54"))) void testAttrCpuOnly() {} + +//. +// CHECK: attributes #0 = { {{.*}}"target-features"="+64bit,+a,+m,+save-restore,+zifencei" } +// CHECK: attributes #1 = { {{.*}}"target-cpu"="rocket-rv64" "target-features"="+64bit,+a,+d,+f,+m,+save-restore,+v,+zicsr,+zifencei,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b" "tune-cpu"="generic-rv64" } +// CHECK: attributes #2 = { {{.*}}"target-features"="+64bit,+a,+m,+save-restore,+zbb,+zifencei" } +// CHECK: attributes #3 = { {{.*}}"target-features"="+64bit,+a,+d,+experimental-zicond,+f,+m,+save-restore,+v,+zbb,+zicsr,+zifencei,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b" } +// CHECK: attributes #4 = { {{.*}}"target-features"="+64bit,+a,+c,+d,+f,+m,+save-restore,+zbb,+zicsr,+zifencei" } +// CHECK: attributes #5 = { {{.*}}"target-features"="+64bit,+m,+save-restore" } +// CHECK: attributes #6 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+a,+m,+save-restore,+zbb,+zifencei" } +// CHECK: attributes #7 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+m,+save-restore" } +// CHECK: attributes #8 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+a,+c,+d,+f,+m,+save-restore,+zicsr,+zifencei" } Index: clang/test/CodeGen/RISCV/riscv-func-attr-target-err.c =================================================================== --- /dev/null +++ clang/test/CodeGen/RISCV/riscv-func-attr-target-err.c @@ -0,0 +1,10 @@ +// REQUIRES: riscv-registered-target +// RUN: not %clang_cc1 -triple riscv64 -target-feature +zifencei -target-feature +m -target-feature +a \ +// RUN: -emit-llvm %s 2>&1 | FileCheck %s + +// CHECK: error: duplicate 'arch=' in the 'target' attribute string; +__attribute__((target("arch=rv64gc;arch=rv64gc_zbb"))) void testMultiArchSelectLast() {} +// CHECK: error: duplicate 'cpu=' in the 'target' attribute string; +__attribute__((target("cpu=sifive-u74;cpu=sifive-u54"))) void testMultiCpuSelectLast() {} +// CHECK: error: duplicate 'tune=' in the 'target' attribute string; +__attribute__((target("tune=sifive-u74;tune=sifive-u54"))) void testMultiTuneSelectLast() {} Index: clang/lib/Sema/SemaDeclAttr.cpp =================================================================== --- clang/lib/Sema/SemaDeclAttr.cpp +++ clang/lib/Sema/SemaDeclAttr.cpp @@ -3450,6 +3450,11 @@ return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) << Unknown << Tune << ParsedAttrs.Tune << Target; + if (Context.getTargetInfo().getTriple().isRISCV() && + ParsedAttrs.Duplicate != "") + return Diag(LiteralLoc, diag::err_duplicate_target_attribute) + << Duplicate << None << ParsedAttrs.Duplicate << Target; + if (ParsedAttrs.Duplicate != "") return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) << Duplicate << None << ParsedAttrs.Duplicate << Target; Index: clang/lib/Basic/Targets/RISCV.h =================================================================== --- clang/lib/Basic/Targets/RISCV.h +++ clang/lib/Basic/Targets/RISCV.h @@ -114,6 +114,8 @@ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; bool isValidTuneCPUName(StringRef Name) const override; void fillValidTuneCPUList(SmallVectorImpl<StringRef> &Values) const override; + bool supportsTargetAttributeTune() const override { return true; } + ParsedTargetAttr parseTargetAttr(StringRef Str) const override; }; class LLVM_LIBRARY_VISIBILITY RISCV32TargetInfo : public RISCVTargetInfo { public: Index: clang/lib/Basic/Targets/RISCV.cpp =================================================================== --- clang/lib/Basic/Targets/RISCV.cpp +++ clang/lib/Basic/Targets/RISCV.cpp @@ -224,6 +224,47 @@ clang::RISCV::LastTSBuiltin - Builtin::FirstTSBuiltin); } +static std::vector<std::string> +collectNonISAExtFeature(const std::vector<std::string> &FeaturesVec, int XLen) { + auto I = llvm::find(FeaturesVec, "__RISCV_TargetAttrNeedOverride"); + auto FeatureNeedOveride = std::vector<std::string>(FeaturesVec.begin(), I); + auto ParseResult = + llvm::RISCVISAInfo::parseFeatures(XLen, FeatureNeedOveride); + + if (!ParseResult) { + consumeError(ParseResult.takeError()); + return std::vector<std::string>(); + } + + std::vector<std::string> ImpliedFeatures = (*ParseResult)->toFeatureVector(); + + std::vector<std::string> NonISAExtFeatureVec; + + for (auto Feat : FeatureNeedOveride) { + if (!llvm::is_contained(ImpliedFeatures, Feat)) + NonISAExtFeatureVec.push_back(Feat); + } + + return NonISAExtFeatureVec; +} + +static std::vector<std::string> +resolveTargetAttrOverride(const std::vector<std::string> &FeaturesVec, + int XLen) { + auto I = llvm::find(FeaturesVec, "__RISCV_TargetAttrNeedOverride"); + if (I == FeaturesVec.end()) + return FeaturesVec; + + std::vector<std::string> NonISAExtFeature = + collectNonISAExtFeature(FeaturesVec, XLen); + + auto ResolvedFeature = std::vector(++I, FeaturesVec.end()); + ResolvedFeature.insert(ResolvedFeature.end(), NonISAExtFeature.begin(), + NonISAExtFeature.end()); + + return ResolvedFeature; +} + bool RISCVTargetInfo::initFeatureMap( llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU, const std::vector<std::string> &FeaturesVec) const { @@ -237,7 +278,10 @@ Features["32bit"] = true; } - auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, FeaturesVec); + std::vector<std::string> NewFeaturesVec = + resolveTargetAttrOverride(FeaturesVec, XLen); + + auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, NewFeaturesVec); if (!ParseResult) { std::string Buffer; llvm::raw_string_ostream OutputErrMsg(Buffer); @@ -251,7 +295,7 @@ // RISCVISAInfo makes implications for ISA features std::vector<std::string> ImpliedFeatures = (*ParseResult)->toFeatureVector(); // Add non-ISA features like `relax` and `save-restore` back - for (const std::string &Feature : FeaturesVec) + for (const std::string &Feature : NewFeaturesVec) if (!llvm::is_contained(ImpliedFeatures, Feature)) ImpliedFeatures.push_back(Feature); @@ -346,3 +390,82 @@ bool Is64Bit = getTriple().isArch64Bit(); llvm::RISCV::fillValidTuneCPUArchList(Values, Is64Bit); } + +static void handleFullArchString(StringRef FullArchStr, + std::vector<std::string> &Features) { + Features.push_back("__RISCV_TargetAttrNeedOverride"); + auto RII = llvm::RISCVISAInfo::parseArchString( + FullArchStr, /* EnableExperimentalExtension */ true); + if (!RII) { + consumeError(RII.takeError()); + // Forward the invalid FullArchStr. + Features.push_back("+" + FullArchStr.str()); + } else { + std::vector<std::string> FeatStrings = (*RII)->toFeatureVector(); + for (auto FeatString : FeatStrings) + Features.push_back(FeatString); + } +} + +ParsedTargetAttr RISCVTargetInfo::parseTargetAttr(StringRef Features) const { + ParsedTargetAttr Ret; + if (Features == "default") + return Ret; + SmallVector<StringRef, 1> AttrFeatures; + Features.split(AttrFeatures, ";"); + bool FoundArch = false; + + for (auto &Feature : AttrFeatures) { + Feature = Feature.trim(); + StringRef AttrString = Feature.split("=").second.trim(); + + if (Feature.startswith("arch=")) { + // Override last features + Ret.Features.clear(); + if (FoundArch) + Ret.Duplicate = "arch="; + FoundArch = true; + + if (AttrString.startswith("+")) { + // EXTENSION like arch=+v,+zbb + SmallVector<StringRef, 1> Exts; + AttrString.split(Exts, ","); + for (auto Ext : Exts) { + if (Ext.empty()) + continue; + + StringRef ExtName = Ext.substr(1); + std::string TargetFeature = + llvm::RISCVISAInfo::getTargetFeatureForExtension(ExtName); + if (!TargetFeature.empty()) + Ret.Features.push_back(Ext.front() + TargetFeature); + else + Ret.Features.push_back(Ext.str()); + } + } else { + // full-arch-string like arch=rv64gcv + handleFullArchString(AttrString, Ret.Features); + } + } else if (Feature.startswith("cpu=")) { + if (!Ret.CPU.empty()) + Ret.Duplicate = "cpu="; + + Ret.CPU = AttrString; + + if (!FoundArch) { + // Update Features with CPU's features + StringRef MarchFromCPU = llvm::RISCV::getMArchFromMcpu(Ret.CPU); + if (MarchFromCPU != "") { + Ret.Features.clear(); + handleFullArchString(MarchFromCPU, Ret.Features); + } + } + } else if (Feature.startswith("tune=")) { + if (!Ret.Tune.empty()) + Ret.Duplicate = "tune="; + + Ret.Tune = AttrString; + } + } + return Ret; +} Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3143,6 +3143,10 @@ def err_attribute_unsupported : Error<"%0 attribute is not supported on targets missing %1;" " specify an appropriate -march= or -mcpu=">; +def err_duplicate_target_attribute + : Error<"%select{unsupported|duplicate|unknown}0%select{| CPU|" + " tune CPU}1 '%2' in the '%select{target|target_clones|target_version}3' " + "attribute string; ">; // The err_*_attribute_argument_not_int are separate because they're used by // VerifyIntegerConstantExpression. def err_aligned_attribute_argument_not_int : Error<
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits