forked from OSchip/llvm-project
[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:
parent
c819d903e1
commit
669d8dd8e1
|
@ -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();
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue