Skip to content

Commit 66f1c6f

Browse files
author
Serguei Katkov
committed
[RS4GC] Extract rematerilazable candidate search. NFC.
Finding re-materialization chain for derived pointer does not depend on call site. To avoid this finding for each call site it can be extracted in a separate routine. Reviewers: reames, dantrushin Reviewed By: reames Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D118676
1 parent 374f5f0 commit 66f1c6f

File tree

1 file changed

+73
-32
lines changed

1 file changed

+73
-32
lines changed

llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp

Lines changed: 73 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,16 @@ struct PartiallyConstructedSafepointRecord {
281281
RematerializedValueMapTy RematerializedValues;
282282
};
283283

284+
struct RematerizlizationCandidateRecord {
285+
// Chain from derived pointer to base.
286+
SmallVector<Instruction *, 3> ChainToBase;
287+
// Original base.
288+
Value *RootOfChain;
289+
// Cost of chain.
290+
InstructionCost Cost;
291+
};
292+
using RematCandTy = MapVector<Value *, RematerizlizationCandidateRecord>;
293+
284294
} // end anonymous namespace
285295

286296
static ArrayRef<Use> GetDeoptBundleOperands(const CallBase *Call) {
@@ -2221,27 +2231,25 @@ static bool AreEquivalentPhiNodes(PHINode &OrigRootPhi, PHINode &AlternateRootPh
22212231
return true;
22222232
}
22232233

2224-
// From the statepoint live set pick values that are cheaper to recompute then
2225-
// to relocate. Remove this values from the live set, rematerialize them after
2226-
// statepoint and record them in "Info" structure. Note that similar to
2227-
// relocated values we don't do any user adjustments here.
2228-
static void rematerializeLiveValues(CallBase *Call,
2229-
PartiallyConstructedSafepointRecord &Info,
2230-
PointerToBaseTy &PointerToBase,
2231-
TargetTransformInfo &TTI) {
2234+
// Find derived pointers that can be recomputed cheap enough and fill
2235+
// RematerizationCandidates with such candidates.
2236+
static void
2237+
findRematerializationCandidates(PointerToBaseTy PointerToBase,
2238+
RematCandTy &RematerizationCandidates,
2239+
TargetTransformInfo &TTI) {
22322240
const unsigned int ChainLengthThreshold = 10;
22332241

2234-
// Record values we are going to delete from this statepoint live set.
2235-
// We can not di this in following loop due to iterator invalidation.
2236-
SmallVector<Value *, 32> LiveValuesToBeDeleted;
2242+
for (auto P2B : PointerToBase) {
2243+
auto *Derived = P2B.first;
2244+
auto *Base = P2B.second;
2245+
// Consider only derived pointers.
2246+
if (Derived == Base)
2247+
continue;
22372248

2238-
for (Value *LiveValue: Info.LiveSet) {
2239-
// For each live pointer find its defining chain
2249+
// For each live pointer find its defining chain.
22402250
SmallVector<Instruction *, 3> ChainToBase;
2241-
assert(PointerToBase.count(LiveValue));
22422251
Value *RootOfChain =
2243-
findRematerializableChainToBasePointer(ChainToBase,
2244-
LiveValue);
2252+
findRematerializableChainToBasePointer(ChainToBase, Derived);
22452253

22462254
// Nothing to do, or chain is too long
22472255
if ( ChainToBase.size() == 0 ||
@@ -2250,9 +2258,9 @@ static void rematerializeLiveValues(CallBase *Call,
22502258

22512259
// Handle the scenario where the RootOfChain is not equal to the
22522260
// Base Value, but they are essentially the same phi values.
2253-
if (RootOfChain != PointerToBase[LiveValue]) {
2261+
if (RootOfChain != PointerToBase[Derived]) {
22542262
PHINode *OrigRootPhi = dyn_cast<PHINode>(RootOfChain);
2255-
PHINode *AlternateRootPhi = dyn_cast<PHINode>(PointerToBase[LiveValue]);
2263+
PHINode *AlternateRootPhi = dyn_cast<PHINode>(PointerToBase[Derived]);
22562264
if (!OrigRootPhi || !AlternateRootPhi)
22572265
continue;
22582266
// PHI nodes that have the same incoming values, and belonging to the same
@@ -2266,33 +2274,61 @@ static void rematerializeLiveValues(CallBase *Call,
22662274
// deficiency in the findBasePointer algorithm.
22672275
if (!AreEquivalentPhiNodes(*OrigRootPhi, *AlternateRootPhi))
22682276
continue;
2269-
// Now that the phi nodes are proved to be the same, assert that
2270-
// findBasePointer's newly generated AlternateRootPhi is present in the
2271-
// liveset of the call.
2272-
assert(Info.LiveSet.count(AlternateRootPhi));
22732277
}
2274-
// Compute cost of this chain
2278+
// Compute cost of this chain.
22752279
InstructionCost Cost = chainToBasePointerCost(ChainToBase, TTI);
22762280
// TODO: We can also account for cases when we will be able to remove some
22772281
// of the rematerialized values by later optimization passes. I.e if
22782282
// we rematerialized several intersecting chains. Or if original values
22792283
// don't have any uses besides this statepoint.
22802284

2285+
// Ok, there is a candidate.
2286+
RematerizlizationCandidateRecord Record;
2287+
Record.ChainToBase = ChainToBase;
2288+
Record.RootOfChain = RootOfChain;
2289+
Record.Cost = Cost;
2290+
RematerizationCandidates.insert({ Derived, Record });
2291+
}
2292+
}
2293+
2294+
// From the statepoint live set pick values that are cheaper to recompute then
2295+
// to relocate. Remove this values from the live set, rematerialize them after
2296+
// statepoint and record them in "Info" structure. Note that similar to
2297+
// relocated values we don't do any user adjustments here.
2298+
static void rematerializeLiveValues(CallBase *Call,
2299+
PartiallyConstructedSafepointRecord &Info,
2300+
PointerToBaseTy &PointerToBase,
2301+
RematCandTy &RematerizationCandidates,
2302+
TargetTransformInfo &TTI) {
2303+
// Record values we are going to delete from this statepoint live set.
2304+
// We can not di this in following loop due to iterator invalidation.
2305+
SmallVector<Value *, 32> LiveValuesToBeDeleted;
2306+
2307+
for (Value *LiveValue : Info.LiveSet) {
2308+
auto It = RematerizationCandidates.find(LiveValue);
2309+
if (It == RematerizationCandidates.end())
2310+
continue;
2311+
2312+
RematerizlizationCandidateRecord &Record = It->second;
2313+
2314+
InstructionCost Cost = Record.Cost;
22812315
// For invokes we need to rematerialize each chain twice - for normal and
22822316
// for unwind basic blocks. Model this by multiplying cost by two.
2283-
if (isa<InvokeInst>(Call)) {
2317+
if (isa<InvokeInst>(Call))
22842318
Cost *= 2;
2285-
}
2286-
// If it's too expensive - skip it
2319+
2320+
// If it's too expensive - skip it.
22872321
if (Cost >= RematerializationThreshold)
22882322
continue;
22892323

22902324
// Remove value from the live set
22912325
LiveValuesToBeDeleted.push_back(LiveValue);
22922326

2293-
// Clone instructions and record them inside "Info" structure
2327+
// Clone instructions and record them inside "Info" structure.
22942328

2295-
// Walk backwards to visit top-most instructions first
2329+
// For each live pointer find get its defining chain.
2330+
SmallVector<Instruction *, 3> ChainToBase = Record.ChainToBase;
2331+
// Walk backwards to visit top-most instructions first.
22962332
std::reverse(ChainToBase.begin(), ChainToBase.end());
22972333

22982334
// Utility function which clones all instructions from "ChainToBase"
@@ -2352,7 +2388,7 @@ static void rematerializeLiveValues(CallBase *Call,
23522388
Instruction *InsertBefore = Call->getNextNode();
23532389
assert(InsertBefore);
23542390
Instruction *RematerializedValue = rematerializeChain(
2355-
InsertBefore, RootOfChain, PointerToBase[LiveValue]);
2391+
InsertBefore, Record.RootOfChain, PointerToBase[LiveValue]);
23562392
Info.RematerializedValues[RematerializedValue] = LiveValue;
23572393
} else {
23582394
auto *Invoke = cast<InvokeInst>(Call);
@@ -2363,9 +2399,9 @@ static void rematerializeLiveValues(CallBase *Call,
23632399
&*Invoke->getUnwindDest()->getFirstInsertionPt();
23642400

23652401
Instruction *NormalRematerializedValue = rematerializeChain(
2366-
NormalInsertBefore, RootOfChain, PointerToBase[LiveValue]);
2402+
NormalInsertBefore, Record.RootOfChain, PointerToBase[LiveValue]);
23672403
Instruction *UnwindRematerializedValue = rematerializeChain(
2368-
UnwindInsertBefore, RootOfChain, PointerToBase[LiveValue]);
2404+
UnwindInsertBefore, Record.RootOfChain, PointerToBase[LiveValue]);
23692405

23702406
Info.RematerializedValues[NormalRematerializedValue] = LiveValue;
23712407
Info.RematerializedValues[UnwindRematerializedValue] = LiveValue;
@@ -2563,11 +2599,16 @@ static bool insertParsePoints(Function &F, DominatorTree &DT,
25632599

25642600
Holders.clear();
25652601

2602+
// Compute the cost of possible re-materialization of derived pointers.
2603+
RematCandTy RematerizationCandidates;
2604+
findRematerializationCandidates(PointerToBase, RematerizationCandidates, TTI);
2605+
25662606
// In order to reduce live set of statepoint we might choose to rematerialize
25672607
// some values instead of relocating them. This is purely an optimization and
25682608
// does not influence correctness.
25692609
for (size_t i = 0; i < Records.size(); i++)
2570-
rematerializeLiveValues(ToUpdate[i], Records[i], PointerToBase, TTI);
2610+
rematerializeLiveValues(ToUpdate[i], Records[i], PointerToBase,
2611+
RematerizationCandidates, TTI);
25712612

25722613
// We need this to safely RAUW and delete call or invoke return values that
25732614
// may themselves be live over a statepoint. For details, please see usage in

0 commit comments

Comments
 (0)