Index: lib/Target/PowerPC/PPCFrameLowering.cpp =================================================================== --- lib/Target/PowerPC/PPCFrameLowering.cpp +++ lib/Target/PowerPC/PPCFrameLowering.cpp @@ -838,11 +838,15 @@ // If we need to spill the CR and the LR but we don't have two separate // registers available, we must spill them one at a time if (MustSaveCR && SingleScratchReg && MustSaveLR) { - // FIXME: In the ELFv2 ABI, we are not required to save all CR fields. - // If only one or two CR fields are clobbered, it could be more - // efficient to use mfocrf to selectively save just those fields. + // In the ELFv2 ABI, we are not required to save all CR fields. + // If only one or two CR fields are clobbered, it is more efficient to use + // mfocrf to selectively save just those fields, because mfocrf has short + // latency compares to mfcr. + unsigned MfcrOpcode = PPC::MFCR8; + if (isELFv2ABI && MustSaveCRs.size() == 1) + MfcrOpcode = PPC::MFOCRF8; MachineInstrBuilder MIB = - BuildMI(MBB, MBBI, dl, TII.get(PPC::MFCR8), TempReg); + BuildMI(MBB, MBBI, dl, TII.get(MfcrOpcode), TempReg); for (unsigned i = 0, e = MustSaveCRs.size(); i != e; ++i) MIB.addReg(MustSaveCRs[i], RegState::ImplicitKill); BuildMI(MBB, MBBI, dl, TII.get(PPC::STW8)) @@ -856,11 +860,15 @@ if (MustSaveCR && !(SingleScratchReg && MustSaveLR)) { // will only occur for PPC64 - // FIXME: In the ELFv2 ABI, we are not required to save all CR fields. - // If only one or two CR fields are clobbered, it could be more - // efficient to use mfocrf to selectively save just those fields. + // In the ELFv2 ABI, we are not required to save all CR fields. + // If only one or two CR fields are clobbered, it is more efficient to use + // mfocrf to selectively save just those fields, because mfocrf has short + // latency compares to mfcr. + unsigned MfcrOpcode = PPC::MFCR8; + if (isELFv2ABI && MustSaveCRs.size() == 1) + MfcrOpcode = PPC::MFOCRF8; MachineInstrBuilder MIB = - BuildMI(MBB, MBBI, dl, TII.get(PPC::MFCR8), TempReg); + BuildMI(MBB, MBBI, dl, TII.get(MfcrOpcode), TempReg); for (unsigned i = 0, e = MustSaveCRs.size(); i != e; ++i) MIB.addReg(MustSaveCRs[i], RegState::ImplicitKill); } Index: test/CodeGen/PowerPC/crsave.ll =================================================================== --- test/CodeGen/PowerPC/crsave.ll +++ test/CodeGen/PowerPC/crsave.ll @@ -1,5 +1,6 @@ ; 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 -mcpu=g5 < %s | FileCheck %s -check-prefix=PPC64 +; RUN: llc -O0 -mtriple=powerpc64le-unknown-linux-gnu < %s | FileCheck %s -check-prefix=PPC64-ELFv2 declare void @foo() @@ -60,3 +61,22 @@ ; PPC64: mtocrf 16, 12 ; PPC64: mtocrf 8, 12 +; Generate mfocrf in prologue when we need to save 1 nonvolatile CR field +define void @cloberOneNvCrField() { +entry: + tail call void asm sideeffect "# clobbers", "~{cr2}"() + ret void + +; PPC64-ELFv2-LABEL: @cloberOneNvCrField +; PPC64-ELFv2: mfocrf [[REG1:[0-9]+]], 32 +} + +; Generate mfcr in prologue when we need to save all nonvolatile CR field +define void @cloberAllNvCrField() { +entry: + tail call void asm sideeffect "# clobbers", "~{cr2},~{cr3},~{cr4}"() + ret void + +; PPC64-ELFv2-LABEL: @cloberAllNvCrField +; PPC64-ELFv2: mfcr [[REG1:[0-9]+]] +} Index: test/CodeGen/PowerPC/pr26690.ll =================================================================== --- test/CodeGen/PowerPC/pr26690.ll +++ test/CodeGen/PowerPC/pr26690.ll @@ -101,7 +101,7 @@ ret i32 2 } -; CHECK: mfcr {{[0-9]+}} +; CHECK: mfocrf {{[0-9]+}} !llvm.ident = !{!0}