19#include "llvm/Support/Debug.h"
21#define DEBUG_TYPE "int-divisibility-analysis"
36 auto inferrable = dyn_cast<InferIntDivisibilityOpInterface>(op);
42 LLVM_DEBUG(dbgs() <<
"Inferring divisibility for " << *op <<
"\n");
43 auto argDivs = llvm::map_to_vector(
48 auto result = dyn_cast<OpResult>(v);
54 LLVM_DEBUG(dbgs() <<
"Inferred divisibility " << newDiv <<
"\n");
65 return op->hasTrait<OpTrait::IsTerminator>();
69 LLVM_DEBUG(llvm::dbgs() <<
"Loop variant loop result detected\n");
75 inferrable.inferResultDivisibility(argDivs, joinCallback);
83 auto getDivFromOfr = [&](std::optional<OpFoldResult> ofr,
Block *block,
84 bool isUnsigned) -> uint64_t {
85 if (ofr.has_value()) {
87 return constBound.value();
89 auto value = cast<Value>(ofr.value());
103 if (
auto loop = dyn_cast<LoopLikeOpInterface>(op)) {
104 std::optional<SmallVector<Value>> ivs = loop.getLoopInductionVars();
105 std::optional<SmallVector<OpFoldResult>> lbs = loop.getLoopLowerBounds();
106 std::optional<SmallVector<OpFoldResult>> steps = loop.getLoopSteps();
107 if (!ivs || !lbs || !steps) {
109 op, successor, successorInputs, argLattices);
111 for (
auto [iv, lb, step] : llvm::zip_equal(*ivs, *lbs, *steps)) {
113 Block *block = iv.getParentBlock();
114 uint64_t stepUDiv = getDivFromOfr(step, block,
true);
115 uint64_t stepSDiv = getDivFromOfr(step, block,
false);
116 uint64_t lbUDiv = getDivFromOfr(lb, block,
true);
117 uint64_t lbSDiv = getDivFromOfr(lb, block,
false);
132 op, successor, successorInputs, argLattices);
Block represents an ordered list of Operations.
Statically known divisibility information for an integer SSA value.
ConstantIntDivisibility getUnion(const ConstantIntDivisibility &other) const
ProgramPoint * getProgramPointBefore(Operation *op)
Get a uniqued program point instance.
void propagateIfChanged(AnalysisState *state, ChangeResult changed)
Propagate an update to a state if it changed.
This lattice value represents the integer divisibility of an SSA value.
bool isUninitialized() const
const ConstantIntDivisibility & getValue() const
static IntegerDivisibility getMinDivisibility()
Operation is the basic unit of execution within MLIR.
result_range getResults()
This class represents a successor of a region.
This class provides an abstraction over the different types of ranges over Values.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
user_range getUsers() const
void visitNonControlFlowArguments(Operation *op, const RegionSuccessor &successor, ValueRange successorInputs, ArrayRef< IntegerDivisibilityLattice * > argLattices) override
Visit block arguments or operation results of an operation with region control-flow for which values ...
void setToEntryState(IntegerDivisibilityLattice *lattice) override
At an entry point, set the lattice to the most pessimistic state, indicating that no further reasonin...
LogicalResult visitOperation(Operation *op, ArrayRef< const IntegerDivisibilityLattice * > operands, ArrayRef< IntegerDivisibilityLattice * > results) override
Visit an operation, invoking the transfer function.
This lattice element represents the integer divisibility of an SSA value.
ValueT & getValue()
Return the value held by this lattice.
ChangeResult join(const AbstractSparseLattice &rhs) override
Join the information contained in the 'rhs' lattice into this lattice.
IntegerDivisibilityLattice * getLatticeElement(Value value) override
void setAllToEntryStates(ArrayRef< IntegerDivisibilityLattice * > lattices)
virtual void visitNonControlFlowArguments(Operation *op, const RegionSuccessor &successor, ValueRange nonSuccessorInputs, ArrayRef< StateT * > nonSuccessorInputLattices)
Given an operation with possible region control-flow, the lattices of the operands,...
const IntegerDivisibilityLattice * getLatticeElementFor(ProgramPoint *point, Value value)
std::optional< int64_t > getConstantIntValue(OpFoldResult ofr)
If ofr is a constant integer or an IntegerAttr, return the integer.
ChangeResult
A result type used to indicate if a change happened.