Index: llvm/trunk/lib/Target/Mips/CMakeLists.txt =================================================================== --- llvm/trunk/lib/Target/Mips/CMakeLists.txt +++ llvm/trunk/lib/Target/Mips/CMakeLists.txt @@ -27,6 +27,7 @@ MipsConstantIslandPass.cpp MipsDelaySlotFiller.cpp MipsFastISel.cpp + MipsHazardSchedule.cpp MipsInstrInfo.cpp MipsISelDAGToDAG.cpp MipsISelLowering.cpp Index: llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h =================================================================== --- llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h +++ llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h @@ -117,7 +117,12 @@ /// FrmOther - This form is for instructions that have no specific format. FrmOther = 6, - FormMask = 15 + FormMask = 15, + /// IsCTI - Instruction is a Control Transfer Instruction. + IsCTI = 1 << 4, + /// HasForbiddenSlot - Instruction has a forbidden slot. + HasForbiddenSlot = 1 << 5 + }; } } Index: llvm/trunk/lib/Target/Mips/Mips.h =================================================================== --- llvm/trunk/lib/Target/Mips/Mips.h +++ llvm/trunk/lib/Target/Mips/Mips.h @@ -29,6 +29,7 @@ FunctionPass *createMipsModuleISelDagPass(MipsTargetMachine &TM); FunctionPass *createMipsOptimizePICCallPass(MipsTargetMachine &TM); FunctionPass *createMipsDelaySlotFillerPass(MipsTargetMachine &TM); + FunctionPass *createMipsHazardSchedule(MipsTargetMachine &tm); FunctionPass *createMipsLongBranchPass(MipsTargetMachine &TM); FunctionPass *createMipsConstantIslandPass(MipsTargetMachine &tm); } // end namespace llvm; Index: llvm/trunk/lib/Target/Mips/Mips32r6InstrInfo.td =================================================================== --- llvm/trunk/lib/Target/Mips/Mips32r6InstrInfo.td +++ llvm/trunk/lib/Target/Mips/Mips32r6InstrInfo.td @@ -182,6 +182,7 @@ dag InOperandList = (ins FGROpnd:$fs, FGROpnd:$ft); string AsmString = !strconcat("cmp.", CondStr, ".", Typestr, "\t$fd, $fs, $ft"); list Pattern = [(set FGRCCOpnd:$fd, (Op FGROpnd:$fs, FGROpnd:$ft))]; + bit isCTI = 1; } multiclass CMP_CC_M : BRANCH_DESC_BASE, @@ -309,6 +311,7 @@ string AsmString = !strconcat(instr_asm, "\t$offset"); bit isBarrier = 1; InstrItinClass Itinerary = II_BC; + bit isCTI = 1; } class CMP_BC_DESC_BASE Defs = [AT]; InstrItinClass Itinerary = II_BCCC; + bit hasForbiddenSlot = 1; + bit isCTI = 1; } class CMP_CBR_EQNE_Z_DESC_BASE Defs = [AT]; InstrItinClass Itinerary = II_BCCZC; + bit hasForbiddenSlot = 1; + bit isCTI = 1; } class CMP_CBR_RT_Z_DESC_BASE Defs = [AT]; InstrItinClass Itinerary = II_BCCZC; + bit hasForbiddenSlot = 1; + bit isCTI = 1; } class BAL_DESC : BC_DESC_BASE<"bal", brtarget> { bit isCall = 1; bit hasDelaySlot = 1; list Defs = [RA]; + bit isCTI = 1; } class BALC_DESC : BC_DESC_BASE<"balc", brtarget26> { bit isCall = 1; list Defs = [RA]; InstrItinClass Itinerary = II_BALC; + bit isCTI = 1; } class BC_DESC : BC_DESC_BASE<"bc", brtarget26>; @@ -385,6 +396,7 @@ dag OutOperandList = (outs); string AsmString = instr_asm; bit hasDelaySlot = 1; + bit isCTI = 1; } class BC2EQZ_DESC : COP2_BCCZ_DESC_BASE<"bc2eqz $ct, $offset">; @@ -403,6 +415,7 @@ bit isTerminator = 1; bit hasDelaySlot = 0; InstrItinClass Itinerary = itin; + bit isCTI = 1; } class JIALC_DESC : JMP_IDX_COMPACT_DESC_BASE<"jialc", calloffset16, @@ -423,6 +436,7 @@ bit hasDelaySlot = 1; bit isTerminator=1; bit isBarrier=1; + bit isCTI = 1; } class BITSWAP_DESC_BASE Pattern = []; + bit isCTI = 1; } //===----------------------------------------------------------------------===// Index: llvm/trunk/lib/Target/Mips/MipsDelaySlotFiller.cpp =================================================================== --- llvm/trunk/lib/Target/Mips/MipsDelaySlotFiller.cpp +++ llvm/trunk/lib/Target/Mips/MipsDelaySlotFiller.cpp @@ -507,23 +507,13 @@ // Replace Branch with the compact branch instruction. Iter Filler::replaceWithCompactBranch(MachineBasicBlock &MBB, Iter Branch, DebugLoc DL) { - const MipsInstrInfo *TII = - MBB.getParent()->getSubtarget().getInstrInfo(); - - unsigned NewOpcode = - (((unsigned) Branch->getOpcode()) == Mips::BEQ) ? Mips::BEQZC_MM - : Mips::BNEZC_MM; - - const MCInstrDesc &NewDesc = TII->get(NewOpcode); - MachineInstrBuilder MIB = BuildMI(MBB, Branch, DL, NewDesc); - - MIB.addReg(Branch->getOperand(0).getReg()); - MIB.addMBB(Branch->getOperand(2).getMBB()); + const MipsSubtarget &STI = MBB.getParent()->getSubtarget(); + const MipsInstrInfo *TII = STI.getInstrInfo(); - Iter tmpIter = Branch; - Branch = std::prev(Branch); - MBB.erase(tmpIter); + unsigned NewOpcode = TII->getEquivalentCompactForm(Branch); + Branch = TII->genInstrWithNewOpc(NewOpcode, Branch); + std::next(Branch)->eraseFromParent(); return Branch; } @@ -611,27 +601,27 @@ // If instruction is BEQ or BNE with one ZERO register, then instead of // adding NOP replace this instruction with the corresponding compact // branch instruction, i.e. BEQZC or BNEZC. - unsigned Opcode = I->getOpcode(); if (InMicroMipsMode) { - switch (Opcode) { - case Mips::BEQ: - case Mips::BNE: - if (((unsigned) I->getOperand(1).getReg()) == Mips::ZERO) { - I = replaceWithCompactBranch(MBB, I, I->getDebugLoc()); - continue; - } - break; - case Mips::JR: - case Mips::PseudoReturn: - case Mips::PseudoIndirectBranch: - // For microMIPS the PseudoReturn and PseudoIndirectBranch are allways - // expanded to JR_MM, so they can be replaced with JRC16_MM. - I = replaceWithCompactJump(MBB, I, I->getDebugLoc()); - continue; - default: - break; + if (TII->getEquivalentCompactForm(I)) { + I = replaceWithCompactBranch(MBB, I, I->getDebugLoc()); + continue; + } + + if (I->isIndirectBranch() || I->isReturn()) { + // For microMIPS the PseudoReturn and PseudoIndirectBranch are always + // expanded to JR_MM, so they can be replaced with JRC16_MM. + I = replaceWithCompactJump(MBB, I, I->getDebugLoc()); + continue; } } + + // For MIPSR6 attempt to produce the corresponding compact (no delay slot) + // form of the branch. This should save putting in a NOP. + if ((STI.hasMips32r6()) && TII->getEquivalentCompactForm(I)) { + I = replaceWithCompactBranch(MBB, I, I->getDebugLoc()); + continue; + } + // Bundle the NOP to the instruction with the delay slot. BuildMI(MBB, std::next(I), I->getDebugLoc(), TII->get(Mips::NOP)); MIBundleBuilder(MBB, I, std::next(I, 2)); Index: llvm/trunk/lib/Target/Mips/MipsHazardSchedule.cpp =================================================================== --- llvm/trunk/lib/Target/Mips/MipsHazardSchedule.cpp +++ llvm/trunk/lib/Target/Mips/MipsHazardSchedule.cpp @@ -0,0 +1,136 @@ +//===-- MipsHazardSchedule.cpp - Workaround pipeline hazards---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// This pass is used to workaround certain pipeline hazards. For now, this covers +/// compact branch hazards. In future this pass can be extended to other pipeline +/// hazards, such as various MIPS1 hazards, processor errata that require +/// instruction reorganization, etc. +/// +/// This pass has to run after the delay slot filler as that pass can introduce +/// pipeline hazards, hence the existing hazard recognizer is not suitable. +/// +/// Hazards handled: forbidden slots for MIPSR6. +/// +/// A forbidden slot hazard occurs when a compact branch instruction is executed +/// and the adjacent instruction in memory is a control transfer instruction such +/// as a branch or jump, ERET, ERETNC, DERET, WAIT and PAUSE. +/// +/// For example: +/// +/// 0x8004 bnec a1,v0, +/// 0x8008 beqc a1,a2, +/// +/// In such cases, the processor is required to signal a Reserved Instruction +/// exception. +/// +/// Here, if the instruction at 0x8004 is executed, the processor will raise an +/// exception as there is a control transfer instruction at 0x8008. +/// +/// There are two sources of forbidden slot hazards: +/// +/// A) A previous pass has created a compact branch directly. +/// B) Transforming a delay slot branch into compact branch. This case can be +/// difficult to process as lookahead for hazards is insufficent, as +/// backwards delay slot fillling can also produce hazards in previously +/// processed instuctions. +/// +//===----------------------------------------------------------------------===// + +#include "Mips.h" +#include "MipsInstrInfo.h" +#include "MipsSEInstrInfo.h" +#include "MipsTargetMachine.h" +#include "llvm/IR/Function.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" + +using namespace llvm; + +#define DEBUG_TYPE "mips-hazard-schedule" + +STATISTIC(NumInsertedNops, "Number of nops inserted"); + +namespace { + +typedef MachineBasicBlock::iterator Iter; +typedef MachineBasicBlock::reverse_iterator ReverseIter; + +class MipsHazardSchedule : public MachineFunctionPass { + +public: + MipsHazardSchedule(TargetMachine &tm) : MachineFunctionPass(ID), TM(tm) {} + + const char *getPassName() const override { return "Mips Hazard Schedule"; } + + bool runOnMachineFunction(MachineFunction &F) override; + +private: + static char ID; + const TargetMachine &TM; +}; + +char MipsHazardSchedule::ID = 0; +} // end of anonymous namespace + +/// Returns a pass that clears pipeline hazards. +FunctionPass *llvm::createMipsHazardSchedule(MipsTargetMachine &tm) { + return new MipsHazardSchedule(tm); +} + +bool MipsHazardSchedule::runOnMachineFunction(MachineFunction &MF) { + + const MipsSubtarget *STI = + &static_cast(MF.getSubtarget()); + + // Forbidden slot hazards are only defined for MIPSR6. + if (!STI->hasMips32r6() || STI->inMicroMipsMode()) + return false; + + bool Changed = false; + const MipsInstrInfo *TII = STI->getInstrInfo(); + + for (MachineFunction::iterator FI = MF.begin(); FI != MF.end(); ++FI) { + for (Iter I = FI->begin(); I != FI->end(); ++I) { + + // Forbidden slot hazard handling. Use lookahead over state. + if (!TII->HasForbiddenSlot(*I)) + continue; + + bool InsertNop = false; + // Next instruction in the basic block. + if (std::next(I) != FI->end() && + !TII->SafeInForbiddenSlot(*std::next(I))) { + InsertNop = true; + } else { + // Next instruction in the physical successor basic block. + for (auto *Succ : FI->successors()) { + if (FI->isLayoutSuccessor(Succ) && + Succ->getFirstNonDebugInstr() != Succ->end() && + !TII->SafeInForbiddenSlot(*Succ->getFirstNonDebugInstr())) { + InsertNop = true; + break; + } + } + } + + if (InsertNop) { + Changed = true; + MIBundleBuilder(I) + .append(BuildMI(MF, I->getDebugLoc(), TII->get(Mips::NOP))); + NumInsertedNops++; + } + } + } + return Changed; +} Index: llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp =================================================================== --- llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp +++ llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp @@ -1064,6 +1064,8 @@ DebugLoc DL = MI->getDebugLoc(); unsigned LL, SC, AND, NOR, ZERO, BEQ; + // FIXME: The below code should check for the ISA to emit the correct 64bit + // operations when the size is 4. if (Size == 4) { if (isMicroMips) { LL = Mips::LL_MM; Index: llvm/trunk/lib/Target/Mips/MipsInstrFormats.td =================================================================== --- llvm/trunk/lib/Target/Mips/MipsInstrFormats.td +++ llvm/trunk/lib/Target/Mips/MipsInstrFormats.td @@ -94,10 +94,15 @@ // // Attributes specific to Mips instructions... // - bits<4> FormBits = Form.Value; + bits<4> FormBits = Form.Value; + bit isCTI = 0; // Any form of Control Transfer Instruction. + // Required for MIPSR6 + bit hasForbiddenSlot = 0; // Instruction has a forbidden slot. // TSFlags layout should be kept in sync with MipsInstrInfo.h. let TSFlags{3-0} = FormBits; + let TSFlags{4} = isCTI; + let TSFlags{5} = hasForbiddenSlot; let DecoderNamespace = "Mips"; Index: llvm/trunk/lib/Target/Mips/MipsInstrInfo.h =================================================================== --- llvm/trunk/lib/Target/Mips/MipsInstrInfo.h +++ llvm/trunk/lib/Target/Mips/MipsInstrInfo.h @@ -70,6 +70,15 @@ bool AllowModify, SmallVectorImpl &BranchInstrs) const; + /// Determine the opcode of a non-delay slot form for a branch if one exists. + unsigned getEquivalentCompactForm(const MachineBasicBlock::iterator I) const; + + /// Predicate to determine if an instruction can go in a forbidden slot. + bool SafeInForbiddenSlot(const MachineInstr &MI) const; + + /// Predicate to determine if an instruction has a forbidden slot. + bool HasForbiddenSlot(const MachineInstr &MI) const; + /// Insert nop instruction when hazard condition is found void insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const override; Index: llvm/trunk/lib/Target/Mips/MipsInstrInfo.cpp =================================================================== --- llvm/trunk/lib/Target/Mips/MipsInstrInfo.cpp +++ llvm/trunk/lib/Target/Mips/MipsInstrInfo.cpp @@ -256,6 +256,71 @@ return BT_CondUncond; } +/// Return the corresponding compact (no delay slot) form of a branch. +unsigned MipsInstrInfo::getEquivalentCompactForm( + const MachineBasicBlock::iterator I) const { + unsigned Opcode = I->getOpcode(); + bool canUseShortMMBranches = + Subtarget.inMicroMipsMode() && + (Opcode == Mips::BNE || Opcode == Mips::BEQ) && + I->getOperand(1).getReg() == Subtarget.getABI().GetZeroReg(); + + if (Subtarget.hasMips32r6() || canUseShortMMBranches) { + switch (Opcode) { + case Mips::B: + return Mips::BC; + case Mips::BAL: + return Mips::BALC; + case Mips::BEQ: + if (canUseShortMMBranches) + return Mips::BEQZC_MM; + else + return Mips::BEQC; + case Mips::BNE: + if (canUseShortMMBranches) + return Mips::BNEZC_MM; + else + return Mips::BNEC; + case Mips::BGE: + return Mips::BGEC; + case Mips::BGEU: + return Mips::BGEUC; + case Mips::BGEZ: + return Mips::BGEZC; + case Mips::BGTZ: + return Mips::BGTZC; + case Mips::BLEZ: + return Mips::BLEZC; + case Mips::BLT: + return Mips::BLTC; + case Mips::BLTU: + return Mips::BLTUC; + case Mips::BLTZ: + return Mips::BLTZC; + default: + return 0; + } + } + + return 0; +} + +/// Predicate for distingushing between control transfer instructions and all +/// other instructions for handling forbidden slots. Consider inline assembly +/// as unsafe as well. +bool MipsInstrInfo::SafeInForbiddenSlot(const MachineInstr &MI) const { + if (MI.isInlineAsm()) + return false; + + return (MI.getDesc().TSFlags & MipsII::IsCTI) == 0; + +} + +/// Predicate for distingushing instructions that have forbidden slots. +bool MipsInstrInfo::HasForbiddenSlot(const MachineInstr &MI) const { + return (MI.getDesc().TSFlags & MipsII::HasForbiddenSlot) != 0; +} + /// Return the number of bytes of code the specified instruction may be. unsigned MipsInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const { switch (MI->getOpcode()) { @@ -277,10 +342,46 @@ MipsInstrInfo::genInstrWithNewOpc(unsigned NewOpc, MachineBasicBlock::iterator I) const { MachineInstrBuilder MIB; + bool BranchWithZeroOperand = false; + + // Certain branches have two forms: e.g beq $1, $zero, dst vs beqz $1, dest + // Pick the zero form of the branch for readable assembly and for greater + // branch distance in non-microMIPS mode. + if (I->isBranch() && I->getOperand(1).isReg() && + // FIXME: Certain atomic sequences on mips64 generate 32bit references to + // Mips::ZERO, which is incorrect. This test should be updated to use + // Subtarget.getABI().GetZeroReg() when those atomic sequences and others + // are fixed. + (I->getOperand(1).getReg() == Mips::ZERO || + I->getOperand(1).getReg() == Mips::ZERO_64)) { + BranchWithZeroOperand = true; + switch (NewOpc) { + case Mips::BEQC: + NewOpc = Mips::BEQZC; + break; + case Mips::BNEC: + NewOpc = Mips::BNEZC; + break; + case Mips::BGEC: + NewOpc = Mips::BGEZC; + break; + case Mips::BLTC: + NewOpc = Mips::BLTZC; + break; + case Mips::BNEZC_MM: + case Mips::BEQZC_MM: + break; + default: + BranchWithZeroOperand = false; + break; + } + } + MIB = BuildMI(*I->getParent(), I, I->getDebugLoc(), get(NewOpc)); for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J) - MIB.addOperand(I->getOperand(J)); + if (!(BranchWithZeroOperand && (J == 1))) + MIB.addOperand(I->getOperand(J)); MIB.setMemRefs(I->memoperands_begin(), I->memoperands_end()); return MIB; Index: llvm/trunk/lib/Target/Mips/MipsInstrInfo.td =================================================================== --- llvm/trunk/lib/Target/Mips/MipsInstrInfo.td +++ llvm/trunk/lib/Target/Mips/MipsInstrInfo.td @@ -348,14 +348,17 @@ class IsBranch { bit isBranch = 1; + bit isCTI = 1; } class IsReturn { bit isReturn = 1; + bit isCTI = 1; } class IsCall { bit isCall = 1; + bit isCTI = 1; } class IsTailCall { @@ -365,6 +368,7 @@ bit isBarrier = 1; bit hasExtraSrcRegAllocReq = 1; bit isCodeGenOnly = 1; + bit isCTI = 1; } class IsAsCheapAsAMove { @@ -1068,6 +1072,7 @@ let isTerminator = 1; let hasDelaySlot = DelaySlot; let Defs = [AT]; + bit isCTI = 1; } class CBranchZero: InstSE<(outs), (ins RO:$rs), "jr\t$rs", [(operator RO:$rs)], II_JR, @@ -1134,7 +1142,7 @@ } // Jump and Link (Call) -let isCall=1, hasDelaySlot=1, Defs = [RA] in { +let isCall=1, hasDelaySlot=1, isCTI=1, Defs = [RA] in { class JumpLink : InstSE<(outs), (ins opnd:$target), !strconcat(opstr, "\t$target"), [(MipsJmpLink tglobaladdr:$target)], II_JAL, FrmJ, opstr> { @@ -1160,7 +1168,7 @@ } let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, hasDelaySlot = 1, - hasExtraSrcRegAllocReq = 1, Defs = [AT] in { + hasExtraSrcRegAllocReq = 1, isCTI = 1, Defs = [AT] in { class TailCall : PseudoSE<(outs), (ins calltarget:$target), [], II_J>, PseudoInstExpansion<(JumpInst jmptarget:$target)>; @@ -1179,8 +1187,10 @@ let isBarrier = 1; let hasDelaySlot = 1; let Defs = [RA]; + bit isCTI = 1; } +let isCTI = 1 in { // Syscall class SYS_FT : InstSE<(outs), (ins ImmOp:$code_), @@ -1196,15 +1206,16 @@ InstSE<(outs), (ins), opstr, [], NoItinerary, FrmOther, opstr>; +// Wait +class WAIT_FT : + InstSE<(outs), (ins), opstr, [], NoItinerary, FrmOther, opstr>; +} + // Interrupts class DEI_FT : InstSE<(outs RO:$rt), (ins), !strconcat(opstr, "\t$rt"), [], NoItinerary, FrmOther, opstr>; -// Wait -class WAIT_FT : - InstSE<(outs), (ins), opstr, [], NoItinerary, FrmOther, opstr>; - // Sync let hasSideEffects = 1 in class SYNC_FT : @@ -1218,17 +1229,15 @@ let DecoderMethod = "DecodeSyncI"; } +let hasSideEffects = 1, isCTI = 1 in { class TEQ_FT : InstSE<(outs), (ins RO:$rs, RO:$rt, ImmOp:$code_), !strconcat(opstr, "\t$rs, $rt, $code_"), [], NoItinerary, - FrmI, opstr> { - let hasSideEffects = 1; -} + FrmI, opstr>; class TEQI_FT : InstSE<(outs), (ins RO:$rs, simm16:$imm16), - !strconcat(opstr, "\t$rs, $imm16"), [], NoItinerary, FrmOther, opstr> { - let hasSideEffects = 1; + !strconcat(opstr, "\t$rs, $imm16"), [], NoItinerary, FrmOther, opstr>; } // Mul, Div @@ -1392,6 +1401,7 @@ let isBarrier = 1; let isTerminator = 1; let isCodeGenOnly = 1; + let isCTI = 1; } //===----------------------------------------------------------------------===// @@ -1399,11 +1409,13 @@ //===----------------------------------------------------------------------===// // Return RA. -let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, hasCtrlDep=1 in -def RetRA : PseudoSE<(outs), (ins), [(MipsRet)]>; +let isReturn=1, isTerminator=1, isBarrier=1, hasCtrlDep=1, isCTI=1 in { + let hasDelaySlot=1 in + def RetRA : PseudoSE<(outs), (ins), [(MipsRet)]>; -let isReturn=1, isTerminator=1, isBarrier=1, hasCtrlDep=1, hasSideEffects=1 in -def ERet : PseudoSE<(outs), (ins), [(MipsERet)]>; + let hasSideEffects=1 in + def ERet : PseudoSE<(outs), (ins), [(MipsERet)]>; +} let Defs = [SP], Uses = [SP], hasSideEffects = 1 in { def ADJCALLSTACKDOWN : MipsPseudo<(outs), (ins i32imm:$amt), @@ -1703,6 +1715,7 @@ let hasDelaySlot = 1; let isBranch = 1; let isIndirectBranch = 1; + bit isCTI = 1; } def PseudoIndirectBranch : PseudoIndirectBranchBase; @@ -1720,6 +1733,7 @@ let isCodeGenOnly = 1; let hasCtrlDep = 1; let hasExtraSrcRegAllocReq = 1; + bit isCTI = 1; } def PseudoReturn : PseudoReturnBase; @@ -1737,7 +1751,7 @@ def MIPSehret : SDNode<"MipsISD::EH_RETURN", SDT_MipsEHRET, [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; -let Uses = [V0, V1], isTerminator = 1, isReturn = 1, isBarrier = 1 in { +let Uses = [V0, V1], isTerminator = 1, isReturn = 1, isBarrier = 1, isCTI = 1 in { def MIPSeh_return32 : MipsPseudo<(outs), (ins GPR32:$spoff, GPR32:$dst), [(MIPSehret GPR32:$spoff, GPR32:$dst)]>; def MIPSeh_return64 : MipsPseudo<(outs), (ins GPR64:$spoff, @@ -1845,6 +1859,8 @@ FrmOther, asmstr>; def SSNOP : MMRel, StdMMR6Rel, Barrier<"ssnop">, BARRIER_FM<1>; def EHB : MMRel, Barrier<"ehb">, BARRIER_FM<3>; + +let isCTI = 1 in def PAUSE : MMRel, StdMMR6Rel, Barrier<"pause">, BARRIER_FM<5>, ISA_MIPS32R2; // JR_HB and JALR_HB are defined here using the new style naming @@ -1873,12 +1889,14 @@ let hasDelaySlot=1; let isTerminator=1; let isBarrier=1; + bit isCTI = 1; } class JALR_HB_DESC : InstSE<(outs), (ins), "", [], NoItinerary, FrmJ>, JALR_HB_DESC_BASE<"jalr.hb", GPR32Opnd> { let isIndirectBranch=1; let hasDelaySlot=1; + bit isCTI = 1; } class JR_HB_ENC : JR_HB_FM<8>; @@ -2095,7 +2113,7 @@ def NORImm : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), "nor\t$rs, $rt, $imm"> ; -let hasDelaySlot = 1 in { +let hasDelaySlot = 1, isCTI = 1 in { def BneImm : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins imm64:$imm64, brtarget:$offset), "bne\t$rt, $imm64, $offset">; @@ -2126,6 +2144,7 @@ def BGEUL: CondBranchPseudo<"bgeul">, ISA_MIPS2_NOT_32R6_64R6; def BGTUL: CondBranchPseudo<"bgtul">, ISA_MIPS2_NOT_32R6_64R6; +let isCTI = 1 in class CondBranchImmPseudo : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, imm64:$imm, brtarget:$offset), !strconcat(instr_asm, "\t$rs, $imm, $offset")>; Index: llvm/trunk/lib/Target/Mips/MipsSEInstrInfo.cpp =================================================================== --- llvm/trunk/lib/Target/Mips/MipsSEInstrInfo.cpp +++ llvm/trunk/lib/Target/Mips/MipsSEInstrInfo.cpp @@ -421,6 +421,14 @@ case Mips::BC1F: return Mips::BC1T; case Mips::BEQZC_MM: return Mips::BNEZC_MM; case Mips::BNEZC_MM: return Mips::BEQZC_MM; + case Mips::BEQZC: return Mips::BNEZC; + case Mips::BNEZC: return Mips::BEQZC; + case Mips::BEQC: return Mips::BNEC; + case Mips::BNEC: return Mips::BEQC; + case Mips::BGTZC: return Mips::BLEZC; + case Mips::BGEZC: return Mips::BLTZC; + case Mips::BLTZC: return Mips::BGEZC; + case Mips::BLEZC: return Mips::BGTZC; } } @@ -494,8 +502,12 @@ Opc == Mips::BEQ64 || Opc == Mips::BNE64 || Opc == Mips::BGTZ64 || Opc == Mips::BGEZ64 || Opc == Mips::BLTZ64 || Opc == Mips::BLEZ64 || Opc == Mips::BC1T || Opc == Mips::BC1F || Opc == Mips::B || - Opc == Mips::J || Opc == Mips::BEQZC_MM || Opc == Mips::BNEZC_MM) ? - Opc : 0; + Opc == Mips::J || Opc == Mips::BEQZC_MM || Opc == Mips::BNEZC_MM || + Opc == Mips::BEQC || Opc == Mips::BNEC || Opc == Mips::BLTC || + Opc == Mips::BGEC || Opc == Mips::BLTUC || Opc == Mips::BGEUC || + Opc == Mips::BGTZC || Opc == Mips::BLEZC || Opc == Mips::BGEZC || + Opc == Mips::BGTZC || Opc == Mips::BEQZC || Opc == Mips::BNEZC || + Opc == Mips::BC) ? Opc : 0; } void MipsSEInstrInfo::expandRetRA(MachineBasicBlock &MBB, Index: llvm/trunk/lib/Target/Mips/MipsTargetMachine.cpp =================================================================== --- llvm/trunk/lib/Target/Mips/MipsTargetMachine.cpp +++ llvm/trunk/lib/Target/Mips/MipsTargetMachine.cpp @@ -250,7 +250,13 @@ // print out the code after the passes. void MipsPassConfig::addPreEmitPass() { MipsTargetMachine &TM = getMipsTargetMachine(); + + // The delay slot filler pass can potientially create forbidden slot (FS) + // hazards for MIPSR6 which the hazard schedule pass (HSP) will fix. Any + // (new) pass that creates compact branches after the HSP must handle FS + // hazards itself or be pipelined before the HSP. addPass(createMipsDelaySlotFillerPass(TM)); + addPass(createMipsHazardSchedule(TM)); addPass(createMipsLongBranchPass(TM)); addPass(createMipsConstantIslandPass(TM)); } Index: llvm/trunk/test/CodeGen/Mips/analyzebranch.ll =================================================================== --- llvm/trunk/test/CodeGen/Mips/analyzebranch.ll +++ llvm/trunk/test/CodeGen/Mips/analyzebranch.ll @@ -19,7 +19,7 @@ ; GPR: cmp.lt.d $[[FGRCC:f[0-9]+]], $[[Z]], $f12 ; GPR: mfc1 $[[GPRCC:[0-9]+]], $[[FGRCC]] ; GPR-NOT: not $[[GPRCC]], $[[GPRCC]] -; GPR: bnez $[[GPRCC]], $BB +; GPR: bnezc $[[GPRCC]], $BB %cmp = fcmp ogt double %a, 0.000000e+00 br i1 %cmp, label %if.end6, label %if.else @@ -50,7 +50,8 @@ ; GPR: cmp.eq.s $[[FGRCC:f[0-9]+]], $f12, $[[Z]] ; GPR: mfc1 $[[GPRCC:[0-9]+]], $[[FGRCC]] ; GPR-NOT: not $[[GPRCC]], $[[GPRCC]] -; GPR: beqz $[[GPRCC]], $BB +; 64-GPR beqzc $[[GPRCC]], $BB +; 32-GPR beqz $[[GPRCC]], $BB %cmp = fcmp une float %f, 0.000000e+00 br i1 %cmp, label %if.then, label %if.end Index: llvm/trunk/test/CodeGen/Mips/atomic.ll =================================================================== --- llvm/trunk/test/CodeGen/Mips/atomic.ll +++ llvm/trunk/test/CodeGen/Mips/atomic.ll @@ -1,10 +1,10 @@ ; RUN: llc -march=mipsel --disable-machine-licm -mcpu=mips32 < %s | FileCheck %s -check-prefix=ALL -check-prefix=MIPS32-ANY -check-prefix=NO-SEB-SEH -check-prefix=CHECK-EL -check-prefix=NOT-MICROMIPS ; RUN: llc -march=mipsel --disable-machine-licm -mcpu=mips32r2 < %s | FileCheck %s -check-prefix=ALL -check-prefix=MIPS32-ANY -check-prefix=HAS-SEB-SEH -check-prefix=CHECK-EL -check-prefix=NOT-MICROMIPS -; RUN: llc -march=mipsel --disable-machine-licm -mcpu=mips32r6 < %s | FileCheck %s -check-prefix=ALL -check-prefix=MIPS32-ANY -check-prefix=HAS-SEB-SEH -check-prefix=CHECK-EL -check-prefix=NOT-MICROMIPS +; RUN: llc -march=mipsel --disable-machine-licm -mcpu=mips32r6 < %s | FileCheck %s -check-prefix=ALL -check-prefix=MIPS32-ANY -check-prefix=HAS-SEB-SEH -check-prefix=CHECK-EL -check-prefix=MIPSR6 ; RUN: llc -march=mips64el --disable-machine-licm -mcpu=mips4 < %s | FileCheck %s -check-prefix=ALL -check-prefix=MIPS64-ANY -check-prefix=NO-SEB-SEH -check-prefix=CHECK-EL -check-prefix=NOT-MICROMIPS ; RUN: llc -march=mips64el --disable-machine-licm -mcpu=mips64 < %s | FileCheck %s -check-prefix=ALL -check-prefix=MIPS64-ANY -check-prefix=NO-SEB-SEH -check-prefix=CHECK-EL -check-prefix=NOT-MICROMIPS ; RUN: llc -march=mips64el --disable-machine-licm -mcpu=mips64r2 < %s | FileCheck %s -check-prefix=ALL -check-prefix=MIPS64-ANY -check-prefix=HAS-SEB-SEH -check-prefix=CHECK-EL -check-prefix=NOT-MICROMIPS -; RUN: llc -march=mips64el --disable-machine-licm -mcpu=mips64r6 < %s | FileCheck %s -check-prefix=ALL -check-prefix=MIPS64-ANY -check-prefix=HAS-SEB-SEH -check-prefix=CHECK-EL -check-prefix=NOT-MICROMIPS +; RUN: llc -march=mips64el --disable-machine-licm -mcpu=mips64r6 < %s | FileCheck %s -check-prefix=ALL -check-prefix=MIPS64-ANY -check-prefix=HAS-SEB-SEH -check-prefix=CHECK-EL -check-prefix=MIPSR6 ; RUN: llc -march=mipsel --disable-machine-licm -mcpu=mips32r2 -mattr=micromips < %s | FileCheck %s -check-prefix=ALL -check-prefix=MIPS32-ANY -check-prefix=HAS-SEB-SEH -check-prefix=CHECK-EL -check-prefix=MICROMIPS ; Keep one big-endian check so that we don't reduce testing, but don't add more @@ -29,6 +29,7 @@ ; ALL: sc $[[R2]], 0($[[R0]]) ; NOT-MICROMIPS: beqz $[[R2]], $[[BB0]] ; MICROMIPS: beqzc $[[R2]], $[[BB0]] +; MIPSR6: beqzc $[[R2]], $[[BB0]] } define i32 @AtomicLoadNand32(i32 signext %incr) nounwind { @@ -48,6 +49,7 @@ ; ALL: sc $[[R2]], 0($[[R0]]) ; NOT-MICROMIPS: beqz $[[R2]], $[[BB0]] ; MICROMIPS: beqzc $[[R2]], $[[BB0]] +; MIPSR6: beqzc $[[R2]], $[[BB0]] } define i32 @AtomicSwap32(i32 signext %newval) nounwind { @@ -68,6 +70,7 @@ ; ALL: sc $[[R2:[0-9]+]], 0($[[R0]]) ; NOT-MICROMIPS: beqz $[[R2]], $[[BB0]] ; MICROMIPS: beqzc $[[R2]], $[[BB0]] +; MIPSR6: beqzc $[[R2]], $[[BB0]] } define i32 @AtomicCmpSwap32(i32 signext %oldval, i32 signext %newval) nounwind { @@ -86,10 +89,13 @@ ; ALL: $[[BB0:[A-Z_0-9]+]]: ; ALL: ll $2, 0($[[R0]]) -; ALL: bne $2, $4, $[[BB1:[A-Z_0-9]+]] +; NOT-MICROMIPS: bne $2, $4, $[[BB1:[A-Z_0-9]+]] +; MICROMIPS: bne $2, $4, $[[BB1:[A-Z_0-9]+]] +; MIPSR6: bnec $2, $4, $[[BB1:[A-Z_0-9]+]] ; ALL: sc $[[R2:[0-9]+]], 0($[[R0]]) ; NOT-MICROMIPS: beqz $[[R2]], $[[BB0]] ; MICROMIPS: beqzc $[[R2]], $[[BB0]] +; MIPSR6: beqzc $[[R2]], $[[BB0]] ; ALL: $[[BB1]]: } @@ -127,6 +133,7 @@ ; ALL: sc $[[R14]], 0($[[R2]]) ; NOT-MICROMIPS: beqz $[[R14]], $[[BB0]] ; MICROMIPS: beqzc $[[R14]], $[[BB0]] +; MIPSR6: beqzc $[[R14]], $[[BB0]] ; ALL: and $[[R15:[0-9]+]], $[[R10]], $[[R7]] ; ALL: srlv $[[R16:[0-9]+]], $[[R15]], $[[R5]] @@ -167,6 +174,7 @@ ; ALL: sc $[[R14]], 0($[[R2]]) ; NOT-MICROMIPS: beqz $[[R14]], $[[BB0]] ; MICROMIPS: beqzc $[[R14]], $[[BB0]] +; MIPSR6: beqzc $[[R14]], $[[BB0]] ; ALL: and $[[R15:[0-9]+]], $[[R10]], $[[R7]] ; ALL: srlv $[[R16:[0-9]+]], $[[R15]], $[[R5]] @@ -208,6 +216,7 @@ ; ALL: sc $[[R14]], 0($[[R2]]) ; NOT-MICROMIPS: beqz $[[R14]], $[[BB0]] ; MICROMIPS: beqzc $[[R14]], $[[BB0]] +; MIPSR6: beqzc $[[R14]], $[[BB0]] ; ALL: and $[[R15:[0-9]+]], $[[R10]], $[[R7]] ; ALL: srlv $[[R16:[0-9]+]], $[[R15]], $[[R5]] @@ -247,6 +256,7 @@ ; ALL: sc $[[R14]], 0($[[R2]]) ; NOT-MICROMIPS: beqz $[[R14]], $[[BB0]] ; MICROMIPS: beqzc $[[R14]], $[[BB0]] +; MIPSR6: beqzc $[[R14]], $[[BB0]] ; ALL: and $[[R15:[0-9]+]], $[[R10]], $[[R7]] ; ALL: srlv $[[R16:[0-9]+]], $[[R15]], $[[R5]] @@ -286,13 +296,16 @@ ; ALL: $[[BB0:[A-Z_0-9]+]]: ; ALL: ll $[[R13:[0-9]+]], 0($[[R2]]) ; ALL: and $[[R14:[0-9]+]], $[[R13]], $[[R7]] -; ALL: bne $[[R14]], $[[R10]], $[[BB1:[A-Z_0-9]+]] +; NOT-MICROMIPS: bne $[[R14]], $[[R10]], $[[BB1:[A-Z_0-9]+]] +; MICROMIPS: bne $[[R14]], $[[R10]], $[[BB1:[A-Z_0-9]+]] +; MIPSR6: bnec $[[R14]], $[[R10]], $[[BB1:[A-Z_0-9]+]] ; ALL: and $[[R15:[0-9]+]], $[[R13]], $[[R8]] ; ALL: or $[[R16:[0-9]+]], $[[R15]], $[[R12]] ; ALL: sc $[[R16]], 0($[[R2]]) ; NOT-MICROMIPS: beqz $[[R16]], $[[BB0]] ; MICROMIPS: beqzc $[[R16]], $[[BB0]] +; MIPSR6: beqzc $[[R16]], $[[BB0]] ; ALL: $[[BB1]]: ; ALL: srlv $[[R17:[0-9]+]], $[[R14]], $[[R5]] @@ -327,13 +340,16 @@ ; ALL: $[[BB0:[A-Z_0-9]+]]: ; ALL: ll $[[R13:[0-9]+]], 0($[[R2]]) ; ALL: and $[[R14:[0-9]+]], $[[R13]], $[[R7]] -; ALL: bne $[[R14]], $[[R10]], $[[BB1:[A-Z_0-9]+]] +; NOT-MICROMIPS: bne $[[R14]], $[[R10]], $[[BB1:[A-Z_0-9]+]] +; MICROMIPS: bne $[[R14]], $[[R10]], $[[BB1:[A-Z_0-9]+]] +; MIPSR6: bnec $[[R14]], $[[R10]], $[[BB1:[A-Z_0-9]+]] ; ALL: and $[[R15:[0-9]+]], $[[R13]], $[[R8]] ; ALL: or $[[R16:[0-9]+]], $[[R15]], $[[R12]] ; ALL: sc $[[R16]], 0($[[R2]]) ; NOT-MICROMIPS: beqz $[[R16]], $[[BB0]] ; MICROMIPS: beqzc $[[R16]], $[[BB0]] +; MIPSR6: beqzc $[[R16]], $[[BB0]] ; ALL: $[[BB1]]: ; ALL: srlv $[[R17:[0-9]+]], $[[R14]], $[[R5]] @@ -380,6 +396,7 @@ ; ALL: sc $[[R14]], 0($[[R2]]) ; NOT-MICROMIPS: beqz $[[R14]], $[[BB0]] ; MICROMIPS: beqzc $[[R14]], $[[BB0]] +; MIPSR6: beqzc $[[R14]], $[[BB0]] ; ALL: and $[[R15:[0-9]+]], $[[R10]], $[[R7]] ; ALL: srlv $[[R16:[0-9]+]], $[[R15]], $[[R5]] @@ -444,4 +461,5 @@ ; ALL: sc $[[R2]], 0($[[PTR]]) ; NOT-MICROMIPS: beqz $[[R2]], $[[BB0]] ; MICROMIPS: beqzc $[[R2]], $[[BB0]] +; MIPSR6: beqzc $[[R2]], $[[BB0]] } Index: llvm/trunk/test/CodeGen/Mips/compactbranches/compact-branches.ll =================================================================== --- llvm/trunk/test/CodeGen/Mips/compactbranches/compact-branches.ll +++ llvm/trunk/test/CodeGen/Mips/compactbranches/compact-branches.ll @@ -0,0 +1,155 @@ +; RUN: llc -march=mipsel -mcpu=mips32r6 -relocation-model=static < %s | FileCheck %s + +; Function Attrs: nounwind +define void @l() { +entry: + %call = tail call i32 @k() + %call1 = tail call i32 @j() + %cmp = icmp eq i32 %call, %call1 +; CHECK: bnec + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry: +; CHECK: nop +; CHECK: jal + tail call void @f(i32 signext -2) + br label %if.end + +if.end: ; preds = %if.then, %entry + ret void +} + +declare i32 @k() + +declare i32 @j() + +declare void @f(i32 signext) + +; Function Attrs: define void @l2() { +define void @l2() { +entry: + %call = tail call i32 @k() + %call1 = tail call i32 @i() + %cmp = icmp eq i32 %call, %call1 +; CHECK beqc + br i1 %cmp, label %if.end, label %if.then + +if.then: ; preds = %entry: +; CHECK: nop +; CHECK: jal + tail call void @f(i32 signext -1) + br label %if.end + +if.end: ; preds = %entry, %if.then + ret void +} + +declare i32 @i() + +; Function Attrs: nounwind +define void @l3() { +entry: + %call = tail call i32 @k() + %cmp = icmp slt i32 %call, 0 +; CHECK : bgez + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry: +; CHECK: nop +; CHECK: jal + tail call void @f(i32 signext 0) + br label %if.end + +if.end: ; preds = %if.then, %entry + ret void +} + +; Function Attrs: nounwind +define void @l4() { +entry: + %call = tail call i32 @k() + %cmp = icmp slt i32 %call, 1 +; CHECK: bgtzc + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry: +; CHECK: nop +; CHECK: jal + tail call void @f(i32 signext 1) + br label %if.end + +if.end: ; preds = %if.then, %entry + ret void +} + +; Function Attrs: nounwind +define void @l5() { +entry: + %call = tail call i32 @k() + %cmp = icmp sgt i32 %call, 0 +; CHECK: blezc + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry: +; CHECK: nop +; CHECK: jal + tail call void @f(i32 signext 2) + br label %if.end + +if.end: ; preds = %if.then, %entry + ret void +} + +; Function Attrs: nounwind +define void @l6() { +entry: + %call = tail call i32 @k() + %cmp = icmp sgt i32 %call, -1 +; CHECK: bltzc + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry: +; CHECK: nop +; CHECK: jal + tail call void @f(i32 signext 3) + br label %if.end + +if.end: ; preds = %if.then, %entry + ret void +} + +; Function Attrs: nounwind +define void @l7() { +entry: + %call = tail call i32 @k() + %cmp = icmp eq i32 %call, 0 +; CHECK: bnezc + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry: +; CHECK: nop +; CHECK: jal + tail call void @f(i32 signext 4) + br label %if.end + +if.end: ; preds = %if.then, %entry + ret void +} + +; Function Attrs: nounwind +define void @l8() { +entry: + %call = tail call i32 @k() + %cmp = icmp eq i32 %call, 0 +; CHECK: beqzc + br i1 %cmp, label %if.end, label %if.then + +if.then: ; preds = %entry: +; CHECK: nop +; CHECK: jal + tail call void @f(i32 signext 5) + br label %if.end + +if.end: ; preds = %entry, %if.then + ret void +} Index: llvm/trunk/test/CodeGen/Mips/fcmp.ll =================================================================== --- llvm/trunk/test/CodeGen/Mips/fcmp.ll +++ llvm/trunk/test/CodeGen/Mips/fcmp.ll @@ -750,7 +750,7 @@ ; 32-CMP-DAG: mfc1 $[[T3:[0-9]+]], $[[T2]] ; FIXME: This instruction is redundant. ; 32-CMP-DAG: andi $[[T4:[0-9]+]], $[[T3]], 1 -; 32-CMP-DAG: bnez $[[T4]], +; 32-CMP-DAG: bnezc $[[T4]], ; 64-C-DAG: add.s $[[T0:f[0-9]+]], $f13, $f12 ; 64-C-DAG: lwc1 $[[T1:f[0-9]+]], %got_ofst($CPI32_0)( @@ -763,7 +763,7 @@ ; 64-CMP-DAG: mfc1 $[[T3:[0-9]+]], $[[T2]] ; FIXME: This instruction is redundant. ; 64-CMP-DAG: andi $[[T4:[0-9]+]], $[[T3]], 1 -; 64-CMP-DAG: bnez $[[T4]], +; 64-CMP-DAG: bnezc $[[T4]], %add = fadd fast float %at, %angle %cmp = fcmp ogt float %add, 1.000000e+00 @@ -794,7 +794,7 @@ ; 32-CMP-DAG: mfc1 $[[T3:[0-9]+]], $[[T2]] ; FIXME: This instruction is redundant. ; 32-CMP-DAG: andi $[[T4:[0-9]+]], $[[T3]], 1 -; 32-CMP-DAG: bnez $[[T4]], +; 32-CMP-DAG: bnezc $[[T4]], ; 64-C-DAG: add.d $[[T0:f[0-9]+]], $f13, $f12 ; 64-C-DAG: ldc1 $[[T1:f[0-9]+]], %got_ofst($CPI33_0)( @@ -807,7 +807,7 @@ ; 64-CMP-DAG: mfc1 $[[T3:[0-9]+]], $[[T2]] ; FIXME: This instruction is redundant. ; 64-CMP-DAG: andi $[[T4:[0-9]+]], $[[T3]], 1 -; 64-CMP-DAG: bnez $[[T4]], +; 64-CMP-DAG: bnezc $[[T4]], %add = fadd fast double %at, %angle %cmp = fcmp ogt double %add, 1.000000e+00 Index: llvm/trunk/test/CodeGen/Mips/fpbr.ll =================================================================== --- llvm/trunk/test/CodeGen/Mips/fpbr.ll +++ llvm/trunk/test/CodeGen/Mips/fpbr.ll @@ -18,7 +18,8 @@ ; GPR: mfc1 $[[GPRCC:[0-9]+]], $[[FGRCC:f[0-9]+]] ; FIXME: We ought to be able to transform not+bnez -> beqz ; GPR: not $[[GPRCC]], $[[GPRCC]] -; GPR: bnez $[[GPRCC]], $BB0_2 +; 32-GPR: bnez $[[GPRCC]], $BB0_2 +; 64-GPR: bnezc $[[GPRCC]], $BB0_2 %cmp = fcmp oeq float %f2, %f3 br i1 %cmp, label %if.then, label %if.else @@ -51,7 +52,8 @@ ; 64-GPR: cmp.ule.s $[[FGRCC:f[0-9]+]], $f13, $f12 ; GPR: mfc1 $[[GPRCC:[0-9]+]], $[[FGRCC:f[0-9]+]] ; GPR-NOT: not $[[GPRCC]], $[[GPRCC]] -; GPR: bnez $[[GPRCC]], $BB1_2 +; 32-GPR: bnez $[[GPRCC]], $BB1_2 +; 64-GPR: bnezc $[[GPRCC]], $BB1_2 %cmp = fcmp olt float %f2, %f3 br i1 %cmp, label %if.then, label %if.else @@ -80,7 +82,8 @@ ; 64-GPR: cmp.ult.s $[[FGRCC:f[0-9]+]], $f13, $f12 ; GPR: mfc1 $[[GPRCC:[0-9]+]], $[[FGRCC:f[0-9]+]] ; GPR-NOT: not $[[GPRCC]], $[[GPRCC]] -; GPR: beqz $[[GPRCC]], $BB2_2 +; 32-GPR: beqz $[[GPRCC]], $BB2_2 +; 64-GPR: beqzc $[[GPRCC]], $BB2_2 %cmp = fcmp ugt float %f2, %f3 br i1 %cmp, label %if.else, label %if.then @@ -110,7 +113,8 @@ ; GPR: mfc1 $[[GPRCC:[0-9]+]], $[[FGRCC:f[0-9]+]] ; FIXME: We ought to be able to transform not+bnez -> beqz ; GPR: not $[[GPRCC]], $[[GPRCC]] -; GPR: bnez $[[GPRCC]], $BB3_2 +; 32-GPR: bnez $[[GPRCC]], $BB3_2 +; 64-GPR: bnezc $[[GPRCC]], $BB3_2 %cmp = fcmp oeq double %f2, %f3 br i1 %cmp, label %if.then, label %if.else @@ -139,7 +143,8 @@ ; 64-GPR: cmp.ule.d $[[FGRCC:f[0-9]+]], $f13, $f12 ; GPR: mfc1 $[[GPRCC:[0-9]+]], $[[FGRCC:f[0-9]+]] ; GPR-NOT: not $[[GPRCC]], $[[GPRCC]] -; GPR: bnez $[[GPRCC]], $BB4_2 +; 32-GPR: bnez $[[GPRCC]], $BB4_2 +; 64-GPR: bnezc $[[GPRCC]], $BB4_2 %cmp = fcmp olt double %f2, %f3 br i1 %cmp, label %if.then, label %if.else @@ -168,7 +173,8 @@ ; 64-GPR: cmp.ult.d $[[FGRCC:f[0-9]+]], $f13, $f12 ; GPR: mfc1 $[[GPRCC:[0-9]+]], $[[FGRCC:f[0-9]+]] ; GPR-NOT: not $[[GPRCC]], $[[GPRCC]] -; GPR: beqz $[[GPRCC]], $BB5_2 +; 32-GPR: beqz $[[GPRCC]], $BB5_2 +; 64-GPR: beqzc $[[GPRCC]], $BB5_2 %cmp = fcmp ugt double %f2, %f3 br i1 %cmp, label %if.else, label %if.then