[GISel] Add KnownFPClass Analysis to GISelValueTrackingPass (#134611)
- add KnownFPClass analysis to GISelValueTrackingPass - add MI pattern for `m_GIsFPClass`
This commit is contained in:
@@ -14,13 +14,16 @@
|
||||
#ifndef LLVM_CODEGEN_GLOBALISEL_GISELVALUETRACKING_H
|
||||
#define LLVM_CODEGEN_GLOBALISEL_GISELVALUETRACKING_H
|
||||
|
||||
#include "llvm/ADT/APFloat.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/Register.h"
|
||||
#include "llvm/IR/InstrTypes.h"
|
||||
#include "llvm/IR/PassManager.h"
|
||||
#include "llvm/InitializePasses.h"
|
||||
#include "llvm/Support/KnownBits.h"
|
||||
#include "llvm/Support/KnownFPClass.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@@ -42,6 +45,18 @@ class GISelValueTracking : public GISelChangeObserver {
|
||||
unsigned computeNumSignBitsMin(Register Src0, Register Src1,
|
||||
const APInt &DemandedElts, unsigned Depth = 0);
|
||||
|
||||
void computeKnownFPClass(Register R, KnownFPClass &Known,
|
||||
FPClassTest InterestedClasses, unsigned Depth);
|
||||
|
||||
void computeKnownFPClassForFPTrunc(const MachineInstr &MI,
|
||||
const APInt &DemandedElts,
|
||||
FPClassTest InterestedClasses,
|
||||
KnownFPClass &Known, unsigned Depth);
|
||||
|
||||
void computeKnownFPClass(Register R, const APInt &DemandedElts,
|
||||
FPClassTest InterestedClasses, KnownFPClass &Known,
|
||||
unsigned Depth);
|
||||
|
||||
public:
|
||||
GISelValueTracking(MachineFunction &MF, unsigned MaxDepth = 6);
|
||||
virtual ~GISelValueTracking() = default;
|
||||
@@ -87,6 +102,34 @@ public:
|
||||
/// \return The known alignment for the pointer-like value \p R.
|
||||
Align computeKnownAlignment(Register R, unsigned Depth = 0);
|
||||
|
||||
/// Determine which floating-point classes are valid for \p V, and return them
|
||||
/// in KnownFPClass bit sets.
|
||||
///
|
||||
/// This function is defined on values with floating-point type, values
|
||||
/// vectors of floating-point type, and arrays of floating-point type.
|
||||
|
||||
/// \p InterestedClasses is a compile time optimization hint for which
|
||||
/// floating point classes should be queried. Queries not specified in \p
|
||||
/// InterestedClasses should be reliable if they are determined during the
|
||||
/// query.
|
||||
KnownFPClass computeKnownFPClass(Register R, const APInt &DemandedElts,
|
||||
FPClassTest InterestedClasses,
|
||||
unsigned Depth);
|
||||
|
||||
KnownFPClass computeKnownFPClass(Register R,
|
||||
FPClassTest InterestedClasses = fcAllFlags,
|
||||
unsigned Depth = 0);
|
||||
|
||||
/// Wrapper to account for known fast math flags at the use instruction.
|
||||
KnownFPClass computeKnownFPClass(Register R, const APInt &DemandedElts,
|
||||
uint32_t Flags,
|
||||
FPClassTest InterestedClasses,
|
||||
unsigned Depth);
|
||||
|
||||
KnownFPClass computeKnownFPClass(Register R, uint32_t Flags,
|
||||
FPClassTest InterestedClasses,
|
||||
unsigned Depth);
|
||||
|
||||
// Observer API. No-op for non-caching implementation.
|
||||
void erasingInstr(MachineInstr &MI) override {}
|
||||
void createdInstr(MachineInstr &MI) override {}
|
||||
|
||||
@@ -14,8 +14,11 @@
|
||||
#define LLVM_CODEGEN_GLOBALISEL_MIPATTERNMATCH_H
|
||||
|
||||
#include "llvm/ADT/APInt.h"
|
||||
#include "llvm/ADT/FloatingPointMode.h"
|
||||
#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
|
||||
#include "llvm/CodeGen/GlobalISel/Utils.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/CodeGen/TargetOpcodes.h"
|
||||
#include "llvm/IR/InstrTypes.h"
|
||||
|
||||
namespace llvm {
|
||||
@@ -393,6 +396,7 @@ inline bind_ty<const MachineInstr *> m_MInstr(const MachineInstr *&MI) {
|
||||
inline bind_ty<LLT> m_Type(LLT &Ty) { return Ty; }
|
||||
inline bind_ty<CmpInst::Predicate> m_Pred(CmpInst::Predicate &P) { return P; }
|
||||
inline operand_type_match m_Pred() { return operand_type_match(); }
|
||||
inline bind_ty<FPClassTest> m_FPClassTest(FPClassTest &T) { return T; }
|
||||
|
||||
template <typename BindTy> struct deferred_helper {
|
||||
static bool match(const MachineRegisterInfo &MRI, BindTy &VR, BindTy &V) {
|
||||
@@ -762,6 +766,32 @@ struct CompareOp_match {
|
||||
}
|
||||
};
|
||||
|
||||
template <typename LHS_P, typename Test_P, unsigned Opcode>
|
||||
struct ClassifyOp_match {
|
||||
LHS_P L;
|
||||
Test_P T;
|
||||
|
||||
ClassifyOp_match(const LHS_P &LHS, const Test_P &Tst) : L(LHS), T(Tst) {}
|
||||
|
||||
template <typename OpTy>
|
||||
bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
|
||||
MachineInstr *TmpMI;
|
||||
if (!mi_match(Op, MRI, m_MInstr(TmpMI)) || TmpMI->getOpcode() != Opcode)
|
||||
return false;
|
||||
|
||||
Register LHS = TmpMI->getOperand(1).getReg();
|
||||
if (!L.match(MRI, LHS))
|
||||
return false;
|
||||
|
||||
FPClassTest TmpClass =
|
||||
static_cast<FPClassTest>(TmpMI->getOperand(2).getImm());
|
||||
if (T.match(MRI, TmpClass))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Pred, typename LHS, typename RHS>
|
||||
inline CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_ICMP>
|
||||
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) {
|
||||
return CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_FCMP, true>(P, L, R);
|
||||
}
|
||||
|
||||
/// Matches the register and immediate used in a fpclass test
|
||||
/// G_IS_FPCLASS %val, 96
|
||||
template <typename LHS, typename Test>
|
||||
inline ClassifyOp_match<LHS, Test, TargetOpcode::G_IS_FPCLASS>
|
||||
m_GIsFPClass(const LHS &L, const Test &T) {
|
||||
return ClassifyOp_match<LHS, Test, TargetOpcode::G_IS_FPCLASS>(L, T);
|
||||
}
|
||||
|
||||
// Helper for checking if a Reg is of specific type.
|
||||
struct CheckType {
|
||||
LLT Ty;
|
||||
|
||||
@@ -655,6 +655,9 @@ public:
|
||||
/// }
|
||||
/// provides low-level access.
|
||||
class GFConstant {
|
||||
using VecTy = SmallVector<APFloat>;
|
||||
using const_iterator = VecTy::const_iterator;
|
||||
|
||||
public:
|
||||
enum class GFConstantKind { Scalar, FixedVector, ScalableVector };
|
||||
|
||||
@@ -672,6 +675,23 @@ public:
|
||||
/// Returns the kind of of this constant, e.g, Scalar.
|
||||
GFConstantKind getKind() const { return Kind; }
|
||||
|
||||
const_iterator begin() const {
|
||||
assert(Kind != GFConstantKind::ScalableVector &&
|
||||
"Expected fixed vector or scalar constant");
|
||||
return Values.begin();
|
||||
}
|
||||
|
||||
const_iterator end() const {
|
||||
assert(Kind != GFConstantKind::ScalableVector &&
|
||||
"Expected fixed vector or scalar constant");
|
||||
return Values.end();
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
assert(Kind == GFConstantKind::FixedVector && "Expected fixed vector");
|
||||
return Values.size();
|
||||
}
|
||||
|
||||
/// Returns the value, if this constant is a scalar.
|
||||
APFloat getScalarValue() const;
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
#include "llvm/Support/AtomicOrdering.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/KnownFPClass.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <climits>
|
||||
@@ -4233,6 +4234,13 @@ public:
|
||||
const MachineRegisterInfo &MRI,
|
||||
unsigned Depth = 0) const;
|
||||
|
||||
virtual void computeKnownFPClassForTargetInstr(GISelValueTracking &Analysis,
|
||||
Register R,
|
||||
KnownFPClass &Known,
|
||||
const APInt &DemandedElts,
|
||||
const MachineRegisterInfo &MRI,
|
||||
unsigned Depth = 0) const;
|
||||
|
||||
/// Determine the known alignment for the pointer value \p R. This is can
|
||||
/// typically be inferred from the number of low known 0 bits. However, for a
|
||||
/// pointer with a non-integral address space, the alignment value may be
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3801,6 +3801,13 @@ void TargetLowering::computeKnownBitsForTargetInstr(
|
||||
Known.resetAll();
|
||||
}
|
||||
|
||||
void TargetLowering::computeKnownFPClassForTargetInstr(
|
||||
GISelValueTracking &Analysis, Register R, KnownFPClass &Known,
|
||||
const APInt &DemandedElts, const MachineRegisterInfo &MRI,
|
||||
unsigned Depth) const {
|
||||
Known.resetAll();
|
||||
}
|
||||
|
||||
void TargetLowering::computeKnownBitsForFrameIndex(
|
||||
const int FrameIdx, KnownBits &Known, const MachineFunction &MF) const {
|
||||
// The low bits are known zero if the pointer is aligned.
|
||||
|
||||
@@ -24,6 +24,7 @@ add_llvm_unittest(GlobalISelTests
|
||||
GISelMITest.cpp
|
||||
PatternMatchTest.cpp
|
||||
KnownBitsTest.cpp
|
||||
KnownFPClassTest.cpp
|
||||
KnownBitsVectorTest.cpp
|
||||
GISelUtilsTest.cpp
|
||||
GISelAliasTest.cpp
|
||||
|
||||
1062
llvm/unittests/CodeGen/GlobalISel/KnownFPClassTest.cpp
Normal file
1062
llvm/unittests/CodeGen/GlobalISel/KnownFPClassTest.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user