FloatingPointMode.h 7.1 KB

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