31#define DL_NAME "delinearize"
32#define DEBUG_TYPE DL_NAME
46struct SCEVCollectStrides {
48 SmallVectorImpl<const SCEV *> &Strides;
50 SCEVCollectStrides(ScalarEvolution &SE, SmallVectorImpl<const SCEV *> &S)
51 : SE(SE), Strides(S) {}
53 bool follow(
const SCEV *S) {
62 bool isDone()
const {
return false; }
66struct SCEVCollectTerms {
67 SmallVectorImpl<const SCEV *> &Terms;
69 SCEVCollectTerms(SmallVectorImpl<const SCEV *> &
T) : Terms(
T) {}
71 bool follow(
const SCEV *S) {
81 bool isDone()
const {
return false; }
88 SCEVHasAddRec(
bool &ContainsAddRec) : ContainsAddRec(ContainsAddRec) {
89 ContainsAddRec =
false;
92 bool follow(
const SCEV *S) {
94 ContainsAddRec =
true;
104 bool isDone()
const {
return false; }
119struct SCEVCollectAddRecMultiplies {
120 SmallVectorImpl<const SCEV *> &Terms;
123 SCEVCollectAddRecMultiplies(SmallVectorImpl<const SCEV *> &
T,
125 : Terms(
T), SE(SE) {}
127 bool follow(
const SCEV *S) {
129 bool HasAddRec =
false;
131 for (
const SCEV *
Op :
Mul->operands()) {
138 bool ContainsAddRec =
false;
139 SCEVHasAddRec ContiansAddRec(ContainsAddRec);
141 HasAddRec |= ContainsAddRec;
150 Terms.push_back(SE.getMulExpr(
Operands));
157 bool isDone()
const {
return false; }
169 SCEVCollectStrides StrideCollector(SE, Strides);
173 dbgs() <<
"Strides:\n";
174 for (
const SCEV *S : Strides)
178 for (
const SCEV *S : Strides) {
179 SCEVCollectTerms TermCollector(Terms);
184 dbgs() <<
"Terms:\n";
185 for (
const SCEV *
T : Terms)
189 SCEVCollectAddRecMultiplies MulCollector(Terms, SE);
203 for (
const SCEV *
Op : M->operands())
210 Sizes.push_back(Step);
214 for (
const SCEV *&Term : Terms) {
229 if (Terms.
size() > 0)
233 Sizes.push_back(Step);
239 for (
const SCEV *
T : Terms)
249 return Expr->getNumOperands();
262 for (
const SCEV *
Op : M->operands())
275 const SCEV *ElementSize) {
276 if (Terms.
size() < 1 || !ElementSize)
285 dbgs() <<
"Terms:\n";
286 for (
const SCEV *
T : Terms)
301 for (
const SCEV *&Term : Terms) {
311 for (
const SCEV *
T : Terms)
316 dbgs() <<
"Terms after sorting:\n";
317 for (
const SCEV *
T : NewTerms)
327 Sizes.push_back(ElementSize);
330 dbgs() <<
"Sizes:\n";
331 for (
const SCEV *S : Sizes)
351 <<
"Memory Access Function: " << *Expr <<
"\n");
353 const SCEV *Res = Expr;
354 int Last = Sizes.size() - 1;
356 for (
int i =
Last; i >= 0; i--) {
363 dbgs() <<
"Computing 'MemAccFn / Sizes[" << i <<
"]':\n";
364 dbgs() <<
" MemAccFn: " << *Res <<
"\n";
365 dbgs() <<
" Sizes[" << i <<
"]: " << *
Size <<
"\n";
366 dbgs() <<
" Quotient (Leftover): " << *Q <<
"\n";
367 dbgs() <<
" Remainder (Subscript Access Function): " << *R <<
"\n";
394 std::reverse(Subscripts.
begin(), Subscripts.
end());
397 dbgs() <<
"Subscripts:\n";
398 for (
const SCEV *S : Subscripts)
456 const SCEV *ElementSize) {
480 return Const->getAPInt();
494 const uint64_t Mod = Const->getAPInt().urem(ElementSize);
524 const SCEV *ElementSize) {
528 std::optional<APInt> ElementSizeAPInt =
tryIntoAPInt(ElementSize);
529 if (!ElementSizeAPInt || *ElementSizeAPInt == 0)
532 std::optional<uint64_t> ElementSizeConst = ElementSizeAPInt->tryZExtValue();
535 if (!ElementSizeConst)
566 assert(Sizes.back() != 0 &&
"Unexpected zero size in Sizes.");
569 for (
unsigned I = 0;
I + 1 < Sizes.size();
I++) {
570 uint64_t PrevSize = Sizes[
I + 1];
571 if (Sizes[
I] % PrevSize) {
575 Sizes[
I] /= PrevSize;
579 Sizes.back() = *ElementSizeConst;
637 const SCEV *ElementSize) {
650 for (uint64_t
Size : ConstSizes)
656 return !Subscripts.
empty();
682 for (
size_t I = 1;
I < Sizes.size(); ++
I) {
684 const SCEV *Subscript = Subscripts[
I];
694 LLVM_DEBUG(
dbgs() <<
"Range check failed: " << *Subscript <<
" <s "
750 "Expected output lists to be empty on entry to this function.");
751 assert(
GEP &&
"getIndexExpressionsFromGEP called with a null GEP");
755 bool DroppedFirstDim =
false;
756 for (
unsigned i = 1; i <
GEP->getNumOperands(); i++) {
759 Ty =
GEP->getSourceElementType();
761 if (Const->getValue()->isZero()) {
762 DroppedFirstDim =
true;
772 <<
" is not an array type.\n");
779 if (!(DroppedFirstDim && i == 2))
780 Sizes.push_back(SE.
getConstant(IndexTy, ArrayTy->getNumElements()));
782 Ty = ArrayTy->getElementType();
785 dbgs() <<
"Subscripts:\n";
786 for (
const SCEV *S : Subscripts)
787 dbgs() << *S <<
"\n";
791 return !Subscripts.
empty();
798 O <<
"Printing analysis 'Delinearization' for function '" <<
F->getName()
823 O <<
"Inst:" << Inst <<
"\n";
824 O <<
"AccessFunction: " << *AccessFn <<
"\n";
828 auto IsDelinearizationFailed = [&]() {
829 return Subscripts.
size() == 0 || Sizes.size() == 0 ||
830 Subscripts.
size() != Sizes.size();
834 if (Opts.delinearize_use_fixed_size_array_heuristic &&
835 IsDelinearizationFailed()) {
842 if (IsDelinearizationFailed()) {
843 O <<
"failed to delinearize\n";
847 O <<
"Base offset: " << *BasePointer <<
"\n";
848 O <<
"ArrayDecl[UnknownSize]";
850 for (
int i = 0; i <
Size - 1; i++)
851 O <<
"[" << *Sizes[i] <<
"]";
852 O <<
" with elements of " << *
Sizes[
Size - 1] <<
" bytes.\n";
855 for (
int i = 0; i <
Size; i++)
856 O <<
"[" << *Subscripts[i] <<
"]";
860 O <<
"Delinearization validation: " << (IsValid ?
"Succeeded" :
"Failed")
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Expand Atomic instructions
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
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 collectConstantAbsSteps(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< uint64_t > &Steps, uint64_t ElementSize)
Collects the absolute values of constant steps for all induction variables.
static bool findArrayDimensionsRec(ScalarEvolution &SE, SmallVectorImpl< const SCEV * > &Terms, SmallVectorImpl< const SCEV * > &Sizes)
static bool containsUndefs(const SCEV *S)
static std::optional< APInt > tryIntoAPInt(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.
if(auto Err=PB.parsePassPipeline(MPM, Passes)) return wrap(std MPM run * Mod
static SymbolRef::Type getType(const Symbol *Sym)
Class for arbitrary precision integers.
std::optional< uint64_t > tryZExtValue() const
Get zero extended value if possible.
static LLVM_ABI void udivrem(const APInt &LHS, const APInt &RHS, APInt &Quotient, APInt &Remainder)
Dual division/remainder interface.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
LLVM Basic Block Representation.
const Function * getParent() const
Return the enclosing method, or null if none.
@ ICMP_SLT
signed less than
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.
bool isAffine() const
Return true if this represents an expression A + B*x where A and B are loop invariant values.
SCEVUse getStepRecurrence(ScalarEvolution &SE) const
Constructs and returns the recurrence indicating how much this expression steps by.
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.
LLVM_ABI bool isZero() const
Return true if the expression is a constant zero.
Type * getType() const
Return the LLVM type of this SCEV expression.
Analysis pass that exposes the ScalarEvolution for a function.
The main scalar evolution driver.
LLVM_ABI bool isKnownNonNegative(const SCEV *S)
Test if the given expression is known to be non-negative.
LLVM_ABI Type * getWiderType(Type *Ty1, Type *Ty2) const
LLVM_ABI bool willNotOverflow(Instruction::BinaryOps BinOp, bool Signed, const SCEV *LHS, const SCEV *RHS, const Instruction *CtxI=nullptr)
Is operation BinOp between LHS and RHS provably does not have a signed/unsigned overflow (Signed)?
LLVM_ABI const SCEV * getMinusSCEV(SCEVUse LHS, SCEVUse RHS, SCEVFlags Flags=SCEV::FlagNone, unsigned Depth=0)
Return LHS-RHS.
LLVM_ABI SCEVUse getSCEVAtScope(const SCEV *S, const Loop *L)
Return a SCEV expression for the specified value at the specified scope in the program.
LLVM_ABI const SCEV * getConstant(ConstantInt *V)
LLVM_ABI const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
LLVM_ABI const SCEV * getNoopOrSignExtend(const SCEV *V, Type *Ty)
Return a SCEV corresponding to a conversion of the input value to the specified type.
const SCEV * getOne(Type *Ty)
Return a SCEV for the constant 1 of a specific type.
LLVM_ABI SCEVUse getAddExpr(SmallVectorImpl< SCEVUse > &Ops, SCEVFlagsPair Flags={}, unsigned Depth=0)
Get a canonical add expression, or something simpler if possible.
LLVM_ABI Type * getEffectiveSCEVType(Type *Ty) const
Return a type with the same bitwidth as the given type and which represents how SCEV will treat the g...
LLVM_ABI SCEVUse getMulExpr(SmallVectorImpl< SCEVUse > &Ops, SCEVFlagsPair Flags={}, unsigned Depth=0)
Get a canonical multiply expression, or something simpler if possible.
LLVM_ABI const SCEV * getPointerBase(const SCEV *V)
Transitively follow the chain of pointer-type operands until reaching a SCEV that does not have a sin...
LLVM_ABI bool isKnownPredicate(CmpPredicate Pred, SCEVUse LHS, SCEVUse RHS)
Test if the given expression is known to satisfy the condition described by Pred, LHS,...
LLVM_ABI 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.
This class implements an extremely fast bulk output stream that can only output to a stream.
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
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.
LLVM_ABI void collectParametricTerms(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< const SCEV * > &Terms)
Collect parametric terms occurring in step expressions (first step of delinearization).
LLVM_ABI 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...
@ Unknown
Not known to have no common set bits.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
constexpr std::enable_if_t< std::is_signed_v< T >, std::pair< T, bool > > AddOverflow(T X, T Y)
Add two signed integers, computing the two's complement truncated result, returning a pair {result,...
auto unique(Range &&R, Predicate P)
LLVM_ABI bool validateDelinearizationResult(ScalarEvolution &SE, ArrayRef< const SCEV * > Sizes, ArrayRef< const SCEV * > Subscripts)
Check that each subscript in Subscripts is within the corresponding size in Sizes.
const Value * getPointerOperand(const Value *V)
A helper function that returns the pointer operand of a load, store or GEP instruction.
const AnalysisOptions & getAnalysisOptions(const LLVMContext &C)
LLVM_ABI 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)...
LLVM_ABI bool delinearizeFixedSizeArray(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 acces...
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
@ Mul
Product of integers.
DWARFExpression::Operation Op
LLVM_ABI 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...
LLVM_ABI bool findFixedSizeArrayDimensions(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< uint64_t > &Sizes, const SCEV *ElementSize)
Compute the dimensions of fixed size array from \Expr and save the results in Sizes.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
constexpr std::enable_if_t< std::is_signed_v< T >, std::pair< T, bool > > MulOverflow(T X, T Y)
Multiply two signed integers, computing the two's complement truncated result, returning a pair {resu...
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
void array_pod_sort(IteratorTy Start, IteratorTy End)
array_pod_sort - This sorts an array with the specified start and end extent.
LLVM_ABI bool getIndexExpressionsFromGEP(ScalarEvolution &SE, const GetElementPtrInst *GEP, SmallVectorImpl< const SCEV * > &Subscripts, SmallVectorImpl< const SCEV * > &Sizes)
Gathers the individual index expressions from a GEP instruction.
bool SCEVExprContains(const SCEV *Root, PredTy Pred)
Return true if any node in Root satisfies the predicate Pred.
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
LLVM_ABI DelinearizationPrinterPass(raw_ostream &OS)
static LLVM_ABI void divide(ScalarEvolution &SE, const SCEV *Numerator, const SCEV *Denominator, const SCEV **Quotient, const SCEV **Remainder)
Computes the Quotient and Remainder of the division of Numerator by Denominator.