Skip to content

Conversation

@Ami-zhang
Copy link
Contributor

This adds support under LoongArch for the target("..") attributes.

The supported formats are:

  • "arch=" strings, that specify the architecture features for a function as per the -march=arch option.
  • "tune=" strings, that specify the tune-cpu cpu for a function as per -mtune.
  • "", "no-" enabled/disables the specific feature.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" backend:loongarch labels May 20, 2025
@llvmbot
Copy link
Member

llvmbot commented May 20, 2025

@llvm/pr-subscribers-backend-loongarch

@llvm/pr-subscribers-clang

Author: None (Ami-zhang)

Changes

This adds support under LoongArch for the target("..") attributes.

The supported formats are:

  • "arch=<arch>" strings, that specify the architecture features for a function as per the -march=arch option.
  • "tune=<cpu>" strings, that specify the tune-cpu cpu for a function as per -mtune.
  • "<feature>", "no-<feature>" enabled/disables the specific feature.

Full diff: https://github.com/llvm/llvm-project/pull/140700.diff

7 Files Affected:

  • (modified) clang/lib/Basic/Targets/LoongArch.cpp (+49)
  • (modified) clang/lib/Basic/Targets/LoongArch.h (+4)
  • (modified) clang/lib/Sema/SemaDeclAttr.cpp (+11)
  • (added) clang/test/CodeGen/LoongArch/targetattr.c (+92)
  • (added) clang/test/Sema/attr-target-loongarch.c (+19)
  • (modified) llvm/include/llvm/TargetParser/LoongArchTargetParser.h (+1)
  • (modified) llvm/lib/TargetParser/LoongArchTargetParser.cpp (+11)
diff --git a/clang/lib/Basic/Targets/LoongArch.cpp b/clang/lib/Basic/Targets/LoongArch.cpp
index ca742797d7a3b..aee273a76a608 100644
--- a/clang/lib/Basic/Targets/LoongArch.cpp
+++ b/clang/lib/Basic/Targets/LoongArch.cpp
@@ -388,6 +388,51 @@ bool LoongArchTargetInfo::handleTargetFeatures(
   return true;
 }
 
+ParsedTargetAttr
+LoongArchTargetInfo::parseTargetAttr(StringRef Features) const {
+  ParsedTargetAttr Ret;
+  if (Features == "default")
+    return Ret;
+  SmallVector<StringRef, 1> AttrFeatures;
+  Features.split(AttrFeatures, ",");
+
+  for (auto &Feature : AttrFeatures) {
+    Feature = Feature.trim();
+
+    if (Feature.starts_with("arch=")) {
+      StringRef ArchValue = Feature.split("=").second.trim();
+
+      if (llvm::LoongArch::isValidArchName(ArchValue) ||
+          ArchValue == "la64v1.0" || ArchValue == "la64v1.1") {
+        std::vector<llvm::StringRef> ArchFeatures;
+        if (llvm::LoongArch::getArchFeatures(ArchValue, ArchFeatures)) {
+          Ret.Features.insert(Ret.Features.end(), ArchFeatures.begin(),
+                              ArchFeatures.end());
+        }
+
+        if (!Ret.CPU.empty())
+          Ret.Duplicate = "arch=";
+        else if (ArchValue == "la64v1.0" || ArchValue == "la64v1.1")
+          Ret.CPU = "loongarch64";
+        else
+          Ret.CPU = ArchValue;
+      } else {
+        Ret.Features.push_back("!arch=" + ArchValue.str());
+      }
+    } else if (Feature.starts_with("tune=")) {
+      if (!Ret.Tune.empty())
+        Ret.Duplicate = "tune=";
+      else
+        Ret.Tune = Feature.split("=").second.trim();
+    } else if (Feature.starts_with("no-")) {
+      Ret.Features.push_back("-" + Feature.split("-").second.str());
+    } else {
+      Ret.Features.push_back("+" + Feature.str());
+    }
+  }
+  return Ret;
+}
+
 bool LoongArchTargetInfo::isValidCPUName(StringRef Name) const {
   return llvm::LoongArch::isValidCPUName(Name);
 }
