diff --git a/polly/include/polly/Support/VirtualInstruction.h b/polly/include/polly/Support/VirtualInstruction.h index bf7ebe4d67a9..81d954e093e4 100644 --- a/polly/include/polly/Support/VirtualInstruction.h +++ b/polly/include/polly/Support/VirtualInstruction.h @@ -99,7 +99,10 @@ public: /// @return The VirtualUse representing the same use as @p U. static VirtualUse create(Scop *S, const Use &U, LoopInfo *LI, bool Virtual); - /// Get a VirtualUse for any kind of use of a value within a statement. + /// Get a VirtualUse for uses within statements. + /// + /// It is assumed that the user is not a PHINode. Such uses are always + /// VirtualUse::Inter unless in a regions statement. /// /// @param S The Scop object. /// @param UserStmt The statement in which @p Val is used. Can be nullptr, in diff --git a/polly/lib/Support/VirtualInstruction.cpp b/polly/lib/Support/VirtualInstruction.cpp index 0e4718864896..29bb46b30466 100644 --- a/polly/lib/Support/VirtualInstruction.cpp +++ b/polly/lib/Support/VirtualInstruction.cpp @@ -21,13 +21,33 @@ using namespace llvm; VirtualUse VirtualUse ::create(Scop *S, const Use &U, LoopInfo *LI, bool Virtual) { auto *UserBB = getUseBlock(U); + Loop *UserScope = LI->getLoopFor(UserBB); Instruction *UI = dyn_cast(U.getUser()); - ScopStmt *UserStmt = nullptr; - if (PHINode *PHI = dyn_cast(UI)) - UserStmt = S->getLastStmtFor(PHI->getIncomingBlock(U)); - else - UserStmt = S->getStmtFor(UI); - auto *UserScope = LI->getLoopFor(UserBB); + ScopStmt *UserStmt = S->getStmtFor(UI); + + // Uses by PHI nodes are always reading values written by other statements, + // except it is within a region statement. + if (PHINode *PHI = dyn_cast(UI)) { + // Handle PHI in exit block. + if (S->getRegion().getExit() == PHI->getParent()) + return VirtualUse(UserStmt, U.get(), Inter, nullptr, nullptr); + + if (UserStmt->getEntryBlock() != PHI->getParent()) + return VirtualUse(UserStmt, U.get(), Intra, nullptr, nullptr); + + // The MemoryAccess is expected to be set if @p Virtual is true. + MemoryAccess *IncomingMA = nullptr; + if (Virtual) { + if (const ScopArrayInfo *SAI = + S->getScopArrayInfoOrNull(PHI, MemoryKind::PHI)) { + IncomingMA = S->getPHIRead(SAI); + assert(IncomingMA->getStatement() == UserStmt); + } + } + + return VirtualUse(UserStmt, U.get(), Inter, nullptr, IncomingMA); + } + return create(S, UserStmt, UserScope, U.get(), Virtual); }