@@ -295,6 +295,8 @@ struct State {
295
295
// Those values that - if live out from our parent basic block - are live
296
296
// at this safepoint.
297
297
std::vector<std::vector<int >> LiveIfLiveOut;
298
+ // The set of values that are kept alive by the callee.
299
+ std::vector<std::vector<int >> CalleeRoots;
298
300
// We don't bother doing liveness on Allocas that were not mem2reg'ed.
299
301
// they just get directly sunk into the root array.
300
302
std::vector<AllocaInst *> Allocas;
@@ -359,7 +361,7 @@ struct LateLowerGCFrame: public FunctionPass, private JuliaPassContext {
359
361
void NoteUseChain (State &S, BBState &BBS, User *TheUser);
360
362
SmallVector<int , 1 > GetPHIRefinements (PHINode *phi, State &S);
361
363
void FixUpRefinements (ArrayRef<int > PHINumbers, State &S);
362
- void RefineLiveSet (BitVector &LS, State &S);
364
+ void RefineLiveSet (BitVector &LS, State &S, const std::vector< int > &CalleeRoots );
363
365
Value *EmitTagPtr (IRBuilder<> &builder, Type *T, Value *V);
364
366
Value *EmitLoadTag (IRBuilder<> &builder, Value *V);
365
367
};
@@ -1002,7 +1004,7 @@ void LateLowerGCFrame::MaybeNoteDef(State &S, BBState &BBS, Value *Def, const st
1002
1004
}
1003
1005
}
1004
1006
1005
- static int NoteSafepoint (State &S, BBState &BBS, CallInst *CI) {
1007
+ static int NoteSafepoint (State &S, BBState &BBS, CallInst *CI, std::vector< int > CalleeRoots ) {
1006
1008
int Number = ++S.MaxSafepointNumber ;
1007
1009
S.SafepointNumbering [CI] = Number;
1008
1010
S.ReverseSafepointNumbering .push_back (CI);
@@ -1012,6 +1014,7 @@ static int NoteSafepoint(State &S, BBState &BBS, CallInst *CI) {
1012
1014
// computation)
1013
1015
S.LiveSets .push_back (BBS.UpExposedUses );
1014
1016
S.LiveIfLiveOut .push_back (std::vector<int >{});
1017
+ S.CalleeRoots .push_back (std::move (CalleeRoots));
1015
1018
return Number;
1016
1019
}
1017
1020
@@ -1515,7 +1518,25 @@ State LateLowerGCFrame::LocalScan(Function &F) {
1515
1518
// Intrinsics are never safepoints.
1516
1519
continue ;
1517
1520
}
1518
- int SafepointNumber = NoteSafepoint (S, BBS, CI);
1521
+ std::vector<int > CalleeRoots;
1522
+ for (Use &U : CI->arg_operands ()) {
1523
+ // Find all callee rooted arguments.
1524
+ // Record them instead of simply remove them from live values here
1525
+ // since they can be useful during refinment
1526
+ // (e.g. to remove roots of objects that are refined to these)
1527
+ Value *V = U;
1528
+ if (isa<Constant>(V) || !isa<PointerType>(V->getType ()) ||
1529
+ getValueAddrSpace (V) != AddressSpace::CalleeRooted)
1530
+ continue ;
1531
+ V = V->stripPointerCasts ();
1532
+ if (!isTrackedValue (V))
1533
+ continue ;
1534
+ auto Num = Number (S, V);
1535
+ if (Num < 0 )
1536
+ continue ;
1537
+ CalleeRoots.push_back (Num);
1538
+ }
1539
+ int SafepointNumber = NoteSafepoint (S, BBS, CI, std::move (CalleeRoots));
1519
1540
BBS.HasSafepoint = true ;
1520
1541
BBS.TopmostSafepoint = SafepointNumber;
1521
1542
BBS.Safepoints .push_back (SafepointNumber);
@@ -1845,12 +1866,18 @@ JL_USED_FUNC static void dumpSafepointsForBBName(Function &F, State &S, const ch
1845
1866
}
1846
1867
}
1847
1868
1848
- void LateLowerGCFrame::RefineLiveSet (BitVector &LS, State &S)
1869
+ void LateLowerGCFrame::RefineLiveSet (BitVector &LS, State &S, const std::vector< int > &CalleeRoots )
1849
1870
{
1850
1871
BitVector FullLS (S.MaxPtrNumber + 1 , false );
1851
1872
FullLS |= LS;
1852
1873
// First expand the live set according to the refinement map
1853
1874
// so that we can see all the values that are effectively live.
1875
+ for (auto Num: CalleeRoots) {
1876
+ // For callee rooted values, they are all kept alive at the safepoint.
1877
+ // Make sure they are marked (even though they probably are already)
1878
+ // so that other values can be refined to them.
1879
+ FullLS[Num] = 1 ;
1880
+ }
1854
1881
bool changed;
1855
1882
do {
1856
1883
changed = false ;
@@ -1891,6 +1918,11 @@ void LateLowerGCFrame::RefineLiveSet(BitVector &LS, State &S)
1891
1918
LS[Idx] = 0 ;
1892
1919
}
1893
1920
}
1921
+ for (auto Num: CalleeRoots) {
1922
+ // Now unmark all values that are rooted by the callee after
1923
+ // refining other values to them.
1924
+ LS[Num] = 0 ;
1925
+ }
1894
1926
}
1895
1927
1896
1928
void LateLowerGCFrame::ComputeLiveSets (State &S) {
@@ -1909,7 +1941,7 @@ void LateLowerGCFrame::ComputeLiveSets(State &S) {
1909
1941
if (HasBitSet (BBS.LiveOut , Live))
1910
1942
LS[Live] = 1 ;
1911
1943
}
1912
- RefineLiveSet (LS, S);
1944
+ RefineLiveSet (LS, S, S. CalleeRoots [idx] );
1913
1945
// If the function has GC preserves, figure out whether we need to
1914
1946
// add in any extra live values.
1915
1947
if (!S.GCPreserves .empty ()) {
0 commit comments