@@ -161,10 +161,16 @@ class ShrinkWrap : public MachineFunctionPass {
161
161
// / Current MachineFunction.
162
162
MachineFunction *MachineFunc = nullptr ;
163
163
164
+ // / Is `true` for block numbers where we can guarantee no stack access
165
+ // / or computation of stack-relative addresses on any CFG path including
166
+ // / the block itself.
167
+ BitVector StackAddressUsedBlockInfo;
168
+
164
169
// / Check if \p MI uses or defines a callee-saved register or
165
170
// / a frame index. If this is the case, this means \p MI must happen
166
171
// / after Save and before Restore.
167
- bool useOrDefCSROrFI (const MachineInstr &MI, RegScavenger *RS) const ;
172
+ bool useOrDefCSROrFI (const MachineInstr &MI, RegScavenger *RS,
173
+ bool StackAddressUsed) const ;
168
174
169
175
const SetOfRegs &getCurrentCSRs (RegScavenger *RS) const {
170
176
if (CurrentCSRs.empty ()) {
@@ -190,7 +196,9 @@ class ShrinkWrap : public MachineFunctionPass {
190
196
191
197
// Try to find safe point based on dominance and block frequency without
192
198
// any change in IR.
193
- bool performShrinkWrapping (MachineFunction &MF, RegScavenger *RS);
199
+ bool performShrinkWrapping (
200
+ const ReversePostOrderTraversal<MachineBasicBlock *> &RPOT,
201
+ RegScavenger *RS);
194
202
195
203
// / This function tries to split the restore point if doing so can shrink the
196
204
// / save point further. \return True if restore point is split.
@@ -285,8 +293,8 @@ INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
285
293
INITIALIZE_PASS_DEPENDENCY(MachineOptimizationRemarkEmitterPass)
286
294
INITIALIZE_PASS_END(ShrinkWrap, DEBUG_TYPE, " Shrink Wrap Pass" , false , false )
287
295
288
- bool ShrinkWrap::useOrDefCSROrFI(const MachineInstr &MI,
289
- RegScavenger *RS ) const {
296
+ bool ShrinkWrap::useOrDefCSROrFI(const MachineInstr &MI, RegScavenger *RS,
297
+ bool StackAddressUsed ) const {
290
298
// / Check if \p Op is known to access an address not on the function's stack .
291
299
// / At the moment, accesses where the underlying object is a global, function
292
300
// / argument, or jump table are considered non-stack accesses. Note that the
@@ -306,12 +314,9 @@ bool ShrinkWrap::useOrDefCSROrFI(const MachineInstr &MI,
306
314
return PSV->isJumpTable ();
307
315
return false ;
308
316
};
309
- // This prevents premature stack popping when occurs a indirect stack
310
- // access. It is overly aggressive for the moment.
311
- // TODO:
312
- // - Further, data dependency and alias analysis can validate
313
- // that load and stores never derive from the stack pointer.
314
- if (MI.mayLoadOrStore () &&
317
+ // Load/store operations may access the stack indirectly when we previously
318
+ // computed an address to a stack location.
319
+ if (StackAddressUsed && MI.mayLoadOrStore () &&
315
320
(MI.isCall () || MI.hasUnmodeledSideEffects () || MI.memoperands_empty () ||
316
321
!all_of (MI.memoperands (), IsKnownNonStackPtr)))
317
322
return true ;
@@ -553,7 +558,7 @@ bool ShrinkWrap::checkIfRestoreSplittable(
553
558
SmallVectorImpl<MachineBasicBlock *> &CleanPreds,
554
559
const TargetInstrInfo *TII, RegScavenger *RS) {
555
560
for (const MachineInstr &MI : *CurRestore)
556
- if (useOrDefCSROrFI (MI, RS))
561
+ if (useOrDefCSROrFI (MI, RS, /* StackAddressUsed= */ true ))
557
562
return false ;
558
563
559
564
for (MachineBasicBlock *PredBB : CurRestore->predecessors ()) {
@@ -613,7 +618,7 @@ bool ShrinkWrap::postShrinkWrapping(bool HasCandidate, MachineFunction &MF,
613
618
continue ;
614
619
}
615
620
for (const MachineInstr &MI : MBB)
616
- if (useOrDefCSROrFI (MI, RS)) {
621
+ if (useOrDefCSROrFI (MI, RS, /* StackAddressUsed= */ true )) {
617
622
DirtyBBs.insert (&MBB);
618
623
break ;
619
624
}
@@ -700,7 +705,7 @@ void ShrinkWrap::updateSaveRestorePoints(MachineBasicBlock &MBB,
700
705
// terminator.
701
706
if (Restore == &MBB) {
702
707
for (const MachineInstr &Terminator : MBB.terminators ()) {
703
- if (!useOrDefCSROrFI (Terminator, RS))
708
+ if (!useOrDefCSROrFI (Terminator, RS, /* StackAddressUsed= */ true ))
704
709
continue ;
705
710
// One of the terminator needs to happen before the restore point.
706
711
if (MBB.succ_empty ()) {
@@ -807,46 +812,62 @@ static bool giveUpWithRemarks(MachineOptimizationRemarkEmitter *ORE,
807
812
return false ;
808
813
}
809
814
810
- bool ShrinkWrap::performShrinkWrapping (MachineFunction &MF, RegScavenger *RS) {
811
- for (MachineBasicBlock &MBB : MF) {
812
- LLVM_DEBUG (dbgs () << " Look into: " << MBB.getNumber () << ' '
813
- << MBB.getName () << ' \n ' );
815
+ bool ShrinkWrap::performShrinkWrapping (
816
+ const ReversePostOrderTraversal<MachineBasicBlock *> &RPOT,
817
+ RegScavenger *RS) {
818
+ for (MachineBasicBlock *MBB : RPOT) {
819
+ LLVM_DEBUG (dbgs () << " Look into: " << printMBBReference (*MBB) << ' \n ' );
814
820
815
- if (MBB. isEHFuncletEntry ())
821
+ if (MBB-> isEHFuncletEntry ())
816
822
return giveUpWithRemarks (ORE, " UnsupportedEHFunclets" ,
817
823
" EH Funclets are not supported yet." ,
818
- MBB. front ().getDebugLoc (), & MBB);
824
+ MBB-> front ().getDebugLoc (), MBB);
819
825
820
- if (MBB. isEHPad () || MBB. isInlineAsmBrIndirectTarget ()) {
826
+ if (MBB-> isEHPad () || MBB-> isInlineAsmBrIndirectTarget ()) {
821
827
// Push the prologue and epilogue outside of the region that may throw (or
822
828
// jump out via inlineasm_br), by making sure that all the landing pads
823
829
// are at least at the boundary of the save and restore points. The
824
830
// problem is that a basic block can jump out from the middle in these
825
831
// cases, which we do not handle.
826
- updateSaveRestorePoints (MBB, RS);
832
+ updateSaveRestorePoints (* MBB, RS);
827
833
if (!ArePointsInteresting ()) {
828
834
LLVM_DEBUG (dbgs () << " EHPad/inlineasm_br prevents shrink-wrapping\n " );
829
835
return false ;
830
836
}
831
837
continue ;
832
838
}
833
839
834
- for (const MachineInstr &MI : MBB) {
835
- if (!useOrDefCSROrFI (MI, RS))
836
- continue ;
837
- // Save (resp. restore) point must dominate (resp. post dominate)
838
- // MI. Look for the proper basic block for those.
839
- updateSaveRestorePoints (MBB, RS);
840
- // If we are at a point where we cannot improve the placement of
841
- // save/restore instructions, just give up.
842
- if (!ArePointsInteresting ()) {
843
- LLVM_DEBUG (dbgs () << " No Shrink wrap candidate found\n " );
844
- return false ;
840
+ bool StackAddressUsed = false ;
841
+ // Check if we found any stack accesses in the predecessors. We are not
842
+ // doing a full dataflow analysis here to keep things simple but just
843
+ // rely on a reverse portorder traversal (RPOT) to guarantee predecessors
844
+ // are already processed except for loops (and accept the conservative
845
+ // result for loops).
846
+ for (const MachineBasicBlock *Pred : MBB->predecessors ()) {
847
+ if (StackAddressUsedBlockInfo.test (Pred->getNumber ())) {
848
+ StackAddressUsed = true ;
849
+ break ;
845
850
}
846
- // No need to look for other instructions, this basic block
847
- // will already be part of the handled region.
848
- break ;
849
851
}
852
+
853
+ for (const MachineInstr &MI : *MBB) {
854
+ if (useOrDefCSROrFI (MI, RS, StackAddressUsed)) {
855
+ // Save (resp. restore) point must dominate (resp. post dominate)
856
+ // MI. Look for the proper basic block for those.
857
+ updateSaveRestorePoints (*MBB, RS);
858
+ // If we are at a point where we cannot improve the placement of
859
+ // save/restore instructions, just give up.
860
+ if (!ArePointsInteresting ()) {
861
+ LLVM_DEBUG (dbgs () << " No Shrink wrap candidate found\n " );
862
+ return false ;
863
+ }
864
+ // No need to look for other instructions, this basic block
865
+ // will already be part of the handled region.
866
+ StackAddressUsed = true ;
867
+ break ;
868
+ }
869
+ }
870
+ StackAddressUsedBlockInfo[MBB->getNumber ()] = StackAddressUsed;
850
871
}
851
872
if (!ArePointsInteresting ()) {
852
873
// If the points are not interesting at this point, then they must be null
@@ -860,13 +881,13 @@ bool ShrinkWrap::performShrinkWrapping(MachineFunction &MF, RegScavenger *RS) {
860
881
LLVM_DEBUG (dbgs () << " \n ** Results **\n Frequency of the Entry: " << EntryFreq
861
882
<< ' \n ' );
862
883
863
- const TargetFrameLowering *TFI = MF.getSubtarget ().getFrameLowering ();
884
+ const TargetFrameLowering *TFI =
885
+ MachineFunc->getSubtarget ().getFrameLowering ();
864
886
do {
865
887
LLVM_DEBUG (dbgs () << " Shrink wrap candidates (#, Name, Freq):\n Save: "
866
- << Save-> getNumber () << ' ' << Save-> getName ( ) << ' '
888
+ << printMBBReference (* Save) << ' '
867
889
<< MBFI->getBlockFreq (Save).getFrequency ()
868
- << " \n Restore: " << Restore->getNumber () << ' '
869
- << Restore->getName () << ' '
890
+ << " \n Restore: " << printMBBReference (*Restore) << ' '
870
891
<< MBFI->getBlockFreq (Restore).getFrequency () << ' \n ' );
871
892
872
893
bool IsSaveCheap, TargetCanUseSaveAsPrologue = false ;
@@ -927,17 +948,18 @@ bool ShrinkWrap::runOnMachineFunction(MachineFunction &MF) {
927
948
928
949
bool Changed = false ;
929
950
930
- bool HasCandidate = performShrinkWrapping (MF, RS.get ());
951
+ StackAddressUsedBlockInfo.resize (MF.getNumBlockIDs (), true );
952
+ bool HasCandidate = performShrinkWrapping (RPOT, RS.get ());
953
+ StackAddressUsedBlockInfo.clear ();
931
954
Changed = postShrinkWrapping (HasCandidate, MF, RS.get ());
932
955
if (!HasCandidate && !Changed)
933
956
return false ;
934
957
if (!ArePointsInteresting ())
935
958
return Changed;
936
959
937
960
LLVM_DEBUG (dbgs () << " Final shrink wrap candidates:\n Save: "
938
- << Save->getNumber () << ' ' << Save->getName ()
939
- << " \n Restore: " << Restore->getNumber () << ' '
940
- << Restore->getName () << ' \n ' );
961
+ << printMBBReference (*Save) << ' '
962
+ << " \n Restore: " << printMBBReference (*Restore) << ' \n ' );
941
963
942
964
MachineFrameInfo &MFI = MF.getFrameInfo ();
943
965
MFI.setSavePoint (Save);
0 commit comments