@@ -396,3 +441,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 4d7f0455444f1..8e44e2e44bb24 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..a99e12051452b
--- /dev/null
+++ b/clang/test/CodeGen/LoongArch/targetattr.c
@@ -0,0 +1,92 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals all --version 5
+// RUN: %clang --target=loongarch64-linux-gnu %s -S -emit-llvm -o - \
+// RUN:   | 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: ) #[[ATTR1]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    ret void
+//
+void testLa64v10() {}
+
+__attribute__((target("arch=la64v1.1")))
+// CHECK-LABEL: define dso_local void @testLa64v11(
+// CHECK-SAME: ) #[[ATTR2:[0-9]+]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    ret void
+//
+void testLa64v11() {}
+
+__attribute__((target("arch=la464")))
+// CHECK-LABEL: define dso_local void @testLa464(
+// CHECK-SAME: ) #[[ATTR3:[0-9]+]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    ret void
+//
+void testLa464() {}
+
+__attribute__((target("arch=la664")))
+// CHECK-LABEL: define dso_local void @testLa664(
+// CHECK-SAME: ) #[[ATTR4:[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: ) #[[ATTR5:[0-9]+]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    ret void
+//
+void la664Nodiv32() {}
+
+__attribute__((target("tune=la464")))
+// CHECK-LABEL: define dso_local void @tuneLa664(
+// CHECK-SAME: ) #[[ATTR6:[0-9]+]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    ret void
+//
+void tuneLa664() {}
+
+__attribute__((target("arch=la464, tune=la664")))
+// CHECK-LABEL: define dso_local void @archLa464tuneLa664(
+// CHECK-SAME: ) #[[ATTR7:[0-9]+]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    ret void
+//
+void archLa464tuneLa664() {}
+
+//.
+// CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="loongarch64" "target-features"="+64bit,+d,+div32,+f,+lsx,+ual" }
+// CHECK: attributes #[[ATTR1]] = { noinline nounwind optnone "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="loongarch64" "target-features"="+64bit,+d,+f,+lsx,+ual" }
+// CHECK: attributes #[[ATTR2]] = { noinline nounwind optnone "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="loongarch64" "target-features"="+64bit,+d,+div32,+f,+frecipe,+lam-bh,+lamcas,+ld-seq-sa,+lsx,+scq,+ual" }
+// CHECK: attributes #[[ATTR3]] = { noinline nounwind optnone "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="la464" "target-features"="+64bit,+d,+f,+lasx,+lsx,+ual" }
+// CHECK: attributes #[[ATTR4]] = { noinline nounwind optnone "frame-pointer"="all" "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 #[[ATTR5]] = { noinline nounwind optnone "frame-pointer"="all" "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 #[[ATTR6]] = { noinline nounwind optnone "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="loongarch64" "target-features"="+64bit,+d,+f,+lsx,+ual" "tune-cpu"="la464" }
+// CHECK: attributes #[[ATTR7]] = { noinline nounwind optnone "frame-pointer"="all" "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]+]] = !{i32 8, !"PIC Level", i32 2}
+// CHECK: [[META2:![0-9]+]] = !{i32 7, !"PIE Level", i32 2}
+// CHECK: [[META3:![0-9]+]] = !{i32 7, !"frame-pointer", i32 2}
+// CHECK: [[META4:![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..77f13e891ea63
--- /dev/null
+++ b/clang/test/Sema/attr-target-loongarch.c
@@ -0,0 +1,19 @@
+// 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 '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..c425ce271c559 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 Arch);
 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..7bd1711538d25 100644
--- a/llvm/lib/TargetParser/LoongArchTargetParser.cpp
+++ b/llvm/lib/TargetParser/LoongArchTargetParser.cpp
@@ -34,6 +34,17 @@ bool LoongArch::isValidArchName(StringRef Arch) {
   return false;
 }
 
