@@ -1400,6 +1400,61 @@ static void recomputeLiveInValues(
14001400 }
14011401}
14021402
1403+ // Utility function which clones all instructions from "ChainToBase"
1404+ // and inserts them before "InsertBefore". Returns rematerialized value
1405+ // which should be used after statepoint.
1406+ static Instruction *rematerializeChain (ArrayRef<Instruction *> ChainToBase,
1407+ Instruction *InsertBefore,
1408+ Value *RootOfChain,
1409+ Value *AlternateLiveBase) {
1410+ Instruction *LastClonedValue = nullptr ;
1411+ Instruction *LastValue = nullptr ;
1412+ // Walk backwards to visit top-most instructions first.
1413+ for (Instruction *Instr :
1414+ make_range (ChainToBase.rbegin (), ChainToBase.rend ())) {
1415+ // Only GEP's and casts are supported as we need to be careful to not
1416+ // introduce any new uses of pointers not in the liveset.
1417+ // Note that it's fine to introduce new uses of pointers which were
1418+ // otherwise not used after this statepoint.
1419+ assert (isa<GetElementPtrInst>(Instr) || isa<CastInst>(Instr));
1420+
1421+ Instruction *ClonedValue = Instr->clone ();
1422+ ClonedValue->insertBefore (InsertBefore);
1423+ ClonedValue->setName (Instr->getName () + " .remat" );
1424+
1425+ // If it is not first instruction in the chain then it uses previously
1426+ // cloned value. We should update it to use cloned value.
1427+ if (LastClonedValue) {
1428+ assert (LastValue);
1429+ ClonedValue->replaceUsesOfWith (LastValue, LastClonedValue);
1430+ #ifndef NDEBUG
1431+ for (auto *OpValue : ClonedValue->operand_values ()) {
1432+ // Assert that cloned instruction does not use any instructions from
1433+ // this chain other than LastClonedValue
1434+ assert (!is_contained (ChainToBase, OpValue) &&
1435+ " incorrect use in rematerialization chain" );
1436+ // Assert that the cloned instruction does not use the RootOfChain
1437+ // or the AlternateLiveBase.
1438+ assert (OpValue != RootOfChain && OpValue != AlternateLiveBase);
1439+ }
1440+ #endif
1441+ } else {
1442+ // For the first instruction, replace the use of unrelocated base i.e.
1443+ // RootOfChain/OrigRootPhi, with the corresponding PHI present in the
1444+ // live set. They have been proved to be the same PHI nodes. Note
1445+ // that the *only* use of the RootOfChain in the ChainToBase list is
1446+ // the first Value in the list.
1447+ if (RootOfChain != AlternateLiveBase)
1448+ ClonedValue->replaceUsesOfWith (RootOfChain, AlternateLiveBase);
1449+ }
1450+
1451+ LastClonedValue = ClonedValue;
1452+ LastValue = Instr;
1453+ }
1454+ assert (LastClonedValue);
1455+ return LastClonedValue;
1456+ }
1457+
14031458// When inserting gc.relocate and gc.result calls, we need to ensure there are
14041459// no uses of the original value / return value between the gc.statepoint and
14051460// the gc.relocate / gc.result call. One case which can arise is a phi node
@@ -2415,69 +2470,14 @@ static void rematerializeLiveValues(CallBase *Call,
24152470
24162471 // Clone instructions and record them inside "Info" structure.
24172472
2418- // For each live pointer find get its defining chain.
2419- SmallVector<Instruction *, 3 > ChainToBase = Record.ChainToBase ;
2420- // Walk backwards to visit top-most instructions first.
2421- std::reverse (ChainToBase.begin (), ChainToBase.end ());
2422-
2423- // Utility function which clones all instructions from "ChainToBase"
2424- // and inserts them before "InsertBefore". Returns rematerialized value
2425- // which should be used after statepoint.
2426- auto rematerializeChain = [&ChainToBase](
2427- Instruction *InsertBefore, Value *RootOfChain, Value *AlternateLiveBase) {
2428- Instruction *LastClonedValue = nullptr ;
2429- Instruction *LastValue = nullptr ;
2430- for (Instruction *Instr: ChainToBase) {
2431- // Only GEP's and casts are supported as we need to be careful to not
2432- // introduce any new uses of pointers not in the liveset.
2433- // Note that it's fine to introduce new uses of pointers which were
2434- // otherwise not used after this statepoint.
2435- assert (isa<GetElementPtrInst>(Instr) || isa<CastInst>(Instr));
2436-
2437- Instruction *ClonedValue = Instr->clone ();
2438- ClonedValue->insertBefore (InsertBefore);
2439- ClonedValue->setName (Instr->getName () + " .remat" );
2440-
2441- // If it is not first instruction in the chain then it uses previously
2442- // cloned value. We should update it to use cloned value.
2443- if (LastClonedValue) {
2444- assert (LastValue);
2445- ClonedValue->replaceUsesOfWith (LastValue, LastClonedValue);
2446- #ifndef NDEBUG
2447- for (auto *OpValue : ClonedValue->operand_values ()) {
2448- // Assert that cloned instruction does not use any instructions from
2449- // this chain other than LastClonedValue
2450- assert (!is_contained (ChainToBase, OpValue) &&
2451- " incorrect use in rematerialization chain" );
2452- // Assert that the cloned instruction does not use the RootOfChain
2453- // or the AlternateLiveBase.
2454- assert (OpValue != RootOfChain && OpValue != AlternateLiveBase);
2455- }
2456- #endif
2457- } else {
2458- // For the first instruction, replace the use of unrelocated base i.e.
2459- // RootOfChain/OrigRootPhi, with the corresponding PHI present in the
2460- // live set. They have been proved to be the same PHI nodes. Note
2461- // that the *only* use of the RootOfChain in the ChainToBase list is
2462- // the first Value in the list.
2463- if (RootOfChain != AlternateLiveBase)
2464- ClonedValue->replaceUsesOfWith (RootOfChain, AlternateLiveBase);
2465- }
2466-
2467- LastClonedValue = ClonedValue;
2468- LastValue = Instr;
2469- }
2470- assert (LastClonedValue);
2471- return LastClonedValue;
2472- };
2473-
24742473 // Different cases for calls and invokes. For invokes we need to clone
24752474 // instructions both on normal and unwind path.
24762475 if (isa<CallInst>(Call)) {
24772476 Instruction *InsertBefore = Call->getNextNode ();
24782477 assert (InsertBefore);
2479- Instruction *RematerializedValue = rematerializeChain (
2480- InsertBefore, Record.RootOfChain , PointerToBase[LiveValue]);
2478+ Instruction *RematerializedValue =
2479+ rematerializeChain (Record.ChainToBase , InsertBefore,
2480+ Record.RootOfChain , PointerToBase[LiveValue]);
24812481 Info.RematerializedValues [RematerializedValue] = LiveValue;
24822482 } else {
24832483 auto *Invoke = cast<InvokeInst>(Call);
@@ -2487,17 +2487,19 @@ static void rematerializeLiveValues(CallBase *Call,
24872487 Instruction *UnwindInsertBefore =
24882488 &*Invoke->getUnwindDest ()->getFirstInsertionPt ();
24892489
2490- Instruction *NormalRematerializedValue = rematerializeChain (
2491- NormalInsertBefore, Record.RootOfChain , PointerToBase[LiveValue]);
2492- Instruction *UnwindRematerializedValue = rematerializeChain (
2493- UnwindInsertBefore, Record.RootOfChain , PointerToBase[LiveValue]);
2490+ Instruction *NormalRematerializedValue =
2491+ rematerializeChain (Record.ChainToBase , NormalInsertBefore,
2492+ Record.RootOfChain , PointerToBase[LiveValue]);
2493+ Instruction *UnwindRematerializedValue =
2494+ rematerializeChain (Record.ChainToBase , UnwindInsertBefore,
2495+ Record.RootOfChain , PointerToBase[LiveValue]);
24942496
24952497 Info.RematerializedValues [NormalRematerializedValue] = LiveValue;
24962498 Info.RematerializedValues [UnwindRematerializedValue] = LiveValue;
24972499 }
24982500 }
24992501
2500- // Remove rematerializaed values from the live set
2502+ // Remove rematerialized values from the live set.
25012503 for (auto *LiveValue: LiveValuesToBeDeleted) {
25022504 Info.LiveSet .remove (LiveValue);
25032505 }
0 commit comments