Skip to content

Commit d1a3396

Browse files
committed
[Driver][ARM] Disable unsupported features when nofp arch extension is used
A list of target features is disabled when there is no hardware floating-point support. This is the case when one of the following options is passed to clang: - -mfloat-abi=soft - -mfpu=none This option list is missing, however, the extension "+nofp" that can be specified in -march flags, such as "-march=armv8-a+nofp". This patch also disables unsupported target features when nofp is passed to -march. Differential Revision: https://reviews.llvm.org/D82948
1 parent 8725a49 commit d1a3396

File tree

6 files changed

+66
-30
lines changed

6 files changed

+66
-30
lines changed

clang/lib/Driver/ToolChains/Arch/ARM.cpp

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,15 @@ static unsigned getARMFPUFeatures(const Driver &D, const Arg *A,
7373
}
7474

7575
// Decode ARM features from string like +[no]featureA+[no]featureB+...
76-
static bool DecodeARMFeatures(const Driver &D, StringRef text,
77-
StringRef CPU, llvm::ARM::ArchKind ArchKind,
78-
std::vector<StringRef> &Features) {
76+
static bool DecodeARMFeatures(const Driver &D, StringRef text, StringRef CPU,
77+
llvm::ARM::ArchKind ArchKind,
78+
std::vector<StringRef> &Features,
79+
unsigned &ArgFPUID) {
7980
SmallVector<StringRef, 8> Split;
8081
text.split(Split, StringRef("+"), -1, false);
8182

8283
for (StringRef Feature : Split) {
83-
if (!appendArchExtFeatures(CPU, ArchKind, Feature, Features))
84+
if (!appendArchExtFeatures(CPU, ArchKind, Feature, Features, ArgFPUID))
8485
return false;
8586
}
8687
return true;
@@ -102,30 +103,30 @@ static void DecodeARMFeaturesFromCPU(const Driver &D, StringRef CPU,
102103
static void checkARMArchName(const Driver &D, const Arg *A, const ArgList &Args,
103104
llvm::StringRef ArchName, llvm::StringRef CPUName,
104105
std::vector<StringRef> &Features,
105-
const llvm::Triple &Triple) {
106+
const llvm::Triple &Triple, unsigned &ArgFPUID) {
106107
std::pair<StringRef, StringRef> Split = ArchName.split("+");
107108

108109
std::string MArch = arm::getARMArch(ArchName, Triple);
109110
llvm::ARM::ArchKind ArchKind = llvm::ARM::parseArch(MArch);
110111
if (ArchKind == llvm::ARM::ArchKind::INVALID ||
111-
(Split.second.size() && !DecodeARMFeatures(
112-
D, Split.second, CPUName, ArchKind, Features)))
112+
(Split.second.size() && !DecodeARMFeatures(D, Split.second, CPUName,
113+
ArchKind, Features, ArgFPUID)))
113114
D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
114115
}
115116

116117
// Check -mcpu=. Needs ArchName to handle -mcpu=generic.
117118
static void checkARMCPUName(const Driver &D, const Arg *A, const ArgList &Args,
118119
llvm::StringRef CPUName, llvm::StringRef ArchName,
119120
std::vector<StringRef> &Features,
120-
const llvm::Triple &Triple) {
121+
const llvm::Triple &Triple, unsigned &ArgFPUID) {
121122
std::pair<StringRef, StringRef> Split = CPUName.split("+");
122123

123124
std::string CPU = arm::getARMTargetCPU(CPUName, ArchName, Triple);
124125
llvm::ARM::ArchKind ArchKind =
125126
arm::getLLVMArchKindForARM(CPU, ArchName, Triple);
126127
if (ArchKind == llvm::ARM::ArchKind::INVALID ||
127-
(Split.second.size() && !DecodeARMFeatures(
128-
D, Split.second, CPU, ArchKind, Features)))
128+
(Split.second.size() &&
129+
!DecodeARMFeatures(D, Split.second, CPU, ArchKind, Features, ArgFPUID)))
129130
D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
130131
}
131132

@@ -347,6 +348,8 @@ void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
347348
const Arg *CPUArg = Args.getLastArg(options::OPT_mcpu_EQ);
348349
StringRef ArchName;
349350
StringRef CPUName;
351+
unsigned ArchArgFPUID = llvm::ARM::FK_INVALID;
352+
unsigned CPUArgFPUID = llvm::ARM::FK_INVALID;
350353

351354
// Check -mcpu. ClangAs gives preference to -Wa,-mcpu=.
352355
if (WaCPU) {
@@ -364,14 +367,14 @@ void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
364367
D.Diag(clang::diag::warn_drv_unused_argument)
365368
<< ArchArg->getAsString(Args);
366369
ArchName = StringRef(WaArch->getValue()).substr(7);
367-
checkARMArchName(D, WaArch, Args, ArchName, CPUName,
368-
ExtensionFeatures, Triple);
370+
checkARMArchName(D, WaArch, Args, ArchName, CPUName, ExtensionFeatures,
371+
Triple, ArchArgFPUID);
369372
// FIXME: Set Arch.
370373
D.Diag(clang::diag::warn_drv_unused_argument) << WaArch->getAsString(Args);
371374
} else if (ArchArg) {
372375
ArchName = ArchArg->getValue();
373-
checkARMArchName(D, ArchArg, Args, ArchName, CPUName,
374-
ExtensionFeatures, Triple);
376+
checkARMArchName(D, ArchArg, Args, ArchName, CPUName, ExtensionFeatures,
377+
Triple, ArchArgFPUID);
375378
}
376379

377380
// Add CPU features for generic CPUs
@@ -390,8 +393,8 @@ void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
390393
}
391394

