Skip to content

Commit

Permalink
[ARM] Fix bugs introduced by the fp64/d32 rework.
Browse files Browse the repository at this point in the history
Change D60691 caused some knock-on failures that weren't caught by the
existing tests. Firstly, selecting a CPU that should have had a
restricted FPU (e.g. `-mcpu=cortex-m4`, which should have 16 d-regs
and no double precision) could give the unrestricted version, because
`ARM::getFPUFeatures` returned a list of features including subtracted
ones (here `-fp64`,`-d32`), but `ARMTargetInfo::initFeatureMap` threw
away all the ones that didn't start with `+`. Secondly, the
preprocessor macros didn't reliably match the actual compilation
settings: for example, `-mfpu=softvfp` could still set `__ARM_FP` as
if hardware FP was available, because the list of features on the cc1
command line would include things like `+vfp4`,`-vfp4d16` and clang
didn't realise that one of those cancelled out the other.

I've fixed both of these issues by rewriting `ARM::getFPUFeatures` so
that it returns a list that enables every FP-related feature
compatible with the selected FPU and disables every feature not
compatible, which is more verbose but means clang doesn't have to
understand the dependency relationships between the backend features.
Meanwhile, `ARMTargetInfo::handleTargetFeatures` is testing for all
the various forms of the FP feature names, so that it won't miss cases
where it should have set `HW_FP` to feed into feature test macros.

That in turn caused an ordering problem when handling `-mcpu=foo+bar`
together with `-mfpu=something_that_turns_off_bar`. To fix that, I've
arranged that the `+bar` suffixes on the end of `-mcpu` and `-march`
cause feature names to be put into a separate vector which is
concatenated after the output of `getFPUFeatures`.

Another side effect of all this is to fix a bug where `clang -target
armv8-eabi` by itself would fail to set `__ARM_FEATURE_FMA`, even
though `armv8` (aka Arm v8-A) implies FP-Armv8 which has FMA. That was
because `HW_FP` was being set to a value including only the `FPARMV8`
bit, but that feature test macro was testing only the `VFP4FPU` bit.
Now `HW_FP` ends up with all the bits set, so it gives the right
answer.

Changes to tests included in this patch:

* `arm-target-features.c`: I had to change basically all the expected
  results. (The Cortex-M4 test in there should function as a
  regression test for the accidental double-precision bug.)
* `arm-mfpu.c`, `armv8.1m.main.c`: switched to using `CHECK-DAG`
  everywhere so that those tests are no longer sensitive to the order
  of cc1 feature options on the command line.
* `arm-acle-6.5.c`: been updated to expect the right answer to that
  FMA test.
* `Preprocessor/arm-target-features.c`: added a regression test for
  the `mfpu=softvfp` issue.

Reviewers: SjoerdMeijer, dmgreen, ostannard, samparker, JamesNagurne

Reviewed By: ostannard

Subscribers: srhines, javed.absar, kristof.beyls, hiraditya, cfe-commits, llvm-commits

Tags: #clang, #llvm

Differential Revision: https://reviews.llvm.org/D62998

llvm-svn: 362791
  • Loading branch information
