diff --git a/include/llvm/CodeGen/CommandFlags.h b/include/llvm/CodeGen/CommandFlags.h index 4c05e7fd9e0..6821ec07a69 100644 --- a/include/llvm/CodeGen/CommandFlags.h +++ b/include/llvm/CodeGen/CommandFlags.h @@ -149,6 +149,26 @@ EnableNoNaNsFPMath("enable-no-nans-fp-math", cl::desc("Enable FP math optimizations that assume no NaNs"), cl::init(false)); +cl::opt +EnableNoTrappingFPMath("enable-no-trapping-fp-math", + cl::desc("Enable setting the FP exceptions build " + "attribute not to use exceptions"), + cl::init(false)); + +cl::opt +DenormalType("denormal-fp-math", + cl::desc("Select which denormal numbers the code is permitted to require"), + cl::init(FPDenormal::IEEE), + cl::values( + clEnumValN(FPDenormal::IEEE, "ieee", + "IEEE 754 denormal numbers"), + clEnumValN(FPDenormal::PreserveSign, "preserve-sign", + "the sign of a flushed-to-zero number is preserved " + "in the sign of 0"), + clEnumValN(FPDenormal::PositiveZero, "positive-zero", + "denormals are flushed to positive zero"), + clEnumValEnd)); + cl::opt EnableHonorSignDependentRoundingFPMath("enable-sign-dependent-rounding-fp-math", cl::Hidden, @@ -289,6 +309,8 @@ static inline TargetOptions InitTargetOptionsFromCodeGenFlags() { Options.UnsafeFPMath = EnableUnsafeFPMath; Options.NoInfsFPMath = EnableNoInfsFPMath; Options.NoNaNsFPMath = EnableNoNaNsFPMath; + Options.NoTrappingFPMath = EnableNoTrappingFPMath; + Options.FPDenormalType = DenormalType; Options.HonorSignDependentRoundingFPMathOption = EnableHonorSignDependentRoundingFPMath; if (FloatABIForCalls != FloatABI::Default) diff --git a/include/llvm/Target/TargetOptions.h b/include/llvm/Target/TargetOptions.h index b1e938e4027..07906e3f7e5 100644 --- a/include/llvm/Target/TargetOptions.h +++ b/include/llvm/Target/TargetOptions.h @@ -56,6 +56,15 @@ namespace llvm { }; } + namespace FPDenormal { + enum DenormalType { + IEEE, // IEEE 754 denormal numbers + PreserveSign, // the sign of a flushed-to-zero number is preserved in + // the sign of 0 + PositiveZero // denormals are flushed to positive zero + }; + } + enum class EABI { Unknown, Default, // Default means not specified @@ -93,6 +102,7 @@ namespace llvm { TargetOptions() : PrintMachineCode(false), LessPreciseFPMADOption(false), UnsafeFPMath(false), NoInfsFPMath(false), NoNaNsFPMath(false), + NoTrappingFPMath(false), HonorSignDependentRoundingFPMathOption(false), NoZerosInBSS(false), GuaranteedTailCallOpt(false), StackAlignmentOverride(0), StackSymbolOrdering(true), EnableFastISel(false), UseInitArray(false), @@ -104,6 +114,7 @@ namespace llvm { AllowFPOpFusion(FPOpFusion::Standard), Reciprocals(TargetRecip()), JTType(JumpTable::Single), ThreadModel(ThreadModel::POSIX), EABIVersion(EABI::Default), DebuggerTuning(DebuggerKind::Default), + FPDenormalType(FPDenormal::IEEE), ExceptionModel(ExceptionHandling::None) {} /// PrintMachineCode - This flag is enabled when the -print-machineinstrs @@ -143,6 +154,11 @@ namespace llvm { /// assume the FP arithmetic arguments and results are never NaNs. unsigned NoNaNsFPMath : 1; + /// NoTrappingFPMath - This flag is enabled when the + /// -enable-no-trapping-fp-math is specified on the command line. This + /// specifies that there are no trap handlers to handle exceptions. + unsigned NoTrappingFPMath : 1; + /// HonorSignDependentRoundingFPMath - This returns true when the /// -enable-sign-dependent-rounding-fp-math is specified. If this returns /// false (the default), the code generator is allowed to assume that the @@ -253,6 +269,10 @@ namespace llvm { /// Which debugger to tune for. DebuggerKind DebuggerTuning; + /// FPDenormalType - This flags specificies which denormal numbers the code + /// is permitted to require. + FPDenormal::DenormalType FPDenormalType; + /// What exception model to use ExceptionHandling ExceptionModel; @@ -270,6 +290,7 @@ inline bool operator==(const TargetOptions &LHS, ARE_EQUAL(UnsafeFPMath) && ARE_EQUAL(NoInfsFPMath) && ARE_EQUAL(NoNaNsFPMath) && + ARE_EQUAL(NoTrappingFPMath) && ARE_EQUAL(HonorSignDependentRoundingFPMathOption) && ARE_EQUAL(NoZerosInBSS) && ARE_EQUAL(GuaranteedTailCallOpt) && @@ -285,6 +306,7 @@ inline bool operator==(const TargetOptions &LHS, ARE_EQUAL(ThreadModel) && ARE_EQUAL(EABIVersion) && ARE_EQUAL(DebuggerTuning) && + ARE_EQUAL(FPDenormalType) && ARE_EQUAL(ExceptionModel) && ARE_EQUAL(MCOptions) && ARE_EQUAL(EnableIPRA); diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp index 53b2c3da9c2..9e3d1ee8602 100644 --- a/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/ARMAsmPrinter.cpp @@ -451,8 +451,16 @@ void ARMAsmPrinter::EmitStartOfAsmFile(Module &M) { OutStreamer->EmitAssemblerFlag(MCAF_SyntaxUnified); // Emit ARM Build Attributes - if (TT.isOSBinFormatELF()) + if (TT.isOSBinFormatELF()) { + if (!M.empty()) { + // FIXME: this is a hack, but it is not more broken than + // resetTargetOptions already was. The purpose of reading the target + // options here is to read function attributes denormal and trapping-math + // that we want to map onto build attributes. + TM.resetTargetOptions(*M.begin()); + } emitAttributes(); + } // Use the triple's architecture and subarchitecture to determine // if we're thumb for the purposes of the top level code16 assembler @@ -750,17 +758,17 @@ void ARMAsmPrinter::emitAttributes() { ARMBuildAttrs::AddressDirect); } - // Signal various FP modes. - if (!TM.Options.UnsafeFPMath) { + // Set FP Denormals. + if (TM.Options.FPDenormalType == FPDenormal::PreserveSign) + ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal, + ARMBuildAttrs::PreserveFPSign); + else if (TM.Options.FPDenormalType == FPDenormal::PositiveZero) + ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal, + ARMBuildAttrs::PositiveZero); + else if (!TM.Options.UnsafeFPMath) ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal, ARMBuildAttrs::IEEEDenormals); - ATS.emitAttribute(ARMBuildAttrs::ABI_FP_exceptions, ARMBuildAttrs::Allowed); - - // If the user has permitted this code to choose the IEEE 754 - // rounding at run-time, emit the rounding attribute. - if (TM.Options.HonorSignDependentRoundingFPMathOption) - ATS.emitAttribute(ARMBuildAttrs::ABI_FP_rounding, ARMBuildAttrs::Allowed); - } else { + else { if (!STI.hasVFP2()) { // When the target doesn't have an FPU (by design or // intention), the assumptions made on the software support @@ -786,6 +794,19 @@ void ARMAsmPrinter::emitAttributes() { // absence of its emission implies zero). } + // Set FP exceptions and rounding + if (TM.Options.NoTrappingFPMath) + ATS.emitAttribute(ARMBuildAttrs::ABI_FP_exceptions, + ARMBuildAttrs::Not_Allowed); + else if (!TM.Options.UnsafeFPMath) { + ATS.emitAttribute(ARMBuildAttrs::ABI_FP_exceptions, ARMBuildAttrs::Allowed); + + // If the user has permitted this code to choose the IEEE 754 + // rounding at run-time, emit the rounding attribute. + if (TM.Options.HonorSignDependentRoundingFPMathOption) + ATS.emitAttribute(ARMBuildAttrs::ABI_FP_rounding, ARMBuildAttrs::Allowed); + } + // TM.Options.NoInfsFPMath && TM.Options.NoNaNsFPMath is the // equivalent of GCC's -ffinite-math-only flag. if (TM.Options.NoInfsFPMath && TM.Options.NoNaNsFPMath) diff --git a/lib/Target/TargetMachine.cpp b/lib/Target/TargetMachine.cpp index 82c68505c4e..60505f49a6b 100644 --- a/lib/Target/TargetMachine.cpp +++ b/lib/Target/TargetMachine.cpp @@ -77,6 +77,16 @@ void TargetMachine::resetTargetOptions(const Function &F) const { RESET_OPTION(UnsafeFPMath, "unsafe-fp-math"); RESET_OPTION(NoInfsFPMath, "no-infs-fp-math"); RESET_OPTION(NoNaNsFPMath, "no-nans-fp-math"); + RESET_OPTION(NoTrappingFPMath, "no-trapping-math"); + + StringRef Denormal = + F.getFnAttribute("denormal-fp-math").getValueAsString(); + if (Denormal == "ieee") + Options.FPDenormalType = FPDenormal::IEEE; + else if (Denormal == "preserve-sign") + Options.FPDenormalType = FPDenormal::PreserveSign; + else if (Denormal == "positive-zero") + Options.FPDenormalType = FPDenormal::PositiveZero; } /// Returns the code generation relocation model. The choices are static, PIC, diff --git a/test/CodeGen/ARM/build-attributes.ll b/test/CodeGen/ARM/build-attributes.ll index 53b8fc39a7c..bd0ad02d42e 100644 --- a/test/CodeGen/ARM/build-attributes.ll +++ b/test/CodeGen/ARM/build-attributes.ll @@ -61,6 +61,11 @@ ; RUN: llc < %s -mtriple=armv7-linux-gnueabi -mcpu=cortex-a17 -mattr=-vfp2 | FileCheck %s --check-prefix=CORTEX-A17-NOFPU ; RUN: llc < %s -mtriple=armv7-linux-gnueabi -mcpu=cortex-a17 -mattr=-vfp2 -enable-unsafe-fp-math -disable-fp-elim -enable-no-infs-fp-math -enable-no-nans-fp-math -fp-contract=fast | FileCheck %s --check-prefix=CORTEX-A17-NOFPU-FAST +; RUN: llc < %s -mtriple=armv7-linux-gnueabi -mcpu=cortex-a15 -enable-no-trapping-fp-math | FileCheck %s --check-prefix=NO-TRAPPING-MATH +; RUN: llc < %s -mtriple=armv7-linux-gnueabi -mcpu=cortex-a15 -denormal-fp-math=ieee | FileCheck %s --check-prefix=DENORMAL-IEEE +; RUN: llc < %s -mtriple=armv7-linux-gnueabi -mcpu=cortex-a15 -denormal-fp-math=preserve-sign | FileCheck %s --check-prefix=DENORMAL-PRESERVE-SIGN +; RUN: llc < %s -mtriple=armv7-linux-gnueabi -mcpu=cortex-a15 -denormal-fp-math=positive-zero | FileCheck %s --check-prefix=DENORMAL-POSITIVE-ZERO + ; RUN: llc < %s -mtriple=armv7-linux-gnueabi -mattr=-neon,+vfp3,+fp16 | FileCheck %s --check-prefix=GENERIC-FPU-VFPV3-FP16 ; RUN: llc < %s -mtriple=armv7-linux-gnueabi -mattr=-neon,+vfp3,+d16,+fp16 | FileCheck %s --check-prefix=GENERIC-FPU-VFPV3-D16-FP16 ; RUN: llc < %s -mtriple=armv7-linux-gnueabi -mattr=-neon,+vfp3,+fp-only-sp,+d16 | FileCheck %s --check-prefix=GENERIC-FPU-VFPV3XD @@ -846,6 +851,12 @@ ; CORTEX-A17-NOFPU-FAST-NOT: .eabi_attribute 22 ; CORTEX-A17-NOFPU-FAST: .eabi_attribute 23, 1 +; Test flags -enable-no-trapping-fp-math and -denormal-fp-math: +; NO-TRAPPING-MATH: .eabi_attribute 21, 0 +; DENORMAL-IEEE: .eabi_attribute 20, 1 +; DENORMAL-PRESERVE-SIGN: .eabi_attribute 20, 2 +; DENORMAL-POSITIVE-ZERO: .eabi_attribute 20, 0 + ; CORTEX-M0: .cpu cortex-m0 ; CORTEX-M0: .eabi_attribute 6, 12 ; CORTEX-M0-NOT: .eabi_attribute 7