392395
if (CPUArg)
393-
checkARMCPUName(D, CPUArg, Args, CPUName, ArchName,
394-
ExtensionFeatures, Triple);
396+
checkARMCPUName(D, CPUArg, Args, CPUName, ArchName, ExtensionFeatures,
397+
Triple, CPUArgFPUID);
395398
// Honor -mfpu=. ClangAs gives preference to -Wa,-mfpu=.
396399
unsigned FPUID = llvm::ARM::FK_INVALID;
397400
const Arg *FPUArg = Args.getLastArg(options::OPT_mfpu_EQ);
@@ -455,20 +458,26 @@ void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
455458
Features.push_back("+fullfp16");
456459
}
457460

458-
// Setting -msoft-float/-mfloat-abi=soft effectively disables the FPU (GCC
459-
// ignores the -mfpu options in this case).
460-
// Note that the ABI can also be set implicitly by the target selected.
461+
// Setting -msoft-float/-mfloat-abi=soft, -mfpu=none, or adding +nofp to
462+
// -march/-mcpu effectively disables the FPU (GCC ignores the -mfpu options in
463+
// this case). Note that the ABI can also be set implicitly by the target
464+
// selected.
461465
if (ABI == arm::FloatABI::Soft) {
462466
llvm::ARM::getFPUFeatures(llvm::ARM::FK_NONE, Features);
463467

464468
// Disable all features relating to hardware FP, not already disabled by the
465469
// above call.
470+
Features.insert(Features.end(), {"-dotprod", "-fp16fml", "-bf16", "-mve",
471+
"-mve.fp", "-fpregs"});
472+
} else if (FPUID == llvm::ARM::FK_NONE ||
473+
ArchArgFPUID == llvm::ARM::FK_NONE ||
474+
CPUArgFPUID == llvm::ARM::FK_NONE) {
475+
// -mfpu=none, -march=armvX+nofp or -mcpu=X+nofp is *very* similar to
476+
// -mfloat-abi=soft, only that it should not disable MVE-I. They disable the
477+
// FPU, but not the FPU registers, thus MVE-I, which depends only on the
478+
// latter, is still supported.
466479
Features.insert(Features.end(),
467-
{"-dotprod", "-fp16fml", "-mve", "-mve.fp", "-fpregs"});
468-
} else if (FPUID == llvm::ARM::FK_NONE) {
469-
// -mfpu=none is *very* similar to -mfloat-abi=soft, only that it should not
470-
// disable MVE-I.
471-
Features.insert(Features.end(), {"-dotprod", "-fp16fml", "-mve.fp"});
480+
{"-dotprod", "-fp16fml", "-bf16", "-mve.fp"});
472481
if (!hasIntegerMVE(Features))
473482
Features.emplace_back("-fpregs");
474483
}
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
// RUN: not %clang -o %t.out -target arm-arm-eabi -march=armv8-a+bf16 -mfloat-abi=soft -c %s 2>&1 | FileCheck %s
1+
// RUN: not %clang -target arm-arm-none-eabi -march=armv8-a+bf16 -mfloat-abi=soft -c %s -o %t 2>&1 | FileCheck %s
2+
// RUN: not %clang -target arm-arm-none-eabi -march=armv8-a+bf16 -mfpu=none -c %s -o %t 2>&1 | FileCheck %s
3+
// RUN: not %clang -target arm-arm-none-eabi -march=armv8-a+bf16+nofp -c %s -o %t 2>&1 | FileCheck %s
4+
// RUN: not %clang -target arm-arm-none-eabi -march=armv8-a+bf16+fp+nofp -c %s -o %t 2>&1 | FileCheck %s
5+
// RUN: %clang -target arm-arm-none-eabi -march=armv8-a+bf16+fp -c %s -o %t
6+
// RUN: %clang -target arm-arm-none-eabi -march=armv8-a+bf16+nofp+fp -c %s -o %t
27