+bool LoongArch::isValidFeatureName(StringRef Feature) {
+  Feature = Feature.starts_with("+") ? Feature.drop_front() : Feature;
+  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) {

@Ami-zhang Ami-zhang requested review from SixWeining and wangleiat May 20, 2025 11:01
for (auto &Feature : AttrFeatures) {
Feature = Feature.trim();

if (Feature.starts_with("arch=")) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's recommended to use use a helper function to handle the types of features. Like below.
If it's ok to define a FeatureKind enum, that would be even better.

static std::pair<llvm::StringRef, llvm::StringRef> getFeatureTypeAndValue(llvm::StringRef Feature) {
  auto Split = Feature.split("=");
  if (!Split.second.empty())
    return {Split.first.trim(), Split.second.trim()};
  if (Feature.starts_with("no-"))
    return {"no", Feature.drop_front(3).trim()};
  return {"feature", Feature.trim()};
}
  for (auto &Feature : AttrFeatures) {
    Feature = Feature.trim();
    auto [Kind, Value] = getFeatureTypeAndValue(Feature);

    if (Kind == "arch") {
    } else if (Kind == "tune") {
    } ..
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion! Using a helper function with a FeatureKind enum is indeed a cleaner and more modular approach.
However, since parseTargetAttr is a common-layer interface that we are simply overriding, I'd prefer to maintain consistency with the common-layer and current RISCV/AArch64 implementations. Keeping the same style offers several benefits:

  1. Codebase uniformity – Ensures architectural implementations remain predictable.
  2. Easier maintenance – Developers working across architectures can recognize the pattern immediately.
  3. Historical consistency – Follows the established patterns for this interface.

If we decide to refactor this interface globally(e.g., by introducing helper functions), I'd be happy to align the LoongArch implementation accordingly.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that the previous approach was essentially off-the-cuff, done whichever way was most convenient.

If someone were to implement the same functionality for other architectures as well, they would find three pieces of code with very poor style.

To leave behind code that is more ergonomic for future developers, at the very least, the logic for handling features should be separated and handled individually.

auto handleArch = [&](StringRef Feature) { ... }
auto handleTune = [&](StringRef Feature) { ... }

if(feature.startwith("arch=") handleArch(feature)
else (feature.startwith("tune=") handleTune(feature)
else if ( ... ) ...
else {

}

// 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){}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
void __attribute__((target("default"))) bar(void){}
void __attribute__((target("default"))) bar(void) {}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

// 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 'aaa' in the 'target' attribute string; 'target' attribute ignored}}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
//expected-warning@+1 {{unsupported 'aaa' in the 'target' attribute string; 'target' attribute ignored}}
// expected-warning@+1 {{unsupported 'aaa' in the 'target' attribute string; 'target' attribute ignored}}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

//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}}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
//expected-warning@+1 {{unsupported 'aaa' in the 'target' attribute string; 'target' attribute ignored}}
// expected-warning@+1 {{unsupported 'aaa' in the 'target' attribute string; 'target' attribute ignored}}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Member

@heiher heiher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with nits.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make the test function name align with the target feature.

Suggested change
void tuneLa664() {}
void tuneLa464() {}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The caller has already performed trim(), so it's unnecessary here, just like starts_with() above doesn't use it either.

Suggested change
return {AttrFeatureKind::Feature, AttrFeature.trim()};
return {AttrFeatureKind::Feature, AttrFeature};

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, thanks.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default return may cause us to miss the check for invalid strings. (like this: "+lasx", here will be two plus signs in the generated IR) . Perhaps we can perform the check inside isValidFeature()?"

Copy link
Contributor Author

@Ami-zhang Ami-zhang May 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Appreciate the review suggestion. The validation will be handled in isValidFeatureName(), with corresponding test cases added.Thanks!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to LoongArchTargetInfo::parseTargetAttr(), this condition may always be false.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My mistake — I didn't notice the !.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Arch -> Feature

Copy link
Contributor Author

@Ami-zhang Ami-zhang May 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done,thanks.

Copy link
Contributor

@wangleiat wangleiat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with some minor nits, thanks.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The braces can be omitted.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Beware unnecessary copies.
auto &F

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Contributor

@wangleiat wangleiat May 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is Invalid unused?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed.

Ami-zhang added 2 commits May 29, 2025 11:39
This adds support under LoongArch for the target("..") attributes.

The supported formats are:
- "arch=<arch>" strings, that specify the architecture features for a
  function as per the -march=arch option.
- "tune=<cpu>" strings, that specify the tune-cpu cpu for a function as
  per -mtune.
- "<feature>", "no-<feature>" enabled/disables the specific feature.
Introduce AttrFeatureKind enum to classify target attributes, and
implement getAttrFeatureTypeAndValue() helper for centralized parsing.
@Ami-zhang Ami-zhang merged commit b359422 into llvm:main May 29, 2025
11 checks passed
@Ami-zhang Ami-zhang deleted the targetattr branch May 29, 2025 11:54
@llvm-ci
Copy link
Collaborator

llvm-ci commented May 29, 2025

LLVM Buildbot has detected a new failure on builder fuchsia-x86_64-linux running on fuchsia-debian-64-us-central1-a-1 while building clang,llvm at step 4 "annotate".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/11/builds/16173

Here is the relevant piece of the build log for the reference
Step 4 (annotate) failure: 'python ../llvm-zorg/zorg/buildbot/builders/annotated/fuchsia-linux.py ...' (failure)
...
[849/1374] Running the Clang regression tests
llvm-lit: /var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using clang: /var/lib/buildbot/fuchsia-x86_64-linux/build/llvm-build-ilqvuc8n/bin/clang
llvm-lit: /var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/llvm/utils/lit/lit/llvm/subst.py:126: note: Did not find cir-opt in /var/lib/buildbot/fuchsia-x86_64-linux/build/llvm-build-ilqvuc8n/bin:/var/lib/buildbot/fuchsia-x86_64-linux/build/llvm-build-ilqvuc8n/bin
llvm-lit: /var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/llvm/utils/lit/lit/llvm/subst.py:126: note: Did not find clang-repl in /var/lib/buildbot/fuchsia-x86_64-linux/build/llvm-build-ilqvuc8n/bin:/var/lib/buildbot/fuchsia-x86_64-linux/build/llvm-build-ilqvuc8n/bin
llvm-lit: /var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using ld.lld: /var/lib/buildbot/fuchsia-x86_64-linux/build/llvm-build-ilqvuc8n/bin/ld.lld
llvm-lit: /var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using lld-link: /var/lib/buildbot/fuchsia-x86_64-linux/build/llvm-build-ilqvuc8n/bin/lld-link
llvm-lit: /var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using ld64.lld: /var/lib/buildbot/fuchsia-x86_64-linux/build/llvm-build-ilqvuc8n/bin/ld64.lld
llvm-lit: /var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using wasm-ld: /var/lib/buildbot/fuchsia-x86_64-linux/build/llvm-build-ilqvuc8n/bin/wasm-ld
-- Testing: 21544 tests, 60 workers --
Testing:  0.. 10.
FAIL: Clang :: CodeGen/LoongArch/targetattr.c (3867 of 21544)
******************** TEST 'Clang :: CodeGen/LoongArch/targetattr.c' FAILED ********************
Exit Code: 1

Command Output (stderr):
--
/var/lib/buildbot/fuchsia-x86_64-linux/build/llvm-build-ilqvuc8n/bin/clang --target=loongarch64-linux-gnu /var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/clang/test/CodeGen/LoongArch/targetattr.c -S -emit-llvm -o -    | /var/lib/buildbot/fuchsia-x86_64-linux/build/llvm-build-ilqvuc8n/bin/FileCheck /var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/clang/test/CodeGen/LoongArch/targetattr.c # RUN: at line 2
+ /var/lib/buildbot/fuchsia-x86_64-linux/build/llvm-build-ilqvuc8n/bin/clang --target=loongarch64-linux-gnu /var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/clang/test/CodeGen/LoongArch/targetattr.c -S -emit-llvm -o -
+ /var/lib/buildbot/fuchsia-x86_64-linux/build/llvm-build-ilqvuc8n/bin/FileCheck /var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/clang/test/CodeGen/LoongArch/targetattr.c
/var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/clang/test/CodeGen/LoongArch/targetattr.c:8:16: error: CHECK-NEXT: is not on the line after the previous match
// CHECK-NEXT: [[ENTRY:.*:]]
               ^
<stdin>:11:1: note: 'next' match was here
; Function Attrs: noinline nounwind optnone
^
<stdin>:7:40: note: previous match ended here
define dso_local void @testdiv32() #0 {
                                       ^
<stdin>:8:1: note: non-matching line after previous match is here
 ret void
^
/var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/clang/test/CodeGen/LoongArch/targetattr.c:16:16: error: CHECK-NEXT: is not on the line after the previous match
// CHECK-NEXT: [[ENTRY:.*:]]
               ^
<stdin>:16:1: note: 'next' match was here
; Function Attrs: noinline nounwind optnone
^
<stdin>:12:46: note: previous match ended here
define dso_local void @testLoongarch64() #1 {
                                             ^
<stdin>:13:1: note: non-matching line after previous match is here
 ret void
^
/var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/clang/test/CodeGen/LoongArch/targetattr.c:24:16: error: CHECK-NEXT: is not on the line after the previous match
// CHECK-NEXT: [[ENTRY:.*:]]
               ^
<stdin>:21:1: note: 'next' match was here
; Function Attrs: noinline nounwind optnone
^
Step 7 (check) failure: check (failure)
...
[849/1374] Running the Clang regression tests
llvm-lit: /var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using clang: /var/lib/buildbot/fuchsia-x86_64-linux/build/llvm-build-ilqvuc8n/bin/clang
llvm-lit: /var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/llvm/utils/lit/lit/llvm/subst.py:126: note: Did not find cir-opt in /var/lib/buildbot/fuchsia-x86_64-linux/build/llvm-build-ilqvuc8n/bin:/var/lib/buildbot/fuchsia-x86_64-linux/build/llvm-build-ilqvuc8n/bin
llvm-lit: /var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/llvm/utils/lit/lit/llvm/subst.py:126: note: Did not find clang-repl in /var/lib/buildbot/fuchsia-x86_64-linux/build/llvm-build-ilqvuc8n/bin:/var/lib/buildbot/fuchsia-x86_64-linux/build/llvm-build-ilqvuc8n/bin
llvm-lit: /var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using ld.lld: /var/lib/buildbot/fuchsia-x86_64-linux/build/llvm-build-ilqvuc8n/bin/ld.lld
llvm-lit: /var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using lld-link: /var/lib/buildbot/fuchsia-x86_64-linux/build/llvm-build-ilqvuc8n/bin/lld-link
llvm-lit: /var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using ld64.lld: /var/lib/buildbot/fuchsia-x86_64-linux/build/llvm-build-ilqvuc8n/bin/ld64.lld
llvm-lit: /var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using wasm-ld: /var/lib/buildbot/fuchsia-x86_64-linux/build/llvm-build-ilqvuc8n/bin/wasm-ld
-- Testing: 21544 tests, 60 workers --
Testing:  0.. 10.
FAIL: Clang :: CodeGen/LoongArch/targetattr.c (3867 of 21544)
******************** TEST 'Clang :: CodeGen/LoongArch/targetattr.c' FAILED ********************
Exit Code: 1

Command Output (stderr):
--
/var/lib/buildbot/fuchsia-x86_64-linux/build/llvm-build-ilqvuc8n/bin/clang --target=loongarch64-linux-gnu /var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/clang/test/CodeGen/LoongArch/targetattr.c -S -emit-llvm -o -    | /var/lib/buildbot/fuchsia-x86_64-linux/build/llvm-build-ilqvuc8n/bin/FileCheck /var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/clang/test/CodeGen/LoongArch/targetattr.c # RUN: at line 2
+ /var/lib/buildbot/fuchsia-x86_64-linux/build/llvm-build-ilqvuc8n/bin/clang --target=loongarch64-linux-gnu /var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/clang/test/CodeGen/LoongArch/targetattr.c -S -emit-llvm -o -
+ /var/lib/buildbot/fuchsia-x86_64-linux/build/llvm-build-ilqvuc8n/bin/FileCheck /var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/clang/test/CodeGen/LoongArch/targetattr.c
/var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/clang/test/CodeGen/LoongArch/targetattr.c:8:16: error: CHECK-NEXT: is not on the line after the previous match
// CHECK-NEXT: [[ENTRY:.*:]]
               ^
<stdin>:11:1: note: 'next' match was here
; Function Attrs: noinline nounwind optnone
^
<stdin>:7:40: note: previous match ended here
define dso_local void @testdiv32() #0 {
                                       ^
<stdin>:8:1: note: non-matching line after previous match is here
 ret void
^
/var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/clang/test/CodeGen/LoongArch/targetattr.c:16:16: error: CHECK-NEXT: is not on the line after the previous match
// CHECK-NEXT: [[ENTRY:.*:]]
               ^
<stdin>:16:1: note: 'next' match was here
; Function Attrs: noinline nounwind optnone
^
<stdin>:12:46: note: previous match ended here
define dso_local void @testLoongarch64() #1 {
                                             ^
<stdin>:13:1: note: non-matching line after previous match is here
 ret void
^
/var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/clang/test/CodeGen/LoongArch/targetattr.c:24:16: error: CHECK-NEXT: is not on the line after the previous match
// CHECK-NEXT: [[ENTRY:.*:]]
               ^
<stdin>:21:1: note: 'next' match was here
; Function Attrs: noinline nounwind optnone
^

@llvm-ci
Copy link
Collaborator

llvm-ci commented May 29, 2025

LLVM Buildbot has detected a new failure on builder llvm-clang-x86_64-gcc-ubuntu-no-asserts running on doug-worker-6 while building clang,llvm at step 6 "test-build-unified-tree-check-all".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/202/builds/1531

Here is the relevant piece of the build log for the reference
Step 6 (test-build-unified-tree-check-all) failure: test (failure)
******************** TEST 'Clang :: CodeGen/LoongArch/targetattr.c' FAILED ********************
Exit Code: 1

Command Output (stderr):
--
/home/buildbot/buildbot-root/gcc-no-asserts/build/bin/clang --target=loongarch64-linux-gnu /home/buildbot/buildbot-root/gcc-no-asserts/llvm-project/clang/test/CodeGen/LoongArch/targetattr.c -S -emit-llvm -o -    | /home/buildbot/buildbot-root/gcc-no-asserts/build/bin/FileCheck /home/buildbot/buildbot-root/gcc-no-asserts/llvm-project/clang/test/CodeGen/LoongArch/targetattr.c # RUN: at line 2
+ /home/buildbot/buildbot-root/gcc-no-asserts/build/bin/clang --target=loongarch64-linux-gnu /home/buildbot/buildbot-root/gcc-no-asserts/llvm-project/clang/test/CodeGen/LoongArch/targetattr.c -S -emit-llvm -o -
+ /home/buildbot/buildbot-root/gcc-no-asserts/build/bin/FileCheck /home/buildbot/buildbot-root/gcc-no-asserts/llvm-project/clang/test/CodeGen/LoongArch/targetattr.c
�[1m/home/buildbot/buildbot-root/gcc-no-asserts/llvm-project/clang/test/CodeGen/LoongArch/targetattr.c:8:16: �[0m�[0;1;31merror: �[0m�[1mCHECK-NEXT: is not on the line after the previous match
�[0m// CHECK-NEXT: [[ENTRY:.*:]]
�[0;1;32m               ^
�[0m�[1m<stdin>:11:1: �[0m�[0;1;30mnote: �[0m�[1m'next' match was here
�[0m; Function Attrs: noinline nounwind optnone
�[0;1;32m^
�[0m�[1m<stdin>:7:40: �[0m�[0;1;30mnote: �[0m�[1mprevious match ended here
�[0mdefine dso_local void @testdiv32() #0 {
�[0;1;32m                                       ^
�[0m�[1m<stdin>:8:1: �[0m�[0;1;30mnote: �[0m�[1mnon-matching line after previous match is here
�[0m ret void
�[0;1;32m^
�[0m�[1m/home/buildbot/buildbot-root/gcc-no-asserts/llvm-project/clang/test/CodeGen/LoongArch/targetattr.c:16:16: �[0m�[0;1;31merror: �[0m�[1mCHECK-NEXT: is not on the line after the previous match
�[0m// CHECK-NEXT: [[ENTRY:.*:]]
�[0;1;32m               ^
�[0m�[1m<stdin>:16:1: �[0m�[0;1;30mnote: �[0m�[1m'next' match was here
�[0m; Function Attrs: noinline nounwind optnone
�[0;1;32m^
�[0m�[1m<stdin>:12:46: �[0m�[0;1;30mnote: �[0m�[1mprevious match ended here
�[0mdefine dso_local void @testLoongarch64() #1 {
�[0;1;32m                                             ^
�[0m�[1m<stdin>:13:1: �[0m�[0;1;30mnote: �[0m�[1mnon-matching line after previous match is here
�[0m ret void
�[0;1;32m^
�[0m�[1m/home/buildbot/buildbot-root/gcc-no-asserts/llvm-project/clang/test/CodeGen/LoongArch/targetattr.c:24:16: �[0m�[0;1;31merror: �[0m�[1mCHECK-NEXT: is not on the line after the previous match
�[0m// CHECK-NEXT: [[ENTRY:.*:]]
�[0;1;32m               ^
�[0m�[1m<stdin>:21:1: �[0m�[0;1;30mnote: �[0m�[1m'next' match was here
�[0m; Function Attrs: noinline nounwind optnone
�[0;1;32m^
�[0m�[1m<stdin>:17:42: �[0m�[0;1;30mnote: �[0m�[1mprevious match ended here
�[0mdefine dso_local void @testLa64v10() #1 {
�[0;1;32m                                         ^
�[0m�[1m<stdin>:18:1: �[0m�[0;1;30mnote: �[0m�[1mnon-matching line after previous match is here
�[0m ret void
�[0;1;32m^
�[0m�[1m/home/buildbot/buildbot-root/gcc-no-asserts/llvm-project/clang/test/CodeGen/LoongArch/targetattr.c:32:16: �[0m�[0;1;31merror: �[0m�[1mCHECK-NEXT: is not on the line after the previous match
�[0m// CHECK-NEXT: [[ENTRY:.*:]]
�[0;1;32m               ^
�[0m�[1m<stdin>:26:1: �[0m�[0;1;30mnote: �[0m�[1m'next' match was here
�[0m; Function Attrs: noinline nounwind optnone
�[0;1;32m^
...

ilovepi added a commit that referenced this pull request May 29, 2025
svkeerthy pushed a commit that referenced this pull request May 29, 2025
This adds support under LoongArch for the target("..") attributes.

The supported formats are:
- "arch=<arch>" strings, that specify the architecture features for a
function as per the -march=arch option.
- "tune=<cpu>" strings, that specify the tune-cpu cpu for a function as
per -mtune.
- "<feature>", "no-<feature>" enabled/disables the specific feature.
Ami-zhang added a commit to Ami-zhang/llvm-project that referenced this pull request Jun 3, 2025
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.
Ami-zhang added a commit that referenced this pull request Jun 3, 2025
…42546)

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend:loongarch clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants