Index: llvm/trunk/include/llvm/Support/TargetParser.h =================================================================== --- llvm/trunk/include/llvm/Support/TargetParser.h +++ llvm/trunk/include/llvm/Support/TargetParser.h @@ -32,13 +32,16 @@ // FPU names. enum FPUKind { FK_INVALID = 0, + FK_NONE, FK_VFP, FK_VFPV2, FK_VFPV3, FK_VFPV3_D16, FK_VFPV4, FK_VFPV4_D16, + FK_FPV4_SP_D16, FK_FPV5_D16, + FK_FPV5_SP_D16, FK_FP_ARMV8, FK_NEON, FK_NEON_VFPV4, Index: llvm/trunk/lib/Support/TargetParser.cpp =================================================================== --- llvm/trunk/lib/Support/TargetParser.cpp +++ llvm/trunk/lib/Support/TargetParser.cpp @@ -33,13 +33,16 @@ ARM::FPURestriction Restriction; } FPUNames[] = { { "invalid", ARM::FK_INVALID, 0, ARM::NS_None, ARM::FR_None}, + { "none", ARM::FK_NONE, 0, ARM::NS_None, ARM::FR_None}, { "vfp", ARM::FK_VFP, 2, ARM::NS_None, ARM::FR_None}, { "vfpv2", ARM::FK_VFPV2, 2, ARM::NS_None, ARM::FR_None}, { "vfpv3", ARM::FK_VFPV3, 3, ARM::NS_None, ARM::FR_None}, { "vfpv3-d16", ARM::FK_VFPV3_D16, 3, ARM::NS_None, ARM::FR_D16}, { "vfpv4", ARM::FK_VFPV4, 4, ARM::NS_None, ARM::FR_None}, { "vfpv4-d16", ARM::FK_VFPV4_D16, 4, ARM::NS_None, ARM::FR_D16}, + { "fpv4-sp-d16", ARM::FK_FPV4_SP_D16, 4, ARM::NS_None, ARM::FR_SP_D16}, { "fpv5-d16", ARM::FK_FPV5_D16, 5, ARM::NS_None, ARM::FR_D16}, + { "fpv5-sp-d16", ARM::FK_FPV5_SP_D16, 5, ARM::NS_None, ARM::FR_SP_D16}, { "fp-armv8", ARM::FK_FP_ARMV8, 5, ARM::NS_None, ARM::FR_None}, { "neon", ARM::FK_NEON, 3, ARM::NS_Neon, ARM::FR_None}, { "neon-vfpv4", ARM::FK_NEON_VFPV4, 4, ARM::NS_Neon, ARM::FR_None}, @@ -376,10 +379,9 @@ .Case("vfp4", "vfpv4") .Case("vfp3-d16", "vfpv3-d16") .Case("vfp4-d16", "vfpv4-d16") - // FIXME: sp-16 is NOT the same as d16 - .Cases("fp4-sp-d16", "fpv4-sp-d16", "vfpv4-d16") + .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16") .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16") - .Cases("fp5-sp-d16", "fpv5-sp-d16", "fpv5-d16") + .Case("fp5-sp-d16", "fpv5-sp-d16") .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16") // FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3. .Case("neon-vfpv3", "neon") Index: llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp =================================================================== --- llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp +++ llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp @@ -640,9 +640,13 @@ if (STI.hasFPARMv8()) // FPv5 and FP-ARMv8 have the same instructions, so are modeled as one // FPU, but there are two different names for it depending on the CPU. - ATS.emitFPU(STI.hasD16() ? ARM::FK_FPV5_D16 : ARM::FK_FP_ARMV8); + ATS.emitFPU(STI.hasD16() + ? (STI.isFPOnlySP() ? ARM::FK_FPV5_SP_D16 : ARM::FK_FPV5_D16) + : ARM::FK_FP_ARMV8); else if (STI.hasVFP4()) - ATS.emitFPU(STI.hasD16() ? ARM::FK_VFPV4_D16 : ARM::FK_VFPV4); + ATS.emitFPU(STI.hasD16() + ? (STI.isFPOnlySP() ? ARM::FK_FPV4_SP_D16 : ARM::FK_VFPV4_D16) + : ARM::FK_VFPV4); else if (STI.hasVFP3()) ATS.emitFPU(STI.hasD16() ? ARM::FK_VFPV3_D16 : ARM::FK_VFPV3); else if (STI.hasVFP2()) Index: llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp =================================================================== --- llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp +++ llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp @@ -810,6 +810,9 @@ /* OverwriteExisting= */ false); break; + // ABI_HardFP_use is handled in ARMAsmPrinter, so _SP_D16 is treated the same + // as _D16 here. + case ARM::FK_FPV4_SP_D16: case ARM::FK_VFPV4_D16: setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv4B, @@ -824,6 +827,7 @@ // FPV5_D16 is identical to FP_ARMV8 except for the number of D registers, so // uses the FP_ARMV8_D16 build attribute. + case ARM::FK_FPV5_SP_D16: case ARM::FK_FPV5_D16: setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPARMv8B, @@ -858,6 +862,7 @@ break; case ARM::FK_SOFTVFP: + case ARM::FK_NONE: break; default: Index: llvm/trunk/test/CodeGen/ARM/build-attributes.ll =================================================================== --- llvm/trunk/test/CodeGen/ARM/build-attributes.ll +++ llvm/trunk/test/CodeGen/ARM/build-attributes.ll @@ -923,7 +923,7 @@ ; CORTEX-M4-SOFT: .eabi_attribute 7, 77 ; CORTEX-M4-SOFT: .eabi_attribute 8, 0 ; CORTEX-M4-SOFT: .eabi_attribute 9, 2 -; CORTEX-M4-SOFT: .fpu vfpv4-d16 +; CORTEX-M4-SOFT: .fpu fpv4-sp-d16 ; CORTEX-M4-SOFT-NOT: .eabi_attribute 19 ;; We default to IEEE 754 compliance ; CORTEX-M4-SOFT: .eabi_attribute 20, 1 @@ -953,7 +953,7 @@ ; CORTEX-M4-HARD: .eabi_attribute 7, 77 ; CORTEX-M4-HARD: .eabi_attribute 8, 0 ; CORTEX-M4-HARD: .eabi_attribute 9, 2 -; CORTEX-M4-HARD: .fpu vfpv4-d16 +; CORTEX-M4-HARD: .fpu fpv4-sp-d16 ; CORTEX-M4-HARD-NOT: .eabi_attribute 19 ;; We default to IEEE 754 compliance ; CORTEX-M4-HARD: .eabi_attribute 20, 1 @@ -984,7 +984,7 @@ ; CORTEX-M7: .eabi_attribute 8, 0 ; CORTEX-M7: .eabi_attribute 9, 2 ; CORTEX-M7-SOFT-NOT: .fpu -; CORTEX-M7-SINGLE: .fpu fpv5-d16 +; CORTEX-M7-SINGLE: .fpu fpv5-sp-d16 ; CORTEX-M7-DOUBLE: .fpu fpv5-d16 ; CORTEX-M7: .eabi_attribute 17, 1 ; CORTEX-M7-NOT: .eabi_attribute 19 Index: llvm/trunk/test/MC/ARM/directive-fpu-multiple.s =================================================================== --- llvm/trunk/test/MC/ARM/directive-fpu-multiple.s +++ llvm/trunk/test/MC/ARM/directive-fpu-multiple.s @@ -1,12 +1,28 @@ @ Check multiple .fpu directives. @ The later .fpu directive should overwrite the earlier one. -@ See also: directive-fpu-multiple2.s. +@ We also check here that all the .fpu directives that we expect to work do work @ RUN: llvm-mc -triple arm-eabi -filetype obj %s | llvm-readobj -arm-attributes \ @ RUN: | FileCheck %s -check-prefix CHECK-ATTR + .fpu none + .fpu vfp + .fpu vfpv2 + .fpu vfpv3 + .fpu vfpv3-d16 + .fpu vfpv4 + .fpu vfpv4-d16 + .fpu fpv4-sp-d16 + .fpu fpv5-d16 + .fpu fpv5-sp-d16 + .fpu fp-armv8 .fpu neon + .fpu neon-vfpv4 + .fpu neon-fp-armv8 + .fpu crypto-neon-fp-armv8 + .fpu softvfp + .fpu vfpv4 @ CHECK-ATTR: FileAttributes {