statham-arm committed Jun 7, 2019
1 parent f720647 commit 5d66f2b
Show file tree
Hide file tree
Showing 8 changed files with 324 additions and 300 deletions.
20 changes: 16 additions & 4 deletions clang/lib/Basic/Targets/ARM.cpp
Expand Up @@ -408,18 +408,30 @@ bool ARMTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
SoftFloat = true;
} else if (Feature == "+soft-float-abi") {
SoftFloatABI = true;
} else if (Feature == "+vfp2") {
} else if (Feature == "+vfp2sp" || Feature == "+vfp2d16sp" ||
Feature == "+vfp2" || Feature == "+vfp2d16") {
FPU |= VFP2FPU;
HW_FP |= HW_FP_SP;
} else if (Feature == "+vfp3") {
if (Feature == "+vfp2" || Feature == "+vfp2d16")
HW_FP |= HW_FP_DP;
} else if (Feature == "+vfp3sp" || Feature == "+vfp3d16sp" ||
Feature == "+vfp3" || Feature == "+vfp3d16") {
FPU |= VFP3FPU;
HW_FP |= HW_FP_SP;
} else if (Feature == "+vfp4") {
if (Feature == "+vfp3" || Feature == "+vfp3d16")
HW_FP |= HW_FP_DP;
} else if (Feature == "+vfp4sp" || Feature == "+vfp4d16sp" ||
Feature == "+vfp4" || Feature == "+vfp4d16") {
FPU |= VFP4FPU;
HW_FP |= HW_FP_SP | HW_FP_HP;
} else if (Feature == "+fp-armv8") {
if (Feature == "+vfp4" || Feature == "+vfp4d16")
HW_FP |= HW_FP_DP;
} else if (Feature == "+fp-armv8sp" || Feature == "+fp-armv8d16sp" ||
Feature == "+fp-armv8" || Feature == "+fp-armv8d16") {
FPU |= FPARMV8;
HW_FP |= HW_FP_SP | HW_FP_HP;
if (Feature == "+fp-armv8" || Feature == "+fp-armv8d16")
HW_FP |= HW_FP_DP;
} else if (Feature == "+neon") {
FPU |= NeonFPU;
HW_FP |= HW_FP_SP;
Expand Down
49 changes: 33 additions & 16 deletions clang/lib/Driver/ToolChains/Arch/ARM.cpp
Expand Up @@ -100,21 +100,23 @@ static void DecodeARMFeaturesFromCPU(const Driver &D, StringRef CPU,
static void checkARMArchName(const Driver &D, const Arg *A, const ArgList &Args,
llvm::StringRef ArchName, llvm::StringRef CPUName,
std::vector<StringRef> &Features,
std::vector<StringRef> &ExtensionFeatures,
const llvm::Triple &Triple) {
std::pair<StringRef, StringRef> Split = ArchName.split("+");

std::string MArch = arm::getARMArch(ArchName, Triple);
llvm::ARM::ArchKind ArchKind = llvm::ARM::parseArch(MArch);
if (ArchKind == llvm::ARM::ArchKind::INVALID ||
(Split.second.size() && !DecodeARMFeatures(
D, Split.second, CPUName, ArchKind, Features)))
D, Split.second, CPUName, ArchKind, ExtensionFeatures)))
D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
}

// Check -mcpu=. Needs ArchName to handle -mcpu=generic.
static void checkARMCPUName(const Driver &D, const Arg *A, const ArgList &Args,
llvm::StringRef CPUName, llvm::StringRef ArchName,
std::vector<StringRef> &Features,
std::vector<StringRef> &ExtensionFeatures,
const llvm::Triple &Triple) {
std::pair<StringRef, StringRef> Split = CPUName.split("+");

Expand All @@ -123,7 +125,7 @@ static void checkARMCPUName(const Driver &D, const Arg *A, const ArgList &Args,
arm::getLLVMArchKindForARM(CPU, ArchName, Triple);
if (ArchKind == llvm::ARM::ArchKind::INVALID ||
(Split.second.size() && !DecodeARMFeatures(
D, Split.second, CPU, ArchKind, Features)))
D, Split.second, CPU, ArchKind, ExtensionFeatures)))
D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
}

