[StatepointsForGC] Rematerialize in the presence of PHIs
Summary:
While walking the use chain for identifying rematerializable values in RS4GC,
add the case where the current value and base value are the same PHI nodes.
This will aid rematerialization of geps and casts instead of relocating.
Reviewers: sanjoy, reames, igor
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D23920
llvm-svn: 279975
diff --git a/llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp b/llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp
index 9179834..6726e0e 100644
--- a/llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp
+++ b/llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp
@@ -1797,6 +1797,41 @@
return true;
}
+ // Check for same values, when both BaseValue and CurrentValue are phi nodes.
+ // PHI nodes that have the same incoming values, and belonging to the same
+ // basic blocks are essentially the same SSA value. Such an example of same
+ // BaseValue, CurrentValue phis is created by findBasePointer, when a phi has
+ // incoming values with different base pointers. This phi is marked as
+ // conflict, and hence an additional phi with the same incoming values get
+ // generated. We need to identify the BaseValue (.base version of phi) and
+ // CurrentValue (the phi node itself) as the same, so that we can
+ // rematerialize the gep and casts below.
+ if (PHINode *CurrentPhi = dyn_cast<PHINode>(CurrentValue))
+ if (PHINode *BasePhi = dyn_cast<PHINode>(BaseValue)) {
+ auto PhiNum = CurrentPhi->getNumIncomingValues();
+ if (PhiNum != BasePhi->getNumIncomingValues() ||
+ CurrentPhi->getParent() != BasePhi->getParent())
+ return false;
+ // Map of incoming values and their corresponding basic blocks of
+ // CurrentPhi.
+ SmallDenseMap<Value *, BasicBlock *, 8> CurrentIncomingValues;
+ for (unsigned i = 0; i < PhiNum; i++)
+ CurrentIncomingValues[CurrentPhi->getIncomingValue(i)] =
+ CurrentPhi->getIncomingBlock(i);
+
+ // Both current and base PHIs should have same incoming values and
+ // the same basic blocks corresponding to the incoming values.
+ for (unsigned i = 0; i < PhiNum; i++) {
+ auto CIVI = CurrentIncomingValues.find(BasePhi->getIncomingValue(i));
+ if (CIVI == CurrentIncomingValues.end())
+ return false;
+ BasicBlock *CurrentIncomingBB = CIVI->second;
+ if (CurrentIncomingBB != BasePhi->getIncomingBlock(i))
+ return false;
+ }
+ return true;
+ }
+
if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(CurrentValue)) {
ChainToBase.push_back(GEP);
return findRematerializableChainToBasePointer(ChainToBase,