[PATCH] [mips] Restrict the creation of compact branches

Restrict the creation of compact branches so that they do meet the ISA
requirements. Notably do not permit $zero to be used as a operand for compact
branches and ensure that some other branches fulfil the requirement that
rs != rt.

Fixup cases where $rs > $rt for bnec and beqc.

Recommit of rL269893 with reviewers comments.

Reviewers: dsanders, vkalintiris

Differential Review: http://reviews.llvm.org/D20284

llvm-svn: 269899
This commit is contained in:
Simon Dardis 2016-05-18 10:38:01 +00:00
parent c819d903e1
commit 669d8dd8e1
4 changed files with 47 additions and 2 deletions

View File

@ -106,6 +106,26 @@ static void LowerDins(MCInst& InstIn) {
return; return;
} }
// Fix a bad compact branch encoding for beqc/bnec.
void MipsMCCodeEmitter::LowerCompactBranch(MCInst& Inst) const {
// Encoding may be illegal !(rs < rt), but this situation is
// easily fixed.
unsigned RegOp0 = Inst.getOperand(0).getReg();
unsigned RegOp1 = Inst.getOperand(1).getReg();
unsigned Reg0 = Ctx.getRegisterInfo()->getEncodingValue(RegOp0);
unsigned Reg1 = Ctx.getRegisterInfo()->getEncodingValue(RegOp1);
assert(Reg0 != Reg1 && "Instruction has bad operands ($rs == $rt)!");
if (Reg0 < Reg1)
return;
Inst.getOperand(0).setReg(RegOp1);
Inst.getOperand(1).setReg(RegOp0);
}
bool MipsMCCodeEmitter::isMicroMips(const MCSubtargetInfo &STI) const { bool MipsMCCodeEmitter::isMicroMips(const MCSubtargetInfo &STI) const {
return STI.getFeatureBits()[Mips::FeatureMicroMips]; return STI.getFeatureBits()[Mips::FeatureMicroMips];
} }
@ -160,6 +180,11 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS,
// Double extract instruction is chosen by pos and size operands // Double extract instruction is chosen by pos and size operands
case Mips::DINS: case Mips::DINS:
LowerDins(TmpInst); LowerDins(TmpInst);
break;
// Compact branches.
case Mips::BEQC:
case Mips::BNEC:
LowerCompactBranch(TmpInst);
} }
unsigned long N = Fixups.size(); unsigned long N = Fixups.size();

View File

@ -253,6 +253,8 @@ public:
unsigned getRegisterListOpValue16(const MCInst &MI, unsigned OpNo, unsigned getRegisterListOpValue16(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups, SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const; const MCSubtargetInfo &STI) const;
private:
void LowerCompactBranch(MCInst& Inst) const;
}; // class MipsMCCodeEmitter }; // class MipsMCCodeEmitter
} // namespace llvm. } // namespace llvm.

View File

@ -360,7 +360,7 @@ class SPECIAL_SDBBP_FM : MipsR6Inst {
} }
// This class is ambiguous with other branches: // This class is ambiguous with other branches:
// BEQC/BNEC require that rs > rt // BEQC/BNEC require that rs < rt && rs != 0
class CMP_BRANCH_2R_OFF16_FM<OPGROUP funct> : MipsR6Inst { class CMP_BRANCH_2R_OFF16_FM<OPGROUP funct> : MipsR6Inst {
bits<5> rs; bits<5> rs;
bits<5> rt; bits<5> rt;

View File

@ -282,6 +282,16 @@ unsigned MipsInstrInfo::getEquivalentCompactForm(
} }
} }
// MIPSR6 forbids both operands being the zero register.
if (Subtarget.hasMips32r6() && (I->getNumOperands() > 1) &&
(I->getOperand(0).isReg() &&
(I->getOperand(0).getReg() == Mips::ZERO ||
I->getOperand(0).getReg() == Mips::ZERO_64)) &&
(I->getOperand(1).isReg() &&
(I->getOperand(1).getReg() == Mips::ZERO ||
I->getOperand(1).getReg() == Mips::ZERO_64)))
return 0;
if (Subtarget.hasMips32r6() || canUseShortMicroMipsCTI) { if (Subtarget.hasMips32r6() || canUseShortMicroMipsCTI) {
switch (Opcode) { switch (Opcode) {
case Mips::B: case Mips::B:
@ -299,8 +309,12 @@ unsigned MipsInstrInfo::getEquivalentCompactForm(
else else
return Mips::BNEC; return Mips::BNEC;
case Mips::BGE: case Mips::BGE:
if (I->getOperand(0).getReg() == I->getOperand(1).getReg())
return 0;
return Mips::BGEC; return Mips::BGEC;
case Mips::BGEU: case Mips::BGEU:
if (I->getOperand(0).getReg() == I->getOperand(1).getReg())
return 0;
return Mips::BGEUC; return Mips::BGEUC;
case Mips::BGEZ: case Mips::BGEZ:
return Mips::BGEZC; return Mips::BGEZC;
@ -309,8 +323,12 @@ unsigned MipsInstrInfo::getEquivalentCompactForm(
case Mips::BLEZ: case Mips::BLEZ:
return Mips::BLEZC; return Mips::BLEZC;
case Mips::BLT: case Mips::BLT:
if (I->getOperand(0).getReg() == I->getOperand(1).getReg())
return 0;
return Mips::BLTC; return Mips::BLTC;
case Mips::BLTU: case Mips::BLTU:
if (I->getOperand(0).getReg() == I->getOperand(1).getReg())
return 0;
return Mips::BLTUC; return Mips::BLTUC;
case Mips::BLTZ: case Mips::BLTZ:
return Mips::BLTZC; return Mips::BLTZC;