Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -12781,6 +12781,12 @@ def warn_target_clone_duplicate_options
def warn_target_clone_no_impact_options
: Warning<"version list contains entries that don't impact code generation">,
InGroup<FunctionMultiVersioning>;
def warn_version_priority_out_of_range
: Warning<"version priority '%0' is outside the allowed range [1-255]; ignoring priority">,
InGroup<FunctionMultiVersioning>;
def warn_invalid_default_version_priority
: Warning<"priority of default version cannot be overridden; ignoring priority">,
InGroup<FunctionMultiVersioning>;

// three-way comparison operator diagnostics
def err_implied_comparison_category_type_not_found : Error<
Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/Sema/SemaARM.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ class SemaARM : public SemaBase {
/// false otherwise.
bool areLaxCompatibleSveTypes(QualType FirstType, QualType SecondType);

bool checkTargetVersionAttr(const StringRef Str, const SourceLocation Loc);
bool checkTargetVersionAttr(const StringRef Param, const SourceLocation Loc,
SmallString<64> &NewParam);
bool checkTargetClonesAttr(SmallVectorImpl<StringRef> &Params,
SmallVectorImpl<SourceLocation> &Locs,
SmallVectorImpl<SmallString<64>> &NewParams);
Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/Sema/SemaRISCV.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ class SemaRISCV : public SemaBase {

std::unique_ptr<sema::RISCVIntrinsicManager> IntrinsicManager;

bool checkTargetVersionAttr(const StringRef Param, const SourceLocation Loc);
bool checkTargetVersionAttr(const StringRef Param, const SourceLocation Loc,
SmallString<64> &NewParam);
bool checkTargetClonesAttr(SmallVectorImpl<StringRef> &Params,
SmallVectorImpl<SourceLocation> &Locs,
SmallVectorImpl<SmallString<64>> &NewParams);
Expand Down
7 changes: 4 additions & 3 deletions clang/lib/CodeGen/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1338,9 +1338,10 @@ void AArch64ABIInfo::appendAttributeMangling(StringRef AttrStr,

llvm::SmallDenseSet<StringRef, 8> UniqueFeats;
for (auto &Feat : Features)
if (auto Ext = llvm::AArch64::parseFMVExtension(Feat))
if (UniqueFeats.insert(Ext->Name).second)
Out << 'M' << Ext->Name;
if (getTarget().doesFeatureAffectCodeGen(Feat))
if (auto Ext = llvm::AArch64::parseFMVExtension(Feat))
if (UniqueFeats.insert(Ext->Name).second)
Out << 'M' << Ext->Name;
}

std::unique_ptr<TargetCodeGenInfo>
Expand Down
63 changes: 55 additions & 8 deletions clang/lib/Sema/SemaARM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1579,19 +1579,53 @@ bool SemaARM::areLaxCompatibleSveTypes(QualType FirstType,
IsLaxCompatible(SecondType, FirstType);
}

static void appendFeature(StringRef Feat, SmallString<64> &Buffer) {
if (!Buffer.empty())
Buffer.append("+");
Buffer.append(Feat);
}

static void convertPriorityString(unsigned Priority,
SmallString<64> &NewParam) {
StringRef PriorityString[8] = {"P0", "P1", "P2", "P3",
"P4", "P5", "P6", "P7"};

assert(Priority > 0 && Priority < 256 && "priority out of range");
// Convert priority=[1-255] -> P0 + ... + P7
for (unsigned BitPos = 0; BitPos < 8; ++BitPos)
if (Priority & (1U << BitPos))
appendFeature(PriorityString[BitPos], NewParam);
}

bool SemaARM::checkTargetVersionAttr(const StringRef Param,
const SourceLocation Loc) {
const SourceLocation Loc,
SmallString<64> &NewParam) {
using namespace DiagAttrParams;

auto [LHS, RHS] = Param.split(';');
bool IsDefault = false;
llvm::SmallVector<StringRef, 8> Features;
Param.split(Features, '+');
LHS.split(Features, '+');
for (StringRef Feat : Features) {
Feat = Feat.trim();
if (Feat == "default")
continue;
if (!getASTContext().getTargetInfo().validateCpuSupports(Feat))
IsDefault = true;
else if (!getASTContext().getTargetInfo().validateCpuSupports(Feat))
return Diag(Loc, diag::warn_unsupported_target_attribute)
<< Unsupported << None << Feat << TargetVersion;
appendFeature(Feat, NewParam);
}

if (!RHS.empty() && RHS.consume_front("priority=")) {
if (IsDefault)
Diag(Loc, diag::warn_invalid_default_version_priority);
else {
unsigned Digit;
if (RHS.getAsInteger(0, Digit) || Digit < 1 || Digit > 255)
Diag(Loc, diag::warn_version_priority_out_of_range) << RHS;
else
convertPriorityString(Digit, NewParam);
}
}
return false;
}
Expand All @@ -1613,15 +1647,20 @@ bool SemaARM::checkTargetClonesAttr(
const StringRef Param = Params[I].trim();
const SourceLocation &Loc = Locs[I];

if (Param.empty())
auto [LHS, RHS] = Param.split(';');
bool HasPriority = !RHS.empty() && RHS.consume_front("priority=");

if (LHS.empty())
return Diag(Loc, diag::warn_unsupported_target_attribute)
<< Unsupported << None << "" << TargetClones;

if (Param == "default") {
if (LHS == "default") {
if (HasDefault)
Diag(Loc, diag::warn_target_clone_duplicate_options);
else {
NewParams.push_back(Param);
if (HasPriority)
Diag(Loc, diag::warn_invalid_default_version_priority);
NewParams.push_back(LHS);
HasDefault = true;
}
continue;
Expand All @@ -1630,7 +1669,7 @@ bool SemaARM::checkTargetClonesAttr(
bool HasCodeGenImpact = false;
llvm::SmallVector<StringRef, 8> Features;
llvm::SmallVector<StringRef, 8> ValidFeatures;
Param.split(Features, '+');
LHS.split(Features, '+');
for (StringRef Feat : Features) {
Feat = Feat.trim();
if (!getASTContext().getTargetInfo().validateCpuSupports(Feat)) {
Expand Down Expand Up @@ -1660,6 +1699,14 @@ bool SemaARM::checkTargetClonesAttr(
continue;
}

if (HasPriority) {
unsigned Digit;
if (RHS.getAsInteger(0, Digit) || Digit < 1 || Digit > 255)
Diag(Loc, diag::warn_version_priority_out_of_range) << RHS;
else
convertPriorityString(Digit, NewParam);
}

// Valid non-default argument.
NewParams.push_back(NewParam);
HasNonDefault = true;
Expand Down
7 changes: 4 additions & 3 deletions clang/lib/Sema/SemaDeclAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3343,19 +3343,20 @@ bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) {
static void handleTargetVersionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
StringRef Param;
SourceLocation Loc;
SmallString<64> NewParam;
if (!S.checkStringLiteralArgumentAttr(AL, 0, Param, &Loc))
return;

if (S.Context.getTargetInfo().getTriple().isAArch64()) {
if (S.ARM().checkTargetVersionAttr(Param, Loc))
if (S.ARM().checkTargetVersionAttr(Param, Loc, NewParam))
return;
} else if (S.Context.getTargetInfo().getTriple().isRISCV()) {
if (S.RISCV().checkTargetVersionAttr(Param, Loc))
if (S.RISCV().checkTargetVersionAttr(Param, Loc, NewParam))
return;
}

TargetVersionAttr *NewAttr =
::new (S.Context) TargetVersionAttr(S.Context, AL, Param);
::new (S.Context) TargetVersionAttr(S.Context, AL, NewParam);
D->addAttr(NewAttr);
}

Expand Down
4 changes: 3 additions & 1 deletion clang/lib/Sema/SemaRISCV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1646,7 +1646,8 @@ bool SemaRISCV::isValidFMVExtension(StringRef Ext) {
}

bool SemaRISCV::checkTargetVersionAttr(const StringRef Param,
const SourceLocation Loc) {
const SourceLocation Loc,
SmallString<64> &NewParam) {
using namespace DiagAttrParams;

llvm::SmallVector<StringRef, 8> AttrStrs;
Expand Down Expand Up @@ -1692,6 +1693,7 @@ bool SemaRISCV::checkTargetVersionAttr(const StringRef Param,
return Diag(Loc, diag::warn_unsupported_target_attribute)
<< Unsupported << None << Param << TargetVersion;

NewParam = Param;
return false;
}

Expand Down
30 changes: 26 additions & 4 deletions clang/test/AST/attr-target-version.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,29 @@

int __attribute__((target_version("sve2-bitperm + sha2"))) foov(void) { return 1; }
int __attribute__((target_clones(" lse + fp + sha3 ", "default"))) fooc(void) { return 2; }
// CHECK: TargetVersionAttr
// CHECK: sve2-bitperm + sha2
// CHECK: TargetClonesAttr
// CHECK: fp+lse+sha3 default

int __attribute__((target_version("aes;priority=1"))) explicit_priority(void) { return 1; }
int __attribute__((target_version("bf16;priority=2"))) explicit_priority(void) { return 2; }
int __attribute__((target_version("crc;priority=4"))) explicit_priority(void) { return 4; }
int __attribute__((target_version("dpb2;priority=8"))) explicit_priority(void) { return 8; }
int __attribute__((target_version("fp16fml;priority=16"))) explicit_priority(void) { return 16; }
int __attribute__((target_version("dotprod;priority=32"))) explicit_priority(void) { return 32; }
int __attribute__((target_version("sve;priority=64"))) explicit_priority(void) { return 64; }
int __attribute__((target_version("mops;priority=128"))) explicit_priority(void) { return 128; }

int __attribute__((target_clones("simd;priority=255", "default"))) explicit_priority(void) {
return 0;
}

// CHECK: TargetVersionAttr {{.*}} "sve2-bitperm+sha2"
// CHECK: TargetClonesAttr {{.*}} fp+lse+sha3 default

// CHECK: TargetVersionAttr {{.*}} "aes+P0"
// CHECK: TargetVersionAttr {{.*}} "bf16+P1"
// CHECK: TargetVersionAttr {{.*}} "crc+P2"
// CHECK: TargetVersionAttr {{.*}} "dpb2+P3"
// CHECK: TargetVersionAttr {{.*}} "fp16fml+P4"
// CHECK: TargetVersionAttr {{.*}} "dotprod+P5"
// CHECK: TargetVersionAttr {{.*}} "sve+P6"
// CHECK: TargetVersionAttr {{.*}} "mops+P7"
// CHECK: TargetClonesAttr {{.*}} simd+P0+P1+P2+P3+P4+P5+P6+P7 default
16 changes: 16 additions & 0 deletions clang/test/CodeGen/AArch64/fmv-duplicate-mangled-name.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -triple aarch64-linux-gnu -verify -emit-llvm-only %s -DCHECK_IMPLICIT_DEFAULT
// RUN: %clang_cc1 -triple aarch64-linux-gnu -verify -emit-llvm-only %s -DCHECK_EXPLICIT_DEFAULT
// RUN: %clang_cc1 -triple aarch64-linux-gnu -verify -emit-llvm-only %s -DCHECK_EXPLICIT_VERSION_PRIORITY
// RUN: %clang_cc1 -triple aarch64-linux-gnu -verify -emit-llvm-only %s -DCHECK_EXPLICIT_CLONES_PRIORITY

#if defined(CHECK_IMPLICIT_DEFAULT)

Expand All @@ -21,4 +23,18 @@ __attribute__((target_version("default"))) int explicit_default_bad(void) { retu
// expected-note@-2 {{previous definition is here}}
__attribute__((target_clones("aes", "lse", "default"))) int explicit_default_bad(void) { return 1; }

#elif defined(CHECK_EXPLICIT_VERSION_PRIORITY)

__attribute__((target_version("aes"))) int explicit_version_priority(void) { return 0; }
// expected-error@+2 {{definition with same mangled name 'explicit_version_priority._Maes' as another definition}}
// expected-note@-2 {{previous definition is here}}
__attribute__((target_version("aes;priority=10"))) int explicit_version_priority(void) { return 1; }

#elif defined(CHECK_EXPLICIT_CLONES_PRIORITY)

__attribute__((target_version("aes;priority=20"))) int explicit_clones_priority(void) { return 0; }
// expected-error@+2 {{definition with same mangled name 'explicit_clones_priority._Maes' as another definition}}
// expected-note@-2 {{previous definition is here}}
__attribute__((target_clones("aes;priority=5", "lse"))) int explicit_clones_priority(void) { return 1; }

#endif
Loading