@@ -67,6 +67,10 @@ cl::opt<bool> UseRegistersForDeoptValues(
67
67
" use-registers-for-deopt-values" , cl::Hidden, cl::init(false ),
68
68
cl::desc(" Allow using registers for non pointer deopt args" ));
69
69
70
+ cl::opt<unsigned > MaxRegistersForGCPointers (
71
+ " max-registers-for-gc-values" , cl::Hidden, cl::init(0 ),
72
+ cl::desc(" Max number of VRegs allowed to pass GC pointer meta args in" ));
73
+
70
74
static void pushStackMapConstant (SmallVectorImpl<SDValue>& Ops,
71
75
SelectionDAGBuilder &Builder, uint64_t Value) {
72
76
SDLoc L = Builder.getCurSDLoc ();
@@ -86,11 +90,13 @@ void StatepointLoweringState::startNewStatepoint(SelectionDAGBuilder &Builder) {
86
90
// FunctionLoweringInfo. Also need to ensure used bits get cleared.
87
91
AllocatedStackSlots.clear ();
88
92
AllocatedStackSlots.resize (Builder.FuncInfo .StatepointStackSlots .size ());
93
+ DerivedPtrMap.clear ();
89
94
}
90
95
91
96
void StatepointLoweringState::clear () {
92
97
Locations.clear ();
93
98
AllocatedStackSlots.clear ();
99
+ DerivedPtrMap.clear ();
94
100
assert (PendingGCRelocateCalls.empty () &&
95
101
" cleared before statepoint sequence completed" );
96
102
}
@@ -221,7 +227,6 @@ static Optional<int> findPreviousSpillSlot(const Value *Val,
221
227
return None;
222
228
}
223
229
224
-
225
230
// / Return true if-and-only-if the given SDValue can be lowered as either a
226
231
// / constant argument or a stack reference. The key point is that the value
227
232
// / doesn't need to be spilled or tracked as a vreg use.
@@ -242,7 +247,6 @@ static bool willLowerDirectly(SDValue Incoming) {
242
247
Incoming.isUndef ());
243
248
}
244
249
245
-
246
250
// / Try to find existing copies of the incoming values in stack slots used for
247
251
// / statepoint spilling. If we can find a spill slot for the incoming value,
248
252
// / mark that slot as allocated, and reuse the same slot for this safepoint.
@@ -388,7 +392,7 @@ spillIncomingStatepointValue(SDValue Incoming, SDValue Chain,
388
392
StoreMMO);
389
393
390
394
MMO = getMachineMemOperand (MF, *cast<FrameIndexSDNode>(Loc));
391
-
395
+
392
396
Builder.StatepointLowering .setLocation (Incoming, Loc);
393
397
}
394
398
@@ -485,7 +489,9 @@ lowerIncomingStatepointValue(SDValue Incoming, bool RequireSpillSlot,
485
489
// / will be set to the last value spilled (if any were).
486
490
static void
487
491
lowerStatepointMetaArgs (SmallVectorImpl<SDValue> &Ops,
488
- SmallVectorImpl<MachineMemOperand*> &MemRefs, SelectionDAGBuilder::StatepointLoweringInfo &SI,
492
+ SmallVectorImpl<MachineMemOperand *> &MemRefs,
493
+ DenseMap<SDValue, int > &LowerAsVReg,
494
+ SelectionDAGBuilder::StatepointLoweringInfo &SI,
489
495
SelectionDAGBuilder &Builder) {
490
496
// Lower the deopt and gc arguments for this statepoint. Layout will be:
491
497
// deopt argument length, deopt arguments.., gc arguments...
@@ -531,6 +537,37 @@ lowerStatepointMetaArgs(SmallVectorImpl<SDValue> &Ops,
531
537
const bool LiveInDeopt =
532
538
SI.StatepointFlags & (uint64_t )StatepointFlags::DeoptLiveIn;
533
539
540
+ // Decide which deriver pointers will go on VRegs
541
+ const unsigned MaxTiedRegs = 15 ; // Max number of tied regs MI can have.
542
+ unsigned MaxVRegPtrs =
543
+ std::min (MaxTiedRegs, MaxRegistersForGCPointers.getValue ());
544
+ // Use old spill scheme for cross-block relocates.
545
+ if (SI.StatepointInstr ) {
546
+ const BasicBlock *BB = SI.StatepointInstr ->getParent ();
547
+ bool NonLocalReloc =
548
+ llvm::any_of (SI.GCRelocates , [BB](const GCRelocateInst *R) {
549
+ return R->getParent () != BB;
550
+ });
551
+ if (NonLocalReloc)
552
+ MaxVRegPtrs = 0 ;
553
+ }
554
+
555
+ LLVM_DEBUG (dbgs () << " Desiding how to lower GC Pointers:\n " );
556
+ unsigned CurNumVRegs = 0 ;
557
+ for (const Value *P : SI.Ptrs ) {
558
+ if (LowerAsVReg.size () == MaxVRegPtrs)
559
+ break ;
560
+ SDValue PtrSD = Builder.getValue (P);
561
+ if (willLowerDirectly (PtrSD) || P->getType ()->isVectorTy ()) {
562
+ LLVM_DEBUG (dbgs () << " direct/spill " ; PtrSD.dump (&Builder.DAG ));
563
+ continue ;
564
+ }
565
+ LLVM_DEBUG (dbgs () << " vreg " ; PtrSD.dump (&Builder.DAG ));
566
+ LowerAsVReg[PtrSD] = CurNumVRegs++;
567
+ }
568
+ LLVM_DEBUG (dbgs () << LowerAsVReg.size ()
569
+ << " derived pointers will go in vregs\n " );
570
+
534
571
auto isGCValue = [&](const Value *V) {
535
572
auto *Ty = V->getType ();
536
573
if (!Ty->isPtrOrPtrVectorTy ())
@@ -542,7 +579,9 @@ lowerStatepointMetaArgs(SmallVectorImpl<SDValue> &Ops,
542
579
};
543
580
544
581
auto requireSpillSlot = [&](const Value *V) {
545
- return !(LiveInDeopt || UseRegistersForDeoptValues) || isGCValue (V);
582
+ if (isGCValue (V))
583
+ return !LowerAsVReg.count (Builder.getValue (V));
584
+ return !(LiveInDeopt || UseRegistersForDeoptValues);
546
585
};
547
586
548
587
// Before we actually start lowering (and allocating spill slots for values),
@@ -554,9 +593,14 @@ lowerStatepointMetaArgs(SmallVectorImpl<SDValue> &Ops,
554
593
if (requireSpillSlot (V))
555
594
reservePreviousStackSlotForValue (V, Builder);
556
595
}
596
+
557
597
for (unsigned i = 0 ; i < SI.Bases .size (); ++i) {
558
- reservePreviousStackSlotForValue (SI.Bases [i], Builder);
559
- reservePreviousStackSlotForValue (SI.Ptrs [i], Builder);
598
+ SDValue SDV = Builder.getValue (SI.Bases [i]);
599
+ if (!LowerAsVReg.count (SDV))
600
+ reservePreviousStackSlotForValue (SI.Bases [i], Builder);
601
+ SDV = Builder.getValue (SI.Ptrs [i]);
602
+ if (!LowerAsVReg.count (SDV))
603
+ reservePreviousStackSlotForValue (SI.Ptrs [i], Builder);
560
604
}
561
605
562
606
// First, prefix the list with the number of unique values to be
@@ -567,6 +611,7 @@ lowerStatepointMetaArgs(SmallVectorImpl<SDValue> &Ops,
567
611
568
612
// The vm state arguments are lowered in an opaque manner. We do not know
569
613
// what type of values are contained within.
614
+ LLVM_DEBUG (dbgs () << " Lowering deopt state\n " );
570
615
for (const Value *V : SI.DeoptState ) {
571
616
SDValue Incoming;
572
617
// If this is a function argument at a static frame index, generate it as
@@ -578,6 +623,8 @@ lowerStatepointMetaArgs(SmallVectorImpl<SDValue> &Ops,
578
623
}
579
624
if (!Incoming.getNode ())
580
625
Incoming = Builder.getValue (V);
626
+ LLVM_DEBUG (dbgs () << " Value " << *V
627
+ << " requireSpillSlot = " << requireSpillSlot (V) << " \n " );
581
628
lowerIncomingStatepointValue (Incoming, requireSpillSlot (V), Ops, MemRefs,
582
629
Builder);
583
630
}
@@ -588,14 +635,15 @@ lowerStatepointMetaArgs(SmallVectorImpl<SDValue> &Ops,
588
635
// it's (lowered) derived pointer. i.e
589
636
// (base[0], ptr[0], base[1], ptr[1], ...)
590
637
for (unsigned i = 0 ; i < SI.Bases .size (); ++i) {
591
- const Value *Base = SI.Bases [i];
592
- lowerIncomingStatepointValue (Builder.getValue (Base),
593
- /* RequireSpillSlot*/ true , Ops, MemRefs,
638
+ bool RequireSpillSlot;
639
+ SDValue Base = Builder.getValue (SI.Bases [i]);
640
+ RequireSpillSlot = !LowerAsVReg.count (Base);
641
+ lowerIncomingStatepointValue (Base, RequireSpillSlot, Ops, MemRefs,
594
642
Builder);
595
643
596
- const Value *Ptr = SI.Ptrs [i];
597
- lowerIncomingStatepointValue (Builder. getValue (Ptr),
598
- /* RequireSpillSlot*/ true , Ops, MemRefs,
644
+ SDValue Derived = Builder. getValue ( SI.Ptrs [i]) ;
645
+ RequireSpillSlot = !LowerAsVReg. count (Derived);
646
+ lowerIncomingStatepointValue (Derived, RequireSpillSlot, Ops, MemRefs,
599
647
Builder);
600
648
}
601
649
@@ -630,7 +678,9 @@ lowerStatepointMetaArgs(SmallVectorImpl<SDValue> &Ops,
630
678
SDValue SDV = Builder.getValue (V);
631
679
SDValue Loc = Builder.StatepointLowering .getLocation (SDV);
632
680
633
- if (Loc.getNode ()) {
681
+ if (LowerAsVReg.count (SDV)) {
682
+ SpillMap[V] = None;
683
+ } else if (Loc.getNode ()) {
634
684
SpillMap[V] = cast<FrameIndexSDNode>(Loc)->getIndex ();
635
685
} else {
636
686
// Record value as visited, but not spilled. This is case for allocas
@@ -665,6 +715,7 @@ SDValue SelectionDAGBuilder::LowerAsSTATEPOINT(
665
715
assert (SI.Bases .size () == SI.Ptrs .size () &&
666
716
SI.Ptrs .size () <= SI.GCRelocates .size ());
667
717
718
+ LLVM_DEBUG (dbgs () << " Lowering statepoint " << *SI.StatepointInstr << " \n " );
668
719
#ifndef NDEBUG
669
720
for (auto *Reloc : SI.GCRelocates )
670
721
if (Reloc->getParent () == SI.StatepointInstr ->getParent ())
@@ -674,7 +725,9 @@ SDValue SelectionDAGBuilder::LowerAsSTATEPOINT(
674
725
// Lower statepoint vmstate and gcstate arguments
675
726
SmallVector<SDValue, 10 > LoweredMetaArgs;
676
727
SmallVector<MachineMemOperand*, 16 > MemRefs;
677
- lowerStatepointMetaArgs (LoweredMetaArgs, MemRefs, SI, *this );
728
+ // Maps derived pointer SDValue to statepoint result of relocated pointer.
729
+ DenseMap<SDValue, int > LowerAsVReg;
730
+ lowerStatepointMetaArgs (LoweredMetaArgs, MemRefs, LowerAsVReg, SI, *this );
678
731
679
732
// Now that we've emitted the spills, we need to update the root so that the
680
733
// call sequence is ordered correctly.
@@ -788,14 +841,35 @@ SDValue SelectionDAGBuilder::LowerAsSTATEPOINT(
788
841
789
842
// Compute return values. Provide a glue output since we consume one as
790
843
// input. This allows someone else to chain off us as needed.
791
- SDVTList NodeTys = DAG.getVTList (MVT::Other, MVT::Glue);
844
+ SmallVector<EVT, 8 > NodeTys;
845
+ for (auto &Ptr : SI.Ptrs ) {
846
+ SDValue SD = getValue (Ptr);
847
+ if (LowerAsVReg.count (SD)) {
848
+ NodeTys.push_back (SD.getValueType ());
849
+ }
850
+ }
851
+ LLVM_DEBUG (dbgs () << " Statepoint has " << NodeTys.size () << " results\n " );
852
+ assert (NodeTys.size () == LowerAsVReg.size () && " Inconsistent GC Ptr lowering" );
853
+ NodeTys.push_back (MVT::Other);
854
+ NodeTys.push_back (MVT::Glue);
792
855
856
+ unsigned NumResults = NodeTys.size ();
793
857
MachineSDNode *StatepointMCNode =
794
858
DAG.getMachineNode (TargetOpcode::STATEPOINT, getCurSDLoc (), NodeTys, Ops);
795
859
DAG.setNodeMemRefs (StatepointMCNode, MemRefs);
796
860
797
861
SDNode *SinkNode = StatepointMCNode;
798
862
863
+ // Fill mapping from derived pointer to statepoint result denoting its
864
+ // relocated value.
865
+ auto &DPtrMap = StatepointLowering.DerivedPtrMap ;
866
+ for (const auto *Relocate : SI.GCRelocates ) {
867
+ Value *Derived = Relocate->getDerivedPtr ();
868
+ SDValue SD = getValue (Derived);
869
+ if (LowerAsVReg.count (SD))
870
+ DPtrMap[Derived] = SDValue (StatepointMCNode, LowerAsVReg[SD]);
871
+ }
872
+
799
873
// Build the GC_TRANSITION_END node if necessary.
800
874
//
801
875
// See the comment above regarding GC_TRANSITION_START for the layout of
@@ -804,7 +878,7 @@ SDValue SelectionDAGBuilder::LowerAsSTATEPOINT(
804
878
SmallVector<SDValue, 8 > TEOps;
805
879
806
880
// Add chain
807
- TEOps.push_back (SDValue (StatepointMCNode, 0 ));
881
+ TEOps.push_back (SDValue (StatepointMCNode, NumResults - 2 ));
808
882
809
883
// Add GC transition arguments
810
884
for (const Value *V : SI.GCTransitionArgs ) {
@@ -814,7 +888,7 @@ SDValue SelectionDAGBuilder::LowerAsSTATEPOINT(
814
888
}
815
889
816
890
// Add glue
817
- TEOps.push_back (SDValue (StatepointMCNode, 1 ));
891
+ TEOps.push_back (SDValue (StatepointMCNode, NumResults - 1 ));
818
892
819
893
SDVTList NodeTys = DAG.getVTList (MVT::Other, MVT::Glue);
820
894
@@ -825,7 +899,12 @@ SDValue SelectionDAGBuilder::LowerAsSTATEPOINT(
825
899
}
826
900
827
901
// Replace original call
828
- DAG.ReplaceAllUsesWith (CallNode, SinkNode); // This may update Root
902
+ // Call: ch,glue = CALL ...
903
+ // Statepoint: [gc relocates],ch,glue = STATEPOINT ...
904
+ unsigned NumSinkValues = SinkNode->getNumValues ();
905
+ SDValue StatepointValues[2 ] = {SDValue (SinkNode, NumSinkValues - 2 ),
906
+ SDValue (SinkNode, NumSinkValues - 1 )};
907
+ DAG.ReplaceAllUsesWith (CallNode, StatepointValues);
829
908
// Remove original call node
830
909
DAG.DeleteNode (CallNode);
831
910
@@ -927,7 +1006,7 @@ SelectionDAGBuilder::LowerStatepoint(const GCStatepointInst &I,
927
1006
setValue (&I, ReturnValue);
928
1007
return ;
929
1008
}
930
-
1009
+
931
1010
// Result value will be used in a different basic block so we need to export
932
1011
// it now. Default exporting mechanism will not work here because statepoint
933
1012
// call has a different type than the actual call. It means that by default
@@ -1010,12 +1089,13 @@ void SelectionDAGBuilder::visitGCResult(const GCResultInst &CI) {
1010
1089
}
1011
1090
1012
1091
void SelectionDAGBuilder::visitGCRelocate (const GCRelocateInst &Relocate) {
1092
+ const BasicBlock *StatepointBB = Relocate.getStatepoint ()->getParent ();
1013
1093
#ifndef NDEBUG
1014
1094
// Consistency check
1015
1095
// We skip this check for relocates not in the same basic block as their
1016
1096
// statepoint. It would be too expensive to preserve validation info through
1017
1097
// different basic blocks.
1018
- if (Relocate. getStatepoint ()-> getParent () == Relocate.getParent ())
1098
+ if (StatepointBB == Relocate.getParent ())
1019
1099
StatepointLowering.relocCallVisited (Relocate);
1020
1100
1021
1101
auto *Ty = Relocate.getType ()->getScalarType ();
@@ -1033,6 +1113,16 @@ void SelectionDAGBuilder::visitGCRelocate(const GCRelocateInst &Relocate) {
1033
1113
return ;
1034
1114
}
1035
1115
1116
+ // Relocate is local to statepoint block and its pointer was assigned
1117
+ // to VReg. Use corresponding statepoint result.
1118
+ auto &DPtrMap = StatepointLowering.DerivedPtrMap ;
1119
+ auto It = DPtrMap.find (DerivedPtr);
1120
+ if (It != DPtrMap.end ()) {
1121
+ setValue (&Relocate, It->second );
1122
+ assert (Relocate.getParent () == StatepointBB && " unexpected DPtrMap entry" );
1123
+ return ;
1124
+ }
1125
+
1036
1126
auto &SpillMap = FuncInfo.StatepointSpillMaps [Relocate.getStatepoint ()];
1037
1127
auto SlotIt = SpillMap.find (DerivedPtr);
1038
1128
assert (SlotIt != SpillMap.end () && " Relocating not lowered gc value" );
0 commit comments