Index: include/polly/ScopInfo.h =================================================================== --- include/polly/ScopInfo.h +++ include/polly/ScopInfo.h @@ -494,8 +494,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 instruction 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. @@ -830,6 +831,10 @@ /// @brief Mapping from instructions to (scalar) memory accesses. DenseMap InstructionToAccess; + /// @brief The set of values defined elsewhere 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; @@ -1013,6 +1018,12 @@ return ValueWrites.lookup(Inst); } + /// @brief Return the MemoryAccess that reloads a value, or nullptr if not + /// existing, respectively not yet added. + MemoryAccess *lookupValueReadOf(Value *Inst) const { + return ValueReads.lookup(Inst); + } + void setBasicBlock(BasicBlock *Block) { // TODO: Handle the case where the statement is a region statement, thus // the entry block was split and needs to be changed in the region R. @@ -1931,33 +1942,18 @@ /// The access will be created at the @p Value's definition. /// /// @param Value The value to be written. - /// @see addValueReadAccess() + /// @see ensureValueRead() /// @see ScopArrayInfo::MemoryKind void ensureValueWrite(Instruction *Value); - /// @brief Create a MemoryAccess for reloading an llvm::Value. + /// @brief Ensure an llvm::Value is available in the BB's statement, 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 ensureValueWrite() - /// @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 ensureValueWrite() + /// @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 ensureValueRead(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 @@ -525,8 +525,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); } @@ -913,6 +914,11 @@ assert(!ValueWrites.lookup(AccessVal)); ValueWrites[AccessVal] = Access; + } else if (Access->isValueKind() && Access->isRead()) { + Value *AccessVal = Access->getAccessValue(); + assert(!ValueReads.lookup(AccessVal)); + + ValueReads[AccessVal] = Access; } MemAccs.push_back(Access); @@ -1474,6 +1480,10 @@ void ScopStmt::removeMemoryAccesses(MemoryAccessList &InvMAs) { // Remove all memory accesses in @p InvMAs from this statement // together with all scalar accesses that were caused by them. + // MK_Value READS have no access instruction, hence would not be removed by + // this function. However, it is only used for invariant LoadInst accesses, + // its arguments are always affine, hence synthesizable, and therefore there + // are not MK_Value READ accesses. for (MemoryAccess *MA : InvMAs) { auto Predicate = [&](MemoryAccess *Acc) { return Acc->getAccessInstruction() == MA->getAccessInstruction(); @@ -3558,11 +3568,11 @@ // OpBB if the definition is not in OpBB. if (scop->getStmtForBasicBlock(OpIBB) != scop->getStmtForBasicBlock(OpBB)) { - addValueReadAccess(OpI, PHI, OpBB); + ensureValueRead(OpI, OpBB); ensureValueWrite(OpI); } } else if (ModelReadOnlyScalars && !isa(Op)) { - addValueReadAccess(Op, PHI, OpBB); + ensureValueRead(Op, OpBB); } addPHIWriteAccess(PHI, OpBB, Op, IsExitBlock); @@ -3662,7 +3672,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); + ensureValueRead(Inst, UI->getParent()); } if (ModelReadOnlyScalars && !isa(Inst)) { @@ -3677,7 +3687,7 @@ if (isa(Op)) continue; - addValueReadAccess(Op, Inst); + ensureValueRead(Op, Inst->getParent()); } } @@ -3951,15 +3961,19 @@ true, Value, ArrayRef(), 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::ensureValueRead(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); }