Skip to content

[cherry-pick] Fix MIPS FPU comparisons #124

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 39 additions & 13 deletions llvm/lib/Target/Mips/MipsBranchExpansion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
///
/// Regarding compact branch hazard prevention:
///
/// Hazards handled: forbidden slots for MIPSR6.
/// Hazards handled: forbidden slots for MIPSR6, FPU slots for MIPS3 and below.
///
/// A forbidden slot hazard occurs when a compact branch instruction is executed
/// and the adjacent instruction in memory is a control transfer instruction
Expand Down Expand Up @@ -160,7 +160,10 @@ class MipsBranchExpansion : public MachineFunctionPass {
bool buildProperJumpMI(MachineBasicBlock *MBB,
MachineBasicBlock::iterator Pos, DebugLoc DL);
void expandToLongBranch(MBBInfo &Info);
template <typename Pred, typename Safe>
bool handleSlot(Pred Predicate, Safe SafeInSlot);
bool handleForbiddenSlot();
bool handleFPUDelaySlot();
bool handlePossibleLongBranch();

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

bool MipsBranchExpansion::handleForbiddenSlot() {
// Forbidden slot hazards are only defined for MIPSR6 but not microMIPSR6.
if (!STI->hasMips32r6() || STI->inMicroMipsMode())
return false;

template <typename Pred, typename Safe>
bool MipsBranchExpansion::handleSlot(Pred Predicate, Safe SafeInSlot) {
bool Changed = false;

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

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

Iter Inst;
Iter IInSlot;
bool LastInstInFunction =
std::next(I) == FI->end() && std::next(FI) == MFp->end();
if (!LastInstInFunction) {
std::pair<Iter, bool> Res = getNextMachineInstr(std::next(I), &*FI);
LastInstInFunction |= Res.second;
Inst = Res.first;
IInSlot = Res.first;
}

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

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

bool MipsBranchExpansion::handleForbiddenSlot() {
// Forbidden slot hazards are only defined for MIPSR6 but not microMIPSR6.
if (!STI->hasMips32r6() || STI->inMicroMipsMode())
return false;

return handleSlot(
[this](auto &I) -> bool { return TII->HasForbiddenSlot(I); },
[this](auto &IInSlot, auto &I) -> bool {
return TII->SafeInForbiddenSlot(IInSlot);
});
}

bool MipsBranchExpansion::handleFPUDelaySlot() {
// FPU delay slots are only defined for MIPS3 and below.
if (STI->hasMips32() || STI->hasMips4())
return false;

return handleSlot([this](auto &I) -> bool { return TII->HasFPUDelaySlot(I); },
[this](auto &IInSlot, auto &I) -> bool {
return TII->SafeInFPUDelaySlot(IInSlot, I);
});
}

bool MipsBranchExpansion::handlePossibleLongBranch() {
if (STI->inMips16Mode() || !STI->enableLongBranchPass())
return false;
Expand Down Expand Up @@ -857,13 +880,16 @@ bool MipsBranchExpansion::runOnMachineFunction(MachineFunction &MF) {
// Run these two at least once
bool longBranchChanged = handlePossibleLongBranch();
bool forbiddenSlotChanged = handleForbiddenSlot();
bool fpuDelaySlotChanged = handleFPUDelaySlot();

bool Changed = longBranchChanged || forbiddenSlotChanged;
bool Changed =
longBranchChanged || forbiddenSlotChanged || fpuDelaySlotChanged;

// Then run them alternatively while there are changes
while (forbiddenSlotChanged) {
longBranchChanged = handlePossibleLongBranch();
if (!longBranchChanged)
fpuDelaySlotChanged = handleFPUDelaySlot();
if (!longBranchChanged && !fpuDelaySlotChanged)
break;
forbiddenSlotChanged = handleForbiddenSlot();
}
Expand Down
49 changes: 49 additions & 0 deletions llvm/lib/Target/Mips/MipsInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -568,11 +568,60 @@ bool MipsInstrInfo::SafeInForbiddenSlot(const MachineInstr &MI) const {
return (MI.getDesc().TSFlags & MipsII::IsCTI) == 0;
}

bool MipsInstrInfo::SafeInFPUDelaySlot(const MachineInstr &MIInSlot,
const MachineInstr &FPUMI) const {
if (MIInSlot.isInlineAsm())
return false;

if (HasFPUDelaySlot(MIInSlot))
return false;

switch (MIInSlot.getOpcode()) {
case Mips::BC1F:
case Mips::BC1FL:
case Mips::BC1T:
case Mips::BC1TL:
return false;
}

for (const MachineOperand &Op : FPUMI.defs()) {
if (!Op.isReg())
continue;

bool Reads, Writes;
std::tie(Reads, Writes) = MIInSlot.readsWritesVirtualRegister(Op.getReg());

if (Reads || Writes)
return false;
}

return true;
}

/// Predicate for distingushing instructions that have forbidden slots.
bool MipsInstrInfo::HasForbiddenSlot(const MachineInstr &MI) const {
return (MI.getDesc().TSFlags & MipsII::HasForbiddenSlot) != 0;
}

/// Predicate for distingushing instructions that have FPU delay slots.
bool MipsInstrInfo::HasFPUDelaySlot(const MachineInstr &MI) const {
switch (MI.getOpcode()) {
case Mips::MTC1:
case Mips::MFC1:
case Mips::MTC1_D64:
case Mips::MFC1_D64:
case Mips::DMTC1:
case Mips::DMFC1:
case Mips::FCMP_S32:
case Mips::FCMP_D32:
case Mips::FCMP_D64:
return true;

default:
return false;
}
}

/// Return the number of bytes of code the specified instruction may be.
unsigned MipsInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
switch (MI.getOpcode()) {
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/Target/Mips/MipsInstrInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,16 @@ class MipsInstrInfo : public MipsGenInstrInfo {
/// Predicate to determine if an instruction can go in a forbidden slot.
bool SafeInForbiddenSlot(const MachineInstr &MI) const;

/// Predicate to determine if an instruction can go in an FPU delay slot.
bool SafeInFPUDelaySlot(const MachineInstr &MIInSlot,
const MachineInstr &FPUMI) const;

/// Predicate to determine if an instruction has a forbidden slot.
bool HasForbiddenSlot(const MachineInstr &MI) const;

/// Predicate to determine if an instruction has an FPU delay slot.
bool HasFPUDelaySlot(const MachineInstr &MI) const;

/// Insert nop instruction when hazard condition is found
void insertNoop(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI) const override;
Expand Down
12 changes: 12 additions & 0 deletions llvm/test/CodeGen/Mips/llvm-ir/select-dbl.ll
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ define double @tst_select_fcmp_olt_double(double %x, double %y) {
; M2-LABEL: tst_select_fcmp_olt_double:
; M2: # %bb.0: # %entry
; M2-NEXT: c.olt.d $f12, $f14
; M2-NEXT: nop
; M2-NEXT: bc1t $BB2_2
; M2-NEXT: mov.d $f0, $f12
; M2-NEXT: # %bb.1: # %entry
Expand Down Expand Up @@ -236,6 +237,7 @@ define double @tst_select_fcmp_olt_double(double %x, double %y) {
; M3-LABEL: tst_select_fcmp_olt_double:
; M3: # %bb.0: # %entry
; M3-NEXT: c.olt.d $f12, $f13
; M3-NEXT: nop
; M3-NEXT: bc1t .LBB2_2
; M3-NEXT: mov.d $f0, $f12
; M3-NEXT: # %bb.1: # %entry
Expand Down Expand Up @@ -283,6 +285,7 @@ define double @tst_select_fcmp_ole_double(double %x, double %y) {
; M2-LABEL: tst_select_fcmp_ole_double:
; M2: # %bb.0: # %entry
; M2-NEXT: c.ole.d $f12, $f14
; M2-NEXT: nop
; M2-NEXT: bc1t $BB3_2
; M2-NEXT: mov.d $f0, $f12
; M2-NEXT: # %bb.1: # %entry
Expand Down Expand Up @@ -316,6 +319,7 @@ define double @tst_select_fcmp_ole_double(double %x, double %y) {
; M3-LABEL: tst_select_fcmp_ole_double:
; M3: # %bb.0: # %entry
; M3-NEXT: c.ole.d $f12, $f13
; M3-NEXT: nop
; M3-NEXT: bc1t .LBB3_2
; M3-NEXT: mov.d $f0, $f12
; M3-NEXT: # %bb.1: # %entry
Expand Down Expand Up @@ -363,6 +367,7 @@ define double @tst_select_fcmp_ogt_double(double %x, double %y) {
; M2-LABEL: tst_select_fcmp_ogt_double:
; M2: # %bb.0: # %entry
; M2-NEXT: c.ule.d $f12, $f14
; M2-NEXT: nop
; M2-NEXT: bc1f $BB4_2
; M2-NEXT: mov.d $f0, $f12
; M2-NEXT: # %bb.1: # %entry
Expand Down Expand Up @@ -396,6 +401,7 @@ define double @tst_select_fcmp_ogt_double(double %x, double %y) {
; M3-LABEL: tst_select_fcmp_ogt_double:
; M3: # %bb.0: # %entry
; M3-NEXT: c.ule.d $f12, $f13
; M3-NEXT: nop
; M3-NEXT: bc1f .LBB4_2
; M3-NEXT: mov.d $f0, $f12
; M3-NEXT: # %bb.1: # %entry
Expand Down Expand Up @@ -443,6 +449,7 @@ define double @tst_select_fcmp_oge_double(double %x, double %y) {
; M2-LABEL: tst_select_fcmp_oge_double:
; M2: # %bb.0: # %entry
; M2-NEXT: c.ult.d $f12, $f14
; M2-NEXT: nop
; M2-NEXT: bc1f $BB5_2
; M2-NEXT: mov.d $f0, $f12
; M2-NEXT: # %bb.1: # %entry
Expand Down Expand Up @@ -476,6 +483,7 @@ define double @tst_select_fcmp_oge_double(double %x, double %y) {
; M3-LABEL: tst_select_fcmp_oge_double:
; M3: # %bb.0: # %entry
; M3-NEXT: c.ult.d $f12, $f13
; M3-NEXT: nop
; M3-NEXT: bc1f .LBB5_2
; M3-NEXT: mov.d $f0, $f12
; M3-NEXT: # %bb.1: # %entry
Expand Down Expand Up @@ -523,6 +531,7 @@ define double @tst_select_fcmp_oeq_double(double %x, double %y) {
; M2-LABEL: tst_select_fcmp_oeq_double:
; M2: # %bb.0: # %entry
; M2-NEXT: c.eq.d $f12, $f14
; M2-NEXT: nop
; M2-NEXT: bc1t $BB6_2
; M2-NEXT: mov.d $f0, $f12
; M2-NEXT: # %bb.1: # %entry
Expand Down Expand Up @@ -556,6 +565,7 @@ define double @tst_select_fcmp_oeq_double(double %x, double %y) {
; M3-LABEL: tst_select_fcmp_oeq_double:
; M3: # %bb.0: # %entry
; M3-NEXT: c.eq.d $f12, $f13
; M3-NEXT: nop
; M3-NEXT: bc1t .LBB6_2
; M3-NEXT: mov.d $f0, $f12
; M3-NEXT: # %bb.1: # %entry
Expand Down Expand Up @@ -603,6 +613,7 @@ define double @tst_select_fcmp_one_double(double %x, double %y) {
; M2-LABEL: tst_select_fcmp_one_double:
; M2: # %bb.0: # %entry
; M2-NEXT: c.ueq.d $f12, $f14
; M2-NEXT: nop
; M2-NEXT: bc1f $BB7_2
; M2-NEXT: mov.d $f0, $f12
; M2-NEXT: # %bb.1: # %entry
Expand Down Expand Up @@ -637,6 +648,7 @@ define double @tst_select_fcmp_one_double(double %x, double %y) {
; M3-LABEL: tst_select_fcmp_one_double:
; M3: # %bb.0: # %entry
; M3-NEXT: c.ueq.d $f12, $f13
; M3-NEXT: nop
; M3-NEXT: bc1f .LBB7_2
; M3-NEXT: mov.d $f0, $f12
; M3-NEXT: # %bb.1: # %entry
Expand Down
12 changes: 12 additions & 0 deletions llvm/test/CodeGen/Mips/llvm-ir/select-flt.ll
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ define float @tst_select_fcmp_olt_float(float %x, float %y) {
; M2-LABEL: tst_select_fcmp_olt_float:
; M2: # %bb.0: # %entry
; M2-NEXT: c.olt.s $f12, $f14
; M2-NEXT: nop
; M2-NEXT: bc1t $BB2_2
; M2-NEXT: mov.s $f0, $f12
; M2-NEXT: # %bb.1: # %entry
Expand Down Expand Up @@ -220,6 +221,7 @@ define float @tst_select_fcmp_olt_float(float %x, float %y) {
; M3-LABEL: tst_select_fcmp_olt_float:
; M3: # %bb.0: # %entry
; M3-NEXT: c.olt.s $f12, $f13
; M3-NEXT: nop
; M3-NEXT: bc1t .LBB2_2
; M3-NEXT: mov.s $f0, $f12
; M3-NEXT: # %bb.1: # %entry
Expand Down Expand Up @@ -263,6 +265,7 @@ define float @tst_select_fcmp_ole_float(float %x, float %y) {
; M2-LABEL: tst_select_fcmp_ole_float:
; M2: # %bb.0: # %entry
; M2-NEXT: c.ole.s $f12, $f14
; M2-NEXT: nop
; M2-NEXT: bc1t $BB3_2
; M2-NEXT: mov.s $f0, $f12
; M2-NEXT: # %bb.1: # %entry
Expand Down Expand Up @@ -294,6 +297,7 @@ define float @tst_select_fcmp_ole_float(float %x, float %y) {
; M3-LABEL: tst_select_fcmp_ole_float:
; M3: # %bb.0: # %entry
; M3-NEXT: c.ole.s $f12, $f13
; M3-NEXT: nop
; M3-NEXT: bc1t .LBB3_2
; M3-NEXT: mov.s $f0, $f12
; M3-NEXT: # %bb.1: # %entry
Expand Down Expand Up @@ -337,6 +341,7 @@ define float @tst_select_fcmp_ogt_float(float %x, float %y) {
; M2-LABEL: tst_select_fcmp_ogt_float:
; M2: # %bb.0: # %entry
; M2-NEXT: c.ule.s $f12, $f14
; M2-NEXT: nop
; M2-NEXT: bc1f $BB4_2
; M2-NEXT: mov.s $f0, $f12
; M2-NEXT: # %bb.1: # %entry
Expand Down Expand Up @@ -368,6 +373,7 @@ define float @tst_select_fcmp_ogt_float(float %x, float %y) {
; M3-LABEL: tst_select_fcmp_ogt_float:
; M3: # %bb.0: # %entry
; M3-NEXT: c.ule.s $f12, $f13
; M3-NEXT: nop
; M3-NEXT: bc1f .LBB4_2
; M3-NEXT: mov.s $f0, $f12
; M3-NEXT: # %bb.1: # %entry
Expand Down Expand Up @@ -411,6 +417,7 @@ define float @tst_select_fcmp_oge_float(float %x, float %y) {
; M2-LABEL: tst_select_fcmp_oge_float:
; M2: # %bb.0: # %entry
; M2-NEXT: c.ult.s $f12, $f14
; M2-NEXT: nop
; M2-NEXT: bc1f $BB5_2
; M2-NEXT: mov.s $f0, $f12
; M2-NEXT: # %bb.1: # %entry
Expand Down Expand Up @@ -442,6 +449,7 @@ define float @tst_select_fcmp_oge_float(float %x, float %y) {
; M3-LABEL: tst_select_fcmp_oge_float:
; M3: # %bb.0: # %entry
; M3-NEXT: c.ult.s $f12, $f13
; M3-NEXT: nop
; M3-NEXT: bc1f .LBB5_2
; M3-NEXT: mov.s $f0, $f12
; M3-NEXT: # %bb.1: # %entry
Expand Down Expand Up @@ -485,6 +493,7 @@ define float @tst_select_fcmp_oeq_float(float %x, float %y) {
; M2-LABEL: tst_select_fcmp_oeq_float:
; M2: # %bb.0: # %entry
; M2-NEXT: c.eq.s $f12, $f14
; M2-NEXT: nop
; M2-NEXT: bc1t $BB6_2
; M2-NEXT: mov.s $f0, $f12
; M2-NEXT: # %bb.1: # %entry
Expand Down Expand Up @@ -516,6 +525,7 @@ define float @tst_select_fcmp_oeq_float(float %x, float %y) {
; M3-LABEL: tst_select_fcmp_oeq_float:
; M3: # %bb.0: # %entry
; M3-NEXT: c.eq.s $f12, $f13
; M3-NEXT: nop
; M3-NEXT: bc1t .LBB6_2
; M3-NEXT: mov.s $f0, $f12
; M3-NEXT: # %bb.1: # %entry
Expand Down Expand Up @@ -559,6 +569,7 @@ define float @tst_select_fcmp_one_float(float %x, float %y) {
; M2-LABEL: tst_select_fcmp_one_float:
; M2: # %bb.0: # %entry
; M2-NEXT: c.ueq.s $f12, $f14
; M2-NEXT: nop
; M2-NEXT: bc1f $BB7_2
; M2-NEXT: mov.s $f0, $f12
; M2-NEXT: # %bb.1: # %entry
Expand Down Expand Up @@ -593,6 +604,7 @@ define float @tst_select_fcmp_one_float(float %x, float %y) {
; M3-LABEL: tst_select_fcmp_one_float:
; M3: # %bb.0: # %entry
; M3-NEXT: c.ueq.s $f12, $f13
; M3-NEXT: nop
; M3-NEXT: bc1f .LBB7_2
; M3-NEXT: mov.s $f0, $f12
; M3-NEXT: # %bb.1: # %entry
Expand Down