@@ -281,6 +281,16 @@ struct PartiallyConstructedSafepointRecord {
281
281
RematerializedValueMapTy RematerializedValues;
282
282
};
283
283
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
+
284
294
} // end anonymous namespace
285
295
286
296
static ArrayRef<Use> GetDeoptBundleOperands (const CallBase *Call) {
@@ -2221,27 +2231,25 @@ static bool AreEquivalentPhiNodes(PHINode &OrigRootPhi, PHINode &AlternateRootPh
2221
2231
return true ;
2222
2232
}
2223
2233
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) {
2232
2240
const unsigned int ChainLengthThreshold = 10 ;
2233
2241
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 ;
2237
2248
2238
- for (Value *LiveValue: Info.LiveSet ) {
2239
- // For each live pointer find its defining chain
2249
+ // For each live pointer find its defining chain.
2240
2250
SmallVector<Instruction *, 3 > ChainToBase;
2241
- assert (PointerToBase.count (LiveValue));
2242
2251
Value *RootOfChain =
2243
- findRematerializableChainToBasePointer (ChainToBase,
2244
- LiveValue);
2252
+ findRematerializableChainToBasePointer (ChainToBase, Derived);
2245
2253
2246
2254
// Nothing to do, or chain is too long
2247
2255
if ( ChainToBase.size () == 0 ||
@@ -2250,9 +2258,9 @@ static void rematerializeLiveValues(CallBase *Call,
2250
2258
2251
2259
// Handle the scenario where the RootOfChain is not equal to the
2252
2260
// Base Value, but they are essentially the same phi values.
2253
- if (RootOfChain != PointerToBase[LiveValue ]) {
2261
+ if (RootOfChain != PointerToBase[Derived ]) {
2254
2262
PHINode *OrigRootPhi = dyn_cast<PHINode>(RootOfChain);
2255
- PHINode *AlternateRootPhi = dyn_cast<PHINode>(PointerToBase[LiveValue ]);
2263
+ PHINode *AlternateRootPhi = dyn_cast<PHINode>(PointerToBase[Derived ]);
2256
2264
if (!OrigRootPhi || !AlternateRootPhi)
2257
2265
continue ;
2258
2266
// PHI nodes that have the same incoming values, and belonging to the same
@@ -2266,33 +2274,61 @@ static void rematerializeLiveValues(CallBase *Call,
2266
2274
// deficiency in the findBasePointer algorithm.
2267
2275
if (!AreEquivalentPhiNodes (*OrigRootPhi, *AlternateRootPhi))
2268
2276
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));
2273
2277
}
2274
- // Compute cost of this chain
2278
+ // Compute cost of this chain.
2275
2279
InstructionCost Cost = chainToBasePointerCost (ChainToBase, TTI);
2276
2280
// TODO: We can also account for cases when we will be able to remove some
2277
2281
// of the rematerialized values by later optimization passes. I.e if
2278
2282
// we rematerialized several intersecting chains. Or if original values
2279
2283
// don't have any uses besides this statepoint.
2280
2284
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 ;
2281
2315
// For invokes we need to rematerialize each chain twice - for normal and
2282
2316
// for unwind basic blocks. Model this by multiplying cost by two.
2283
- if (isa<InvokeInst>(Call)) {
2317
+ if (isa<InvokeInst>(Call))
2284
2318
Cost *= 2 ;
2285
- }
2286
- // If it's too expensive - skip it
2319
+
2320
+ // If it's too expensive - skip it.
2287
2321
if (Cost >= RematerializationThreshold)
2288
2322
continue ;
2289
2323
2290
2324
// Remove value from the live set
2291
2325
LiveValuesToBeDeleted.push_back (LiveValue);
2292
2326
2293
- // Clone instructions and record them inside "Info" structure
2327
+ // Clone instructions and record them inside "Info" structure.
2294
2328
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.
2296
2332
std::reverse (ChainToBase.begin (), ChainToBase.end ());
2297
2333
2298
2334
// Utility function which clones all instructions from "ChainToBase"
@@ -2352,7 +2388,7 @@ static void rematerializeLiveValues(CallBase *Call,
2352
2388
Instruction *InsertBefore = Call->getNextNode ();
2353
2389
assert (InsertBefore);
2354
2390
Instruction *RematerializedValue = rematerializeChain (
2355
- InsertBefore, RootOfChain, PointerToBase[LiveValue]);
2391
+ InsertBefore, Record. RootOfChain , PointerToBase[LiveValue]);
2356
2392
Info.RematerializedValues [RematerializedValue] = LiveValue;
2357
2393
} else {
2358
2394
auto *Invoke = cast<InvokeInst>(Call);
@@ -2363,9 +2399,9 @@ static void rematerializeLiveValues(CallBase *Call,
2363
2399
&*Invoke->getUnwindDest ()->getFirstInsertionPt ();
2364
2400
2365
2401
Instruction *NormalRematerializedValue = rematerializeChain (
2366
- NormalInsertBefore, RootOfChain, PointerToBase[LiveValue]);
2402
+ NormalInsertBefore, Record. RootOfChain , PointerToBase[LiveValue]);
2367
2403
Instruction *UnwindRematerializedValue = rematerializeChain (
2368
- UnwindInsertBefore, RootOfChain, PointerToBase[LiveValue]);
2404
+ UnwindInsertBefore, Record. RootOfChain , PointerToBase[LiveValue]);
2369
2405
2370
2406
Info.RematerializedValues [NormalRematerializedValue] = LiveValue;
2371
2407
Info.RematerializedValues [UnwindRematerializedValue] = LiveValue;
@@ -2563,11 +2599,16 @@ static bool insertParsePoints(Function &F, DominatorTree &DT,
2563
2599
2564
2600
Holders.clear ();
2565
2601
2602
+ // Compute the cost of possible re-materialization of derived pointers.
2603
+ RematCandTy RematerizationCandidates;
2604
+ findRematerializationCandidates (PointerToBase, RematerizationCandidates, TTI);
2605
+
2566
2606
// In order to reduce live set of statepoint we might choose to rematerialize
2567
2607
// some values instead of relocating them. This is purely an optimization and
2568
2608
// does not influence correctness.
2569
2609
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);
2571
2612
2572
2613
// We need this to safely RAUW and delete call or invoke return values that
2573
2614
// may themselves be live over a statepoint. For details, please see usage in
0 commit comments