-
Notifications
You must be signed in to change notification settings - Fork 13.9k
Reland "[Clang][LoongArch] Support target attribute for function" #142546
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This relands llvm#140700. I have updated the test case('targetattr.c') to resolve the test failure. Original PR resulted in test fail: https://lab.llvm.org/buildbot/#/builders/11/builds/16173 https://lab.llvm.org/buildbot/#/builders/202/builds/1531 Original description: Followup to llvm#140700.
@llvm/pr-subscribers-backend-loongarch @llvm/pr-subscribers-clang Author: None (Ami-zhang) ChangesThis relands #140700. I have updated the test case('targetattr.c') to resolve the test failure. Original PR resulted in test fail: Original description: Full diff: https://github.com/llvm/llvm-project/pull/142546.diff 7 Files Affected:
diff --git a/clang/lib/Basic/Targets/LoongArch.cpp b/clang/lib/Basic/Targets/LoongArch.cpp
index 67476ee651c2b..5312767498d96 100644
--- a/clang/lib/Basic/Targets/LoongArch.cpp
+++ b/clang/lib/Basic/Targets/LoongArch.cpp
@@ -392,6 +392,73 @@ bool LoongArchTargetInfo::handleTargetFeatures(
return true;
}
+enum class AttrFeatureKind { Arch, Tune, NoFeature, Feature };
+
+static std::pair<AttrFeatureKind, llvm::StringRef>
+getAttrFeatureTypeAndValue(llvm::StringRef AttrFeature) {
+ if (auto Split = AttrFeature.split("="); !Split.second.empty()) {
+ if (Split.first.trim() == "arch")
+ return {AttrFeatureKind::Arch, Split.second.trim()};
+ if (Split.first.trim() == "tune")
+ return {AttrFeatureKind::Tune, Split.second.trim()};
+ }
+ if (AttrFeature.starts_with("no-"))
+ return {AttrFeatureKind::NoFeature, AttrFeature.drop_front(3)};
+ return {AttrFeatureKind::Feature, AttrFeature};
+}
+
+ParsedTargetAttr
+LoongArchTargetInfo::parseTargetAttr(StringRef Features) const {
+ ParsedTargetAttr Ret;
+ if (Features == "default")
+ return Ret;
+ SmallVector<StringRef, 1> AttrFeatures;
+ Features.split(AttrFeatures, ",");
+
+ for (auto &Feature : AttrFeatures) {
+ auto [Kind, Value] = getAttrFeatureTypeAndValue(Feature.trim());
+
+ switch (Kind) {
+ case AttrFeatureKind::Arch: {
+ if (llvm::LoongArch::isValidArchName(Value) || Value == "la64v1.0" ||
+ Value == "la64v1.1") {
+ std::vector<llvm::StringRef> ArchFeatures;
+ if (llvm::LoongArch::getArchFeatures(Value, ArchFeatures)) {
+ Ret.Features.insert(Ret.Features.end(), ArchFeatures.begin(),
+ ArchFeatures.end());
+ }
+
+ if (!Ret.CPU.empty())
+ Ret.Duplicate = "arch=";
+ else if (Value == "la64v1.0" || Value == "la64v1.1")
+ Ret.CPU = "loongarch64";
+ else
+ Ret.CPU = Value;
+ } else {
+ Ret.Features.push_back("!arch=" + Value.str());
+ }
+ break;
+ }
+
+ case AttrFeatureKind::Tune:
+ if (!Ret.Tune.empty())
+ Ret.Duplicate = "tune=";
+ else
+ Ret.Tune = Value;
+ break;
+
+ case AttrFeatureKind::NoFeature:
+ Ret.Features.push_back("-" + Value.str());
+ break;
+
+ case AttrFeatureKind::Feature:
+ Ret.Features.push_back("+" + Value.str());
+ break;
+ }
+ }
+ return Ret;
+}
+
bool LoongArchTargetInfo::isValidCPUName(StringRef Name) const {
return llvm::LoongArch::isValidCPUName(Name);
}
@@ -400,3 +467,7 @@ void LoongArchTargetInfo::fillValidCPUList(
SmallVectorImpl<StringRef> &Values) const {
llvm::LoongArch::fillValidCPUList(Values);
}
+
+bool LoongArchTargetInfo::isValidFeatureName(StringRef Name) const {
+ return llvm::LoongArch::isValidFeatureName(Name);
+}
diff --git a/clang/lib/Basic/Targets/LoongArch.h b/clang/lib/Basic/Targets/LoongArch.h
index 4c7b53abfef9b..a83bb925bc310 100644
--- a/clang/lib/Basic/Targets/LoongArch.h
+++ b/clang/lib/Basic/Targets/LoongArch.h
@@ -101,6 +101,9 @@ class LLVM_LIBRARY_VISIBILITY LoongArchTargetInfo : public TargetInfo {
bool handleTargetFeatures(std::vector<std::string> &Features,
DiagnosticsEngine &Diags) override;
+ ParsedTargetAttr parseTargetAttr(StringRef Str) const override;
+ bool supportsTargetAttributeTune() const override { return true; }
+
bool
initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
StringRef CPU,
@@ -110,6 +113,7 @@ class LLVM_LIBRARY_VISIBILITY LoongArchTargetInfo : public TargetInfo {
bool isValidCPUName(StringRef Name) const override;
void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
+ bool isValidFeatureName(StringRef Name) const override;
};
class LLVM_LIBRARY_VISIBILITY LoongArch32TargetInfo
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index aba989f1029b9..a8e4023fb02ba 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -3195,6 +3195,17 @@ bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) {
}
}
+ if (Context.getTargetInfo().getTriple().isLoongArch()) {
+ for (const auto &Feature : ParsedAttrs.Features) {
+ StringRef CurFeature = Feature;
+ if (CurFeature.starts_with("!arch=")) {
+ StringRef ArchValue = CurFeature.split("=").second.trim();
+ return Diag(LiteralLoc, diag::err_attribute_unsupported)
+ << "target(arch=..)" << ArchValue;
+ }
+ }
+ }
+
if (ParsedAttrs.Duplicate != "")
return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
<< Duplicate << None << ParsedAttrs.Duplicate << Target;
diff --git a/clang/test/CodeGen/LoongArch/targetattr.c b/clang/test/CodeGen/LoongArch/targetattr.c
new file mode 100644
index 0000000000000..91156e6006e75
--- /dev/null
+++ b/clang/test/CodeGen/LoongArch/targetattr.c
@@ -0,0 +1,89 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals all --version 5
+// RUN: %clang_cc1 -triple loongarch64 -emit-llvm %s -o - | FileCheck %s
+
+__attribute__((target("div32")))
+// CHECK-LABEL: define dso_local void @testdiv32(
+// CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: ret void
+//
+void testdiv32() {}
+
+__attribute__((target("arch=loongarch64")))
+// CHECK-LABEL: define dso_local void @testLoongarch64(
+// CHECK-SAME: ) #[[ATTR1:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: ret void
+//
+void testLoongarch64() {}
+
+__attribute__((target("arch=la64v1.0")))
+// CHECK-LABEL: define dso_local void @testLa64v10(
+// CHECK-SAME: ) #[[ATTR2:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: ret void
+//
+void testLa64v10() {}
+
+__attribute__((target("arch=la64v1.1")))
+// CHECK-LABEL: define dso_local void @testLa64v11(
+// CHECK-SAME: ) #[[ATTR3:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: ret void
+//
+void testLa64v11() {}
+
+__attribute__((target("arch=la464")))
+// CHECK-LABEL: define dso_local void @testLa464(
+// CHECK-SAME: ) #[[ATTR4:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: ret void
+//
+void testLa464() {}
+
+__attribute__((target("arch=la664")))
+// CHECK-LABEL: define dso_local void @testLa664(
+// CHECK-SAME: ) #[[ATTR5:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: ret void
+//
+void testLa664() {}
+
+__attribute__((target("arch=la664, no-div32")))
+// CHECK-LABEL: define dso_local void @la664Nodiv32(
+// CHECK-SAME: ) #[[ATTR6:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: ret void
+//
+void la664Nodiv32() {}
+
+__attribute__((target("tune=la464")))
+// CHECK-LABEL: define dso_local void @tuneLa464(
+// CHECK-SAME: ) #[[ATTR7:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: ret void
+//
+void tuneLa464() {}
+
+__attribute__((target("arch=la464, tune=la664")))
+// CHECK-LABEL: define dso_local void @archLa464tuneLa664(
+// CHECK-SAME: ) #[[ATTR8:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: ret void
+//
+void archLa464tuneLa664() {}
+
+//.
+// CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+div32" }
+// CHECK: attributes #[[ATTR1]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="loongarch64" "target-features"="+64bit,+d,+f,+ual" }
+// CHECK: attributes #[[ATTR2]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="loongarch64" "target-features"="+64bit,+d,+lsx,+ual" }
+// CHECK: attributes #[[ATTR3]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="loongarch64" "target-features"="+64bit,+d,+div32,+frecipe,+lam-bh,+lamcas,+ld-seq-sa,+lsx,+scq,+ual" }
+// CHECK: attributes #[[ATTR4]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="la464" "target-features"="+64bit,+d,+f,+lasx,+lsx,+ual" }
+// CHECK: attributes #[[ATTR5]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="la664" "target-features"="+64bit,+d,+div32,+f,+frecipe,+lam-bh,+lamcas,+lasx,+ld-seq-sa,+lsx,+scq,+ual" }
+// CHECK: attributes #[[ATTR6]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="la664" "target-features"="+64bit,+d,+f,+frecipe,+lam-bh,+lamcas,+lasx,+ld-seq-sa,+lsx,+scq,+ual,-div32" }
+// CHECK: attributes #[[ATTR7]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit" "tune-cpu"="la464" }
+// CHECK: attributes #[[ATTR8]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="la464" "target-features"="+64bit,+d,+f,+lasx,+lsx,+ual" "tune-cpu"="la664" }
+//.
+// CHECK: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
+// CHECK: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}
+//.
diff --git a/clang/test/Sema/attr-target-loongarch.c b/clang/test/Sema/attr-target-loongarch.c
new file mode 100644
index 0000000000000..10ac8334bdb0c
--- /dev/null
+++ b/clang/test/Sema/attr-target-loongarch.c
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -triple loongarch64-linux-gnu -fsyntax-only -verify %s
+
+// expected-error@+1 {{function multiversioning is not supported on the current target}}
+void __attribute__((target("default"))) bar(void) {}
+
+// expected-error@+1 {{target(arch=..) attribute is not supported on targets missing invalid; specify an appropriate -march= or -mcpu=}}
+void __attribute__((target("arch=invalid"))) foo(void) {}
+
+// expected-warning@+1 {{unsupported '+div32' in the 'target' attribute string; 'target' attribute ignored}}
+void __attribute__((target("+div32"))) plusfeature(void) {}
+
+// expected-warning@+1 {{unsupported '-div32' in the 'target' attribute string; 'target' attribute ignored}}
+void __attribute__((target("-div32"))) minusfeature(void) {}
+
+// expected-warning@+1 {{unsupported 'aaa' in the 'target' attribute string; 'target' attribute ignored}}
+int __attribute__((target("aaa"))) test_feature(void) { return 4; }
+
+// expected-warning@+1 {{unsupported 'aaa' in the 'target' attribute string; 'target' attribute ignored}}
+int __attribute__((target("no-aaa"))) test_nofeature(void) { return 4; }
+
+// expected-warning@+1 {{duplicate 'arch=' in the 'target' attribute string; 'target' attribute ignored}}
+int __attribute__((target("arch=la464,arch=la664"))) test_duplarch(void) { return 4; }
+
+// expected-warning@+1 {{unknown tune CPU 'la64v1.0' in the 'target' attribute string; 'target' attribute ignored}}
+int __attribute__((target("tune=la64v1.0"))) test_tune(void) { return 4; }
diff --git a/llvm/include/llvm/TargetParser/LoongArchTargetParser.h b/llvm/include/llvm/TargetParser/LoongArchTargetParser.h
index e08e7bc182e11..a28e4e9eff811 100644
--- a/llvm/include/llvm/TargetParser/LoongArchTargetParser.h
+++ b/llvm/include/llvm/TargetParser/LoongArchTargetParser.h
@@ -85,6 +85,7 @@ struct ArchInfo {
};
bool isValidArchName(StringRef Arch);
+bool isValidFeatureName(StringRef Feature);
bool getArchFeatures(StringRef Arch, std::vector<StringRef> &Features);
bool isValidCPUName(StringRef TuneCPU);
void fillValidCPUList(SmallVectorImpl<StringRef> &Values);
diff --git a/llvm/lib/TargetParser/LoongArchTargetParser.cpp b/llvm/lib/TargetParser/LoongArchTargetParser.cpp
index e394c0c15b207..db68498609b57 100644
--- a/llvm/lib/TargetParser/LoongArchTargetParser.cpp
+++ b/llvm/lib/TargetParser/LoongArchTargetParser.cpp
@@ -34,6 +34,18 @@ bool LoongArch::isValidArchName(StringRef Arch) {
return false;
}
+bool LoongArch::isValidFeatureName(StringRef Feature) {
+ if (Feature.starts_with("+") || Feature.starts_with("-"))
+ return false;
+ for (const auto &F : AllFeatures) {
+ StringRef CanonicalName =
+ F.Name.starts_with("+") ? F.Name.drop_front() : F.Name;
+ if (CanonicalName == Feature)
+ return true;
+ }
+ return false;
+}
+
bool LoongArch::getArchFeatures(StringRef Arch,
std::vector<StringRef> &Features) {
for (const auto A : AllArchs) {
|
…vm#142546) This relands llvm#140700. I have updated the test case('targetattr.c') to resolve the test failure. Original PR resulted in test fail: https://lab.llvm.org/buildbot/#/builders/11/builds/16173 https://lab.llvm.org/buildbot/#/builders/202/builds/1531 Original description: Followup to llvm#140700.
…vm#142546) This relands llvm#140700. I have updated the test case('targetattr.c') to resolve the test failure. Original PR resulted in test fail: https://lab.llvm.org/buildbot/#/builders/11/builds/16173 https://lab.llvm.org/buildbot/#/builders/202/builds/1531 Original description: Followup to llvm#140700.
…vm#142546) This relands llvm#140700. I have updated the test case('targetattr.c') to resolve the test failure. Original PR resulted in test fail: https://lab.llvm.org/buildbot/#/builders/11/builds/16173 https://lab.llvm.org/buildbot/#/builders/202/builds/1531 Original description: Followup to llvm#140700.
This relands #140700. I have updated the test case('targetattr.c') to resolve the test failure.
Original PR resulted in test fail:
https://lab.llvm.org/buildbot/#/builders/11/builds/16173 https://lab.llvm.org/buildbot/#/builders/202/builds/1531
Original description:
Followup to #140700.