Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LLVM][IR] Add constant range support for floating-point types #86483

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

dtcxzyw
Copy link
Member

@dtcxzyw dtcxzyw commented Mar 25, 2024

Related issues: #68301 #70985 #82381

Copy link

✅ With the latest revision this PR passed the Python code formatter.

Copy link

✅ With the latest revision this PR passed the C/C++ code formatter.

@tschuett tschuett requested a review from arsenm March 25, 2024 12:28
@dtcxzyw
Copy link
Member Author

dtcxzyw commented Mar 25, 2024

@tschuett This patch is not ready for review.

@dtcxzyw dtcxzyw removed the request for review from arsenm March 25, 2024 14:53
@tschuett
Copy link
Member

Sorry. The GlobalIsel combiner already uses ConstantRange. I would like to use ConstantFPRange as well.

@tschuett
Copy link
Member

ConstantRange CR1 = ConstantRange::makeExactICmpRegion(

@arsenm arsenm added floating-point Floating-point math llvm:ir labels Mar 26, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Mar 26, 2024

@llvm/pr-subscribers-llvm-ir

Author: Yingwei Zheng (dtcxzyw)

Changes

Related issues: #68301 #70985 #82381


Full diff: https://github.com/llvm/llvm-project/pull/86483.diff

1 Files Affected:

  • (added) llvm/include/llvm/IR/ConstantFPRange.h (+139)
diff --git a/llvm/include/llvm/IR/ConstantFPRange.h b/llvm/include/llvm/IR/ConstantFPRange.h
new file mode 100644
index 00000000000000..89b0cd0b7763b5
--- /dev/null
+++ b/llvm/include/llvm/IR/ConstantFPRange.h
@@ -0,0 +1,139 @@
+//===- ConstantFPRange.h - Represent a range for floating-point -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Represent a range of possible values that may occur when the program is run
+// for a floating-point value. This keeps track of a lower and upper bound for
+// the constant.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_CONSTANTFPRANGE_H
+#define LLVM_IR_CONSTANTFPRANGE_H
+
+#include "llvm/ADT/APFloat.h"
+#include "llvm/IR/InstrTypes.h"
+#include "llvm/IR/Instruction.h"
+#include "llvm/Support/Compiler.h"
+#include <optional>
+
+namespace llvm {
+
+class raw_ostream;
+struct KnownFPClass;
+
+/// This class represents a range of floating-point values.
+class [[nodiscard]] ConstantFPRange {
+  APFloat Lower, Upper;
+  bool MaybeQNaN : 1;
+  bool MaybeSNaN : 1;
+  bool SignBitMaybeZero : 1;
+  bool SignBitMaybeOne : 1;
+
+  /// Create empty constant range with same semantics.
+  ConstantFPRange getEmpty() const {
+    return ConstantFPRange(getSemantics(), /*IsFullSet=*/false);
+  }
+
+  /// Create full constant range with same semantics.
+  ConstantFPRange getFull() const {
+    return ConstantFPRange(getSemantics(), /*IsFullSet=*/true);
+  }
+
+public:
+  /// Initialize a full or empty set for the specified semantics.
+  explicit ConstantFPRange(const fltSemantics &FloatSema, bool IsFullSet);
+
+  /// Initialize a range to hold the single specified value.
+  ConstantFPRange(const APFloat &Value);
+
+  /// Initialize a range of values explicitly.
+  ConstantFPRange(APFloat Lower, APFloat Upper, bool MaybeQNaN, bool MaybeSNaN,
+                  bool SignBitMaybeZero, bool SignBitMaybeOne);
+
+  /// Create empty constant range with the given semantics.
+  static ConstantFPRange getEmpty(const fltSemantics &FloatSema) {
+    return ConstantFPRange(FloatSema, /*IsFullSet=*/false);
+  }
+
+  /// Create full constant range with the given semantics.
+  static ConstantFPRange getFull(const fltSemantics &FloatSema) {
+    return ConstantFPRange(FloatSema, /*IsFullSet=*/true);
+  }
+
+  /// Initialize a range based on a known floating-point classes constraint.
+  static ConstantFPRange fromKnownFPClass(const KnownFPClass &Known);
+
+  /// Produce the exact range such that all values in the returned range satisfy
+  /// the given predicate with any value contained within Other. Formally, this
+  /// returns the exact answer when the superset of 'union over all y in Other
+  /// is exactly same as the subset of intersection over all y in Other.
+  /// { x : fcmp op x y is true}'.
+  ///
+  /// Example: Pred = olt and Other = float 3 returns [-inf, 3)
+  static ConstantFPRange makeExactFCmpRegion(FCmpInst::Predicate Pred,
+                                             const APFloat &Other);
+
+  /// Does the predicate \p Pred hold between ranges this and \p Other?
+  /// NOTE: false does not mean that inverse predicate holds!
+  bool fcmp(FCmpInst::Predicate Pred, const ConstantFPRange &Other) const;
+
+  /// Return the lower value for this range.
+  const APFloat &getLower() const { return Lower; }
+
+  /// Return the upper value for this range.
+  const APFloat &getUpper() const { return Upper; }
+
+  /// Get the semantics of this ConstantFPRange.
+  const fltSemantics &getSemantics() const { return Lower.getSemantics(); }
+
+  /// Return true if this set contains all of the elements possible
+  /// for this data-type.
+  bool isFullSet() const;
+
+  /// Return true if this set contains no members.
+  bool isEmptySet() const;
+
+  /// Return true if the specified value is in the set.
+  bool contains(const APFloat &Val) const;
+
+  /// Return true if the other range is a subset of this one.
+  bool contains(const ConstantFPRange &CR) const;
+
+  /// If this set contains a single element, return it, otherwise return null.
+  const APFloat *getSingleElement() const;
+
+  /// Return true if this set contains exactly one member.
+  bool isSingleElement() const { return getSingleElement() != nullptr; }
+
+  /// Return true if the sign bit of all values in this range is 1.
+  /// Return false if the sign bit of all values in this range is 0.
+  /// Otherwise, return std::nullopt.
+  std::optional<bool> getSignBit();
+
+  /// Return true if this range is equal to another range.
+  bool operator==(const ConstantFPRange &CR) const;
+  bool operator!=(const ConstantFPRange &CR) const { return !operator==(CR); }
+
+  /// Return known floating-point classes for values in this range.
+  KnownFPClass toKnownFPClass();
+
+  /// Print out the bounds to a stream.
+  void print(raw_ostream &OS) const;
+
+  /// Allow printing from a debugger easily.
+  void dump() const;
+};
+
+inline raw_ostream &operator<<(raw_ostream &OS, const ConstantFPRange &CR) {
+  CR.print(OS);
+  return OS;
+}
+
+} // end namespace llvm
+
+#endif // LLVM_IR_CONSTANTFPRANGE_H

Comment on lines +34 to +35
bool SignBitMaybeZero : 1;
bool SignBitMaybeOne : 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't understand why these would be "MaybeZero" or "MaybeOne". Must be? Maybe would need to default to 1

Comment on lines +55 to +56
ConstantFPRange(APFloat Lower, APFloat Upper, bool MaybeQNaN, bool MaybeSNaN,
bool SignBitMaybeZero, bool SignBitMaybeOne);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Default values for the nan/sign params

Copy link
Contributor

@jcranmer-intel jcranmer-intel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not entirely clear to me from the UI whether or not the range is half-open or closed, which tends to matter more for floating-point values than it does for integers.

If it's half-open, then how is one supposed to represent [inf, inf]?

/// Initialize a range to hold the single specified value.
ConstantFPRange(const APFloat &Value);

/// Initialize a range of values explicitly.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be worth having different methods for constructing an (x, y) range and a [x, y] range. Or maybe just a helper for (-inf, inf) (aka, all finite values); that seems to be the only common open range.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
floating-point Floating-point math llvm:ir
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants