103 changes: 102 additions & 1 deletion llvm/lib/Target/Mips/MipsInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,71 @@ MipsInstrInfo::BranchType MipsInstrInfo::AnalyzeBranch(
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()) {
Expand All @@ -277,10 +342,46 @@ MachineInstrBuilder
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;
Expand Down
9 changes: 9 additions & 0 deletions llvm/lib/Target/Mips/MipsInstrInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@ class MipsInstrInfo : public MipsGenInstrInfo {
bool AllowModify,
SmallVectorImpl<MachineInstr*> &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;
Expand Down
55 changes: 37 additions & 18 deletions llvm/lib/Target/Mips/MipsInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -348,14 +348,17 @@ class IsCommutable {

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 {
Expand All @@ -365,6 +368,7 @@ class IsTailCall {
bit isBarrier = 1;
bit hasExtraSrcRegAllocReq = 1;
bit isCodeGenOnly = 1;
bit isCTI = 1;
}

class IsAsCheapAsAMove {
Expand Down Expand Up @@ -1068,6 +1072,7 @@ class CBranch<string opstr, DAGOperand opnd, PatFrag cond_op,
let isTerminator = 1;
let hasDelaySlot = DelaySlot;
let Defs = [AT];
bit isCTI = 1;
}

class CBranchZero<string opstr, DAGOperand opnd, PatFrag cond_op,
Expand All @@ -1080,6 +1085,7 @@ class CBranchZero<string opstr, DAGOperand opnd, PatFrag cond_op,
let isTerminator = 1;
let hasDelaySlot = DelaySlot;
let Defs = [AT];
bit isCTI = 1;
}

// SetCC
Expand All @@ -1106,6 +1112,7 @@ class JumpFJ<DAGOperand opnd, string opstr, SDPatternOperator operator,
let hasDelaySlot = 1;
let DecoderMethod = "DecodeJumpTarget";
let Defs = [AT];
bit isCTI = 1;
}

// Unconditional branch
Expand All @@ -1118,10 +1125,11 @@ class UncondBranch<Instruction BEQInst> :
let hasDelaySlot = 1;
let AdditionalPredicates = [RelocPIC];
let Defs = [AT];
bit isCTI = 1;
}

// Base class for indirect branch and return instruction classes.
let isTerminator=1, isBarrier=1, hasDelaySlot = 1 in
let isTerminator=1, isBarrier=1, hasDelaySlot = 1, isCTI = 1 in
class JumpFR<string opstr, RegisterOperand RO,
SDPatternOperator operator = null_frag>:
InstSE<(outs), (ins RO:$rs), "jr\t$rs", [(operator RO:$rs)], II_JR,
Expand All @@ -1134,7 +1142,7 @@ class IndirectBranch<string opstr, RegisterOperand RO> : JumpFR<opstr, RO> {
}

// Jump and Link (Call)
let isCall=1, hasDelaySlot=1, Defs = [RA] in {
let isCall=1, hasDelaySlot=1, isCTI=1, Defs = [RA] in {
class JumpLink<string opstr, DAGOperand opnd> :
InstSE<(outs), (ins opnd:$target), !strconcat(opstr, "\t$target"),
[(MipsJmpLink tglobaladdr:$target)], II_JAL, FrmJ, opstr> {
Expand All @@ -1160,7 +1168,7 @@ let isCall=1, hasDelaySlot=1, Defs = [RA] in {
}

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<Instruction JumpInst> :
PseudoSE<(outs), (ins calltarget:$target), [], II_J>,
PseudoInstExpansion<(JumpInst jmptarget:$target)>;
Expand All @@ -1179,8 +1187,10 @@ class BAL_BR_Pseudo<Instruction RealInst> :
let isBarrier = 1;
let hasDelaySlot = 1;
let Defs = [RA];
bit isCTI = 1;
}

let isCTI = 1 in {
// Syscall
class SYS_FT<string opstr, Operand ImmOp> :
InstSE<(outs), (ins ImmOp:$code_),
Expand All @@ -1196,15 +1206,16 @@ class ER_FT<string opstr> :
InstSE<(outs), (ins),
opstr, [], NoItinerary, FrmOther, opstr>;

// Wait
class WAIT_FT<string opstr> :
InstSE<(outs), (ins), opstr, [], NoItinerary, FrmOther, opstr>;
}

// Interrupts
class DEI_FT<string opstr, RegisterOperand RO> :
InstSE<(outs RO:$rt), (ins),
!strconcat(opstr, "\t$rt"), [], NoItinerary, FrmOther, opstr>;

// Wait
class WAIT_FT<string opstr> :
InstSE<(outs), (ins), opstr, [], NoItinerary, FrmOther, opstr>;

// Sync
let hasSideEffects = 1 in
class SYNC_FT<string opstr> :
Expand All @@ -1218,17 +1229,15 @@ class SYNCI_FT<string opstr> :
let DecoderMethod = "DecodeSyncI";
}

let hasSideEffects = 1, isCTI = 1 in {
class TEQ_FT<string opstr, RegisterOperand RO, Operand ImmOp> :
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<string opstr, RegisterOperand RO> :
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
Expand Down Expand Up @@ -1392,18 +1401,21 @@ class TrapBase<Instruction RealInst>
let isBarrier = 1;
let isTerminator = 1;
let isCodeGenOnly = 1;
let isCTI = 1;
}

//===----------------------------------------------------------------------===//
// Pseudo instructions
//===----------------------------------------------------------------------===//

// 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),
Expand Down Expand Up @@ -1703,6 +1715,7 @@ class PseudoIndirectBranchBase<RegisterOperand RO> :
let hasDelaySlot = 1;
let isBranch = 1;
let isIndirectBranch = 1;
bit isCTI = 1;
}

def PseudoIndirectBranch : PseudoIndirectBranchBase<GPR32Opnd>;
Expand All @@ -1720,6 +1733,7 @@ class PseudoReturnBase<RegisterOperand RO> : MipsPseudo<(outs), (ins RO:$rs),
let isCodeGenOnly = 1;
let hasCtrlDep = 1;
let hasExtraSrcRegAllocReq = 1;
bit isCTI = 1;
}

