Skip to content

Commit bc2f78c

Browse files
committed
[RISCV] Support target attribute for function
The proposal of target attribute is riscv-non-isa/riscv-c-api-doc#35 This patch implements it by emitting .option arch during codegen. Differential Revision: https://reviews.llvm.org/D151730
1 parent 1de568d commit bc2f78c

File tree

3 files changed

+100
-2
lines changed

3 files changed

+100
-2
lines changed

clang/lib/Basic/Targets/RISCV.cpp

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,12 +250,17 @@ bool RISCVTargetInfo::initFeatureMap(
250250

251251
// RISCVISAInfo makes implications for ISA features
252252
std::vector<std::string> ImpliedFeatures = (*ParseResult)->toFeatureVector();
253+
std::vector<std::string> UpdatedFeatures;
254+
253255
// Add non-ISA features like `relax` and `save-restore` back
254256
for (const std::string &Feature : FeaturesVec)
255257
if (!llvm::is_contained(ImpliedFeatures, Feature))
256-
ImpliedFeatures.push_back(Feature);
258+
UpdatedFeatures.push_back(Feature);
259+
260+
UpdatedFeatures.insert(UpdatedFeatures.end(), ImpliedFeatures.begin(),
261+
ImpliedFeatures.end());
257262

258-
return TargetInfo::initFeatureMap(Features, Diags, CPU, ImpliedFeatures);
263+
return TargetInfo::initFeatureMap(Features, Diags, CPU, UpdatedFeatures);
259264
}
260265

261266
std::optional<std::pair<unsigned, unsigned>>
@@ -346,3 +351,74 @@ void RISCVTargetInfo::fillValidTuneCPUList(
346351
bool Is64Bit = getTriple().isArch64Bit();
347352
llvm::RISCV::fillValidTuneCPUArchList(Values, Is64Bit);
348353
}
354+
355+
// Parse RISC-V Target attributes, which are a comma separated list of:
356+
// "arch=<arch>" - parsed to features as per -march=..
357+
// "cpu=<cpu>" - parsed to features as per -mcpu=.., with CPU set to <cpu>
358+
// "tune=<cpu>" - TuneCPU set to <cpu>
359+
ParsedTargetAttr RISCVTargetInfo::parseTargetAttr(StringRef Features) const {
360+
ParsedTargetAttr Ret;
361+
if (Features == "default")
362+
return Ret;
363+
SmallVector<StringRef, 1> AttrFeatures;
364+
Features.split(AttrFeatures, ";");
365+
bool FoundArch = false;
366+
367+
for (auto &Feature : AttrFeatures) {
368+
Feature = Feature.trim();
369+
StringRef AttrString = Feature.split("=").second.trim();
370+
371+
if (Feature.startswith("arch=")) {
372+
if (FoundArch)
373+
Ret.Duplicate = "arch=";
374+
FoundArch = true;
375+
376+
if (AttrString.startswith("+")) {
377+
// EXTENSION like arch=+v,+zbb
378+
SmallVector<StringRef, 1> Exts;
379+
AttrString.split(Exts, ",");
380+
for (auto Ext : Exts) {
381+
if (Ext.empty())
382+
continue;
383+
384+
StringRef ExtName = Ext.substr(1);
385+
std::string TargetFeature =
386+
llvm::RISCVISAInfo::getTargetFeatureForExtension(ExtName);
387+
if (!TargetFeature.empty())
388+
Ret.Features.push_back(Ext.front() + TargetFeature);
389+
else
390+
Ret.Features.push_back(Ext.str());
391+
}
392+
} else {
393+
// full-arch-string like arch=rv64gcv
394+
auto RII = llvm::RISCVISAInfo::parseArchString(
395+
AttrString, /* EnableExperimentalExtension */ true);
396+
if (!RII) {
397+
consumeError(RII.takeError());
398+
} else {
399+
std::vector<std::string> FeatStrings = (*RII)->toFeatureVector();
400+
for (auto FeatString : FeatStrings)
401+
Ret.Features.push_back(FeatString);
402+
}
403+
}
404+
continue;
405+
} else if (Feature.startswith("cpu=")) {
406+
if (!Ret.CPU.empty())
407+
Ret.Duplicate = "cpu=";
408+
else
409+
Ret.CPU = AttrString;
410+
continue;
411+
} else if (Feature.startswith("tune=")) {
412+
if (!Ret.Tune.empty())
413+
Ret.Duplicate = "tune=";
414+
else
415+
Ret.Tune = AttrString;
416+
continue;
417+
}
418+
}
419+
return Ret;
420+
}
421+
422+
bool RISCVTargetInfo::validateCpuSupports(StringRef FeatureStr) const {
423+
return ISAInfo->isSupportedExtensionFeature(FeatureStr);
424+
}

clang/lib/Basic/Targets/RISCV.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ class RISCVTargetInfo : public TargetInfo {
114114
void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
115115
bool isValidTuneCPUName(StringRef Name) const override;
116116
void fillValidTuneCPUList(SmallVectorImpl<StringRef> &Values) const override;
117+
bool supportsTargetAttributeTune() const override { return true; }
118+
bool validateCpuSupports(StringRef FeatureStr) const override;
119+
ParsedTargetAttr parseTargetAttr(StringRef Str) const override;
117120
};
118121
class LLVM_LIBRARY_VISIBILITY RISCV32TargetInfo : public RISCVTargetInfo {
119122
public:
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// REQUIRES: riscv-registered-target
2+
// RUN: %clang_cc1 -triple riscv64 -target-feature +zifencei \
3+
// RUN: -target-feature +m -target-feature +a \
4+
// RUN: -target-feature +f -target-feature +d \
5+
// RUN: -emit-llvm %s -o - | FileCheck %s \
6+
// RUN: --check-prefix=CHECK-IR
7+
8+
// CHECK-IR: void @test1() #0
9+
__attribute__((target("arch=+v,+zbb,+zicond1p0"))) void test1() {}
10+
11+
// CHECK-IR: void @test2() #1
12+
__attribute__((target("arch=rv64gc_zbb"))) void test2 () {}
13+
14+
// CHECK-IR: void @test3() #2
15+
__attribute__((target("cpu=rocket-rv64;tune=generic-rv64;arch=+v"))) void test3 () {}
16+
17+
// CHECK-IR: attributes #0 {{.*}}+experimental-zicond{{.*}}+v,+zbb{{.*}}+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b{{.*}}
18+
// CHECK-IR: attributes #1 {{.*}}+c{{.*}}+zbb{{.*}}
19+
// CHECK-IR: attributes #2 {{.*}} "target-cpu"="rocket-rv64" {{.*}}+v{{.*}} "tune-cpu"="generic-rv64" {{.*}}

0 commit comments

Comments
 (0)