mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-11 21:56:15 +00:00
[mips] Restrict the creation of compact branches
Restrict the creation of compact branches so that they meet the ISA encoding 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. Reviewers: dsanders, vkalintiris Differential Review: http://reviews.llvm.org/D20284 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@269893 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
06dac21852
commit
79149b9fae
@ -106,6 +106,26 @@ static void LowerDins(MCInst& InstIn) {
|
||||
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 {
|
||||
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
|
||||
case Mips::DINS:
|
||||
LowerDins(TmpInst);
|
||||
break;
|
||||
// Compact branches.
|
||||
case Mips::BEQC:
|
||||
case Mips::BNEC:
|
||||
LowerCompactBranch(TmpInst);
|
||||
}
|
||||
|
||||
unsigned long N = Fixups.size();
|
||||
|
@ -253,6 +253,8 @@ public:
|
||||
unsigned getRegisterListOpValue16(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
private:
|
||||
void LowerCompactBranch(MCInst& Inst) const;
|
||||
}; // class MipsMCCodeEmitter
|
||||
} // namespace llvm.
|
||||
|
||||
|
@ -360,7 +360,7 @@ class SPECIAL_SDBBP_FM : MipsR6Inst {
|
||||
}
|
||||
|
||||
// This class is ambiguous with other branches:
|
||||
// BEQC/BNEC require that rs > rt
|
||||
// BEQC/BNEC require that rs < rt
|
||||
class CMP_BRANCH_2R_OFF16_FM<OPGROUP funct> : MipsR6Inst {
|
||||
bits<5> rs;
|
||||
bits<5> rt;
|
||||
|
@ -282,6 +282,16 @@ unsigned MipsInstrInfo::getEquivalentCompactForm(
|
||||
}
|
||||
}
|
||||
|
||||
// MIPSR6 forbids both operands being the zero register.
|
||||
if (Subtarget.hasMips32r6() &&
|
||||
(I->getOperand(0).getType() == MachineOperand::MO_Register &&
|
||||
(I->getOperand(0).getReg() == Mips::ZERO ||
|
||||
I->getOperand(0).getReg() == Mips::ZERO_64)) &&
|
||||
(I->getOperand(1).getType() == MachineOperand::MO_Register &&
|
||||
(I->getOperand(1).getReg() == Mips::ZERO ||
|
||||
I->getOperand(1).getReg() == Mips::ZERO_64)))
|
||||
return 0;
|
||||
|
||||
if (Subtarget.hasMips32r6() || canUseShortMicroMipsCTI) {
|
||||
switch (Opcode) {
|
||||
case Mips::B:
|
||||
@ -299,8 +309,12 @@ unsigned MipsInstrInfo::getEquivalentCompactForm(
|
||||
else
|
||||
return Mips::BNEC;
|
||||
case Mips::BGE:
|
||||
if (I->getOperand(0).getReg() == I->getOperand(1).getReg())
|
||||
return 0;
|
||||
return Mips::BGEC;
|
||||
case Mips::BGEU:
|
||||
if (I->getOperand(0).getReg() == I->getOperand(1).getReg())
|
||||
return 0;
|
||||
return Mips::BGEUC;
|
||||
case Mips::BGEZ:
|
||||
return Mips::BGEZC;
|
||||
@ -309,8 +323,12 @@ unsigned MipsInstrInfo::getEquivalentCompactForm(
|
||||
case Mips::BLEZ:
|
||||
return Mips::BLEZC;
|
||||
case Mips::BLT:
|
||||
if (I->getOperand(0).getReg() == I->getOperand(1).getReg())
|
||||
return 0;
|
||||
return Mips::BLTC;
|
||||
case Mips::BLTU:
|
||||
if (I->getOperand(0).getReg() == I->getOperand(1).getReg())
|
||||
return 0;
|
||||
return Mips::BLTUC;
|
||||
case Mips::BLTZ:
|
||||
return Mips::BLTZC;
|
||||
@ -330,7 +348,7 @@ unsigned MipsInstrInfo::getEquivalentCompactForm(
|
||||
return Mips::JIC64;
|
||||
case Mips::JALR64Pseudo:
|
||||
return Mips::JIALC64;
|
||||
default:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
52
test/CodeGen/Mips/compactbranches/no-beqzc-bnezc.ll
Normal file
52
test/CodeGen/Mips/compactbranches/no-beqzc-bnezc.ll
Normal file
@ -0,0 +1,52 @@
|
||||
; RUN: llc -march=mipsel -mcpu=mips32r6 -disable-mips-delay-filler < %s | FileCheck %s
|
||||
; RUN: llc -march=mips -mcpu=mips32r6 -disable-mips-delay-filler < %s -filetype=obj -o - | llvm-objdump -arch=mips -mcpu=mips32r6 -d - | FileCheck %s -check-prefix=ENCODING
|
||||
|
||||
; bnezc and beqzc have restriction that $rt != 0
|
||||
|
||||
define i32 @f() {
|
||||
; CHECK-LABEL: f
|
||||
; CHECK-NOT: bnezc $0
|
||||
|
||||
%cmp = icmp eq i32 1, 1
|
||||
br i1 %cmp, label %if.then, label %if.end
|
||||
|
||||
if.then:
|
||||
ret i32 1
|
||||
|
||||
if.end:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @f1() {
|
||||
; CHECK-LABEL: f1
|
||||
; CHECK-NOT: beqzc $0
|
||||
|
||||
%cmp = icmp eq i32 0, 0
|
||||
br i1 %cmp, label %if.then, label %if.end
|
||||
|
||||
if.then:
|
||||
ret i32 1
|
||||
|
||||
if.end:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
; We silently fixup cases where the register allocator or user has given us
|
||||
; an instruction with incorrect operands that is trivially acceptable.
|
||||
; beqc and bnec have the restriction that $rs < $rt.
|
||||
|
||||
define i32 @f2(i32 %a, i32 %b) {
|
||||
; ENCODING-LABEL: f2
|
||||
; ENCODING-NOT: beqc $5, $4
|
||||
; ENCODING-NOT: bnec $5, $4
|
||||
|
||||
%cmp = icmp eq i32 %b, %a
|
||||
br i1 %cmp, label %if.then, label %if.end
|
||||
|
||||
if.then:
|
||||
ret i32 1
|
||||
|
||||
if.end:
|
||||
ret i32 0
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user