ARM: correct handling of .fpu directive

The FPU directive permits the user to switch the target FPU, enabling
instructions that would be otherwise unavailable.  However, when configuring the
new subtarget features, we would not enable the implied functions for newer
FPUs.  This would result in invalid rejection of valid input.  Ensure that we
inherit the implied FPU functionality when enabling newer versions of the FPU.
Fortunately, these are mostly hierarchical, unlike the CPUs.

Addresses PR22395.

llvm-svn: 227584
This commit is contained in:
Saleem Abdulrasool 2015-01-30 17:58:25 +00:00
parent 7f933f4c5e
commit 206d1160ce
2 changed files with 98 additions and 23 deletions

View File

@ -9191,27 +9191,39 @@ bool ARMAsmParser::parseDirectiveCPU(SMLoc L) {
// FIXME: This is duplicated in getARMFPUFeatures() in
// tools/clang/lib/Driver/Tools.cpp
static const struct {
const unsigned Fpu;
const unsigned ID;
const uint64_t Enabled;
const uint64_t Disabled;
} Fpus[] = {
{ARM::VFP, ARM::FeatureVFP2, ARM::FeatureNEON},
{ARM::VFPV2, ARM::FeatureVFP2, ARM::FeatureNEON},
{ARM::VFPV3, ARM::FeatureVFP3, ARM::FeatureNEON},
{ARM::VFPV3_D16, ARM::FeatureVFP3 | ARM::FeatureD16, ARM::FeatureNEON},
{ARM::VFPV4, ARM::FeatureVFP4, ARM::FeatureNEON},
{ARM::VFPV4_D16, ARM::FeatureVFP4 | ARM::FeatureD16, ARM::FeatureNEON},
{ARM::FPV5_D16, ARM::FeatureFPARMv8 | ARM::FeatureD16,
ARM::FeatureNEON | ARM::FeatureCrypto},
{ARM::FP_ARMV8, ARM::FeatureFPARMv8,
ARM::FeatureNEON | ARM::FeatureCrypto},
{ARM::NEON, ARM::FeatureNEON, 0},
{ARM::NEON_VFPV4, ARM::FeatureVFP4 | ARM::FeatureNEON, 0},
{ARM::NEON_FP_ARMV8, ARM::FeatureFPARMv8 | ARM::FeatureNEON,
ARM::FeatureCrypto},
{ARM::CRYPTO_NEON_FP_ARMV8,
ARM::FeatureFPARMv8 | ARM::FeatureNEON | ARM::FeatureCrypto, 0},
{ARM::SOFTVFP, 0, 0},
} FPUs[] = {
{ARM::VFP, ARM::FeatureVFP2, ARM::FeatureNEON},
{ARM::VFPV2, ARM::FeatureVFP2, ARM::FeatureNEON},
{ARM::VFPV3, ARM::FeatureVFP2 | ARM::FeatureVFP3, ARM::FeatureNEON},
{ARM::VFPV3_D16, ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureD16,
ARM::FeatureNEON},
{ARM::VFPV4, ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureVFP4,
ARM::FeatureNEON},
{ARM::VFPV4_D16,
ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureVFP4 | ARM::FeatureD16,
ARM::FeatureNEON},
{ARM::FPV5_D16, ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureVFP4 |
ARM::FeatureFPARMv8 | ARM::FeatureD16,
ARM::FeatureNEON | ARM::FeatureCrypto},
{ARM::FP_ARMV8, ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureVFP4 |
ARM::FeatureFPARMv8,
ARM::FeatureNEON | ARM::FeatureCrypto},
{ARM::NEON, ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureNEON, 0},
{ARM::NEON_VFPV4,
ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureVFP4 | ARM::FeatureNEON,
0},
{ARM::NEON_FP_ARMV8,
ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureVFP4 |
ARM::FeatureFPARMv8 | ARM::FeatureNEON,
ARM::FeatureCrypto},
{ARM::CRYPTO_NEON_FP_ARMV8,
ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureVFP4 |
ARM::FeatureFPARMv8 | ARM::FeatureNEON | ARM::FeatureCrypto,
0},
{ARM::SOFTVFP, 0, 0},
};
/// parseDirectiveFPU
@ -9229,14 +9241,14 @@ bool ARMAsmParser::parseDirectiveFPU(SMLoc L) {
return false;
}
for (const auto &Fpu : Fpus) {
if (Fpu.Fpu != ID)
for (const auto &Entry : FPUs) {
if (Entry.ID != ID)
continue;
// Need to toggle features that should be on but are off and that
// should off but are on.
uint64_t Toggle = (Fpu.Enabled & ~STI.getFeatureBits()) |
(Fpu.Disabled & STI.getFeatureBits());
uint64_t Toggle = (Entry.Enabled & ~STI.getFeatureBits()) |
(Entry.Disabled & STI.getFeatureBits());
setAvailableFeatures(ComputeAvailableFeatures(STI.ToggleFeature(Toggle)));
break;
}

View File

@ -0,0 +1,63 @@
@ RUN: llvm-mc -triple armv4t-eabi -filetype asm -o - %s 2>&1 | FileCheck %s
.text
.thumb
.p2align 2
.fpu neon
vldmia r0, {d16-d31}
@ CHECK: vldmia r0, {d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31}
@ CHECK-NOT: error: instruction requires: VFP2
.fpu vfpv3
vadd.f32 s1, s2, s3
@ CHECK: vadd.f32 s1, s2, s3
@ CHECK-NOT: error: instruction requires: VPF2
.fpu vfpv3-d16
vadd.f32 s1, s2, s3
@ CHECK: vadd.f32 s1, s2, s3
@ CHECK-NOT: error: instruction requires: VPF2
.fpu vfpv4
vadd.f32 s1, s2, s3
@ CHECK: vadd.f32 s1, s2, s3
@ CHECK-NOT: error: instruction requires: VPF2
.fpu vfpv4-d16
vadd.f32 s1, s2, s3
@ CHECK: vadd.f32 s1, s2, s3
@ CHECK-NOT: error: instruction requires: VPF2
.fpu fpv5-d16
vadd.f32 s1, s2, s3
@ CHECK: vadd.f32 s1, s2, s3
@ CHECK-NOT: error: instruction requires: VPF2
.fpu fp-armv8
vadd.f32 s1, s2, s3
@ CHECK: vadd.f32 s1, s2, s3
@ CHECK-NOT: error: instruction requires: VPF2
.fpu fp-armv8
vadd.f32 s1, s2, s3
@ CHECK: vadd.f32 s1, s2, s3
@ CHECK-NOT: error: instruction requires: VPF2
.fpu neon
vadd.f32 s1, s2, s3
@ CHECK: vadd.f32 s1, s2, s3
@ CHECK-NOT: error: instruction requires: VPF2
.fpu neon-vfpv4
vadd.f32 s1, s2, s3
@ CHECK: vadd.f32 s1, s2, s3
@ CHECK-NOT: error: instruction requires: VPF2
.fpu crypto-neon-fp-armv8
vadd.f32 s1, s2, s3
@ CHECK: vadd.f32 s1, s2, s3
@ CHECK-NOT: error: instruction requires: VPF2