FloatingPointMode.h 6.2 KB

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