def PseudoReturn : PseudoReturnBase<GPR32Opnd>;
Expand All @@ -1737,7 +1751,7 @@ def SDT_MipsEHRET : SDTypeProfile<0, 2, [SDTCisInt<0>, SDTCisPtrTy<1>]>;
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,
Expand Down Expand Up @@ -1845,6 +1859,8 @@ class Barrier<string asmstr> : InstSE<(outs), (ins), asmstr, [], NoItinerary,
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
Expand Down Expand Up @@ -1873,12 +1889,14 @@ class JR_HB_DESC : InstSE<(outs), (ins), "", [], NoItinerary, FrmJ>,
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>;
Expand Down Expand Up @@ -2095,7 +2113,7 @@ def JalOneReg : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs),
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">;
Expand Down Expand Up @@ -2126,6 +2144,7 @@ def BLEUL: CondBranchPseudo<"bleul">, ISA_MIPS2_NOT_32R6_64R6;
def BGEUL: CondBranchPseudo<"bgeul">, ISA_MIPS2_NOT_32R6_64R6;
def BGTUL: CondBranchPseudo<"bgtul">, ISA_MIPS2_NOT_32R6_64R6;

let isCTI = 1 in
class CondBranchImmPseudo<string instr_asm> :
MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, imm64:$imm, brtarget:$offset),
!strconcat(instr_asm, "\t$rs, $imm, $offset")>;
Expand Down
16 changes: 14 additions & 2 deletions llvm/lib/Target/Mips/MipsSEInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,14 @@ unsigned MipsSEInstrInfo::getOppositeBranchOpc(unsigned Opc) const {
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;
}
}

Expand Down Expand Up @@ -494,8 +502,12 @@ unsigned MipsSEInstrInfo::getAnalyzableBrOpc(unsigned Opc) const {
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,
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/Target/Mips/MipsTargetMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,13 @@ TargetIRAnalysis MipsTargetMachine::getTargetIRAnalysis() {
// 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));
}
5 changes: 3 additions & 2 deletions llvm/test/CodeGen/Mips/analyzebranch.ll
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ entry:
; 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
Expand Down Expand Up @@ -50,7 +50,8 @@ entry:
; 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
Expand Down
28 changes: 23 additions & 5 deletions llvm/test/CodeGen/Mips/atomic.ll
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -29,6 +29,7 @@ entry:
; 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 {
Expand All @@ -48,6 +49,7 @@ entry:
; 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 {
Expand All @@ -68,6 +70,7 @@ entry:
; 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 {
Expand All @@ -86,10 +89,13 @@ entry:

; 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]]:
}

Expand Down Expand Up @@ -127,6 +133,7 @@ entry:
; 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]]
Expand Down Expand Up @@ -167,6 +174,7 @@ entry:
; 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]]
Expand Down Expand Up @@ -208,6 +216,7 @@ entry:
; 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]]
Expand Down Expand Up @@ -247,6 +256,7 @@ entry:
; 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]]
Expand Down Expand Up @@ -286,13 +296,16 @@ entry:
; 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]]
Expand Down Expand Up @@ -327,13 +340,16 @@ entry:
; 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]]
Expand Down Expand Up @@ -380,6 +396,7 @@ entry:
; 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]]
Expand Down Expand Up @@ -444,4 +461,5 @@ entry:
; ALL: sc $[[R2]], 0($[[PTR]])
; NOT-MICROMIPS: beqz $[[R2]], $[[BB0]]
; MICROMIPS: beqzc $[[R2]], $[[BB0]]
; MIPSR6: beqzc $[[R2]], $[[BB0]]
}
155 changes: 155 additions & 0 deletions llvm/test/CodeGen/Mips/compactbranches/compact-branches.ll
Original file line number Diff line number Diff line change
@@ -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
}
8 changes: 4 additions & 4 deletions llvm/test/CodeGen/Mips/fcmp.ll
Original file line number Diff line number Diff line change
Expand Up @@ -750,7 +750,7 @@ entry:
; 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)(
Expand All @@ -763,7 +763,7 @@ entry:
; 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
Expand Down Expand Up @@ -794,7 +794,7 @@ entry:
; 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)(
Expand All @@ -807,7 +807,7 @@ entry:
; 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
Expand Down
18 changes: 12 additions & 6 deletions llvm/test/CodeGen/Mips/fpbr.ll
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ entry:
; 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
Expand Down Expand Up @@ -51,7 +52,8 @@ entry:
; 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
Expand Down Expand Up @@ -80,7 +82,8 @@ entry:
; 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
Expand Down Expand Up @@ -110,7 +113,8 @@ entry:
; 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
Expand Down Expand Up @@ -139,7 +143,8 @@ entry:
; 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
Expand Down Expand Up @@ -168,7 +173,8 @@ entry:
; 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
Expand Down