Skip to content

Commit 534a499

Browse files
committed
[GlobalISel] Add computeFPClass to GlobaISelValueTracking
1 parent ee78697 commit 534a499

File tree

8 files changed

+1731
-374
lines changed

8 files changed

+1731
-374
lines changed

llvm/include/llvm/ADT/FloatingPointModeUtils.h

Lines changed: 433 additions & 0 deletions
Large diffs are not rendered by default.

llvm/include/llvm/CodeGen/GlobalISel/GISelValueTracking.h

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,16 @@
1414
#ifndef LLVM_CODEGEN_GLOBALISEL_GISELVALUETRACKING_H
1515
#define LLVM_CODEGEN_GLOBALISEL_GISELVALUETRACKING_H
1616

17+
#include "llvm/ADT/APFloat.h"
1718
#include "llvm/ADT/DenseMap.h"
1819
#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
1920
#include "llvm/CodeGen/MachineFunctionPass.h"
2021
#include "llvm/CodeGen/Register.h"
22+
#include "llvm/IR/InstrTypes.h"
2123
#include "llvm/IR/PassManager.h"
2224
#include "llvm/InitializePasses.h"
2325
#include "llvm/Support/KnownBits.h"
26+
#include "llvm/Support/KnownFPClass.h"
2427

2528
namespace llvm {
2629

@@ -35,13 +38,72 @@ class GISelValueTracking : public GISelChangeObserver {
3538
unsigned MaxDepth;
3639
/// Cache maintained during a computeKnownBits request.
3740
SmallDenseMap<Register, KnownBits, 16> ComputeKnownBitsCache;
41+
SmallDenseMap<Register, KnownFPClass, 16> ComputeKnownFPClassCache;
3842

3943
void computeKnownBitsMin(Register Src0, Register Src1, KnownBits &Known,
4044
const APInt &DemandedElts, unsigned Depth = 0);
4145

4246
unsigned computeNumSignBitsMin(Register Src0, Register Src1,
4347
const APInt &DemandedElts, unsigned Depth = 0);
4448

49+
/// Returns a pair of values, which if passed to llvm.is.fpclass, returns the
50+
/// same result as an fcmp with the given operands.
51+
///
52+
/// If \p LookThroughSrc is true, consider the input value when computing the
53+
/// mask.
54+
///
55+
/// If \p LookThroughSrc is false, ignore the source value (i.e. the first
56+
/// pair element will always be LHS.
57+
std::pair<Register, FPClassTest> fcmpToClassTest(CmpInst::Predicate Pred,
58+
const MachineFunction &MF,
59+
Register LHS, Value *RHS,
60+
bool LookThroughSrc = true);
61+
std::pair<Register, FPClassTest> fcmpToClassTest(CmpInst::Predicate Pred,
62+
const MachineFunction &MF,
63+
Register LHS,
64+
const APFloat *ConstRHS,
65+
bool LookThroughSrc = true);
66+
67+
/// Compute the possible floating-point classes that \p LHS could be based on
68+
/// fcmp \Pred \p LHS, \p RHS.
69+
///
70+
/// \returns { TestedValue, ClassesIfTrue, ClassesIfFalse }
71+
///
72+
/// If the compare returns an exact class test, ClassesIfTrue ==
73+
/// ~ClassesIfFalse
74+
///
75+
/// This is a less exact version of fcmpToClassTest (e.g. fcmpToClassTest will
76+
/// only succeed for a test of x > 0 implies positive, but not x > 1).
77+
///
78+
/// If \p LookThroughSrc is true, consider the input value when computing the
79+
/// mask. This may look through sign bit operations.
80+
///
81+
/// If \p LookThroughSrc is false, ignore the source value (i.e. the first
82+
/// pair element will always be LHS.
83+
///
84+
std::tuple<Register, FPClassTest, FPClassTest>
85+
fcmpImpliesClass(CmpInst::Predicate Pred, const MachineFunction &MF,
86+
Register LHS, Register RHS, bool LookThroughSrc = true);
87+
std::tuple<Register, FPClassTest, FPClassTest>
88+
fcmpImpliesClass(CmpInst::Predicate Pred, const MachineFunction &MF,
89+
Register LHS, FPClassTest RHS, bool LookThroughSrc = true);
90+
std::tuple<Register, FPClassTest, FPClassTest>
91+
fcmpImpliesClass(CmpInst::Predicate Pred, const MachineFunction &MF,
92+
Register LHS, const APFloat &RHS,
93+
bool LookThroughSrc = true);
94+
95+
void computeKnownFPClass(Register R, KnownFPClass &Known,
96+
FPClassTest InterestedClasses, unsigned Depth);
97+
98+
void computeKnownFPClassForFPTrunc(const MachineInstr &MI,
99+
const APInt &DemandedElts,
100+
FPClassTest InterestedClasses,
101+
KnownFPClass &Known, unsigned Depth);
102+
103+
void computeKnownFPClass(Register R, const APInt &DemandedElts,
104+
FPClassTest InterestedClasses, KnownFPClass &Known,
105+
unsigned Depth);
106+
45107
public:
46108
GISelValueTracking(MachineFunction &MF, unsigned MaxDepth = 6);
47109
virtual ~GISelValueTracking() = default;
@@ -87,6 +149,34 @@ class GISelValueTracking : public GISelChangeObserver {
87149
/// \return The known alignment for the pointer-like value \p R.
88150
Align computeKnownAlignment(Register R, unsigned Depth = 0);
89151

152+
/// Determine which floating-point classes are valid for \p V, and return them
153+
/// in KnownFPClass bit sets.
154+
///
155+
/// This function is defined on values with floating-point type, values
156+
/// vectors of floating-point type, and arrays of floating-point type.
157+
158+
/// \p InterestedClasses is a compile time optimization hint for which
159+
/// floating point classes should be queried. Queries not specified in \p
160+
/// InterestedClasses should be reliable if they are determined during the
161+
/// query.
162+
KnownFPClass computeKnownFPClass(Register R, const APInt &DemandedElts,
163+
FPClassTest InterestedClasses,
164+
unsigned Depth);
165+
166+
KnownFPClass computeKnownFPClass(Register R,
167+
FPClassTest InterestedClasses = fcAllFlags,
168+
unsigned Depth = 0);
169+
170+
/// Wrapper to account for known fast math flags at the use instruction.
171+
KnownFPClass computeKnownFPClass(Register R, const APInt &DemandedElts,
172+
uint32_t Flags,
173+
FPClassTest InterestedClasses,
174+
unsigned Depth);
175+
176+
KnownFPClass computeKnownFPClass(Register R, uint32_t Flags,
177+
FPClassTest InterestedClasses,
178+
unsigned Depth);
179+
90180
// Observer API. No-op for non-caching implementation.
91181
void erasingInstr(MachineInstr &MI) override {}
92182
void createdInstr(MachineInstr &MI) override {}

llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,11 @@
1414
#define LLVM_CODEGEN_GLOBALISEL_MIPATTERNMATCH_H
1515

1616
#include "llvm/ADT/APInt.h"
17+
#include "llvm/ADT/FloatingPointMode.h"
18+
#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
1719
#include "llvm/CodeGen/GlobalISel/Utils.h"
1820
#include "llvm/CodeGen/MachineRegisterInfo.h"
21+
#include "llvm/CodeGen/TargetOpcodes.h"
1922
#include "llvm/IR/InstrTypes.h"
2023

2124
namespace llvm {
@@ -393,6 +396,7 @@ inline bind_ty<const MachineInstr *> m_MInstr(const MachineInstr *&MI) {
393396
inline bind_ty<LLT> m_Type(LLT &Ty) { return Ty; }
394397
inline bind_ty<CmpInst::Predicate> m_Pred(CmpInst::Predicate &P) { return P; }
395398
inline operand_type_match m_Pred() { return operand_type_match(); }
399+
inline bind_ty<FPClassTest> m_FPClassTest(FPClassTest &T) { return T; }
396400

397401
template <typename BindTy> struct deferred_helper {
398402
static bool match(const MachineRegisterInfo &MRI, BindTy &VR, BindTy &V) {
@@ -762,6 +766,32 @@ struct CompareOp_match {
762766
}
763767
};
764768

769+
template <typename LHS_P, typename Test_P, unsigned Opcode>
770+
struct ClassifyOp_match {
771+
LHS_P L;
772+
Test_P T;
773+
774+
ClassifyOp_match(const LHS_P &LHS, const Test_P &Tst) : L(LHS), T(Tst) {}
775+
776+
template <typename OpTy>
777+
bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
778+
MachineInstr *TmpMI;
779+
if (!mi_match(Op, MRI, m_MInstr(TmpMI)) || TmpMI->getOpcode() != Opcode)
780+
return false;
781+
782+
Register LHS = TmpMI->getOperand(1).getReg();
783+
if (!L.match(MRI, LHS))
784+
return false;
785+
786+
FPClassTest TmpClass =
787+
static_cast<FPClassTest>(TmpMI->getOperand(2).getImm());
788+
if (T.match(MRI, TmpClass))
789+
return true;
790+
791+
return false;
792+
}
793+
};
794+
765795
template <typename Pred, typename LHS, typename RHS>
766796
inline CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_ICMP>
767797
m_GICmp(const Pred &P, const LHS &L, const RHS &R) {
@@ -804,6 +834,14 @@ m_c_GFCmp(const Pred &P, const LHS &L, const RHS &R) {
804834
return CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_FCMP, true>(P, L, R);
805835
}
806836

837+
/// Matches the register and immediate used in a fpclass test
838+
/// G_IS_FPCLASS %val, 96
839+
template <typename LHS, typename Test>
840+
inline ClassifyOp_match<LHS, Test, TargetOpcode::G_IS_FPCLASS>
841+
m_GIsFPClass(const LHS &L, const Test &T) {
842+
return ClassifyOp_match<LHS, Test, TargetOpcode::G_IS_FPCLASS>(L, T);
843+
}
844+
807845
// Helper for checking if a Reg is of specific type.
808846
struct CheckType {
809847
LLT Ty;

llvm/include/llvm/CodeGen/GlobalISel/Utils.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,9 @@ class GIConstant {
655655
/// }
656656
/// provides low-level access.
657657
class GFConstant {
658+
using VecTy = SmallVector<APFloat>;
659+
using const_iterator = VecTy::const_iterator;
660+
658661
public:
659662
enum class GFConstantKind { Scalar, FixedVector, ScalableVector };
660663

@@ -672,6 +675,23 @@ class GFConstant {
672675
/// Returns the kind of of this constant, e.g, Scalar.
673676
GFConstantKind getKind() const { return Kind; }
674677

678+
const_iterator begin() const {
679+
assert(Kind != GFConstantKind::ScalableVector &&
680+
"Expected fixed vector or scalar constant");
681+
return Values.begin();
682+
}
683+
684+
const_iterator end() const {
685+
assert(Kind != GFConstantKind::ScalableVector &&
686+
"Expected fixed vector or scalar constant");
687+
return Values.end();
688+
}
689+
690+
size_t size() const {
691+
assert(Kind == GFConstantKind::FixedVector && "Expected fixed vector");
692+
return Values.size();
693+
}
694+
675695
/// Returns the value, if this constant is a scalar.
676696
APFloat getScalarValue() const;
677697

llvm/include/llvm/CodeGen/TargetLowering.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
#include "llvm/Support/AtomicOrdering.h"
5252
#include "llvm/Support/Casting.h"
5353
#include "llvm/Support/ErrorHandling.h"
54+
#include "llvm/Support/KnownFPClass.h"
5455
#include <algorithm>
5556
#include <cassert>
5657
#include <climits>
@@ -4230,6 +4231,13 @@ class TargetLowering : public TargetLoweringBase {
42304231
const MachineRegisterInfo &MRI,
42314232
unsigned Depth = 0) const;
42324233

4234+
virtual void computeKnownFPClassForTargetInstr(GISelValueTracking &Analysis,
4235+
Register R,
4236+
KnownFPClass &Known,
4237+
const APInt &DemandedElts,
4238+
const MachineRegisterInfo &MRI,
4239+
unsigned Depth = 0) const;
4240+
42334241
/// Determine the known alignment for the pointer value \p R. This is can
42344242
/// typically be inferred from the number of low known 0 bits. However, for a
42354243
/// pointer with a non-integral address space, the alignment value may be

0 commit comments

Comments
 (0)