Skip to content

Commit 8404254

Browse files
Djordje Todoroviccuviper
Djordje Todorovic
authored andcommitted
[MIPS] Add FPU Delay Slot for MIPS1/2/3
MIPS I, II, and III have delay slots for floating point comparisons and floating point register transfers (mtc1, mfc1). Currently, these are not taken into account and thus broken code may be generated on these targets. This patch inserts nops as necessary, while attempting to leave the current instruction if it is safe to stay. The tests in this patch were updated by @sajattack Patch by @overdrivenpotato (Marko Mijalkovic <[email protected]>) Differential Revision: https://reviews.llvm.org/D115127
1 parent 940b668 commit 8404254

File tree

5 files changed

+119
-13
lines changed

5 files changed

+119
-13
lines changed

llvm/lib/Target/Mips/MipsBranchExpansion.cpp

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
///
3737
/// Regarding compact branch hazard prevention:
3838
///
39-
/// Hazards handled: forbidden slots for MIPSR6.
39+
/// Hazards handled: forbidden slots for MIPSR6, FPU slots for MIPS3 and below.
4040
///
4141
/// A forbidden slot hazard occurs when a compact branch instruction is executed
4242
/// and the adjacent instruction in memory is a control transfer instruction
@@ -160,7 +160,10 @@ class MipsBranchExpansion : public MachineFunctionPass {
160160
bool buildProperJumpMI(MachineBasicBlock *MBB,
161161
MachineBasicBlock::iterator Pos, DebugLoc DL);
162162
void expandToLongBranch(MBBInfo &Info);
163+
template <typename Pred, typename Safe>
164+
bool handleSlot(Pred Predicate, Safe SafeInSlot);
163165
bool handleForbiddenSlot();
166+
bool handleFPUDelaySlot();
164167
bool handlePossibleLongBranch();
165168

166169
const MipsSubtarget *STI;
@@ -738,30 +741,27 @@ static void emitGPDisp(MachineFunction &F, const MipsInstrInfo *TII) {
738741
MBB.removeLiveIn(Mips::V0);
739742
}
740743

741-
bool MipsBranchExpansion::handleForbiddenSlot() {
742-
// Forbidden slot hazards are only defined for MIPSR6 but not microMIPSR6.
743-
if (!STI->hasMips32r6() || STI->inMicroMipsMode())
744-
return false;
745-
744+
template <typename Pred, typename Safe>
745+
bool MipsBranchExpansion::handleSlot(Pred Predicate, Safe SafeInSlot) {
746746
bool Changed = false;
747747

748748
for (MachineFunction::iterator FI = MFp->begin(); FI != MFp->end(); ++FI) {
749749
for (Iter I = FI->begin(); I != FI->end(); ++I) {
750750

751-
// Forbidden slot hazard handling. Use lookahead over state.
752-
if (!TII->HasForbiddenSlot(*I))
751+
// Delay slot hazard handling. Use lookahead over state.
752+
if (!Predicate(*I))
753753
continue;
754754

755-
Iter Inst;
755+
Iter IInSlot;
756756
bool LastInstInFunction =
757757
std::next(I) == FI->end() && std::next(FI) == MFp->end();
758758
if (!LastInstInFunction) {
759759
std::pair<Iter, bool> Res = getNextMachineInstr(std::next(I), &*FI);
760760
LastInstInFunction |= Res.second;
761-
Inst = Res.first;
761+
IInSlot = Res.first;
762762
}
763763

764-
if (LastInstInFunction || !TII->SafeInForbiddenSlot(*Inst)) {
764+
if (LastInstInFunction || !SafeInSlot(*IInSlot, *I)) {
765765

766766
MachineBasicBlock::instr_iterator Iit = I->getIterator();
767767
if (std::next(Iit) == FI->end() ||
@@ -778,6 +778,29 @@ bool MipsBranchExpansion::handleForbiddenSlot() {
778778
return Changed;
779779
}
780780

781+
bool MipsBranchExpansion::handleForbiddenSlot() {
782+
// Forbidden slot hazards are only defined for MIPSR6 but not microMIPSR6.
783+
if (!STI->hasMips32r6() || STI->inMicroMipsMode())
784+
return false;
785+
786+
return handleSlot(
787+
[this](auto &I) -> bool { return TII->HasForbiddenSlot(I); },
788+
[this](auto &IInSlot, auto &I) -> bool {
789+
return TII->SafeInForbiddenSlot(IInSlot);
790+
});
791+
}
792+
793+
bool MipsBranchExpansion::handleFPUDelaySlot() {
794+
// FPU delay slots are only defined for MIPS3 and below.
795+
if (STI->hasMips32() || STI->hasMips4())
796+
return false;
797+
798+
return handleSlot([this](auto &I) -> bool { return TII->HasFPUDelaySlot(I); },
799+
[this](auto &IInSlot, auto &I) -> bool {
800+
return TII->SafeInFPUDelaySlot(IInSlot, I);
801+
});
802+
}
803+
781804
bool MipsBranchExpansion::handlePossibleLongBranch() {
782805
if (STI->inMips16Mode() || !STI->enableLongBranchPass())
783806
return false;
@@ -857,13 +880,16 @@ bool MipsBranchExpansion::runOnMachineFunction(MachineFunction &MF) {
857880
// Run these two at least once
858881
bool longBranchChanged = handlePossibleLongBranch();
859882
bool forbiddenSlotChanged = handleForbiddenSlot();
883+
bool fpuDelaySlotChanged = handleFPUDelaySlot();
860884

861-
bool Changed = longBranchChanged || forbiddenSlotChanged;
885+
bool Changed =
886+
longBranchChanged || forbiddenSlotChanged || fpuDelaySlotChanged;
862887

863888
// Then run them alternatively while there are changes
864889
while (forbiddenSlotChanged) {
865890
longBranchChanged = handlePossibleLongBranch();
866-
if (!longBranchChanged)
891+
fpuDelaySlotChanged = handleFPUDelaySlot();
892+
if (!longBranchChanged && !fpuDelaySlotChanged)
867893
break;
868894
forbiddenSlotChanged = handleForbiddenSlot();
869895
}

llvm/lib/Target/Mips/MipsInstrInfo.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,11 +568,60 @@ bool MipsInstrInfo::SafeInForbiddenSlot(const MachineInstr &MI) const {
568568
return (MI.getDesc().TSFlags & MipsII::IsCTI) == 0;
569569
}
570570

571+
bool MipsInstrInfo::SafeInFPUDelaySlot(const MachineInstr &MIInSlot,
572+
const MachineInstr &FPUMI) const {
573+
if (MIInSlot.isInlineAsm())
574+
return false;
575+
576+
if (HasFPUDelaySlot(MIInSlot))
577+
return false;
578+
579+
switch (MIInSlot.getOpcode()) {
580+
case Mips::BC1F:
581+
case Mips::BC1FL:
582+
case Mips::BC1T:
583+
case Mips::BC1TL:
584+
return false;
585+
}
586+
587+
for (const MachineOperand &Op : FPUMI.defs()) {
588+
if (!Op.isReg())
589+
continue;
590+
591+
bool Reads, Writes;
592+
std::tie(Reads, Writes) = MIInSlot.readsWritesVirtualRegister(Op.getReg());
593+
594+
if (Reads || Writes)
595+
return false;
596+
}
597+
598+
return true;
599+
}
600+
571601
/// Predicate for distingushing instructions that have forbidden slots.
572602
bool MipsInstrInfo::HasForbiddenSlot(const MachineInstr &MI) const {
573603
return (MI.getDesc().TSFlags & MipsII::HasForbiddenSlot) != 0;
574604
}
575605

606+
/// Predicate for distingushing instructions that have FPU delay slots.
607+
bool MipsInstrInfo::HasFPUDelaySlot(const MachineInstr &MI) const {
608+
switch (MI.getOpcode()) {
609+
case Mips::MTC1:
610+
case Mips::MFC1:
611+
case Mips::MTC1_D64:
612+
case Mips::MFC1_D64:
613+
case Mips::DMTC1:
614+
case Mips::DMFC1:
615+
case Mips::FCMP_S32:
616+
case Mips::FCMP_D32:
617+
case Mips::FCMP_D64:
618+
return true;
619+
620+
default:
621+
return false;
622+
}
623+
}
624+
576625
/// Return the number of bytes of code the specified instruction may be.
577626
unsigned MipsInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
578627
switch (MI.getOpcode()) {

llvm/lib/Target/Mips/MipsInstrInfo.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,16 @@ class MipsInstrInfo : public MipsGenInstrInfo {
9292
/// Predicate to determine if an instruction can go in a forbidden slot.
9393
bool SafeInForbiddenSlot(const MachineInstr &MI) const;
9494

95+
/// Predicate to determine if an instruction can go in an FPU delay slot.
96+
bool SafeInFPUDelaySlot(const MachineInstr &MIInSlot,
97+
const MachineInstr &FPUMI) const;
98+
9599
/// Predicate to determine if an instruction has a forbidden slot.
96100
bool HasForbiddenSlot(const MachineInstr &MI) const;
97101

102+
/// Predicate to determine if an instruction has an FPU delay slot.
103+
bool HasFPUDelaySlot(const MachineInstr &MI) const;
104+
98105
/// Insert nop instruction when hazard condition is found
99106
void insertNoop(MachineBasicBlock &MBB,
100107
MachineBasicBlock::iterator MI) const override;

llvm/test/CodeGen/Mips/llvm-ir/select-dbl.ll

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ define double @tst_select_fcmp_olt_double(double %x, double %y) {
203203
; M2-LABEL: tst_select_fcmp_olt_double:
204204
; M2: # %bb.0: # %entry
205205
; M2-NEXT: c.olt.d $f12, $f14
206+
; M2-NEXT: nop
206207
; M2-NEXT: bc1t $BB2_2
207208
; M2-NEXT: mov.d $f0, $f12
208209
; M2-NEXT: # %bb.1: # %entry
@@ -236,6 +237,7 @@ define double @tst_select_fcmp_olt_double(double %x, double %y) {
236237
; M3-LABEL: tst_select_fcmp_olt_double:
237238
; M3: # %bb.0: # %entry
238239
; M3-NEXT: c.olt.d $f12, $f13
240+
; M3-NEXT: nop
239241
; M3-NEXT: bc1t .LBB2_2
240242
; M3-NEXT: mov.d $f0, $f12
241243
; M3-NEXT: # %bb.1: # %entry
@@ -283,6 +285,7 @@ define double @tst_select_fcmp_ole_double(double %x, double %y) {
283285
; M2-LABEL: tst_select_fcmp_ole_double:
284286
; M2: # %bb.0: # %entry
285287
; M2-NEXT: c.ole.d $f12, $f14
288+
; M2-NEXT: nop
286289
; M2-NEXT: bc1t $BB3_2
287290
; M2-NEXT: mov.d $f0, $f12
288291
; M2-NEXT: # %bb.1: # %entry
@@ -316,6 +319,7 @@ define double @tst_select_fcmp_ole_double(double %x, double %y) {
316319
; M3-LABEL: tst_select_fcmp_ole_double:
317320
; M3: # %bb.0: # %entry
318321
; M3-NEXT: c.ole.d $f12, $f13
322+
; M3-NEXT: nop
319323
; M3-NEXT: bc1t .LBB3_2
320324
; M3-NEXT: mov.d $f0, $f12
321325
; M3-NEXT: # %bb.1: # %entry
@@ -363,6 +367,7 @@ define double @tst_select_fcmp_ogt_double(double %x, double %y) {
363367
; M2-LABEL: tst_select_fcmp_ogt_double:
364368
; M2: # %bb.0: # %entry
365369
; M2-NEXT: c.ule.d $f12, $f14
370+
; M2-NEXT: nop
366371
; M2-NEXT: bc1f $BB4_2
367372
; M2-NEXT: mov.d $f0, $f12
368373
; M2-NEXT: # %bb.1: # %entry
@@ -396,6 +401,7 @@ define double @tst_select_fcmp_ogt_double(double %x, double %y) {
396401
; M3-LABEL: tst_select_fcmp_ogt_double:
397402
; M3: # %bb.0: # %entry
398403
; M3-NEXT: c.ule.d $f12, $f13
404+
; M3-NEXT: nop
399405
; M3-NEXT: bc1f .LBB4_2
400406
; M3-NEXT: mov.d $f0, $f12
401407
; M3-NEXT: # %bb.1: # %entry
@@ -443,6 +449,7 @@ define double @tst_select_fcmp_oge_double(double %x, double %y) {
443449
; M2-LABEL: tst_select_fcmp_oge_double:
444450
; M2: # %bb.0: # %entry
445451
; M2-NEXT: c.ult.d $f12, $f14
452+
; M2-NEXT: nop
446453
; M2-NEXT: bc1f $BB5_2
447454
; M2-NEXT: mov.d $f0, $f12
448455
; M2-NEXT: # %bb.1: # %entry
@@ -476,6 +483,7 @@ define double @tst_select_fcmp_oge_double(double %x, double %y) {
476483
; M3-LABEL: tst_select_fcmp_oge_double:
477484
; M3: # %bb.0: # %entry
478485
; M3-NEXT: c.ult.d $f12, $f13
486+
; M3-NEXT: nop
479487
; M3-NEXT: bc1f .LBB5_2
480488
; M3-NEXT: mov.d $f0, $f12
481489
; M3-NEXT: # %bb.1: # %entry
@@ -523,6 +531,7 @@ define double @tst_select_fcmp_oeq_double(double %x, double %y) {
523531
; M2-LABEL: tst_select_fcmp_oeq_double:
524532
; M2: # %bb.0: # %entry
525533
; M2-NEXT: c.eq.d $f12, $f14
534+
; M2-NEXT: nop
526535
; M2-NEXT: bc1t $BB6_2
527536
; M2-NEXT: mov.d $f0, $f12
528537
; M2-NEXT: # %bb.1: # %entry
@@ -556,6 +565,7 @@ define double @tst_select_fcmp_oeq_double(double %x, double %y) {
556565
; M3-LABEL: tst_select_fcmp_oeq_double:
557566
; M3: # %bb.0: # %entry
558567
; M3-NEXT: c.eq.d $f12, $f13
568+
; M3-NEXT: nop
559569
; M3-NEXT: bc1t .LBB6_2
560570
; M3-NEXT: mov.d $f0, $f12
561571
; M3-NEXT: # %bb.1: # %entry
@@ -603,6 +613,7 @@ define double @tst_select_fcmp_one_double(double %x, double %y) {
603613
; M2-LABEL: tst_select_fcmp_one_double:
604614
; M2: # %bb.0: # %entry
605615
; M2-NEXT: c.ueq.d $f12, $f14
616+
; M2-NEXT: nop
606617
; M2-NEXT: bc1f $BB7_2
607618
; M2-NEXT: mov.d $f0, $f12
608619
; M2-NEXT: # %bb.1: # %entry
@@ -637,6 +648,7 @@ define double @tst_select_fcmp_one_double(double %x, double %y) {
637648
; M3-LABEL: tst_select_fcmp_one_double:
638649
; M3: # %bb.0: # %entry
639650
; M3-NEXT: c.ueq.d $f12, $f13
651+
; M3-NEXT: nop
640652
; M3-NEXT: bc1f .LBB7_2
641653
; M3-NEXT: mov.d $f0, $f12
642654
; M3-NEXT: # %bb.1: # %entry

llvm/test/CodeGen/Mips/llvm-ir/select-flt.ll

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ define float @tst_select_fcmp_olt_float(float %x, float %y) {
189189
; M2-LABEL: tst_select_fcmp_olt_float:
190190
; M2: # %bb.0: # %entry
191191
; M2-NEXT: c.olt.s $f12, $f14
192+
; M2-NEXT: nop
192193
; M2-NEXT: bc1t $BB2_2
193194
; M2-NEXT: mov.s $f0, $f12
194195
; M2-NEXT: # %bb.1: # %entry
@@ -220,6 +221,7 @@ define float @tst_select_fcmp_olt_float(float %x, float %y) {
220221
; M3-LABEL: tst_select_fcmp_olt_float:
221222
; M3: # %bb.0: # %entry
222223
; M3-NEXT: c.olt.s $f12, $f13
224+
; M3-NEXT: nop
223225
; M3-NEXT: bc1t .LBB2_2
224226
; M3-NEXT: mov.s $f0, $f12
225227
; M3-NEXT: # %bb.1: # %entry
@@ -263,6 +265,7 @@ define float @tst_select_fcmp_ole_float(float %x, float %y) {
263265
; M2-LABEL: tst_select_fcmp_ole_float:
264266
; M2: # %bb.0: # %entry
265267
; M2-NEXT: c.ole.s $f12, $f14
268+
; M2-NEXT: nop
266269
; M2-NEXT: bc1t $BB3_2
267270
; M2-NEXT: mov.s $f0, $f12
268271
; M2-NEXT: # %bb.1: # %entry
@@ -294,6 +297,7 @@ define float @tst_select_fcmp_ole_float(float %x, float %y) {
294297
; M3-LABEL: tst_select_fcmp_ole_float:
295298
; M3: # %bb.0: # %entry
296299
; M3-NEXT: c.ole.s $f12, $f13
300+
; M3-NEXT: nop
297301
; M3-NEXT: bc1t .LBB3_2
298302
; M3-NEXT: mov.s $f0, $f12
299303
; M3-NEXT: # %bb.1: # %entry
@@ -337,6 +341,7 @@ define float @tst_select_fcmp_ogt_float(float %x, float %y) {
337341
; M2-LABEL: tst_select_fcmp_ogt_float:
338342
; M2: # %bb.0: # %entry
339343
; M2-NEXT: c.ule.s $f12, $f14
344+
; M2-NEXT: nop
340345
; M2-NEXT: bc1f $BB4_2
341346
; M2-NEXT: mov.s $f0, $f12
342347
; M2-NEXT: # %bb.1: # %entry
@@ -368,6 +373,7 @@ define float @tst_select_fcmp_ogt_float(float %x, float %y) {
368373
; M3-LABEL: tst_select_fcmp_ogt_float:
369374
; M3: # %bb.0: # %entry
370375
; M3-NEXT: c.ule.s $f12, $f13
376+
; M3-NEXT: nop
371377
; M3-NEXT: bc1f .LBB4_2
372378
; M3-NEXT: mov.s $f0, $f12
373379
; M3-NEXT: # %bb.1: # %entry
@@ -411,6 +417,7 @@ define float @tst_select_fcmp_oge_float(float %x, float %y) {
411417
; M2-LABEL: tst_select_fcmp_oge_float:
412418
; M2: # %bb.0: # %entry
413419
; M2-NEXT: c.ult.s $f12, $f14
420+
; M2-NEXT: nop
414421
; M2-NEXT: bc1f $BB5_2
415422
; M2-NEXT: mov.s $f0, $f12
416423
; M2-NEXT: # %bb.1: # %entry
@@ -442,6 +449,7 @@ define float @tst_select_fcmp_oge_float(float %x, float %y) {
442449
; M3-LABEL: tst_select_fcmp_oge_float:
443450
; M3: # %bb.0: # %entry
444451
; M3-NEXT: c.ult.s $f12, $f13
452+
; M3-NEXT: nop
445453
; M3-NEXT: bc1f .LBB5_2
446454
; M3-NEXT: mov.s $f0, $f12
447455
; M3-NEXT: # %bb.1: # %entry
@@ -485,6 +493,7 @@ define float @tst_select_fcmp_oeq_float(float %x, float %y) {
485493
; M2-LABEL: tst_select_fcmp_oeq_float:
486494
; M2: # %bb.0: # %entry
487495
; M2-NEXT: c.eq.s $f12, $f14
496+
; M2-NEXT: nop
488497
; M2-NEXT: bc1t $BB6_2
489498
; M2-NEXT: mov.s $f0, $f12
490499
; M2-NEXT: # %bb.1: # %entry
@@ -516,6 +525,7 @@ define float @tst_select_fcmp_oeq_float(float %x, float %y) {
516525
; M3-LABEL: tst_select_fcmp_oeq_float:
517526
; M3: # %bb.0: # %entry
518527
; M3-NEXT: c.eq.s $f12, $f13
528+
; M3-NEXT: nop
519529
; M3-NEXT: bc1t .LBB6_2
520530
; M3-NEXT: mov.s $f0, $f12
521531
; M3-NEXT: # %bb.1: # %entry
@@ -559,6 +569,7 @@ define float @tst_select_fcmp_one_float(float %x, float %y) {
559569
; M2-LABEL: tst_select_fcmp_one_float:
560570
; M2: # %bb.0: # %entry
561571
; M2-NEXT: c.ueq.s $f12, $f14
572+
; M2-NEXT: nop
562573
; M2-NEXT: bc1f $BB7_2
563574
; M2-NEXT: mov.s $f0, $f12
564575
; M2-NEXT: # %bb.1: # %entry
@@ -593,6 +604,7 @@ define float @tst_select_fcmp_one_float(float %x, float %y) {
593604
; M3-LABEL: tst_select_fcmp_one_float:
594605
; M3: # %bb.0: # %entry
595606
; M3-NEXT: c.ueq.s $f12, $f13
607+
; M3-NEXT: nop
596608
; M3-NEXT: bc1f .LBB7_2
597609
; M3-NEXT: mov.s $f0, $f12
598610
; M3-NEXT: # %bb.1: # %entry

0 commit comments

Comments
 (0)