Index: include/polly/ScopInfo.h =================================================================== --- include/polly/ScopInfo.h +++ include/polly/ScopInfo.h @@ -493,8 +493,9 @@ /// 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. + /// access is nullptr because generally there can be multiple instructions in + /// the statement using the same llvm::Value. The access instruction of a + /// write access is the instruction that defines the llvm::Value. Instruction *AccessInstruction; /// @brief The value associated with this memory access. @@ -829,6 +830,10 @@ /// @brief Mapping from instructions to (scalar) memory accesses. DenseMap InstructionToAccess; + /// @brief The set of values defined elsewehere required in this ScopStmt and + /// their MK_Value READ MemoryAccesses. + DenseMap ValueReads; + /// @brief The set of values defined in this ScopStmt that are required /// elsewhere, mapped to their MK_Value WRITE MemoryAccesses. DenseMap ValueWrites; @@ -991,6 +996,12 @@ return It->getSecond()->empty() ? nullptr : It->getSecond()->front(); } + /// @brief Return the MemoryAccess that reloads a value, or nullptr if not + /// (yet) added. + MemoryAccess *lookupValueReadOf(Value *Inst) const { + return ValueReads.lookup(Inst); + } + /// @brief Return the MemoryAccess that writes the value of an instruction /// defined in this statement, or nullptr if not (yet) added. MemoryAccess *lookupValueWriteOf(Instruction *Inst) const { @@ -1917,33 +1928,18 @@ /// The access will be created at the @p Value's definition. /// /// @param Value The value to be written. - /// @see addValueReadAccess() + /// @see ensureValueReload() /// @see ScopArrayInfo::MemoryKind void ensureValueStore(Instruction *Value); - /// @brief Create a MemoryAccess for reloading an llvm::Value. + /// @brief Ensure an llvm::Value is available in the BB's statment, creating a + /// MemoryAccess for reloading it if necessary. /// - /// Use this overload only for non-PHI instructions. - /// - /// @param Value The scalar expected to be loaded. - /// @param User User of the scalar; this is where the access is added. - /// @see addValueWriteAccess() - /// @see ScopArrayInfo::MemoryKind - void addValueReadAccess(Value *Value, Instruction *User); - - /// @brief Create a MemoryAccess for reloading an llvm::Value. - /// - /// This is for PHINodes using the scalar. As we model it, the used value must - /// be available at the incoming block instead of when hitting the - /// instruction. - /// - /// @param Value The scalar expected to be loaded. - /// @param User The PHI node referencing @p Value. - /// @param UserBB Incoming block for the incoming @p Value. - /// @see addPHIWriteAccess() - /// @see addValueWriteAccess() + /// @param Value The value expected to be loaded. + /// @param UserBB Where to reload the value. + /// @see ensureValueStore() /// @see ScopArrayInfo::MemoryKind - void addValueReadAccess(Value *Value, PHINode *User, BasicBlock *UserBB); + void ensureValueReload(Value *Value, BasicBlock *UserBB); /// @brief Create a write MemoryAccess for the incoming block of a phi node. /// Index: lib/Analysis/ScopInfo.cpp =================================================================== --- lib/Analysis/ScopInfo.cpp +++ lib/Analysis/ScopInfo.cpp @@ -520,8 +520,9 @@ // bail out more often than strictly necessary. Outside = isl_set_remove_divs(Outside); Outside = isl_set_complement(Outside); - Statement->getParent()->addAssumption(INBOUNDS, Outside, - getAccessInstruction()->getDebugLoc()); + Statement->getParent()->addAssumption( + INBOUNDS, Outside, + getAccessInstruction() ? getAccessInstruction()->getDebugLoc() : nullptr); isl_space_free(Space); } @@ -904,6 +905,11 @@ if (!MAL) MAL = new MemoryAccessList(); MAL->emplace_front(Access); + } else if (Access->isValueKind() && Access->isRead()) { + Value *AccessVal = Access->getAccessValue(); + assert(!ValueReads.lookup(AccessVal)); + + ValueReads[AccessVal] = Access; } else if (Access->isValueKind() && Access->isWrite()) { Instruction *AccessVal = cast(Access->getAccessValue()); assert(Parent.getStmtForBasicBlock(AccessVal->getParent()) == this); @@ -3551,11 +3557,11 @@ // OpBB if the definition is not in OpBB. if (scop->getStmtForBasicBlock(OpIBB) != scop->getStmtForBasicBlock(OpBB)) { - addValueReadAccess(OpI, PHI, OpBB); + ensureValueReload(OpI, OpBB); ensureValueStore(OpI); } } else if (ModelReadOnlyScalars && !isa(Op)) { - addValueReadAccess(Op, PHI, OpBB); + ensureValueReload(Op, OpBB); } addPHIWriteAccess(PHI, OpBB, Op, IsExitBlock); @@ -3655,7 +3661,7 @@ // Do not build a read access that is not in the current SCoP // Use the def instruction as base address of the MemoryAccess, so that it // will become the name of the scalar access in the polyhedral form. - addValueReadAccess(Inst, UI); + ensureValueReload(Inst, UI->getParent()); } if (ModelReadOnlyScalars && !isa(Inst)) { @@ -3670,7 +3676,7 @@ if (isa(Op)) continue; - addValueReadAccess(Op, Inst); + ensureValueReload(Op, Inst->getParent()); } } @@ -3946,15 +3952,19 @@ ArrayRef(), ScopArrayInfo::MK_Value); } -void ScopInfo::addValueReadAccess(Value *Value, Instruction *User) { - assert(!isa(User)); - addMemoryAccess(User->getParent(), User, MemoryAccess::READ, Value, 1, true, - Value, ArrayRef(), ArrayRef(), - ScopArrayInfo::MK_Value); -} -void ScopInfo::addValueReadAccess(Value *Value, PHINode *User, - BasicBlock *UserBB) { - addMemoryAccess(UserBB, User, MemoryAccess::READ, Value, 1, true, Value, +void ScopInfo::ensureValueReload(Value *Value, BasicBlock *UserBB) { + ScopStmt *UserStmt = scop->getStmtForBasicBlock(UserBB); + + // We do not model uses outside the scop. + if (!UserStmt) + return; + + // Do not create another MemoryAccess for reloading the value if one already + // exists. + if (UserStmt->lookupValueReadOf(Value)) + return; + + addMemoryAccess(UserBB, nullptr, MemoryAccess::READ, Value, 1, true, Value, ArrayRef(), ArrayRef(), ScopArrayInfo::MK_Value); }