Expand Down Expand Up @@ -289,6 +291,13 @@ void arm::getARMTargetFeatures(const ToolChain &TC,
const Arg *WaCPU = nullptr, *WaFPU = nullptr;
const Arg *WaHDiv = nullptr, *WaArch = nullptr;

// This vector will accumulate features from the architecture
// extension suffixes on -mcpu and -march (e.g. the 'bar' in
// -mcpu=foo+bar). We want to apply those after the features derived
// from the FPU, in case -mfpu generates a negative feature which
// the +bar is supposed to override.
std::vector<StringRef> ExtensionFeatures;

if (!ForAS) {
// FIXME: Note, this is a hack, the LLVM backend doesn't actually use these
// yet (it uses the -mfloat-abi and -msoft-float options), and it is
Expand Down Expand Up @@ -351,12 +360,14 @@ void arm::getARMTargetFeatures(const ToolChain &TC,
D.Diag(clang::diag::warn_drv_unused_argument)
<< ArchArg->getAsString(Args);
ArchName = StringRef(WaArch->getValue()).substr(7);
checkARMArchName(D, WaArch, Args, ArchName, CPUName, Features, Triple);
checkARMArchName(D, WaArch, Args, ArchName, CPUName,
Features, ExtensionFeatures, Triple);
// FIXME: Set Arch.
D.Diag(clang::diag::warn_drv_unused_argument) << WaArch->getAsString(Args);
} else if (ArchArg) {
ArchName = ArchArg->getValue();
checkARMArchName(D, ArchArg, Args, ArchName, CPUName, Features, Triple);
checkARMArchName(D, ArchArg, Args, ArchName, CPUName,
Features, ExtensionFeatures, Triple);
}

// Add CPU features for generic CPUs
Expand All @@ -367,11 +378,12 @@ void arm::getARMTargetFeatures(const ToolChain &TC,
Features.push_back(
Args.MakeArgString((F.second ? "+" : "-") + F.first()));
} else if (!CPUName.empty()) {
DecodeARMFeaturesFromCPU(D, CPUName, Features);
DecodeARMFeaturesFromCPU(D, CPUName, ExtensionFeatures);
}

if (CPUArg)
checkARMCPUName(D, CPUArg, Args, CPUName, ArchName, Features, Triple);
checkARMCPUName(D, CPUArg, Args, CPUName, ArchName,
Features, ExtensionFeatures, Triple);
// Honor -mfpu=. ClangAs gives preference to -Wa,-mfpu=.
const Arg *FPUArg = Args.getLastArg(options::OPT_mfpu_EQ);
if (WaFPU) {
Expand All @@ -389,6 +401,12 @@ void arm::getARMTargetFeatures(const ToolChain &TC,
<< std::string("-mfpu=") + AndroidFPU;
}

// Now we've finished accumulating features from arch, cpu and fpu,
// we can append the ones for architecture extensions that we
// collected separately.
Features.insert(std::end(Features),
std::begin(ExtensionFeatures), std::end(ExtensionFeatures));

// Honor -mhwdiv=. ClangAs gives preference to -Wa,-mhwdiv=.
const Arg *HDivArg = Args.getLastArg(options::OPT_mhwdiv_EQ);
if (WaHDiv) {
Expand Down Expand Up @@ -433,21 +451,20 @@ void arm::getARMTargetFeatures(const ToolChain &TC,
if (ABI == arm::FloatABI::Soft) {
llvm::ARM::getFPUFeatures(llvm::ARM::FK_NONE, Features);

// Disable hardware FP features which have been enabled.
// Disable all features relating to hardware FP.
// FIXME: Disabling fpregs should be enough all by itself, since all
// the other FP features are dependent on it. However
// there is currently no easy way to test this in clang, so for
// now just be explicit and disable all known dependent features
// as well.
for (std::string Feature : {"vfp2", "vfp3", "vfp4", "fp-armv8", "fullfp16",
"neon", "crypto", "dotprod", "fp16fml"})
if (std::find(std::begin(Features), std::end(Features), "+" + Feature) != std::end(Features))
Features.push_back(Args.MakeArgString("-" + Feature));

// Disable the base feature unconditionally, even if it was not
// explicitly in the features list (e.g. if we had +vfp3, which
// implies it).
Features.push_back("-fpregs");
for (std::string Feature : {
"vfp2", "vfp2sp", "vfp2d16", "vfp2d16sp",
"vfp3", "vfp3sp", "vfp3d16", "vfp3d16sp",
"vfp4", "vfp4sp", "vfp4d16", "vfp4d16sp",
"fp-armv8", "fp-armv8sp", "fp-armv8d16", "fp-armv8d16sp",
"fullfp16", "neon", "crypto", "dotprod", "fp16fml",
"fp64", "d32", "fpregs"})
Features.push_back(Args.MakeArgString("-" + Feature));
}

// En/disable crc code generation.
Expand Down
28 changes: 14 additions & 14 deletions clang/test/CodeGen/arm-target-features.c
@@ -1,23 +1,23 @@
// REQUIRES: arm-registered-target

// RUN: %clang_cc1 -triple thumbv7-linux-gnueabihf -target-cpu cortex-a8 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP3
// CHECK-VFP3: "target-features"="+armv7-a,+d32,+dsp,+fp64,+neon,+thumb-mode,+vfp3"
// CHECK-VFP3: "target-features"="+armv7-a,+d32,+dsp,+fp64,+fpregs,+neon,+thumb-mode,+vfp2,+vfp2d16,+vfp2d16sp,+vfp2sp,+vfp3,+vfp3d16,+vfp3d16sp,+vfp3sp"


// RUN: %clang_cc1 -triple thumbv7-linux-gnueabihf -target-cpu cortex-a5 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP4
// CHECK-VFP4: "target-features"="+armv7-a,+d32,+dsp,+fp64,+neon,+thumb-mode,+vfp4"
// CHECK-VFP4: "target-features"="+armv7-a,+d32,+dsp,+fp16,+fp64,+fpregs,+neon,+thumb-mode,+vfp2,+vfp2d16,+vfp2d16sp,+vfp2sp,+vfp3,+vfp3d16,+vfp3d16sp,+vfp3sp,+vfp4,+vfp4d16,+vfp4d16sp,+vfp4sp"


// RUN: %clang_cc1 -triple thumbv7-linux-gnueabihf -target-cpu cortex-a7 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP4-DIV
// RUN: %clang_cc1 -triple thumbv7-linux-gnueabi -target-cpu cortex-a12 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP4-DIV
// RUN: %clang_cc1 -triple thumbv7s-linux-gnueabi -target-cpu swift -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP4-DIV-2
// RUN: %clang_cc1 -triple thumbv7-linux-gnueabihf -target-cpu krait -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP4-DIV
// CHECK-VFP4-DIV: "target-features"="+armv7-a,+d32,+dsp,+fp64,+hwdiv,+hwdiv-arm,+neon,+thumb-mode,+vfp4"
// CHECK-VFP4-DIV-2: "target-features"="+armv7s,+d32,+dsp,+fp64,+hwdiv,+hwdiv-arm,+neon,+thumb-mode,+vfp4"
// CHECK-VFP4-DIV: "target-features"="+armv7-a,+d32,+dsp,+fp16,+fp64,+fpregs,+hwdiv,+hwdiv-arm,+neon,+thumb-mode,+vfp2,+vfp2d16,+vfp2d16sp,+vfp2sp,+vfp3,+vfp3d16,+vfp3d16sp,+vfp3sp,+vfp4,+vfp4d16,+vfp4d16sp,+vfp4sp"
// CHECK-VFP4-DIV-2: "target-features"="+armv7s,+d32,+dsp,+fp16,+fp64,+fpregs,+hwdiv,+hwdiv-arm,+neon,+thumb-mode,+vfp2,+vfp2d16,+vfp2d16sp,+vfp2sp,+vfp3,+vfp3d16,+vfp3d16sp,+vfp3sp,+vfp4,+vfp4d16,+vfp4d16sp,+vfp4sp"

// RUN: %clang_cc1 -triple armv7-linux-gnueabihf -target-cpu cortex-a15 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP4-DIV-ARM
// RUN: %clang_cc1 -triple armv7-linux-gnueabihf -target-cpu cortex-a17 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP4-DIV-ARM
// CHECK-VFP4-DIV-ARM: "target-features"="+armv7-a,+d32,+dsp,+fp64,+hwdiv,+hwdiv-arm,+neon,+vfp4,-thumb-mode"
// CHECK-VFP4-DIV-ARM: "target-features"="+armv7-a,+d32,+dsp,+fp16,+fp64,+fpregs,+hwdiv,+hwdiv-arm,+neon,+vfp2,+vfp2d16,+vfp2d16sp,+vfp2sp,+vfp3,+vfp3d16,+vfp3d16sp,+vfp3sp,+vfp4,+vfp4d16,+vfp4d16sp,+vfp4sp,-thumb-mode"

// RUN: %clang_cc1 -triple thumbv7s-apple-ios7.0 -target-cpu cyclone -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8
// RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu cortex-a32 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8
Expand All @@ -28,34 +28,34 @@
// RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu exynos-m1 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8
// RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu exynos-m2 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8
// RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu exynos-m3 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8
// CHECK-BASIC-V8: "target-features"="+armv8-a,+crc,+crypto,+d32,+dsp,+fp-armv8,+fp64,+hwdiv,+hwdiv-arm,+neon,+thumb-mode"
// CHECK-BASIC-V8: "target-features"="+armv8-a,+crc,+crypto,+d32,+dsp,+fp-armv8,+fp-armv8d16,+fp-armv8d16sp,+fp-armv8sp,+fp16,+fp64,+fpregs,+hwdiv,+hwdiv-arm,+neon,+thumb-mode,+vfp2,+vfp2d16,+vfp2d16sp,+vfp2sp,+vfp3,+vfp3d16,+vfp3d16sp,+vfp3sp,+vfp4,+vfp4d16,+vfp4d16sp,+vfp4sp"

// RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu exynos-m4 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V82
// RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu exynos-m5 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V82
// CHECK-BASIC-V82: "target-features"="+armv8.2-a,+crc,+crypto,+d32,+dotprod,+dsp,+fp-armv8,+fp64,+hwdiv,+hwdiv-arm,+neon,+ras,+thumb-mode"
// CHECK-BASIC-V82: "target-features"="+armv8.2-a,+crc,+crypto,+d32,+dotprod,+dsp,+fp-armv8,+fp-armv8d16,+fp-armv8d16sp,+fp-armv8sp,+fp16,+fp64,+fpregs,+hwdiv,+hwdiv-arm,+neon,+ras,+thumb-mode,+vfp2,+vfp2d16,+vfp2d16sp,+vfp2sp,+vfp3,+vfp3d16,+vfp3d16sp,+vfp3sp,+vfp4,+vfp4d16,+vfp4d16sp,+vfp4sp"

// RUN: %clang_cc1 -triple armv8-linux-gnueabi -target-cpu cortex-a53 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8-ARM
// CHECK-BASIC-V8-ARM: "target-features"="+armv8-a,+crc,+crypto,+d32,+dsp,+fp-armv8,+fp64,+hwdiv,+hwdiv-arm,+neon,-thumb-mode"
// CHECK-BASIC-V8-ARM: "target-features"="+armv8-a,+crc,+crypto,+d32,+dsp,+fp-armv8,+fp-armv8d16,+fp-armv8d16sp,+fp-armv8sp,+fp16,+fp64,+fpregs,+hwdiv,+hwdiv-arm,+neon,+vfp2,+vfp2d16,+vfp2d16sp,+vfp2sp,+vfp3,+vfp3d16,+vfp3d16sp,+vfp3sp,+vfp4,+vfp4d16,+vfp4d16sp,+vfp4sp,-thumb-mode"

// RUN: %clang_cc1 -triple thumbv7-linux-gnueabi -target-cpu cortex-r5 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP3-D16-DIV
// CHECK-VFP3-D16-DIV: "target-features"="+armv7-r,+dsp,+fp64,+hwdiv,+hwdiv-arm,+thumb-mode,+vfp3"
// CHECK-VFP3-D16-DIV: "target-features"="+armv7-r,+dsp,+fp64,+fpregs,+hwdiv,+hwdiv-arm,+thumb-mode,+vfp2d16,+vfp2d16sp,+vfp3d16,+vfp3d16sp"


// RUN: %clang_cc1 -triple armv7-linux-gnueabi -target-cpu cortex-r4f -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP3-D16-THUMB-DIV
// CHECK-VFP3-D16-THUMB-DIV: "target-features"="+armv7-r,+dsp,+fp64,+hwdiv,+vfp3,-thumb-mode"
// CHECK-VFP3-D16-THUMB-DIV: "target-features"="+armv7-r,+dsp,+fp64,+fpregs,+hwdiv,+vfp2d16,+vfp2d16sp,+vfp3d16,+vfp3d16sp,-thumb-mode"


// RUN: %clang_cc1 -triple thumbv7-linux-gnueabi -target-cpu cortex-r7 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP3-D16-FP16-DIV
// RUN: %clang_cc1 -triple thumbv7-linux-gnueabi -target-cpu cortex-r8 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP3-D16-FP16-DIV
// CHECK-VFP3-D16-FP16-DIV: "target-features"="+armv7-r,+dsp,+fp16,+fp64,+hwdiv,+hwdiv-arm,+thumb-mode,+vfp3"
// CHECK-VFP3-D16-FP16-DIV: "target-features"="+armv7-r,+dsp,+fp16,+fp64,+fpregs,+hwdiv,+hwdiv-arm,+thumb-mode,+vfp2d16,+vfp2d16sp,+vfp3d16,+vfp3d16sp"


// RUN: %clang_cc1 -triple thumbv7-linux-gnueabi -target-cpu cortex-m4 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP4-D16-SP-THUMB-DIV
// CHECK-VFP4-D16-SP-THUMB-DIV: "target-features"="+armv7e-m,+dsp,+hwdiv,+thumb-mode,+vfp4"
// CHECK-VFP4-D16-SP-THUMB-DIV: "target-features"="+armv7e-m,+dsp,+fp16,+fpregs,+hwdiv,+thumb-mode,+vfp2d16sp,+vfp3d16sp,+vfp4d16sp"


// RUN: %clang_cc1 -triple thumbv7-linux-gnueabi -target-cpu cortex-m7 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP5-D16-THUMB-DIV
// CHECK-VFP5-D16-THUMB-DIV: "target-features"="+armv7e-m,+dsp,+fp-armv8,+fp64,+hwdiv,+thumb-mode"
// CHECK-VFP5-D16-THUMB-DIV: "target-features"="+armv7e-m,+dsp,+fp-armv8d16,+fp-armv8d16sp,+fp16,+fp64,+fpregs,+hwdiv,+thumb-mode,+vfp2d16,+vfp2d16sp,+vfp3d16,+vfp3d16sp,+vfp4d16,+vfp4d16sp"


// RUN: %clang_cc1 -triple armv7-linux-gnueabi -target-cpu cortex-r4 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-THUMB-DIV
Expand Down Expand Up @@ -107,6 +107,6 @@
// CHECK-ARMV8M-M23-LINUX: "target-features"="+armv8-m.base,+hwdiv,+thumb-mode"

// RUN: %clang_cc1 -triple thumb-linux-gnueabi -target-cpu cortex-m33 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-ARMV8M-MAIN-LINUX
// CHECK-ARMV8M-MAIN-LINUX: "target-features"="+armv8-m.main,+dsp,+fp-armv8,+hwdiv,+thumb-mode"
// CHECK-ARMV8M-MAIN-LINUX: "target-features"="+armv8-m.main,+dsp,+fp-armv8d16sp,+fp16,+fpregs,+hwdiv,+thumb-mode,+vfp2d16sp,+vfp3d16sp,+vfp4d16sp"

void foo() {}

0 comments on commit 5d66f2b

Please sign in to comment.