@@ -167,6 +167,9 @@ class MipsBranchExpansion : public MachineFunctionPass {
167167 bool handleFPUDelaySlot ();
168168 bool handleLoadDelaySlot ();
169169 bool handlePossibleLongBranch ();
170+ bool handleMFLO ();
171+ template <typename Pred, typename Safe>
172+ bool handleMFLOSlot (Pred Predicate, Safe SafeInSlot);
170173
171174 const MipsSubtarget *STI;
172175 const MipsInstrInfo *TII;
@@ -741,6 +744,53 @@ static void emitGPDisp(MachineFunction &F, const MipsInstrInfo *TII) {
741744 MBB.removeLiveIn (Mips::V0);
742745}
743746
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+
744794template <typename Pred, typename Safe>
745795bool MipsBranchExpansion::handleSlot (Pred Predicate, Safe SafeInSlot) {
746796 bool Changed = false ;
@@ -777,6 +827,19 @@ bool MipsBranchExpansion::handleSlot(Pred Predicate, Safe SafeInSlot) {
777827 return Changed;
778828}
779829
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+
780843bool MipsBranchExpansion::handleForbiddenSlot () {
781844 // Forbidden slot hazards are only defined for MIPSR6 but not microMIPSR6.
782845 if (!STI->hasMips32r6 () || STI->inMicroMipsMode ())
@@ -893,16 +956,19 @@ bool MipsBranchExpansion::runOnMachineFunction(MachineFunction &MF) {
893956 bool forbiddenSlotChanged = handleForbiddenSlot ();
894957 bool fpuDelaySlotChanged = handleFPUDelaySlot ();
895958 bool loadDelaySlotChanged = handleLoadDelaySlot ();
959+ bool MfloChanged = handleMFLO ();
896960
897961 bool Changed = longBranchChanged || forbiddenSlotChanged ||
898- fpuDelaySlotChanged || loadDelaySlotChanged;
962+ fpuDelaySlotChanged || loadDelaySlotChanged || MfloChanged ;
899963
900964 // Then run them alternatively while there are changes.
901965 while (forbiddenSlotChanged) {
902966 longBranchChanged = handlePossibleLongBranch ();
903967 fpuDelaySlotChanged = handleFPUDelaySlot ();
904968 loadDelaySlotChanged = handleLoadDelaySlot ();
905- if (!longBranchChanged && !fpuDelaySlotChanged && !loadDelaySlotChanged)
969+ MfloChanged = handleMFLO ();
970+ if (!longBranchChanged && !fpuDelaySlotChanged && !loadDelaySlotChanged &&
971+ !MfloChanged)
906972 break ;
907973 forbiddenSlotChanged = handleForbiddenSlot ();
908974 }
0 commit comments