Index: include/polly/ScopInfo.h =================================================================== --- include/polly/ScopInfo.h +++ include/polly/ScopInfo.h @@ -830,6 +830,10 @@ /// @brief Mapping from instructions to (scalar) memory accesses. DenseMap InstructionToAccess; + /// @brief The set of values defined in this ScopStmt that are required + /// elsewhere, mapped to their MK_Value WRITE MemoryAccesses. + DenseMap ValueWrites; + //@} /// @brief A SCoP statement represents either a basic block (affine/precise @@ -1000,6 +1004,15 @@ return NumAccesses; } + /// @brief Return the MemoryAccess that writes the value of an instruction + /// defined in this statement, or nullptr if not existing, respectively + /// not yet added. + MemoryAccess *lookupValueWriteOf(Instruction *Inst) const { + assert((isRegionStmt() && R->contains(Inst)) || + (!isRegionStmt() && Inst->getParent() == BB)); + return ValueWrites.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. @@ -1920,7 +1933,7 @@ /// @param Value The value to be written. /// @see addValueReadAccess() /// @see ScopArrayInfo::MemoryKind - void addValueWriteAccess(Instruction *Value); + void ensureValueWrite(Instruction *Value); /// @brief Create a MemoryAccess for reloading an llvm::Value. /// @@ -1928,7 +1941,7 @@ /// /// @param Value The scalar expected to be loaded. /// @param User User of the scalar; this is where the access is added. - /// @see addValueWriteAccess() + /// @see ensureValueWrite() /// @see ScopArrayInfo::MemoryKind void addValueReadAccess(Value *Value, Instruction *User); @@ -1942,7 +1955,7 @@ /// @param User The PHI node referencing @p Value. /// @param UserBB Incoming block for the incoming @p Value. /// @see addPHIWriteAccess() - /// @see addValueWriteAccess() + /// @see ensureValueWrite() /// @see ScopArrayInfo::MemoryKind void addValueReadAccess(Value *Value, PHINode *User, BasicBlock *UserBB); Index: lib/Analysis/ScopInfo.cpp =================================================================== --- lib/Analysis/ScopInfo.cpp +++ lib/Analysis/ScopInfo.cpp @@ -907,6 +907,12 @@ if (Access->isArrayKind()) { MemoryAccessList &MAL = InstructionToAccess[AccessInst]; MAL.emplace_front(Access); + } else if (Access->isValueKind() && Access->isWrite()) { + Instruction *AccessVal = cast(Access->getAccessValue()); + assert(Parent.getStmtForBasicBlock(AccessVal->getParent()) == this); + assert(!ValueWrites.lookup(AccessVal)); + + ValueWrites[AccessVal] = Access; } MemAccs.push_back(Access); @@ -3553,7 +3559,7 @@ if (scop->getStmtForBasicBlock(OpIBB) != scop->getStmtForBasicBlock(OpBB)) { addValueReadAccess(OpI, PHI, OpBB); - addValueWriteAccess(OpI); + ensureValueWrite(OpI); } } else if (ModelReadOnlyScalars && !isa(Op)) { addValueReadAccess(Op, PHI, OpBB); @@ -3872,7 +3878,7 @@ if (buildScalarDependences(Inst, &R, NonAffineSubRegion)) { if (!isa(Inst)) - addValueWriteAccess(Inst); + ensureValueWrite(Inst); } } } @@ -3930,7 +3936,17 @@ ElemBytes, IsAffine, AccessValue, Subscripts, Sizes, ScopArrayInfo::MK_Array); } -void ScopInfo::addValueWriteAccess(Instruction *Value) { +void ScopInfo::ensureValueWrite(Instruction *Value) { + ScopStmt *Stmt = scop->getStmtForBasicBlock(Value->getParent()); + + // Value not defined within this SCoP. + if (!Stmt) + return; + + // Do not process further if the value is already written. + if (Stmt->lookupValueWriteOf(Value)) + return; + addMemoryAccess(Value->getParent(), Value, MemoryAccess::MUST_WRITE, Value, 1, true, Value, ArrayRef(), ArrayRef(), ScopArrayInfo::MK_Value); Index: test/ScopInfo/phi_scalar_simple_1.ll =================================================================== --- test/ScopInfo/phi_scalar_simple_1.ll +++ test/ScopInfo/phi_scalar_simple_1.ll @@ -29,9 +29,6 @@ ; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1] ; CHECK: [N] -> { Stmt_for_cond[i0] -> MemRef_x_addr_0[] }; ; CHECK-NOT: Access -; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1] -; CHECK: [N] -> { Stmt_for_cond[i0] -> MemRef_x_addr_0[] }; -; CHECK-NOT: Access %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc4 ], [ 1, %entry ] %x.addr.0 = phi i32 [ %x, %entry ], [ %x.addr.1.lcssa, %for.inc4 ] %cmp = icmp slt i64 %indvars.iv, %tmp Index: test/ScopInfo/phi_scalar_simple_2.ll =================================================================== --- test/ScopInfo/phi_scalar_simple_2.ll +++ test/ScopInfo/phi_scalar_simple_2.ll @@ -28,9 +28,6 @@ ; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] ; CHECK: [N, c] -> { Stmt_for_cond[i0] -> MemRef_A[i0] }; ; CHECK-NOT: Access -; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1] -; CHECK: [N, c] -> { Stmt_for_cond[i0] -> MemRef_x_addr_0[] }; -; CHECK-NOT: Access %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc5 ], [ 0, %entry ] %x.addr.0 = phi i32 [ %x, %entry ], [ %x.addr.1, %for.inc5 ] %arrayidx2 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv @@ -58,12 +55,6 @@ ; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 1] ; CHECK: [N, c] -> { Stmt_for_cond1[i0, i1] -> MemRef_x_addr_1__phi[] }; ; CHECK-NOT: Access -; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1] -; CHECK: [N, c] -> { Stmt_for_cond1[i0, i1] -> MemRef_x_addr_1[] }; -; CHECK-NOT: Access -; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1] -; CHECK: [N, c] -> { Stmt_for_cond1[i0, i1] -> MemRef_x_addr_1[] }; -; CHECK-NOT: Access %x.addr.1 = phi i32 [ %x.addr.0, %for.body ], [ %x.addr.2, %for.inc ] %j.0 = phi i32 [ 0, %for.body ], [ %inc, %for.inc ] %exitcond = icmp ne i32 %j.0, %N