FloatingPointMode.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- llvm/Support/FloatingPointMode.h -------------------------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. ///
  14. /// \file
  15. /// Utilities for dealing with flags related to floating point mode controls.
  16. ///
  17. //===----------------------------------------------------------------------===/
  18. #ifndef LLVM_ADT_FLOATINGPOINTMODE_H
  19. #define LLVM_ADT_FLOATINGPOINTMODE_H
  20. #include "llvm/ADT/StringSwitch.h"
  21. #include "llvm/Support/raw_ostream.h"
  22. namespace llvm {
  23. /// Rounding mode.
  24. ///
  25. /// Enumerates supported rounding modes, as well as some special values. The set
  26. /// of the modes must agree with IEEE-754, 4.3.1 and 4.3.2. The constants
  27. /// assigned to the IEEE rounding modes must agree with the values used by
  28. /// FLT_ROUNDS (C11, 5.2.4.2.2p8).
  29. ///
  30. /// This value is packed into bitfield in some cases, including \c FPOptions, so
  31. /// the rounding mode values and the special value \c Dynamic must fit into the
  32. /// the bit field (now - 3 bits). The value \c Invalid is used only in values
  33. /// returned by intrinsics to indicate errors, it should never be stored as
  34. /// rounding mode value, so it does not need to fit the bit fields.
  35. ///
  36. enum class RoundingMode : int8_t {
  37. // Rounding mode defined in IEEE-754.
  38. TowardZero = 0, ///< roundTowardZero.
  39. NearestTiesToEven = 1, ///< roundTiesToEven.
  40. TowardPositive = 2, ///< roundTowardPositive.
  41. TowardNegative = 3, ///< roundTowardNegative.
  42. NearestTiesToAway = 4, ///< roundTiesToAway.
  43. // Special values.
  44. Dynamic = 7, ///< Denotes mode unknown at compile time.
  45. Invalid = -1 ///< Denotes invalid value.
  46. };
  47. /// Returns text representation of the given rounding mode.
  48. inline StringRef spell(RoundingMode RM) {
  49. switch (RM) {
  50. case RoundingMode::TowardZero: return "towardzero";
  51. case RoundingMode::NearestTiesToEven: return "tonearest";
  52. case RoundingMode::TowardPositive: return "upward";
  53. case RoundingMode::TowardNegative: return "downward";
  54. case RoundingMode::NearestTiesToAway: return "tonearestaway";
  55. case RoundingMode::Dynamic: return "dynamic";
  56. default: return "invalid";
  57. }
  58. }
  59. inline raw_ostream &operator << (raw_ostream &OS, RoundingMode RM) {
  60. OS << spell(RM);
  61. return OS;
  62. }
  63. /// Represent subnormal handling kind for floating point instruction inputs and
  64. /// outputs.
  65. struct DenormalMode {
  66. /// Represent handled modes for denormal (aka subnormal) modes in the floating
  67. /// point environment.
  68. enum DenormalModeKind : int8_t {
  69. Invalid = -1,
  70. /// IEEE-754 denormal numbers preserved.
  71. IEEE,
  72. /// The sign of a flushed-to-zero number is preserved in the sign of 0
  73. PreserveSign,
  74. /// Denormals are flushed to positive zero.
  75. PositiveZero
  76. };
  77. /// Denormal flushing mode for floating point instruction results in the
  78. /// default floating point environment.
  79. DenormalModeKind Output = DenormalModeKind::Invalid;
  80. /// Denormal treatment kind for floating point instruction inputs in the
  81. /// default floating-point environment. If this is not DenormalModeKind::IEEE,
  82. /// floating-point instructions implicitly treat the input value as 0.
  83. DenormalModeKind Input = DenormalModeKind::Invalid;
  84. constexpr DenormalMode() = default;
  85. constexpr DenormalMode(DenormalModeKind Out, DenormalModeKind In) :
  86. Output(Out), Input(In) {}
  87. static constexpr DenormalMode getInvalid() {
  88. return DenormalMode(DenormalModeKind::Invalid, DenormalModeKind::Invalid);
  89. }
  90. static constexpr DenormalMode getIEEE() {
  91. return DenormalMode(DenormalModeKind::IEEE, DenormalModeKind::IEEE);
  92. }
  93. static constexpr DenormalMode getPreserveSign() {
  94. return DenormalMode(DenormalModeKind::PreserveSign,
  95. DenormalModeKind::PreserveSign);
  96. }
  97. static constexpr DenormalMode getPositiveZero() {
  98. return DenormalMode(DenormalModeKind::PositiveZero,
  99. DenormalModeKind::PositiveZero);
  100. }
  101. bool operator==(DenormalMode Other) const {
  102. return Output == Other.Output && Input == Other.Input;
  103. }
  104. bool operator!=(DenormalMode Other) const {
  105. return !(*this == Other);
  106. }
  107. bool isSimple() const {
  108. return Input == Output;
  109. }
  110. bool isValid() const {
  111. return Output != DenormalModeKind::Invalid &&
  112. Input != DenormalModeKind::Invalid;
  113. }
  114. inline void print(raw_ostream &OS) const;
  115. inline std::string str() const {
  116. std::string storage;
  117. raw_string_ostream OS(storage);
  118. print(OS);
  119. return OS.str();
  120. }
  121. };
  122. inline raw_ostream& operator<<(raw_ostream &OS, DenormalMode Mode) {
  123. Mode.print(OS);
  124. return OS;
  125. }
  126. /// Parse the expected names from the denormal-fp-math attribute.
  127. inline DenormalMode::DenormalModeKind
  128. parseDenormalFPAttributeComponent(StringRef Str) {
  129. // Assume ieee on unspecified attribute.
  130. return StringSwitch<DenormalMode::DenormalModeKind>(Str)
  131. .Cases("", "ieee", DenormalMode::IEEE)
  132. .Case("preserve-sign", DenormalMode::PreserveSign)
  133. .Case("positive-zero", DenormalMode::PositiveZero)
  134. .Default(DenormalMode::Invalid);
  135. }
  136. /// Return the name used for the denormal handling mode used by the the
  137. /// expected names from the denormal-fp-math attribute.
  138. inline StringRef denormalModeKindName(DenormalMode::DenormalModeKind Mode) {
  139. switch (Mode) {
  140. case DenormalMode::IEEE:
  141. return "ieee";
  142. case DenormalMode::PreserveSign:
  143. return "preserve-sign";
  144. case DenormalMode::PositiveZero:
  145. return "positive-zero";
  146. default:
  147. return "";
  148. }
  149. }
  150. /// Returns the denormal mode to use for inputs and outputs.
  151. inline DenormalMode parseDenormalFPAttribute(StringRef Str) {
  152. StringRef OutputStr, InputStr;
  153. std::tie(OutputStr, InputStr) = Str.split(',');
  154. DenormalMode Mode;
  155. Mode.Output = parseDenormalFPAttributeComponent(OutputStr);
  156. // Maintain compatability with old form of the attribute which only specified
  157. // one component.
  158. Mode.Input = InputStr.empty() ? Mode.Output :
  159. parseDenormalFPAttributeComponent(InputStr);
  160. return Mode;
  161. }
  162. void DenormalMode::print(raw_ostream &OS) const {
  163. OS << denormalModeKindName(Output) << ',' << denormalModeKindName(Input);
  164. }
  165. }
  166. #endif // LLVM_ADT_FLOATINGPOINTMODE_H
  167. #ifdef __GNUC__
  168. #pragma GCC diagnostic pop
  169. #endif