Index: include/polly/ScopInfo.h =================================================================== --- include/polly/ScopInfo.h +++ include/polly/ScopInfo.h @@ -97,20 +97,125 @@ /// class ScopArrayInfo { public: - /// @brief The type of a memory access. - enum ARRAYKIND { - // Scalar references to SSA values. - KIND_SCALAR, - - // Scalar references used to model PHI nodes - KIND_PHI, - - // Like KIND_PHI, but for PHIs in the exit node. Depending on context, these - // are handled like KIND_SCALAR. - KIND_EXIT_PHI, - - // References to (multi-dimensional) arrays - KIND_ARRAY, + /// @brief The kind of a ScopArrayInfo memory object. + /// + /// We distinguish between arrays and various scalar memory objects. We use + /// the term ``array'' to describe memory objects that consist of a set of + /// individual data elements arranged in a multi-dimensional grid. A scalar + /// memory object describes an individual data element and is used to model + /// the definition and uses of llvm::Values. + /// + /// The polyhedral model does traditionally not reason about SSA values. To + /// reason about llvm::Values we model them "as if" they were zero-dimensional + /// memory objects, even though they were not actually allocated in (main) + /// memory. Memory for such objects is only alloca[ed] at CodeGeneration + /// time. To relate the memory slots used during code generation with the + /// llvm::Values they belong to the new names for these corresponding stack + /// slots are derived by appending suffixes (currently ".s2a" and ".phiops") + /// to the name of the original llvm::Value. To describe how def/uses are + /// modeled exactly we use these suffixes here as well. + /// + /// There are currently four different kinds of memory objects: + enum MemoryKind { + /// MK_Array: Models a one or multi-dimensional array + /// + /// A memory object that can be described by a multi-dimensional array. + /// Memory objects of this type are used to model actual multi-dimensional + /// arrays as they exist in LLVM-IR, but they are also used to describe + /// other objects: + /// - A single data element allocated on the stack using 'alloca' is + /// modeled as a one-dimensional, single-element array. + /// - A single data element allocated as a global variable is modeled as + /// one-dimensional, single-element array. + /// - Certain multi-dimensional arrays with variable size, which in + /// LLVM-IR are commonly expressed as a single-dimensional access with a + /// complicated access function, are modeled as multi-dimensional + /// memory objects (grep for "delinearization"). + MK_Array, + + /// MK_Value: Models an llvm::Value + /// + /// Memory objects of type MK_Value are used to model the data flow + /// induced by llvm::Values. For each llvm::Value that is used across + /// BasicBocks one ScopArrayInfo object is created. A single memory WRITE + /// stores the llvm::Value at its definition into the memory object and at + /// each use of the llvm::Value (ignoring trivial intra-block uses) a + /// corresponding READ is added. For instance, the use/def chain of a + /// llvm::Value %V depicted below + /// ______________________ + /// |DefBB: | + /// | %V = float op ... | + /// ---------------------- + /// | | + /// _________________ _________________ + /// |UseBB1: | |UseBB2: | + /// | use float %V | | use float %V | + /// ----------------- ----------------- + /// + /// is modeled as if the following memory accesses occured: + /// + /// __________________________ + /// |entry: | + /// | %V.s2a = alloca float | + /// -------------------------- + /// | + /// ___________________________________ + /// |DefBB: | + /// | store %float %V, float* %V.sa2 | + /// ----------------------------------- + /// | | + /// ____________________________________ ___________________________________ + /// |UseBB1: | |UseBB2: | + /// | %V.reload1 = load float* %V.s2a | | %V.reload2 = load float* %V.s2a| + /// | use float %V.reload1 | | use float %V.reload2 | + /// ------------------------------------ ----------------------------------- + /// + MK_Value, + + /// MK_PHI: Models PHI nodes within the SCoP + /// + /// Besides the MK_Value memory object used to model the normal + /// llvm::Value dependences described above, PHI nodes require an additional + /// memory object of type MK_PHI to describe the forwarding of values to + /// the PHI node. + /// + /// As an example, a PHIInst instructions + /// + /// %PHI = phi float [ %Val1, %IncomingBlock1 ], [ %Val2, %IncomingBlock2 ] + /// + /// is modeled as if the accesses occured this way: + /// + /// _______________________________ + /// |entry: | + /// | %PHI.phiops = alloca float | + /// ------------------------------- + /// | | + /// __________________________________ __________________________________ + /// |IncomingBlock1: | |IncomingBlock2: | + /// | ... | | ... | + /// | store float %Val1 %PHI.phiops | | store float %Val2 %PHI.phiops | + /// | br label % JoinBlock | | br label %JoinBlock | + /// ---------------------------------- ---------------------------------- + /// \ / + /// \ / + /// _________________________________________ + /// |JoinBlock: | + /// | %PHI = load float, float* PHI.phiops | + /// ----------------------------------------- + /// + /// Note that there can also be a scalar write access for %PHI if used in a + /// different BasicBlock, i.e. there can be a memory object %PHI.phiops as + /// well as a memory object %PHI.s2a. + MK_PHI, + + /// MK_ExitPHI: Models PHI nodes in the SCoP's exit block + /// + /// For PHI nodes in the Scop's exit block a special memory object kind is + /// used. The modeling used is identical to MK_PHI, with the exception + /// that there are no READs from these memory objects. The PHINode's + /// llvm::Value is treated as a value escaping the SCoP. WRITE accesses + /// write directly to the escaping value's ".s2a" alloca. + MK_ExitPHI }; /// @brief Construct a ScopArrayInfo object. @@ -123,7 +228,7 @@ /// @param DL The data layout of the module. /// @param S The scop this array object belongs to. ScopArrayInfo(Value *BasePtr, Type *ElementType, isl_ctx *IslCtx, - ArrayRef DimensionSizes, enum ARRAYKIND Kind, + ArrayRef DimensionSizes, enum MemoryKind Kind, const DataLayout &DL, Scop *S); /// @brief Update the sizes of the ScopArrayInfo object. @@ -201,7 +306,7 @@ /// original PHI node as virtual base pointer, we have this additional /// attribute to distinguish the PHI node specific array modeling from the /// normal scalar array modeling. - bool isPHI() const { return Kind == KIND_PHI; }; + bool isPHIKind() const { return Kind == MK_PHI; }; /// @brief Dump a readable representation to stderr. void dump() const; @@ -250,7 +355,7 @@ /// @brief The type of this scop array info object. /// /// We distinguish between SCALAR, PHI and ARRAY objects. - enum ARRAYKIND Kind; + enum MemoryKind Kind; /// @brief The data layout of the module. const DataLayout &DL; @@ -265,114 +370,6 @@ friend class ScopStmt; public: - /// @brief Description of the cause of a MemoryAccess being added. - /// - /// We distinguish between explicit and implicit accesses. Explicit are those - /// for which there is a load or store instruction in the analyzed IR. - /// Implicit accesses are derived from defintions and uses of llvm::Values. - /// The polyhedral model has no notion of such values or SSA form, hence they - /// are modeled "as if" they were accesses to zero-dimensional arrays even if - /// they do represent accesses to (main) memory in the analyzed IR code. The - /// actual memory for the zero-dimensional arrays is only created using - /// allocas at CodeGeneration, with suffixes (currently ".s2a" and ".phiops") - /// added to the value's name. To describe how def/uses are modeled using - /// accesses we use these these suffixes here as well. - /// There are currently three separate kinds of access origins: - /// - /// - /// * Explicit access - /// - /// Memory is accessed by either a load (READ) or store (*_WRITE) found in the - /// IR. #AccessInst is the LoadInst respectively StoreInst. The #BaseAddr is - /// the array pointer being accesses without subscript. #AccessValue is the - /// llvm::Value the StoreInst writes, respectively the result of the LoadInst - /// (the LoadInst itself). - /// - /// - /// * Accessing an llvm::Value (a scalar) - /// - /// This is either a *_WRITE for the value's definition (i.e. exactly one per - /// llvm::Value) or a READ when the scalar is used in a different - /// BasicBlock. For instance, a use/def chain of such as %V in - /// ______________________ - /// |DefBB: | - /// | %V = float op ... | - /// ---------------------- - /// | | - /// _________________ _________________ - /// |UseBB1: | |UseBB2: | - /// | use float %V | | use float %V | - /// ----------------- ----------------- - /// - /// is modeled as if the accesses had occured this way: - /// - /// __________________________ - /// |entry: | - /// | %V.s2a = alloca float | - /// -------------------------- - /// | - /// ___________________________________ - /// |DefBB: | - /// | store %float %V, float* %V.sa2 | - /// ----------------------------------- - /// | | - /// ____________________________________ ____________________________________ - /// |UseBB1: | |UseBB2: | - /// | %V.reload1 = load float* %V.s2a | | %V.reload2 = load float* %V.s2a | - /// | use float %V.reload1 | | use float %V.reload2 | - /// ------------------------------------ ------------------------------------ - /// - /// #AccessInst is either the llvm::Value for WRITEs or the value's user for - /// READS. The #BaseAddr is represented by the value's definition (i.e. the - /// llvm::Value itself) as no such alloca yet exists before CodeGeneration. - /// #AccessValue is also the llvm::Value itself. - /// - /// - /// * Accesses to emulate PHI nodes within the SCoP - /// - /// PHIInst instructions such as - /// - /// %PHI = phi float [ %Val1, %IncomingBlock1 ], [ %Val2, %IncomingBlock2 ] - /// - /// are modeled as if the accesses occured this way: - /// - /// _______________________________ - /// |entry: | - /// | %PHI.phiops = alloca float | - /// ------------------------------- - /// | | - /// __________________________________ __________________________________ - /// |IncomingBlock1: | |IncomingBlock2: | - /// | ... | | ... | - /// | store float %Val1 %PHI.phiops | | store float %Val2 %PHI.phiops | - /// | br label % JoinBlock | | br label %JoinBlock | - /// ---------------------------------- ---------------------------------- - /// \ / - /// \ / - /// _________________________________________ - /// |JoinBlock: | - /// | %PHI = load float, float* PHI.phiops | - /// ----------------------------------------- - /// - /// Since the stores and loads do not exist in the analyzed code, the - /// #AccessInst of a load is the PHIInst and a incoming block's terminator for - /// stores. The #BaseAddr is represented through the PHINode because there - /// also such alloca in the analyzed code. The #AccessValue is represented by - /// the PHIInst itself. - /// - /// Note that there can also be a scalar write access for %PHI if used in a - /// different BasicBlock, i.e. there can be a %PHI.phiops as well as a - /// %PHI.s2a. - /// - /// - /// * Accesses to emulate PHI nodes that are in the SCoP's exit block - /// - /// Like the previous, but the PHI itself is not located in the SCoP itself. - /// There will be no READ type MemoryAccess for such values. The PHINode's - /// llvm::Value is treated as a value escaping the SCoP. WRITE accesses write - /// directly to the escaping value's ".s2a" alloca. - enum AccessOrigin { EXPLICIT, SCALAR, PHI, EXIT_PHI }; - /// @brief The access type of a memory access /// /// There are three kind of access types: @@ -421,9 +418,9 @@ /// scop statement. isl_id *Id; - /// @brief What is modeled by this MemoetyAccess. - /// @see AccessOrigin - enum AccessOrigin Origin; + /// @brief What is modeled by this MemoryAccess. + /// @see ScopArrayInfo::MemoryKind + ScopArrayInfo::MemoryKind Kind; /// @brief Whether it a reading or writing access, and if writing, whether it /// is conditional (MAY_WRITE). @@ -463,6 +460,13 @@ // @{ /// @brief The base address (e.g., A for A[i+j]). + /// + /// The #BaseAddr of a memory access of kind MK_Array is the base pointer + /// of the memory access. + /// The #BaseAddr of a memory access of kind MK_PHI or MK_ExitPHI is the + /// PHI node itself. + /// The #BaseAddr of a memory access of kind MK_Value is the instruction + /// defining the value. AssertingVH BaseAddr; /// @brief An unique name of the accessed array. @@ -479,13 +483,27 @@ // @{ /// @brief The access instruction of this memory access. + /// + /// For memory accesses of kind MK_Array the access instruction is the + /// Load or Store instruction performing the access. + /// + /// For memory accesses of kind MK_PHI or MK_ExitPHI the access + /// instruction of a load access is the PHI instruction. The access + /// instruction of a PHI-store is the incoming's block's terminator + /// intruction. + /// + /// For memory accesses of kind MK_Value the access instruction of a load + /// access is the instruction that uses the load. The access instruction of + /// a write access is the intruction that defines the llvm::Value. Instruction *AccessInstruction; /// @brief The value associated with this memory access. /// - /// - For real memory accesses it is the loaded result or the stored value. - /// - For straight line scalar accesses it is the access instruction itself. - /// - For PHI operand accesses it is the operand value. + /// - For array memory accesses (MK_Array) it is the loaded result or the + /// stored value. + /// - For accesses of kind MK_Value it is the access instruction itself. + /// - For accesses of kind MK_PHI or MK_ExitPHI it is the operand value + /// of the PHI node. /// AssertingVH AccessValue; @@ -572,14 +590,15 @@ /// @param ElemBytes Number of accessed bytes. /// @param AccType Whether read or write access. /// @param IsAffine Whether the subscripts are affine expressions. - /// @param Origin What is the purpose of this access? + /// @param Kind The kind of memory accessed. /// @param Subscripts Subscipt expressions /// @param Sizes Dimension lengths of the accessed array. /// @param BaseName Name of the acessed array. MemoryAccess(ScopStmt *Stmt, Instruction *AccessInst, AccessType Type, Value *BaseAddress, unsigned ElemBytes, bool Affine, ArrayRef Subscripts, ArrayRef Sizes, - Value *AccessValue, AccessOrigin Origin, StringRef BaseName); + Value *AccessValue, ScopArrayInfo::MemoryKind Kind, + StringRef BaseName); ~MemoryAccess(); /// @brief Get the type of a memory access. @@ -674,21 +693,22 @@ bool isStrideZero(__isl_take const isl_map *Schedule) const; /// @brief Whether this is an access of an explicit load or store in the IR. - bool isExplicit() const { return Origin == EXPLICIT; } + bool isArrayKind() const { return Kind == ScopArrayInfo::MK_Array; } - /// @brief Whether this access represents a register access or models PHI - /// nodes. - bool isImplicit() const { return !isExplicit(); } + /// @brief Whether this access is an array to a scalar memory object. + /// + /// Scalar accesses are accesses to MK_Value, MK_PHI or MK_ExitPHI. + bool isScalarKind() const { return !isArrayKind(); } /// @brief Is this MemoryAccess modeling scalar dependences? - bool isScalar() const { return Origin == SCALAR; } + bool isValueKind() const { return Kind == ScopArrayInfo::MK_Value; } /// @brief Is this MemoryAccess modeling special PHI node accesses? - bool isPHI() const { return Origin == PHI; } + bool isPHIKind() const { return Kind == ScopArrayInfo::MK_PHI; } /// @brief Is this MemoryAccess modeling the accesses of a PHI node in the /// SCoP's exit block? - bool isExitPHI() const { return Origin == EXIT_PHI; } + bool isExitPHIKind() const { return Kind == ScopArrayInfo::MK_ExitPHI; } /// @brief Get the statement that contains this memory access. ScopStmt *getStatement() const { return Statement; } @@ -1591,18 +1611,18 @@ /// @brief Return the (possibly new) ScopArrayInfo object for @p Access. /// /// @param ElementType The type of the elements stored in this array. - /// @param Kind The kind of array info object. + /// @param Kind The kind of the array info object. const ScopArrayInfo *getOrCreateScopArrayInfo(Value *BasePtr, Type *ElementType, ArrayRef Sizes, - ScopArrayInfo::ARRAYKIND Kind); + ScopArrayInfo::MemoryKind Kind); /// @brief Return the cached ScopArrayInfo object for @p BasePtr. /// - /// @param BasePtr The base pointer the object has been stored for. - /// @param Kind The kind of array info object. + /// @param BasePtr The base pointer the object has been stored for. + /// @param Kind The kind of array info object. const ScopArrayInfo *getScopArrayInfo(Value *BasePtr, - ScopArrayInfo::ARRAYKIND Kind); + ScopArrayInfo::MemoryKind Kind); void setContext(isl_set *NewContext); @@ -1811,13 +1831,13 @@ /// @param AccessValue Value read or written. /// @param Subscripts Access subscripts per dimension. /// @param Sizes The array diminsion's sizes. - /// @param Origin Purpose of this access. + /// @param Kind The kind of memory accessed. void addMemoryAccess(BasicBlock *BB, Instruction *Inst, MemoryAccess::AccessType Type, Value *BaseAddress, unsigned ElemBytes, bool Affine, Value *AccessValue, ArrayRef Subscripts, ArrayRef Sizes, - MemoryAccess::AccessOrigin Origin); + ScopArrayInfo::MemoryKind Kind); /// @brief Create a MemoryAccess that represents either a LoadInst or /// StoreInst. @@ -1830,11 +1850,11 @@ /// @param Subscripts Access subscripts per dimension. /// @param Sizes The array dimension's sizes. /// @param AccessValue Value read or written. - /// @see AccessOrigin - void addExplicitAccess(Instruction *MemAccInst, MemoryAccess::AccessType Type, - Value *BaseAddress, unsigned ElemBytes, bool IsAffine, - ArrayRef Subscripts, - ArrayRef Sizes, Value *AccessValue); + /// @see ScopArrayInfo::MemoryKind + void addArrayAccess(Instruction *MemAccInst, MemoryAccess::AccessType Type, + Value *BaseAddress, unsigned ElemBytes, bool IsAffine, + ArrayRef Subscripts, + ArrayRef Sizes, Value *AccessValue); /// @brief Create a MemoryAccess for writing an llvm::Value. /// @@ -1842,7 +1862,7 @@ /// /// @param Value The value to be written. /// @see addScalarReadAccess() - /// @see AccessOrigin + /// @see ScopArrayInfo::MemoryKind void addScalarWriteAccess(Instruction *Value); /// @brief Create a MemoryAccess for reloading an llvm::Value. @@ -1852,7 +1872,7 @@ /// @param Value The scalar expected to be loaded. /// @param User User of the scalar; this is where the access is added. /// @see addScalarWriteAccess() - /// @see AccessOrigin + /// @see ScopArrayInfo::MemoryKind void addScalarReadAccess(Value *Value, Instruction *User); /// @brief Create a MemoryAccess for reloading an llvm::Value. @@ -1866,7 +1886,7 @@ /// @param UserBB Incoming block for the incoming @p Value. /// @see addPHIWriteAccess() /// @see addScalarWriteAccess() - /// @see AccessOrigin + /// @see ScopArrayInfo::MemoryKind void addScalarReadAccess(Value *Value, PHINode *User, BasicBlock *UserBB); /// @brief Create a write MemoryAccess for the incoming block of a phi node. @@ -1881,7 +1901,7 @@ /// .phiops one. Required for values escaping through a /// PHINode in the SCoP region's exit block. /// @see addPHIReadAccess() - /// @see AccessOrigin + /// @see ScopArrayInfo::MemoryKind void addPHIWriteAccess(PHINode *PHI, BasicBlock *IncomingBlock, Value *IncomingValue, bool IsExitBlock); @@ -1894,7 +1914,7 @@ /// @param PHI PHINode under consideration; the READ access will be added /// here. /// @see addPHIWriteAccess() - /// @see AccessOrigin + /// @see ScopArrayInfo::MemoryKind void addPHIReadAccess(PHINode *PHI); public: Index: lib/Analysis/ScopInfo.cpp =================================================================== --- lib/Analysis/ScopInfo.cpp +++ lib/Analysis/ScopInfo.cpp @@ -166,15 +166,15 @@ return nullptr; return S->getScopArrayInfo(OriginBaseSCEVUnknown->getValue(), - ScopArrayInfo::KIND_ARRAY); + ScopArrayInfo::MK_Array); } ScopArrayInfo::ScopArrayInfo(Value *BasePtr, Type *ElementType, isl_ctx *Ctx, - ArrayRef Sizes, enum ARRAYKIND Kind, + ArrayRef Sizes, enum MemoryKind Kind, const DataLayout &DL, Scop *S) : BasePtr(BasePtr), ElementType(ElementType), Kind(Kind), DL(DL), S(*S) { std::string BasePtrName = - getIslCompatibleName("MemRef_", BasePtr, Kind == KIND_PHI ? "__phi" : ""); + getIslCompatibleName("MemRef_", BasePtr, Kind == MK_PHI ? "__phi" : ""); Id = isl_id_alloc(Ctx, BasePtrName.c_str(), this); updateSizes(Sizes); @@ -702,8 +702,8 @@ unsigned ElemBytes, bool Affine, ArrayRef Subscripts, ArrayRef Sizes, Value *AccessValue, - AccessOrigin Origin, StringRef BaseName) - : Origin(Origin), AccType(Type), RedType(RT_NONE), Statement(Stmt), + ScopArrayInfo::MemoryKind Kind, StringRef BaseName) + : Kind(Kind), AccType(Type), RedType(RT_NONE), Statement(Stmt), BaseAddr(BaseAddress), BaseName(BaseName), ElemBytes(ElemBytes), Sizes(Sizes.begin(), Sizes.end()), AccessInstruction(AccessInst), AccessValue(AccessValue), IsAffine(Affine), @@ -747,7 +747,7 @@ break; } OS << "[Reduction Type: " << getReductionType() << "] "; - OS << "[Scalar: " << isImplicit() << "]\n"; + OS << "[Scalar: " << isScalarKind() << "]\n"; OS.indent(16) << getOriginalAccessRelationStr() << ";\n"; if (hasNewAccessRelation()) OS.indent(11) << "new: " << getNewAccessRelationStr() << ";\n"; @@ -880,15 +880,15 @@ for (MemoryAccess *Access : MemAccs) { Type *ElementType = Access->getAccessValue()->getType(); - ScopArrayInfo::ARRAYKIND Ty; - if (Access->isPHI()) - Ty = ScopArrayInfo::KIND_PHI; - else if (Access->isExitPHI()) - Ty = ScopArrayInfo::KIND_EXIT_PHI; - else if (Access->isScalar()) - Ty = ScopArrayInfo::KIND_SCALAR; + ScopArrayInfo::MemoryKind Ty; + if (Access->isPHIKind()) + Ty = ScopArrayInfo::MK_PHI; + else if (Access->isExitPHIKind()) + Ty = ScopArrayInfo::MK_ExitPHI; + else if (Access->isValueKind()) + Ty = ScopArrayInfo::MK_Value; else - Ty = ScopArrayInfo::KIND_ARRAY; + Ty = ScopArrayInfo::MK_Array; const ScopArrayInfo *SAI = getParent()->getOrCreateScopArrayInfo( Access->getBaseAddr(), ElementType, Access->Sizes, Ty); @@ -2467,7 +2467,7 @@ continue; for (MemoryAccess *MA : Stmt) { - if (MA->isImplicit()) + if (MA->isScalarKind()) continue; if (!MA->isRead()) HasWriteAccess.insert(MA->getBaseAddr()); @@ -2868,7 +2868,7 @@ MemoryAccessList InvMAs; for (MemoryAccess *MA : Stmt) { - if (MA->isImplicit() || MA->isWrite() || !MA->isAffine()) + if (MA->isScalarKind() || MA->isWrite() || !MA->isAffine()) continue; // Skip accesses that have an invariant base pointer which is defined but @@ -2959,7 +2959,7 @@ const ScopArrayInfo * Scop::getOrCreateScopArrayInfo(Value *BasePtr, Type *AccessType, ArrayRef Sizes, - ScopArrayInfo::ARRAYKIND Kind) { + ScopArrayInfo::MemoryKind Kind) { auto &SAI = ScopArrayInfoMap[std::make_pair(BasePtr, Kind)]; if (!SAI) { auto &DL = getRegion().getEntry()->getModule()->getDataLayout(); @@ -2976,7 +2976,7 @@ } const ScopArrayInfo *Scop::getScopArrayInfo(Value *BasePtr, - ScopArrayInfo::ARRAYKIND Kind) { + ScopArrayInfo::MemoryKind Kind) { auto *SAI = ScopArrayInfoMap[std::make_pair(BasePtr, Kind)].get(); assert(SAI && "No ScopArrayInfo available for this base pointer"); return SAI; @@ -3734,8 +3734,8 @@ SizesSCEV.push_back(SE->getSCEV(ConstantInt::get( IntegerType::getInt64Ty(BasePtr->getContext()), Size))); - addExplicitAccess(Inst, Type, BasePointer->getValue(), Size, true, - Subscripts, SizesSCEV, Val); + addArrayAccess(Inst, Type, BasePointer->getValue(), Size, true, + Subscripts, SizesSCEV, Val); return; } } @@ -3743,9 +3743,9 @@ auto AccItr = InsnToMemAcc.find(Inst); if (PollyDelinearize && AccItr != InsnToMemAcc.end()) { - addExplicitAccess(Inst, Type, BasePointer->getValue(), Size, true, - AccItr->second.DelinearizedSubscripts, - AccItr->second.Shape->DelinearizedSizes, Val); + addArrayAccess(Inst, Type, BasePointer->getValue(), Size, true, + AccItr->second.DelinearizedSubscripts, + AccItr->second.Shape->DelinearizedSizes, Val); return; } @@ -3776,9 +3776,9 @@ if (!IsAffine && Type == MemoryAccess::MUST_WRITE) Type = MemoryAccess::MAY_WRITE; - addExplicitAccess(Inst, Type, BasePointer->getValue(), Size, IsAffine, - ArrayRef(AccessFunction), - ArrayRef(SizeSCEV), Val); + addArrayAccess(Inst, Type, BasePointer->getValue(), Size, IsAffine, + ArrayRef(AccessFunction), + ArrayRef(SizeSCEV), Val); } void ScopInfo::buildAccessFunctions(Region &R, Region &SR) { @@ -3867,7 +3867,7 @@ bool Affine, Value *AccessValue, ArrayRef Subscripts, ArrayRef Sizes, - MemoryAccess::AccessOrigin Origin) { + ScopArrayInfo::MemoryKind Kind) { ScopStmt *Stmt = scop->getStmtForBasicBlock(BB); // Do not create a memory access for anything not in the SCoP. It would be @@ -3885,48 +3885,51 @@ Type = MemoryAccess::MAY_WRITE; AccList.emplace_back(Stmt, Inst, Type, BaseAddress, ElemBytes, Affine, - Subscripts, Sizes, AccessValue, Origin, BaseName); + Subscripts, Sizes, AccessValue, Kind, BaseName); Stmt->addAccess(&AccList.back()); } -void ScopInfo::addExplicitAccess( - Instruction *MemAccInst, MemoryAccess::AccessType Type, Value *BaseAddress, - unsigned ElemBytes, bool IsAffine, ArrayRef Subscripts, - ArrayRef Sizes, Value *AccessValue) { +void ScopInfo::addArrayAccess(Instruction *MemAccInst, + MemoryAccess::AccessType Type, Value *BaseAddress, + unsigned ElemBytes, bool IsAffine, + ArrayRef Subscripts, + ArrayRef Sizes, + Value *AccessValue) { assert(isa(MemAccInst) || isa(MemAccInst)); assert(isa(MemAccInst) == (Type == MemoryAccess::READ)); addMemoryAccess(MemAccInst->getParent(), MemAccInst, Type, BaseAddress, ElemBytes, IsAffine, AccessValue, Subscripts, Sizes, - MemoryAccess::EXPLICIT); + ScopArrayInfo::MK_Array); } void ScopInfo::addScalarWriteAccess(Instruction *Value) { addMemoryAccess(Value->getParent(), Value, MemoryAccess::MUST_WRITE, Value, 1, true, Value, ArrayRef(), - ArrayRef(), MemoryAccess::SCALAR); + ArrayRef(), ScopArrayInfo::MK_Value); } void ScopInfo::addScalarReadAccess(Value *Value, Instruction *User) { assert(!isa(User)); addMemoryAccess(User->getParent(), User, MemoryAccess::READ, Value, 1, true, Value, ArrayRef(), ArrayRef(), - MemoryAccess::SCALAR); + ScopArrayInfo::MK_Value); } void ScopInfo::addScalarReadAccess(Value *Value, PHINode *User, BasicBlock *UserBB) { addMemoryAccess(UserBB, User, MemoryAccess::READ, Value, 1, true, Value, ArrayRef(), ArrayRef(), - MemoryAccess::SCALAR); + ScopArrayInfo::MK_Value); } void ScopInfo::addPHIWriteAccess(PHINode *PHI, BasicBlock *IncomingBlock, Value *IncomingValue, bool IsExitBlock) { addMemoryAccess(IncomingBlock, IncomingBlock->getTerminator(), MemoryAccess::MUST_WRITE, PHI, 1, true, IncomingValue, ArrayRef(), ArrayRef(), - IsExitBlock ? MemoryAccess::EXIT_PHI : MemoryAccess::PHI); + IsExitBlock ? ScopArrayInfo::MK_ExitPHI + : ScopArrayInfo::MK_PHI); } void ScopInfo::addPHIReadAccess(PHINode *PHI) { addMemoryAccess(PHI->getParent(), PHI, MemoryAccess::READ, PHI, 1, true, PHI, ArrayRef(), ArrayRef(), - MemoryAccess::PHI); + ScopArrayInfo::MK_PHI); } void ScopInfo::buildScop(Region &R, DominatorTree &DT, AssumptionCache &AC) { Index: lib/CodeGen/BlockGenerators.cpp =================================================================== --- lib/CodeGen/BlockGenerators.cpp +++ lib/CodeGen/BlockGenerators.cpp @@ -332,14 +332,14 @@ } Value *BlockGenerator::getOrCreateAlloca(MemoryAccess &Access) { - if (Access.isPHI()) + if (Access.isPHIKind()) return getOrCreatePHIAlloca(Access.getBaseAddr()); else return getOrCreateScalarAlloca(Access.getBaseAddr()); } Value *BlockGenerator::getOrCreateAlloca(const ScopArrayInfo *Array) { - if (Array->isPHI()) + if (Array->isPHIKind()) return getOrCreatePHIAlloca(Array->getBasePtr()); else return getOrCreateScalarAlloca(Array->getBasePtr()); @@ -388,7 +388,7 @@ void BlockGenerator::generateScalarLoads(ScopStmt &Stmt, ValueMapT &BBMap) { for (MemoryAccess *MA : Stmt) { - if (MA->isExplicit() || MA->isWrite()) + if (MA->isArrayKind() || MA->isWrite()) continue; auto *Address = getOrCreateAlloca(*MA); @@ -453,7 +453,7 @@ "RegionGenerator"); for (MemoryAccess *MA : Stmt) { - if (MA->isExplicit() || MA->isRead()) + if (MA->isArrayKind() || MA->isRead()) continue; Value *Val = MA->getAccessValue(); @@ -484,7 +484,7 @@ auto &Array = Pair.second; if (Array->getNumberOfDimensions() != 0) continue; - if (Array->isPHI()) { + if (Array->isPHIKind()) { // For PHI nodes, the only values we need to store are the ones that // reach the PHI node from outside the region. In general there should // only be one such incoming edge and this edge should enter through @@ -578,7 +578,7 @@ if (Array->getNumberOfDimensions() != 0) continue; - if (Array->isPHI()) + if (Array->isPHIKind()) continue; auto *Inst = dyn_cast(Array->getBasePtr()); @@ -1188,7 +1188,7 @@ "function in the BlockGenerator"); for (MemoryAccess *MA : Stmt) { - if (MA->isExplicit() || MA->isRead()) + if (MA->isArrayKind() || MA->isRead()) continue; Instruction *ScalarInst = MA->getAccessInstruction(); @@ -1200,8 +1200,8 @@ auto SavedInsertionPoint = Builder.GetInsertPoint(); ValueMapT *LocalBBMap = &BBMap; - // Implicit writes induced by PHIs must be written in the incoming blocks. - if (MA->isPHI() || MA->isExitPHI()) { + // Scalar writes induced by PHIs must be written in the incoming blocks. + if (MA->isPHIKind() || MA->isExitPHIKind()) { BasicBlock *ExitingBB = ScalarInst->getParent(); BasicBlock *ExitingBBCopy = BlockMap[ExitingBB]; Builder.SetInsertPoint(ExitingBBCopy->getTerminator()); @@ -1217,7 +1217,7 @@ Builder.CreateStore(Val, Address); // Restore the insertion point if necessary. - if (MA->isPHI() || MA->isExitPHI()) + if (MA->isPHIKind() || MA->isExitPHIKind()) Builder.SetInsertPoint(SavedInsertBB, SavedInsertionPoint); } } Index: lib/CodeGen/IslNodeBuilder.cpp =================================================================== --- lib/CodeGen/IslNodeBuilder.cpp +++ lib/CodeGen/IslNodeBuilder.cpp @@ -219,7 +219,7 @@ } for (auto &Access : *Stmt) { - if (Access->isExplicit()) { + if (Access->isArrayKind()) { auto *BasePtr = Access->getScopArrayInfo()->getBasePtr(); if (Instruction *OpInst = dyn_cast(BasePtr)) if (Stmt->getParent()->getRegion().contains(OpInst)) @@ -1008,7 +1008,7 @@ return true; MemoryAccess *MA = MAs.front(); - assert(MA->isExplicit() && MA->isRead()); + assert(MA->isArrayKind() && MA->isRead()); // If the access function was already mapped, the preload of this equivalence // class was triggered earlier already and doesn't need to be done again. @@ -1023,7 +1023,7 @@ // If the base pointer of this class is dependent on another one we have to // make sure it was preloaded already. - auto *SAI = S.getScopArrayInfo(MA->getBaseAddr(), ScopArrayInfo::KIND_ARRAY); + auto *SAI = S.getScopArrayInfo(MA->getBaseAddr(), ScopArrayInfo::MK_Array); if (const auto *BaseIAClass = S.lookupInvariantEquivClass(SAI->getBasePtr())) if (!preloadInvariantEquivClass(*BaseIAClass)) return false; @@ -1075,7 +1075,7 @@ // For scalar derived SAIs we remap the alloca used for the derived value. if (BasePtr == MA->getAccessInstruction()) { - if (DerivedSAI->isPHI()) + if (DerivedSAI->isPHIKind()) PHIOpMap[BasePtr] = Alloca; else ScalarMap[BasePtr] = Alloca;