32#define DL_NAME "delinearize"
33#define DEBUG_TYPE DL_NAME
38 if (
const auto *SU = dyn_cast<SCEVUnknown>(S))
39 return isa<UndefValue>(SU->getValue());
47struct SCEVCollectStrides {
52 : SE(SE), Strides(S) {}
54 bool follow(
const SCEV *S) {
56 Strides.
push_back(AR->getStepRecurrence(SE));
60 bool isDone()
const {
return false; }
64struct SCEVCollectTerms {
69 bool follow(
const SCEV *S) {
70 if (isa<SCEVUnknown>(S) || isa<SCEVMulExpr>(S) ||
71 isa<SCEVSignExtendExpr>(S)) {
83 bool isDone()
const {
return false; }
90 SCEVHasAddRec(
bool &ContainsAddRec) : ContainsAddRec(ContainsAddRec) {
91 ContainsAddRec =
false;
94 bool follow(
const SCEV *S) {
95 if (isa<SCEVAddRecExpr>(S)) {
96 ContainsAddRec =
true;
106 bool isDone()
const {
return false; }
121struct SCEVCollectAddRecMultiplies {
127 : Terms(
T), SE(SE) {}
129 bool follow(
const SCEV *S) {
130 if (
auto *
Mul = dyn_cast<SCEVMulExpr>(S)) {
131 bool HasAddRec =
false;
140 bool ContainsAddRec =
false;
141 SCEVHasAddRec ContiansAddRec(ContainsAddRec);
143 HasAddRec |= ContainsAddRec;
161 bool isDone()
const {
return false; }
173 SCEVCollectStrides StrideCollector(SE, Strides);
177 dbgs() <<
"Strides:\n";
178 for (
const SCEV *S : Strides)
179 dbgs() << *S <<
"\n";
182 for (
const SCEV *S : Strides) {
183 SCEVCollectTerms TermCollector(Terms);
188 dbgs() <<
"Terms:\n";
189 for (
const SCEV *
T : Terms)
190 dbgs() << *
T <<
"\n";
193 SCEVCollectAddRecMultiplies MulCollector(Terms, SE);
205 if (
const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(Step)) {
207 for (
const SCEV *
Op : M->operands())
208 if (!isa<SCEVConstant>(
Op))
214 Sizes.push_back(Step);
218 for (
const SCEV *&Term : Terms) {
231 erase_if(Terms, [](
const SCEV *E) {
return isa<SCEVConstant>(E); });
233 if (Terms.
size() > 0)
237 Sizes.push_back(Step);
243 for (
const SCEV *
T : Terms)
252 if (
const SCEVMulExpr *Expr = dyn_cast<SCEVMulExpr>(S))
253 return Expr->getNumOperands();
258 if (isa<SCEVConstant>(
T))
261 if (isa<SCEVUnknown>(
T))
266 for (
const SCEV *
Op : M->operands())
267 if (!isa<SCEVConstant>(
Op))
279 const SCEV *ElementSize) {
280 if (Terms.
size() < 1 || !ElementSize)
289 dbgs() <<
"Terms:\n";
290 for (
const SCEV *
T : Terms)
291 dbgs() << *
T <<
"\n";
305 for (
const SCEV *&Term : Terms) {
315 for (
const SCEV *
T : Terms)
320 dbgs() <<
"Terms after sorting:\n";
321 for (
const SCEV *
T : NewTerms)
322 dbgs() << *
T <<
"\n";
331 Sizes.push_back(ElementSize);
334 dbgs() <<
"Sizes:\n";
335 for (
const SCEV *S : Sizes)
336 dbgs() << *S <<
"\n";
347 if (
auto *AR = dyn_cast<SCEVAddRecExpr>(Expr))
351 const SCEV *Res = Expr;
352 int Last = Sizes.size() - 1;
353 for (
int i =
Last; i >= 0; i--) {
358 dbgs() <<
"Res: " << *Res <<
"\n";
359 dbgs() <<
"Sizes[i]: " << *Sizes[i] <<
"\n";
360 dbgs() <<
"Res divided by Sizes[i]:\n";
361 dbgs() <<
"Quotient: " << *Q <<
"\n";
362 dbgs() <<
"Remainder: " << *R <<
"\n";
389 std::reverse(Subscripts.
begin(), Subscripts.
end());
392 dbgs() <<
"Subscripts:\n";
393 for (
const SCEV *S : Subscripts)
394 dbgs() << *S <<
"\n";
450 const SCEV *ElementSize) {
467 if (Subscripts.
empty())
471 dbgs() <<
"succeeded to delinearize " << *Expr <<
"\n";
472 dbgs() <<
"ArrayDecl[UnknownSize]";
473 for (
const SCEV *S : Sizes)
474 dbgs() <<
"[" << *S <<
"]";
476 dbgs() <<
"\nArrayRef";
477 for (
const SCEV *S : Subscripts)
478 dbgs() <<
"[" << *S <<
"]";
488 "Expected output lists to be empty on entry to this function.");
489 assert(
GEP &&
"getIndexExpressionsFromGEP called with a null GEP");
491 bool DroppedFirstDim =
false;
492 for (
unsigned i = 1; i <
GEP->getNumOperands(); i++) {
495 Ty =
GEP->getSourceElementType();
496 if (
auto *Const = dyn_cast<SCEVConstant>(Expr))
497 if (Const->getValue()->isZero()) {
498 DroppedFirstDim =
true;
505 auto *ArrayTy = dyn_cast<ArrayType>(Ty);
513 if (!(DroppedFirstDim && i == 2))
514 Sizes.push_back(ArrayTy->getNumElements());
516 Ty = ArrayTy->getElementType();
518 return !Subscripts.
empty();
527 auto *SrcGEP = dyn_cast<GetElementPtrInst>(SrcPtr);
537 if (Sizes.empty() || Subscripts.
size() <= 1) {
547 if (!SrcBase || SrcBasePtr != SrcBase->
getValue()) {
552 assert(Subscripts.
size() == Sizes.size() + 1 &&
553 "Expected equal number of entries in the list of size and "
563 O <<
"Delinearization on function " <<
F->getName() <<
":\n";
566 if (!isa<StoreInst>(&Inst) && !isa<LoadInst>(&Inst) &&
567 !isa<GetElementPtrInst>(&Inst))
573 for (
Loop *L = LI->
getLoopFor(BB); L !=
nullptr; L = L->getParentLoop()) {
584 O <<
"Inst:" << Inst <<
"\n";
585 O <<
"In Loop with Header: " << L->getHeader()->getName() <<
"\n";
586 O <<
"AccessFunction: " << *AccessFn <<
"\n";
590 if (Subscripts.
size() == 0 || Sizes.size() == 0 ||
591 Subscripts.
size() != Sizes.size()) {
592 O <<
"failed to delinearize\n";
596 O <<
"Base offset: " << *BasePointer <<
"\n";
597 O <<
"ArrayDecl[UnknownSize]";
599 for (
int i = 0; i <
Size - 1; i++)
600 O <<
"[" << *Sizes[i] <<
"]";
601 O <<
" with elements of " << *
Sizes[
Size - 1] <<
" bytes.\n";
604 for (
int i = 0; i <
Size; i++)
605 O <<
"[" << *Subscripts[i] <<
"]";
Expand Atomic instructions
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static const SCEV * removeConstantFactors(ScalarEvolution &SE, const SCEV *T)
static bool findArrayDimensionsRec(ScalarEvolution &SE, SmallVectorImpl< const SCEV * > &Terms, SmallVectorImpl< const SCEV * > &Sizes)
static bool containsUndefs(const SCEV *S)
static bool containsParameters(SmallVectorImpl< const SCEV * > &Terms)
static int numberOfTerms(const SCEV *S)
This header defines various interfaces for pass management in LLVM.
mir Rename Register Operands
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
LLVM Basic Block Representation.
const Function * getParent() const
Return the enclosing method, or null if none.
This class represents an Operation in the Expression.
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
Analysis pass that exposes the LoopInfo for a function.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
Represents a single loop in the control flow graph.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
This node represents a polynomial recurrence on the trip count of the specified loop.
This node represents multiplication of some number of SCEVs.
This means that we are dealing with an entirely unknown SCEV value, and only represent it as its LLVM...
This class represents an analyzed expression in the program.
bool isZero() const
Return true if the expression is a constant zero.
Analysis pass that exposes the ScalarEvolution for a function.
The main scalar evolution driver.
const SCEV * getSCEVAtScope(const SCEV *S, const Loop *L)
Return a SCEV expression for the specified value at the specified scope in the program.
const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
const SCEV * getMinusSCEV(const SCEV *LHS, const SCEV *RHS, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Return LHS-RHS.
const SCEV * getPointerBase(const SCEV *V)
Transitively follow the chain of pointer-type operands until reaching a SCEV that does not have a sin...
const SCEV * getMulExpr(SmallVectorImpl< const SCEV * > &Ops, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Get a canonical multiply expression, or something simpler if possible.
const SCEV * getElementSize(Instruction *Inst)
Return the size of an element read or written by Inst.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
iterator erase(const_iterator CI)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
This class implements an extremely fast bulk output stream that can only output to a stream.
This is an optimization pass for GlobalISel generic memory operations.
void visitAll(const SCEV *Root, SV &Visitor)
Use SCEVTraversal to visit all nodes in the given expression tree.
void collectParametricTerms(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< const SCEV * > &Terms)
Collect parametric terms occurring in step expressions (first step of delinearization).
void findArrayDimensions(ScalarEvolution &SE, SmallVectorImpl< const SCEV * > &Terms, SmallVectorImpl< const SCEV * > &Sizes, const SCEV *ElementSize)
Compute the array dimensions Sizes from the set of Terms extracted from the memory access function of...
const Value * getLoadStorePointerOperand(const Value *V)
A helper function that returns the pointer operand of a load or store instruction.
auto unique(Range &&R, Predicate P)
const Value * getPointerOperand(const Value *V)
A helper function that returns the pointer operand of a load, store or GEP instruction.
void computeAccessFunctions(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< const SCEV * > &Subscripts, SmallVectorImpl< const SCEV * > &Sizes)
Return in Subscripts the access functions for each dimension in Sizes (third step of delinearization)...
void sort(IteratorTy Start, IteratorTy End)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool getIndexExpressionsFromGEP(ScalarEvolution &SE, const GetElementPtrInst *GEP, SmallVectorImpl< const SCEV * > &Subscripts, SmallVectorImpl< int > &Sizes)
Gathers the individual index expressions from a GEP instruction.
bool tryDelinearizeFixedSizeImpl(ScalarEvolution *SE, Instruction *Inst, const SCEV *AccessFn, SmallVectorImpl< const SCEV * > &Subscripts, SmallVectorImpl< int > &Sizes)
Implementation of fixed size array delinearization.
void delinearize(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< const SCEV * > &Subscripts, SmallVectorImpl< const SCEV * > &Sizes, const SCEV *ElementSize)
Split this SCEVAddRecExpr into two vectors of SCEVs representing the subscripts and sizes of an array...
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
void array_pod_sort(IteratorTy Start, IteratorTy End)
array_pod_sort - This sorts an array with the specified start and end extent.
bool SCEVExprContains(const SCEV *Root, PredTy Pred)
Return true if any node in Root satisfies the predicate Pred.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
DelinearizationPrinterPass(raw_ostream &OS)
static void divide(ScalarEvolution &SE, const SCEV *Numerator, const SCEV *Denominator, const SCEV **Quotient, const SCEV **Remainder)