33#define DL_NAME "delinearize"
34#define DEBUG_TYPE DL_NAME
39 if (
const auto *SU = dyn_cast<SCEVUnknown>(S))
40 return isa<UndefValue>(SU->getValue());
48struct SCEVCollectStrides {
53 : SE(SE), Strides(S) {}
55 bool follow(
const SCEV *S) {
57 Strides.
push_back(AR->getStepRecurrence(SE));
61 bool isDone()
const {
return false; }
65struct SCEVCollectTerms {
70 bool follow(
const SCEV *S) {
71 if (isa<SCEVUnknown>(S) || isa<SCEVMulExpr>(S) ||
72 isa<SCEVSignExtendExpr>(S)) {
84 bool isDone()
const {
return false; }
91 SCEVHasAddRec(
bool &ContainsAddRec) : ContainsAddRec(ContainsAddRec) {
92 ContainsAddRec =
false;
95 bool follow(
const SCEV *S) {
96 if (isa<SCEVAddRecExpr>(S)) {
97 ContainsAddRec =
true;
107 bool isDone()
const {
return false; }
122struct SCEVCollectAddRecMultiplies {
128 : Terms(
T), SE(SE) {}
130 bool follow(
const SCEV *S) {
131 if (
auto *
Mul = dyn_cast<SCEVMulExpr>(S)) {
132 bool HasAddRec =
false;
141 bool ContainsAddRec =
false;
142 SCEVHasAddRec ContiansAddRec(ContainsAddRec);
144 HasAddRec |= ContainsAddRec;
162 bool isDone()
const {
return false; }
174 SCEVCollectStrides StrideCollector(SE, Strides);
178 dbgs() <<
"Strides:\n";
179 for (
const SCEV *S : Strides)
180 dbgs() << *S <<
"\n";
183 for (
const SCEV *S : Strides) {
184 SCEVCollectTerms TermCollector(Terms);
189 dbgs() <<
"Terms:\n";
190 for (
const SCEV *
T : Terms)
191 dbgs() << *
T <<
"\n";
194 SCEVCollectAddRecMultiplies MulCollector(Terms, SE);
206 if (
const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(Step)) {
208 for (
const SCEV *
Op : M->operands())
209 if (!isa<SCEVConstant>(
Op))
215 Sizes.push_back(Step);
219 for (
const SCEV *&Term : Terms) {
232 erase_if(Terms, [](
const SCEV *E) {
return isa<SCEVConstant>(E); });
234 if (Terms.
size() > 0)
238 Sizes.push_back(Step);
244 for (
const SCEV *
T : Terms)
253 if (
const SCEVMulExpr *Expr = dyn_cast<SCEVMulExpr>(S))
254 return Expr->getNumOperands();
259 if (isa<SCEVConstant>(
T))
262 if (isa<SCEVUnknown>(
T))
267 for (
const SCEV *
Op : M->operands())
268 if (!isa<SCEVConstant>(
Op))
280 const SCEV *ElementSize) {
281 if (Terms.
size() < 1 || !ElementSize)
290 dbgs() <<
"Terms:\n";
291 for (
const SCEV *
T : Terms)
292 dbgs() << *
T <<
"\n";
306 for (
const SCEV *&Term : Terms) {
316 for (
const SCEV *
T : Terms)
321 dbgs() <<
"Terms after sorting:\n";
322 for (
const SCEV *
T : NewTerms)
323 dbgs() << *
T <<
"\n";
332 Sizes.push_back(ElementSize);
335 dbgs() <<
"Sizes:\n";
336 for (
const SCEV *S : Sizes)
337 dbgs() << *S <<
"\n";
348 if (
auto *AR = dyn_cast<SCEVAddRecExpr>(Expr))
352 const SCEV *Res = Expr;
353 int Last = Sizes.size() - 1;
354 for (
int i =
Last; i >= 0; i--) {
359 dbgs() <<
"Res: " << *Res <<
"\n";
360 dbgs() <<
"Sizes[i]: " << *Sizes[i] <<
"\n";
361 dbgs() <<
"Res divided by Sizes[i]:\n";
362 dbgs() <<
"Quotient: " << *Q <<
"\n";
363 dbgs() <<
"Remainder: " << *R <<
"\n";
390 std::reverse(Subscripts.
begin(), Subscripts.
end());
393 dbgs() <<
"Subscripts:\n";
394 for (
const SCEV *S : Subscripts)
395 dbgs() << *S <<
"\n";
451 const SCEV *ElementSize) {
468 if (Subscripts.
empty())
472 dbgs() <<
"succeeded to delinearize " << *Expr <<
"\n";
473 dbgs() <<
"ArrayDecl[UnknownSize]";
474 for (
const SCEV *S : Sizes)
475 dbgs() <<
"[" << *S <<
"]";
477 dbgs() <<
"\nArrayRef";
478 for (
const SCEV *S : Subscripts)
479 dbgs() <<
"[" << *S <<
"]";
489 "Expected output lists to be empty on entry to this function.");
490 assert(
GEP &&
"getIndexExpressionsFromGEP called with a null GEP");
492 bool DroppedFirstDim =
false;
493 for (
unsigned i = 1; i <
GEP->getNumOperands(); i++) {
496 Ty =
GEP->getSourceElementType();
497 if (
auto *Const = dyn_cast<SCEVConstant>(Expr))
498 if (Const->getValue()->isZero()) {
499 DroppedFirstDim =
true;
506 auto *ArrayTy = dyn_cast<ArrayType>(Ty);
514 if (!(DroppedFirstDim && i == 2))
515 Sizes.push_back(ArrayTy->getNumElements());
517 Ty = ArrayTy->getElementType();
519 return !Subscripts.
empty();
528 auto *SrcGEP = dyn_cast<GetElementPtrInst>(SrcPtr);
538 if (Sizes.empty() || Subscripts.
size() <= 1) {
548 if (!SrcBase || SrcBasePtr != SrcBase->
getValue()) {
553 assert(Subscripts.
size() == Sizes.size() + 1 &&
554 "Expected equal number of entries in the list of size and "
564 O <<
"Delinearization on function " <<
F->getName() <<
":\n";
567 if (!isa<StoreInst>(&Inst) && !isa<LoadInst>(&Inst) &&
568 !isa<GetElementPtrInst>(&Inst))
574 for (
Loop *L = LI->
getLoopFor(BB); L !=
nullptr; L = L->getParentLoop()) {
585 O <<
"Inst:" << Inst <<
"\n";
586 O <<
"In Loop with Header: " << L->getHeader()->getName() <<
"\n";
587 O <<
"AccessFunction: " << *AccessFn <<
"\n";
591 if (Subscripts.
size() == 0 || Sizes.size() == 0 ||
592 Subscripts.
size() != Sizes.size()) {
593 O <<
"failed to delinearize\n";
597 O <<
"Base offset: " << *BasePointer <<
"\n";
598 O <<
"ArrayDecl[UnknownSize]";
600 for (
int i = 0; i <
Size - 1; i++)
601 O <<
"[" << *Sizes[i] <<
"]";
602 O <<
" with elements of " << *
Sizes[
Size - 1] <<
" bytes.\n";
605 for (
int i = 0; i <
Size; i++)
606 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)
mir Rename Register Operands
This header defines various interfaces for pass management in LLVM.
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)