@@ -167,6 +167,9 @@ class MipsBranchExpansion : public MachineFunctionPass {
167
167
bool handleFPUDelaySlot ();
168
168
bool handleLoadDelaySlot ();
169
169
bool handlePossibleLongBranch ();
170
+ bool handleMFLO ();
171
+ template <typename Pred, typename Safe>
172
+ bool handleMFLOSlot (Pred Predicate, Safe SafeInSlot);
170
173
171
174
const MipsSubtarget *STI;
172
175
const MipsInstrInfo *TII;
@@ -741,6 +744,53 @@ static void emitGPDisp(MachineFunction &F, const MipsInstrInfo *TII) {
741
744
MBB.removeLiveIn (Mips::V0);
742
745
}
743
746
747
+ template <typename Pred, typename Safe>
748
+ bool MipsBranchExpansion::handleMFLOSlot (Pred Predicate, Safe SafeInSlot) {
749
+ bool Changed = false ;
750
+ bool hasPendingMFLO = false ;
751
+
752
+ for (MachineFunction::iterator FI = MFp->begin (); FI != MFp->end (); ++FI) {
753
+ for (Iter I = FI->begin (); I != FI->end (); ++I) {
754
+
755
+ if (!Predicate (*I) && !hasPendingMFLO) {
756
+ continue ;
757
+ }
758
+
759
+ Iter IInSlot;
760
+ bool LastInstInFunction =
761
+ std::next (I) == FI->end () && std::next (FI) == MFp->end ();
762
+ // We need process several situations:
763
+ // mflo is last instruction, do not process;
764
+ // mflo + div, add two nop between them;
765
+ // mflo + none-div + none-div, do not process;
766
+ // mflo + none-div + div, add nop between none-div and div.
767
+ if (!LastInstInFunction) {
768
+ std::pair<Iter, bool > Res = getNextMachineInstr (std::next (I), &*FI);
769
+ LastInstInFunction |= Res.second ;
770
+ IInSlot = Res.first ;
771
+ if (!SafeInSlot (*IInSlot, *I)) {
772
+ Changed = true ;
773
+ TII->insertNop (*(I->getParent ()), std::next (I), I->getDebugLoc ())
774
+ ->bundleWithPred ();
775
+ NumInsertedNops++;
776
+ if (IsMFLOMFHI (I->getOpcode ())) {
777
+ TII->insertNop (*(I->getParent ()), std::next (I), I->getDebugLoc ())
778
+ ->bundleWithPred ();
779
+ NumInsertedNops++;
780
+ }
781
+ if (hasPendingMFLO)
782
+ hasPendingMFLO = false ;
783
+ } else if (hasPendingMFLO)
784
+ hasPendingMFLO = false ;
785
+ else if (IsMFLOMFHI (I->getOpcode ()))
786
+ hasPendingMFLO = true ;
787
+ }
788
+ }
789
+ }
790
+
791
+ return Changed;
792
+ }
793
+
744
794
template <typename Pred, typename Safe>
745
795
bool MipsBranchExpansion::handleSlot (Pred Predicate, Safe SafeInSlot) {
746
796
bool Changed = false ;
@@ -777,6 +827,19 @@ bool MipsBranchExpansion::handleSlot(Pred Predicate, Safe SafeInSlot) {
777
827
return Changed;
778
828
}
779
829
830
+ bool MipsBranchExpansion::handleMFLO () {
831
+ // mips1-4 require a minimum of 2 instructions between a mflo/mfhi
832
+ // and the next mul/div instruction.
833
+ if (STI->hasMips32 () || STI->hasMips5 ())
834
+ return false ;
835
+
836
+ return handleMFLOSlot (
837
+ [this ](auto &I) -> bool { return TII->IsMfloOrMfhi (I); },
838
+ [this ](auto &IInSlot, auto &I) -> bool {
839
+ return TII->SafeAfterMflo (IInSlot);
840
+ });
841
+ }
842
+
780
843
bool MipsBranchExpansion::handleForbiddenSlot () {
781
844
// Forbidden slot hazards are only defined for MIPSR6 but not microMIPSR6.
782
845
if (!STI->hasMips32r6 () || STI->inMicroMipsMode ())
@@ -893,16 +956,19 @@ bool MipsBranchExpansion::runOnMachineFunction(MachineFunction &MF) {
893
956
bool forbiddenSlotChanged = handleForbiddenSlot ();
894
957
bool fpuDelaySlotChanged = handleFPUDelaySlot ();
895
958
bool loadDelaySlotChanged = handleLoadDelaySlot ();
959
+ bool MfloChanged = handleMFLO ();
896
960
897
961
bool Changed = longBranchChanged || forbiddenSlotChanged ||
898
- fpuDelaySlotChanged || loadDelaySlotChanged;
962
+ fpuDelaySlotChanged || loadDelaySlotChanged || MfloChanged ;
899
963
900
964
// Then run them alternatively while there are changes.
901
965
while (forbiddenSlotChanged) {
902
966
longBranchChanged = handlePossibleLongBranch ();
903
967
fpuDelaySlotChanged = handleFPUDelaySlot ();
904
968
loadDelaySlotChanged = handleLoadDelaySlot ();
905
- if (!longBranchChanged && !fpuDelaySlotChanged && !loadDelaySlotChanged)
969
+ MfloChanged = handleMFLO ();
970
+ if (!longBranchChanged && !fpuDelaySlotChanged && !loadDelaySlotChanged &&
971
+ !MfloChanged)
906
972
break ;
907
973
forbiddenSlotChanged = handleForbiddenSlot ();
908
974
}
0 commit comments