blob: e6328ebcdffbe13f44bf757b12084137009f281a [file] [log] [blame]
//===------ VirtualInstruction.cpp ------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Tools for determining which instructions are within a statement and the
// nature of their operands.
//
//===----------------------------------------------------------------------===//
#ifndef POLLY_SUPPORT_VIRTUALINSTRUCTION_H
#define POLLY_SUPPORT_VIRTUALINSTRUCTION_H
#include "polly/ScopInfo.h"
namespace polly {
/// Determine the nature of a value's use within a statement.
///
/// These are not always representable by llvm::Use. For instance, scalar write
/// MemoryAccesses do use a value, but are not associated with an instruction's
/// argument.
///
/// Despite its name it is not tied to virtual instructions (although it works
/// fine with them), but to promote consistent handling of values used in
/// statements.
class VirtualUse {
public:
/// The different types of uses. Handling usually differentiates a lot between
/// these; one can use a switch to handle each case (and get warned by the
/// compiler if one is not handled).
enum UseKind {
// An llvm::Constant.
Constant,
// An llvm::BasicBlock.
Block,
// A value that can be generated using ScopExpander.
Synthesizable,
// A load that always reads the same value throughout the SCoP (address and
// the value located there a SCoP-invariant) and has been hoisted in front
// of the SCoP.
Hoisted,
// Definition before the SCoP and not synthesizable. Can be an instruction
// outside the SCoP, a function argument or a global value. Whether there is
// a scalar MemoryAccess in this statement for reading it depends on the
// -polly-analyze-read-only-scalars switch.
ReadOnly,
// A definition within the same statement. No MemoryAccess between
// definition and use are necessary.
Intra,
// Definition in another statement. There is a scalar MemoryAccess that
// makes it available in this statement.
Inter
};
private:
/// The statement where a value is used.
ScopStmt *User;
/// The value that is used.
Value *Val;
/// The type of value use.
UseKind Kind;
/// The value represented as llvm::SCEV expression.
const SCEV *ScevExpr;
/// If this is an inter-statement (or read-only) use, contains the
/// MemoryAccess that makes the value available in this statement. In case of
/// intra-statement uses, can contain a MemoryKind::Array access. In all other
/// cases, it is a nullptr.
MemoryAccess *InputMA;
VirtualUse(ScopStmt *User, Value *Val, UseKind Kind, const SCEV *ScevExpr,
MemoryAccess *InputMA)
: User(User), Val(Val), Kind(Kind), ScevExpr(ScevExpr), InputMA(InputMA) {
}
public:
/// Get a VirtualUse for an llvm::Use.
///
/// @param S The Scop object.
/// @param U The llvm::Use the get information for.
/// @param LI The LoopInfo analysis. Needed to determine whether the
/// value is synthesizable.
/// @param Virtual Whether to ignore existing MemoryAcccess.
///
/// @return The VirtualUse representing the same use as @p U.
static VirtualUse create(Scop *S, Use &U, LoopInfo *LI, bool Virtual);
/// Get a VirtualUse for any kind of use of a value within a statement.
///
/// @param S The Scop object.
/// @param UserStmt The statement in which @p Val is used. Can be nullptr, in
/// which case it assumed that the statement has been
/// removed, which is only possible if no instruction in it
/// had side-effects or computes a value used by another
/// statement.
/// @param UserScope Loop scope in which the value is used. Needed to
/// determine whether the value is synthesizable.
/// @param Val The value being used.
/// @param Virtual Whether to use (and prioritize over instruction location)
/// information about MemoryAccesses.
///
/// @return A VirtualUse object that gives information about @p Val's use in
/// @p UserStmt.
static VirtualUse create(Scop *S, ScopStmt *UserStmt, Loop *UserScope,
Value *Val, bool Virtual);
static VirtualUse create(ScopStmt *UserStmt, Loop *UserScope, Value *Val,
bool Virtual) {
return create(UserStmt->getParent(), UserStmt, UserScope, Val, Virtual);
}
bool isConstant() const { return Kind == Constant; }
bool isBlock() const { return Kind == Block; }
bool isSynthesizable() const { return Kind == Synthesizable; }
bool isHoisted() const { return Kind == Hoisted; }
bool isReadOnly() const { return Kind == ReadOnly; }
bool isIntra() const { return Kind == Intra; }
bool isInter() const { return Kind == Inter; }
/// Return user statement.
ScopStmt *getUser() const { return User; }
/// Return the used value.
llvm::Value *getValue() const { return Val; }
/// Return the type of use.
UseKind getKind() const { return Kind; }
/// Return the ScalarEvolution representation of @p Val.
const SCEV *getScevExpr() const { return ScevExpr; }
/// Return the MemoryAccess that makes the value available in this statement,
/// if any.
MemoryAccess *getMemoryAccess() const { return InputMA; }
/// Print a description of this object.
///
/// @param OS Stream to print to.
/// @param Reproducible If true, ensures that the output is stable between
/// runs and is suitable to check in regression tests. This excludes printing
/// e.g. pointer values.
/// If false, the output should not be used for regression
/// tests, but may contain more information useful in
/// debugger sessions.
void print(raw_ostream &OS, bool Reproducible = true) const;
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
void dump() const;
#endif
};
} // namespace polly
#endif /* POLLY_SUPPORT_VIRTUALINSTRUCTION_H */