FloatingPointMode.h 6.4 KB

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