38
// CHECK: error: __bf16 is not supported on this target
49
extern __bf16 var;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: %clang -target arm-arm-none-eabi -mfloat-abi=soft %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-MFLOAT-ABI-SOFT
2+
// CHECK-MFLOAT-ABI-SOFT: "-target-feature" "-dotprod"
3+
// CHECK-MFLOAT-ABI-SOFT: "-target-feature" "-fp16fml"
4+
// CHECK-MFLOAT-ABI-SOFT: "-target-feature" "-bf16"
5+
// CHECK-MFLOAT-ABI-SOFT: "-target-feature" "-mve"
6+
// CHECK-MFLOAT-ABI-SOFT: "-target-feature" "-mve.fp"
7+
// CHECK-MFLOAT-ABI-SOFT: "-target-feature" "-fpregs"
8+
9+
// RUN: %clang -target arm-arm-none-eabi -mfpu=none %s -### 2>&1 | FileCheck %s
10+
// RUN: %clang -target arm-arm-none-eabi -march=armv8-a+nofp %s -### 2>&1 | FileCheck %s
11+
// RUN: %clang -target arm-arm-none-eabi -mcpu=cortex-a35+nofp %s -### 2>&1 | FileCheck %s
12+
// RUN: %clang -target arm-arm-none-eabi -march=armv8-a+nofp+nomve %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-NOMVE
13+
// RUN: %clang -target arm-arm-none-eabi -mcpu=cortex-a35+nofp+nomve %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-NOMVE
14+
// CHECK: "-target-feature" "-dotprod"
15+
// CHECK: "-target-feature" "-fp16fml"
16+
// CHECK: "-target-feature" "-bf16"
17+
// CHECK: "-target-feature" "-mve.fp"
18+
// CHECK-NOMVE: "-target-feature" "-fpregs"

llvm/include/llvm/Support/ARMTargetParser.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,8 @@ StringRef getSubArch(ArchKind AK);
250250
StringRef getArchExtName(uint64_t ArchExtKind);
251251
StringRef getArchExtFeature(StringRef ArchExt);
252252
bool appendArchExtFeatures(StringRef CPU, ARM::ArchKind AK, StringRef ArchExt,
253-
std::vector<StringRef> &Features);
253+
std::vector<StringRef> &Features,
254+
unsigned &ArgFPUKind);
254255
StringRef getHWDivName(uint64_t HWDivKind);
255256

256257
// Information by Name

llvm/lib/Support/ARMTargetParser.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -490,9 +490,10 @@ static unsigned findDoublePrecisionFPU(unsigned InputFPUKind) {
490490
return ARM::FK_INVALID;
491491
}
492492

493-
bool ARM::appendArchExtFeatures(
494-
StringRef CPU, ARM::ArchKind AK, StringRef ArchExt,
495-
std::vector<StringRef> &Features) {
493+
bool ARM::appendArchExtFeatures(StringRef CPU, ARM::ArchKind AK,
494+
StringRef ArchExt,
495+
std::vector<StringRef> &Features,
496+
unsigned &ArgFPUID) {
496497

497498
size_t StartingNumFeatures = Features.size();
498499
const bool Negated = stripNegationPrefix(ArchExt);
@@ -527,6 +528,7 @@ bool ARM::appendArchExtFeatures(
527528
} else {
528529
FPUKind = getDefaultFPU(CPU, AK);
529530
}
531+
ArgFPUID = FPUKind;
530532
return ARM::getFPUFeatures(FPUKind, Features);
531533
}
532534
return StartingNumFeatures != Features.size();

llvm/unittests/Support/TargetParserTest.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -668,9 +668,10 @@ static bool
668668
testArchExtDependency(const char *ArchExt,
669669
const std::initializer_list<const char *> &Expected) {
670670
std::vector<StringRef> Features;
671+
unsigned FPUID;
671672

672673
if (!ARM::appendArchExtFeatures("", ARM::ArchKind::ARMV8_1MMainline, ArchExt,
673-
Features))
674+
Features, FPUID))
674675
return false;
675676

676677
return llvm::all_of(Expected, [&](StringRef Ext) {

0 commit comments

Comments
 (0)