Clang patch r280064 introduced ways to set the FP exceptions and denormal
authorSjoerd Meijer <sjoerd.meijer@arm.com>
Wed, 31 Aug 2016 14:17:38 +0000 (14:17 +0000)
committerSjoerd Meijer <sjoerd.meijer@arm.com>
Wed, 31 Aug 2016 14:17:38 +0000 (14:17 +0000)
types. This is the LLVM counterpart and it adds options that map onto FP
exceptions and denormal build attributes allowing better fp math library
selections.

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

llvm-svn: 280246

llvm/include/llvm/CodeGen/CommandFlags.h
llvm/include/llvm/Target/TargetOptions.h
llvm/lib/Target/ARM/ARMAsmPrinter.cpp
llvm/lib/Target/TargetMachine.cpp
llvm/test/CodeGen/ARM/build-attributes.ll

index 4c05e7f..6821ec0 100644 (file)
@@ -150,6 +150,26 @@ EnableNoNaNsFPMath("enable-no-nans-fp-math",
                    cl::init(false));
 
 cl::opt<bool>
+EnableNoTrappingFPMath("enable-no-trapping-fp-math",
+                       cl::desc("Enable setting the FP exceptions build "
+                                "attribute not to use exceptions"),
+                       cl::init(false));
+
+cl::opt<llvm::FPDenormal::DenormalType>
+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<bool>
 EnableHonorSignDependentRoundingFPMath("enable-sign-dependent-rounding-fp-math",
       cl::Hidden,
       cl::desc("Force codegen to assume rounding mode can change dynamically"),
@@ -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)
index b1e938e..07906e3 100644 (file)
@@ -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);
index 53b2c3d..9e3d1ee 100644 (file)
@@ -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)
index 82c6850..60505f4 100644 (file)
@@ -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,
index 53b8fc3..bd0ad02 100644 (file)
 ; 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
 ; 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