diff options
author | Ahmed Bougacha <ahmed.bougacha@gmail.com> | 2016-05-07 01:11:17 +0000 |
---|---|---|
committer | Ahmed Bougacha <ahmed.bougacha@gmail.com> | 2016-05-07 01:11:17 +0000 |
commit | 04a8fc2e37baf725aa641e789b7237f19d5b515d (patch) | |
tree | 999608823be7cec67ac31f5f9ee4459c8436c261 /llvm/lib/Target/X86/X86FixupBWInsts.cpp | |
parent | 068ac4af391339fc0639e825b51ef53d1a792174 (diff) | |
download | bcm5719-llvm-04a8fc2e37baf725aa641e789b7237f19d5b515d.tar.gz bcm5719-llvm-04a8fc2e37baf725aa641e789b7237f19d5b515d.zip |
[X86] Teach X86FixupBWInsts to promote MOV8rr/MOV16rr to MOV32rr.
This re-applies r268760, reverted in r268794.
Fixes http://llvm.org/PR27670
The original imp-defs assertion was way overzealous: forward all
implicit operands, except imp-defs of the new super-reg def (r268787
for GR64, but also possible for GR16->GR32), or imp-uses of the new
super-reg use.
While there, mark the source use as Undef, and add an imp-use of the
old source reg: that should cover any case of dead super-regs.
At the stage the pass runs, flags are unlikely to matter anyway;
still, let's be as correct as possible.
Also add MIR tests for the various interesting cases.
Original commit message:
Codesize is less (16) or equal (8), and we avoid partial
dependencies.
Differential Revision: http://reviews.llvm.org/D19999
llvm-svn: 268831
Diffstat (limited to 'llvm/lib/Target/X86/X86FixupBWInsts.cpp')
-rw-r--r-- | llvm/lib/Target/X86/X86FixupBWInsts.cpp | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/llvm/lib/Target/X86/X86FixupBWInsts.cpp b/llvm/lib/Target/X86/X86FixupBWInsts.cpp index ad152824c18..0d1a14b67d2 100644 --- a/llvm/lib/Target/X86/X86FixupBWInsts.cpp +++ b/llvm/lib/Target/X86/X86FixupBWInsts.cpp @@ -90,6 +90,11 @@ class FixupBWInstPass : public MachineFunctionPass { /// OK, otherwise return nullptr. MachineInstr *tryReplaceLoad(unsigned New32BitOpcode, MachineInstr *MI) const; + /// Change the MachineInstr \p MI into the equivalent 32-bit copy if it is + /// safe to do so. Return the replacement instruction if OK, otherwise return + /// nullptr. + MachineInstr *tryReplaceCopy(MachineInstr *MI) const; + public: static char ID; @@ -226,6 +231,42 @@ MachineInstr *FixupBWInstPass::tryReplaceLoad(unsigned New32BitOpcode, return MIB; } +MachineInstr *FixupBWInstPass::tryReplaceCopy(MachineInstr *MI) const { + assert(MI->getNumExplicitOperands() == 2); + auto &OldDest = MI->getOperand(0); + auto &OldSrc = MI->getOperand(1); + + unsigned NewDestReg; + if (!getSuperRegDestIfDead(MI, NewDestReg)) + return nullptr; + + unsigned NewSrcReg = getX86SubSuperRegister(OldSrc.getReg(), 32); + + // This is only correct if we access the same subregister index: otherwise, + // we could try to replace "movb %ah, %al" with "movl %eax, %eax". + auto *TRI = &TII->getRegisterInfo(); + if (TRI->getSubRegIndex(NewSrcReg, OldSrc.getReg()) != + TRI->getSubRegIndex(NewDestReg, OldDest.getReg())) + return nullptr; + + // Safe to change the instruction. + // Don't set src flags, as we don't know if we're also killing the superreg. + // However, the superregister might not be defined; make it explicit that + // we don't care about the higher bits by reading it as Undef, and adding + // an imp-use on the original subregister. + MachineInstrBuilder MIB = + BuildMI(*MF, MI->getDebugLoc(), TII->get(X86::MOV32rr), NewDestReg) + .addReg(NewSrcReg, RegState::Undef) + .addReg(OldSrc.getReg(), RegState::Implicit); + + // Drop imp-defs/uses that would be redundant with the new def/use. + for (auto &Op : MI->implicit_operands()) + if (Op.getReg() != (Op.isDef() ? NewDestReg : NewSrcReg)) + MIB.addOperand(Op); + + return MIB; +} + void FixupBWInstPass::processBasicBlock(MachineFunction &MF, MachineBasicBlock &MBB) { @@ -272,6 +313,15 @@ void FixupBWInstPass::processBasicBlock(MachineFunction &MF, NewMI = tryReplaceLoad(X86::MOVZX32rm16, MI); break; + case X86::MOV8rr: + case X86::MOV16rr: + // Always try to replace 8/16 bit copies with a 32 bit copy. + // Code size is either less (16) or equal (8), and there is sometimes a + // perf advantage from eliminating a false dependence on the upper portion + // of the register. + NewMI = tryReplaceCopy(MI); + break; + default: // nothing to do here. break; |