[PowerPC] Use mtocrf when available

Just as with mfocrf, it is also preferable to use mtocrf instead of
mtcrf when only a single CR register is to be written.

Current code however always emits mtcrf.  This probably does not matter
when using an external assembler, since the GNU assembler will in fact
automatically replace mtcrf with mtocrf when possible.  It does create
inefficient code with the integrated assembler, however.

To fix this, this patch adds MTOCRF/MTOCRF8 instruction patterns and
uses those instead of MTCRF/MTCRF8 everything.  Just as done in the
MFOCRF patch committed as 185556, these patterns will be converted
back to MTCRF if MTOCRF is not available on the machine.

As a side effect, this allows to modify the MTCRF pattern to accept
the full range of mask operands for the benefit of the asm parser.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@185561 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Ulrich Weigand 2013-07-03 17:59:07 +00:00
parent 965b20e39c
commit 33efedc048
10 changed files with 54 additions and 25 deletions

View File

@ -228,7 +228,7 @@ unsigned PPCMCCodeEmitter::
get_crbitm_encoding(const MCInst &MI, unsigned OpNo, get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups) const { SmallVectorImpl<MCFixup> &Fixups) const {
const MCOperand &MO = MI.getOperand(OpNo); const MCOperand &MO = MI.getOperand(OpNo);
assert((MI.getOpcode() == PPC::MTCRF || MI.getOpcode() == PPC::MTCRF8 || assert((MI.getOpcode() == PPC::MTOCRF || MI.getOpcode() == PPC::MTOCRF8 ||
MI.getOpcode() == PPC::MFOCRF || MI.getOpcode() == PPC::MFOCRF8) && MI.getOpcode() == PPC::MFOCRF || MI.getOpcode() == PPC::MFOCRF8) &&
(MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7)); (MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7));
return 0x80 >> CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); return 0x80 >> CTX.getRegisterInfo()->getEncodingValue(MO.getReg());
@ -239,9 +239,9 @@ unsigned PPCMCCodeEmitter::
getMachineOpValue(const MCInst &MI, const MCOperand &MO, getMachineOpValue(const MCInst &MI, const MCOperand &MO,
SmallVectorImpl<MCFixup> &Fixups) const { SmallVectorImpl<MCFixup> &Fixups) const {
if (MO.isReg()) { if (MO.isReg()) {
// MTCRF/MFOCRF should go through get_crbitm_encoding for the CR operand. // MTOCRF/MFOCRF should go through get_crbitm_encoding for the CR operand.
// The GPR operand should come through here though. // The GPR operand should come through here though.
assert((MI.getOpcode() != PPC::MTCRF && MI.getOpcode() != PPC::MTCRF8 && assert((MI.getOpcode() != PPC::MTOCRF && MI.getOpcode() != PPC::MTOCRF8 &&
MI.getOpcode() != PPC::MFOCRF && MI.getOpcode() != PPC::MFOCRF8) || MI.getOpcode() != PPC::MFOCRF && MI.getOpcode() != PPC::MFOCRF8) ||
MO.getReg() < PPC::CR0 || MO.getReg() > PPC::CR7); MO.getReg() < PPC::CR0 || MO.getReg() > PPC::CR7);
return CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); return CTX.getRegisterInfo()->getEncodingValue(MO.getReg());

View File

@ -676,6 +676,23 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
return; return;
} }
break; break;
case PPC::MTOCRF:
case PPC::MTOCRF8:
if (!Subtarget.hasMFOCRF()) {
// Transform: %CR7 = MTOCRF %R3
// Into: MTCRF mask, %R3 ;; cr7
unsigned NewOpcode =
MI->getOpcode() == PPC::MTOCRF ? PPC::MTCRF : PPC::MTCRF8;
unsigned Mask = 0x80 >> OutContext.getRegisterInfo()
->getEncodingValue(MI->getOperand(0).getReg());
OutStreamer.AddComment(PPCInstPrinter::
getRegisterName(MI->getOperand(0).getReg()));
OutStreamer.EmitInstruction(MCInstBuilder(NewOpcode)
.addImm(Mask)
.addReg(MI->getOperand(1).getReg()));
return;
}
break;
case PPC::SYNC: case PPC::SYNC:
// In Book E sync is called msync, handle this special case here... // In Book E sync is called msync, handle this special case here...
if (Subtarget.isBookE()) { if (Subtarget.isBookE()) {

View File

@ -142,7 +142,7 @@ void PPCCodeEmitter::emitBasicBlock(MachineBasicBlock &MBB) {
unsigned PPCCodeEmitter::get_crbitm_encoding(const MachineInstr &MI, unsigned PPCCodeEmitter::get_crbitm_encoding(const MachineInstr &MI,
unsigned OpNo) const { unsigned OpNo) const {
const MachineOperand &MO = MI.getOperand(OpNo); const MachineOperand &MO = MI.getOperand(OpNo);
assert((MI.getOpcode() == PPC::MTCRF || MI.getOpcode() == PPC::MTCRF8 || assert((MI.getOpcode() == PPC::MTOCRF || MI.getOpcode() == PPC::MTOCRF8 ||
MI.getOpcode() == PPC::MFOCRF || MI.getOpcode() == PPC::MFOCRF8) && MI.getOpcode() == PPC::MFOCRF || MI.getOpcode() == PPC::MFOCRF8) &&
(MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7)); (MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7));
return 0x80 >> TM.getRegisterInfo()->getEncodingValue(MO.getReg()); return 0x80 >> TM.getRegisterInfo()->getEncodingValue(MO.getReg());
@ -274,9 +274,9 @@ unsigned PPCCodeEmitter::getMachineOpValue(const MachineInstr &MI,
const MachineOperand &MO) const { const MachineOperand &MO) const {
if (MO.isReg()) { if (MO.isReg()) {
// MTCRF/MFOCRF should go through get_crbitm_encoding for the CR operand. // MTOCRF/MFOCRF should go through get_crbitm_encoding for the CR operand.
// The GPR operand should come through here though. // The GPR operand should come through here though.
assert((MI.getOpcode() != PPC::MTCRF && MI.getOpcode() != PPC::MTCRF8 && assert((MI.getOpcode() != PPC::MTOCRF && MI.getOpcode() != PPC::MTOCRF8 &&
MI.getOpcode() != PPC::MFOCRF && MI.getOpcode() != PPC::MFOCRF8) || MI.getOpcode() != PPC::MFOCRF && MI.getOpcode() != PPC::MFOCRF8) ||
MO.getReg() < PPC::CR0 || MO.getReg() > PPC::CR7); MO.getReg() < PPC::CR0 || MO.getReg() > PPC::CR7);
return TM.getRegisterInfo()->getEncodingValue(MO.getReg()); return TM.getRegisterInfo()->getEncodingValue(MO.getReg());

View File

@ -753,7 +753,7 @@ void PPCFrameLowering::emitEpilogue(MachineFunction &MF,
if (!MustSaveCRs.empty()) if (!MustSaveCRs.empty())
for (unsigned i = 0, e = MustSaveCRs.size(); i != e; ++i) for (unsigned i = 0, e = MustSaveCRs.size(); i != e; ++i)
BuildMI(MBB, MBBI, dl, TII.get(PPC::MTCRF8), MustSaveCRs[i]) BuildMI(MBB, MBBI, dl, TII.get(PPC::MTOCRF8), MustSaveCRs[i])
.addReg(PPC::X12, getKillRegState(i == e-1)); .addReg(PPC::X12, getKillRegState(i == e-1));
if (MustSaveLR) if (MustSaveLR)
@ -1212,7 +1212,7 @@ restoreCRs(bool isPPC64, bool is31,
MBB.insert(MI, addFrameReference(BuildMI(*MF, DL, TII.get(PPC::LWZ), MBB.insert(MI, addFrameReference(BuildMI(*MF, DL, TII.get(PPC::LWZ),
PPC::R12), PPC::R12),
CSI[CSIIndex].getFrameIdx())); CSI[CSIIndex].getFrameIdx()));
RestoreOp = PPC::MTCRF; RestoreOp = PPC::MTOCRF;
MoveReg = PPC::R12; MoveReg = PPC::R12;
} }

View File

@ -257,7 +257,11 @@ def : Pat<(PPCtc_return CTRRC8:$dst, imm:$imm),
// 64-bit CR instructions // 64-bit CR instructions
let Interpretation64Bit = 1 in { let Interpretation64Bit = 1 in {
let neverHasSideEffects = 1 in { let neverHasSideEffects = 1 in {
def MTCRF8 : XFXForm_5<31, 144, (outs crbitm:$FXM), (ins g8rc:$rS), def MTOCRF8: XFXForm_5a<31, 144, (outs crbitm:$FXM), (ins g8rc:$ST),
"mtocrf $FXM, $ST", BrMCRX>,
PPC970_DGroup_First, PPC970_Unit_CRU;
def MTCRF8 : XFXForm_5<31, 144, (outs), (ins i32imm:$FXM, g8rc:$rS),
"mtcrf $FXM, $rS", BrMCRX>, "mtcrf $FXM, $rS", BrMCRX>,
PPC970_MicroCode, PPC970_Unit_CRU; PPC970_MicroCode, PPC970_Unit_CRU;

View File

@ -1898,7 +1898,11 @@ def RESTORE_VRSAVE : Pseudo<(outs VRSAVERC:$vrsave), (ins memri:$F),
"#RESTORE_VRSAVE", []>; "#RESTORE_VRSAVE", []>;
let neverHasSideEffects = 1 in { let neverHasSideEffects = 1 in {
def MTCRF : XFXForm_5<31, 144, (outs crbitm:$FXM), (ins gprc:$rS), def MTOCRF: XFXForm_5a<31, 144, (outs crbitm:$FXM), (ins gprc:$ST),
"mtocrf $FXM, $ST", BrMCRX>,
PPC970_DGroup_First, PPC970_Unit_CRU;
def MTCRF : XFXForm_5<31, 144, (outs), (ins i32imm:$FXM, gprc:$rS),
"mtcrf $FXM, $rS", BrMCRX>, "mtcrf $FXM, $rS", BrMCRX>,
PPC970_MicroCode, PPC970_Unit_CRU; PPC970_MicroCode, PPC970_Unit_CRU;
@ -2322,6 +2326,8 @@ def : InstAlias<"mr. $rA, $rB", (OR8o g8rc:$rA, g8rc:$rB, g8rc:$rB)>;
def : InstAlias<"not $rA, $rB", (NOR8 g8rc:$rA, g8rc:$rB, g8rc:$rB)>; def : InstAlias<"not $rA, $rB", (NOR8 g8rc:$rA, g8rc:$rB, g8rc:$rB)>;
def : InstAlias<"not. $rA, $rB", (NOR8o g8rc:$rA, g8rc:$rB, g8rc:$rB)>; def : InstAlias<"not. $rA, $rB", (NOR8o g8rc:$rA, g8rc:$rB, g8rc:$rB)>;
def : InstAlias<"mtcr $rA", (MTCRF8 255, g8rc:$rA)>;
def LAx : PPCAsmPseudo<"la $rA, $addr", (ins gprc:$rA, memri:$addr)>; def LAx : PPCAsmPseudo<"la $rA, $addr", (ins gprc:$rA, memri:$addr)>;
def SUBI : PPCAsmPseudo<"subi $rA, $rB, $imm", def SUBI : PPCAsmPseudo<"subi $rA, $rB, $imm",

View File

@ -403,7 +403,7 @@ void PPCRegisterInfo::lowerCRRestore(MachineBasicBlock::iterator II,
.addImm(31); .addImm(31);
} }
BuildMI(MBB, II, dl, TII.get(LP64 ? PPC::MTCRF8 : PPC::MTCRF), DestReg) BuildMI(MBB, II, dl, TII.get(LP64 ? PPC::MTOCRF8 : PPC::MTOCRF), DestReg)
.addReg(Reg, RegState::Kill); .addReg(Reg, RegState::Kill);
// Discard the pseudo instruction. // Discard the pseudo instruction.

View File

@ -1,5 +1,5 @@
; RUN: llc -O0 -disable-fp-elim -mtriple=powerpc-unknown-linux-gnu < %s | FileCheck %s -check-prefix=PPC32 ; RUN: llc -O0 -disable-fp-elim -mtriple=powerpc-unknown-linux-gnu -mcpu=g5 < %s | FileCheck %s -check-prefix=PPC32
; RUN: llc -O0 -mtriple=powerpc64-unknown-linux-gnu < %s | FileCheck %s -check-prefix=PPC64 ; RUN: llc -O0 -mtriple=powerpc64-unknown-linux-gnu -mcpu=g5 < %s | FileCheck %s -check-prefix=PPC64
declare void @foo() declare void @foo()
@ -18,7 +18,7 @@ entry:
; PPC32: mfcr 12 ; PPC32: mfcr 12
; PPC32-NEXT: stw 12, 24(31) ; PPC32-NEXT: stw 12, 24(31)
; PPC32: lwz 12, 24(31) ; PPC32: lwz 12, 24(31)
; PPC32-NEXT: mtcrf 32, 12 ; PPC32-NEXT: mtocrf 32, 12
; PPC64: .cfi_startproc ; PPC64: .cfi_startproc
; PPC64: mfcr 12 ; PPC64: mfcr 12
@ -29,7 +29,7 @@ entry:
; PPC64: .cfi_offset cr2, 8 ; PPC64: .cfi_offset cr2, 8
; PPC64: addi 1, 1, [[AMT]] ; PPC64: addi 1, 1, [[AMT]]
; PPC64: lwz 12, 8(1) ; PPC64: lwz 12, 8(1)
; PPC64: mtcrf 32, 12 ; PPC64: mtocrf 32, 12
; PPC64: .cfi_endproc ; PPC64: .cfi_endproc
define i32 @test_cr234() nounwind { define i32 @test_cr234() nounwind {
@ -47,16 +47,16 @@ entry:
; PPC32: mfcr 12 ; PPC32: mfcr 12
; PPC32-NEXT: stw 12, 24(31) ; PPC32-NEXT: stw 12, 24(31)
; PPC32: lwz 12, 24(31) ; PPC32: lwz 12, 24(31)
; PPC32-NEXT: mtcrf 32, 12 ; PPC32-NEXT: mtocrf 32, 12
; PPC32-NEXT: mtcrf 16, 12 ; PPC32-NEXT: mtocrf 16, 12
; PPC32-NEXT: mtcrf 8, 12 ; PPC32-NEXT: mtocrf 8, 12
; PPC64: mfcr 12 ; PPC64: mfcr 12
; PPC64: stw 12, 8(1) ; PPC64: stw 12, 8(1)
; PPC64: stdu 1, -[[AMT:[0-9]+]](1) ; PPC64: stdu 1, -[[AMT:[0-9]+]](1)
; PPC64: addi 1, 1, [[AMT]] ; PPC64: addi 1, 1, [[AMT]]
; PPC64: lwz 12, 8(1) ; PPC64: lwz 12, 8(1)
; PPC64: mtcrf 32, 12 ; PPC64: mtocrf 32, 12
; PPC64: mtcrf 16, 12 ; PPC64: mtocrf 16, 12
; PPC64: mtcrf 8, 12 ; PPC64: mtocrf 8, 12

View File

@ -1986,4 +1986,6 @@
not 2, 3 not 2, 3
# CHECK: nor. 2, 3, 3 # encoding: [0x7c,0x62,0x18,0xf9] # CHECK: nor. 2, 3, 3 # encoding: [0x7c,0x62,0x18,0xf9]
not. 2, 3 not. 2, 3
# CHECK: mtcrf 255, 2 # encoding: [0x7c,0x4f,0xf1,0x20]
mtcr 2

View File

@ -508,12 +508,12 @@
mtspr 600, 2 mtspr 600, 2
# CHECK: mfspr 2, 600 # encoding: [0x7c,0x58,0x92,0xa6] # CHECK: mfspr 2, 600 # encoding: [0x7c,0x58,0x92,0xa6]
mfspr 2, 600 mfspr 2, 600
# CHECK: mtcrf 16, 2 # encoding: [0x7c,0x41,0x01,0x20] # CHECK: mtcrf 123, 2 # encoding: [0x7c,0x47,0xb1,0x20]
mtcrf 16, 2 mtcrf 123, 2
# CHECK: mfcr 2 # encoding: [0x7c,0x40,0x00,0x26] # CHECK: mfcr 2 # encoding: [0x7c,0x40,0x00,0x26]
mfcr 2 mfcr 2
# FIXME: mtocrf 16, 2 # CHECK: mtocrf 16, 2 # encoding: [0x7c,0x51,0x01,0x20]
mtocrf 16, 2
# CHECK: mfocrf 16, 8 # encoding: [0x7e,0x10,0x80,0x26] # CHECK: mfocrf 16, 8 # encoding: [0x7e,0x10,0x80,0x26]
mfocrf 16, 8 mfocrf 16, 8
# FIXME: mcrxr 2