Skip to content

Commit 06f779b

Browse files
authored
Reland "[Clang][LoongArch] Support target attribute for function" (#142546)
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.
1 parent 56acb06 commit 06f779b

File tree

7 files changed

+213
-0
lines changed

7 files changed

+213
-0
lines changed

clang/lib/Basic/Targets/LoongArch.cpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,73 @@ bool LoongArchTargetInfo::handleTargetFeatures(
392392
return true;
393393
}
394394

395+
enum class AttrFeatureKind { Arch, Tune, NoFeature, Feature };
396+
397+
static std::pair<AttrFeatureKind, llvm::StringRef>
398+
getAttrFeatureTypeAndValue(llvm::StringRef AttrFeature) {
399+
if (auto Split = AttrFeature.split("="); !Split.second.empty()) {
400+
if (Split.first.trim() == "arch")
401+
return {AttrFeatureKind::Arch, Split.second.trim()};
402+
if (Split.first.trim() == "tune")
403+
return {AttrFeatureKind::Tune, Split.second.trim()};
404+
}
405+
if (AttrFeature.starts_with("no-"))
406+
return {AttrFeatureKind::NoFeature, AttrFeature.drop_front(3)};
407+
return {AttrFeatureKind::Feature, AttrFeature};
408+
}
409+
410+
ParsedTargetAttr
411+
LoongArchTargetInfo::parseTargetAttr(StringRef Features) const {
412+
ParsedTargetAttr Ret;
413+
if (Features == "default")
414+
return Ret;
415+
SmallVector<StringRef, 1> AttrFeatures;
416+
Features.split(AttrFeatures, ",");
417+
418+
for (auto &Feature : AttrFeatures) {
419+
auto [Kind, Value] = getAttrFeatureTypeAndValue(Feature.trim());
420+
421+
switch (Kind) {
422+
case AttrFeatureKind::Arch: {
423+
if (llvm::LoongArch::isValidArchName(Value) || Value == "la64v1.0" ||
424+
Value == "la64v1.1") {
425+
std::vector<llvm::StringRef> ArchFeatures;
426+
if (llvm::LoongArch::getArchFeatures(Value, ArchFeatures)) {
427+
Ret.Features.insert(Ret.Features.end(), ArchFeatures.begin(),
428+
ArchFeatures.end());
429+
}
430+
431+
if (!Ret.CPU.empty())
432+
Ret.Duplicate = "arch=";
433+
else if (Value == "la64v1.0" || Value == "la64v1.1")
434+
Ret.CPU = "loongarch64";
435+
else
436+
Ret.CPU = Value;
437+
} else {
438+
Ret.Features.push_back("!arch=" + Value.str());
439+
}
440+
break;
441+
}
442+
443+
case AttrFeatureKind::Tune:
444+
if (!Ret.Tune.empty())
445+
Ret.Duplicate = "tune=";
446+
else
447+
Ret.Tune = Value;
448+
break;
449+
450+
case AttrFeatureKind::NoFeature:
451+
Ret.Features.push_back("-" + Value.str());
452+
break;
453+
454+
case AttrFeatureKind::Feature:
455+
Ret.Features.push_back("+" + Value.str());
456+
break;
457+
}
458+
}
459+
return Ret;
460+
}
461+
395462
bool LoongArchTargetInfo::isValidCPUName(StringRef Name) const {
396463
return llvm::LoongArch::isValidCPUName(Name);
397464
}
@@ -400,3 +467,7 @@ void LoongArchTargetInfo::fillValidCPUList(
400467
SmallVectorImpl<StringRef> &Values) const {
401468
llvm::LoongArch::fillValidCPUList(Values);
402469
}
470+
471+
bool LoongArchTargetInfo::isValidFeatureName(StringRef Name) const {
472+
return llvm::LoongArch::isValidFeatureName(Name);
473+
}

clang/lib/Basic/Targets/LoongArch.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ class LLVM_LIBRARY_VISIBILITY LoongArchTargetInfo : public TargetInfo {
104104
bool handleTargetFeatures(std::vector<std::string> &Features,
105105
DiagnosticsEngine &Diags) override;
106106

107+
ParsedTargetAttr parseTargetAttr(StringRef Str) const override;
108+
bool supportsTargetAttributeTune() const override { return true; }
109+
107110
bool
108111
initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
109112
StringRef CPU,
@@ -113,6 +116,7 @@ class LLVM_LIBRARY_VISIBILITY LoongArchTargetInfo : public TargetInfo {
113116

114117
bool isValidCPUName(StringRef Name) const override;
115118
void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
119+
bool isValidFeatureName(StringRef Name) const override;
116120
};
117121

118122
class LLVM_LIBRARY_VISIBILITY LoongArch32TargetInfo

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3195,6 +3195,17 @@ bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) {
31953195
}
31963196
}
31973197

3198+
if (Context.getTargetInfo().getTriple().isLoongArch()) {
3199+
for (const auto &Feature : ParsedAttrs.Features) {
3200+
StringRef CurFeature = Feature;
3201+
if (CurFeature.starts_with("!arch=")) {
3202+
StringRef ArchValue = CurFeature.split("=").second.trim();
3203+
return Diag(LiteralLoc, diag::err_attribute_unsupported)
3204+
<< "target(arch=..)" << ArchValue;
3205+
}
3206+
}
3207+
}
3208+
31983209
if (ParsedAttrs.Duplicate != "")
31993210
return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
32003211
<< Duplicate << None << ParsedAttrs.Duplicate << Target;
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals all --version 5
2+
// RUN: %clang_cc1 -triple loongarch64 -emit-llvm %s -o - | FileCheck %s
3+
4+
__attribute__((target("div32")))
5+
// CHECK-LABEL: define dso_local void @testdiv32(
6+
// CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
7+
// CHECK-NEXT: [[ENTRY:.*:]]
8+
// CHECK-NEXT: ret void
9+
//
10+
void testdiv32() {}
11+
12+
__attribute__((target("arch=loongarch64")))
13+
// CHECK-LABEL: define dso_local void @testLoongarch64(
14+
// CHECK-SAME: ) #[[ATTR1:[0-9]+]] {
15+
// CHECK-NEXT: [[ENTRY:.*:]]
16+
// CHECK-NEXT: ret void
17+
//
18+
void testLoongarch64() {}
19+
20+
__attribute__((target("arch=la64v1.0")))
21+
// CHECK-LABEL: define dso_local void @testLa64v10(
22+
// CHECK-SAME: ) #[[ATTR2:[0-9]+]] {
23+
// CHECK-NEXT: [[ENTRY:.*:]]
24+
// CHECK-NEXT: ret void
25+
//
26+
void testLa64v10() {}
27+
28+
__attribute__((target("arch=la64v1.1")))
29+
// CHECK-LABEL: define dso_local void @testLa64v11(
30+
// CHECK-SAME: ) #[[ATTR3:[0-9]+]] {
31+
// CHECK-NEXT: [[ENTRY:.*:]]
32+
// CHECK-NEXT: ret void
33+
//
34+
void testLa64v11() {}
35+
36+
__attribute__((target("arch=la464")))
37+
// CHECK-LABEL: define dso_local void @testLa464(
38+
// CHECK-SAME: ) #[[ATTR4:[0-9]+]] {
39+
// CHECK-NEXT: [[ENTRY:.*:]]
40+
// CHECK-NEXT: ret void
41+
//
42+
void testLa464() {}
43+
44+
__attribute__((target("arch=la664")))
45+
// CHECK-LABEL: define dso_local void @testLa664(
46+
// CHECK-SAME: ) #[[ATTR5:[0-9]+]] {
47+
// CHECK-NEXT: [[ENTRY:.*:]]
48+
// CHECK-NEXT: ret void
49+
//
50+
void testLa664() {}
51+
52+
__attribute__((target("arch=la664, no-div32")))
53+
// CHECK-LABEL: define dso_local void @la664Nodiv32(
54+
// CHECK-SAME: ) #[[ATTR6:[0-9]+]] {
55+
// CHECK-NEXT: [[ENTRY:.*:]]
56+
// CHECK-NEXT: ret void
57+
//
58+
void la664Nodiv32() {}
59+
60+
__attribute__((target("tune=la464")))
61+
// CHECK-LABEL: define dso_local void @tuneLa464(
62+
// CHECK-SAME: ) #[[ATTR7:[0-9]+]] {
63+
// CHECK-NEXT: [[ENTRY:.*:]]
64+
// CHECK-NEXT: ret void
65+
//
66+
void tuneLa464() {}
67+
68+
__attribute__((target("arch=la464, tune=la664")))
69+
// CHECK-LABEL: define dso_local void @archLa464tuneLa664(
70+
// CHECK-SAME: ) #[[ATTR8:[0-9]+]] {
71+
// CHECK-NEXT: [[ENTRY:.*:]]
72+
// CHECK-NEXT: ret void
73+
//
74+
void archLa464tuneLa664() {}
75+
76+
//.
77+
// CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+div32" }
78+
// CHECK: attributes #[[ATTR1]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="loongarch64" "target-features"="+64bit,+d,+f,+ual" }
79+
// CHECK: attributes #[[ATTR2]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="loongarch64" "target-features"="+64bit,+d,+lsx,+ual" }
80+
// 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" }
81+
// 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" }
82+
// 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" }
83+
// 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" }
84+
// CHECK: attributes #[[ATTR7]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit" "tune-cpu"="la464" }
85+
// 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" }
86+
//.
87+
// CHECK: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
88+
// CHECK: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}
89+
//.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: %clang_cc1 -triple loongarch64-linux-gnu -fsyntax-only -verify %s
2+
3+
// expected-error@+1 {{function multiversioning is not supported on the current target}}
4+
void __attribute__((target("default"))) bar(void) {}
5+
6+
// expected-error@+1 {{target(arch=..) attribute is not supported on targets missing invalid; specify an appropriate -march= or -mcpu=}}
7+
void __attribute__((target("arch=invalid"))) foo(void) {}
8+
9+
// expected-warning@+1 {{unsupported '+div32' in the 'target' attribute string; 'target' attribute ignored}}
10+
void __attribute__((target("+div32"))) plusfeature(void) {}
11+
12+
// expected-warning@+1 {{unsupported '-div32' in the 'target' attribute string; 'target' attribute ignored}}
13+
void __attribute__((target("-div32"))) minusfeature(void) {}
14+
15+
// expected-warning@+1 {{unsupported 'aaa' in the 'target' attribute string; 'target' attribute ignored}}
16+
int __attribute__((target("aaa"))) test_feature(void) { return 4; }
17+
18+
// expected-warning@+1 {{unsupported 'aaa' in the 'target' attribute string; 'target' attribute ignored}}
19+
int __attribute__((target("no-aaa"))) test_nofeature(void) { return 4; }
20+
21+
// expected-warning@+1 {{duplicate 'arch=' in the 'target' attribute string; 'target' attribute ignored}}
22+
int __attribute__((target("arch=la464,arch=la664"))) test_duplarch(void) { return 4; }
23+
24+
// expected-warning@+1 {{unknown tune CPU 'la64v1.0' in the 'target' attribute string; 'target' attribute ignored}}
25+
int __attribute__((target("tune=la64v1.0"))) test_tune(void) { return 4; }

llvm/include/llvm/TargetParser/LoongArchTargetParser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ struct ArchInfo {
8585
};
8686

8787
bool isValidArchName(StringRef Arch);
88+
bool isValidFeatureName(StringRef Feature);
8889
bool getArchFeatures(StringRef Arch, std::vector<StringRef> &Features);
8990
bool isValidCPUName(StringRef TuneCPU);
9091
void fillValidCPUList(SmallVectorImpl<StringRef> &Values);

llvm/lib/TargetParser/LoongArchTargetParser.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,18 @@ bool LoongArch::isValidArchName(StringRef Arch) {
3434
return false;
3535
}
3636

37+
bool LoongArch::isValidFeatureName(StringRef Feature) {
38+
if (Feature.starts_with("+") || Feature.starts_with("-"))
39+
return false;
40+
for (const auto &F : AllFeatures) {
41+
StringRef CanonicalName =
42+
F.Name.starts_with("+") ? F.Name.drop_front() : F.Name;
43+
if (CanonicalName == Feature)
44+
return true;
45+
}
46+
return false;
47+
}
48+
3749
bool LoongArch::getArchFeatures(StringRef Arch,
3850
std::vector<StringRef> &Features) {
3951
for (const auto A : AllArchs) {

0 commit comments

Comments
 (0)