From 0364d89b6d60e305ffec8bae74e9564f4e9355f2 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 6 Sep 2019 19:14:49 +0000 Subject: [PATCH] [X86] Teach FixupBWInsts to turn MOVSX16rr8/MOVZX16rr8/MOVSX16rm8/MOVZX16rm8 into their 32-bit dest equivalents when the upper part of the register is dead. llvm-svn: 371240 --- llvm/lib/Target/X86/X86FixupBWInsts.cpp | 54 +++++++++++++++++++++++++++---- llvm/test/CodeGen/X86/fast-isel-divrem.ll | 8 ++--- 2 files changed, 52 insertions(+), 10 deletions(-) diff --git a/llvm/lib/Target/X86/X86FixupBWInsts.cpp b/llvm/lib/Target/X86/X86FixupBWInsts.cpp index 4a5f05c..9f7c4af 100644 --- a/llvm/lib/Target/X86/X86FixupBWInsts.cpp +++ b/llvm/lib/Target/X86/X86FixupBWInsts.cpp @@ -92,6 +92,12 @@ class FixupBWInstPass : public MachineFunctionPass { /// nullptr. MachineInstr *tryReplaceCopy(MachineInstr *MI) const; + /// Change the MachineInstr \p MI into the equivalent extend to 32 bit + /// register if it is safe to do so. Return the replacement instruction if + /// OK, otherwise return nullptr. + MachineInstr *tryReplaceExtend(unsigned New32BitOpcode, + MachineInstr *MI) const; + // Change the MachineInstr \p MI into an eqivalent 32 bit instruction if // possible. Return the replacement instruction if OK, return nullptr // otherwise. @@ -232,12 +238,12 @@ bool FixupBWInstPass::getSuperRegDestIfDead(MachineInstr *OrigMI, // %ax = KILL %ax, implicit killed %eax // RET 0, %ax unsigned Opc = OrigMI->getOpcode(); (void)Opc; - // These are the opcodes currently handled by the pass, if something - // else will be added we need to ensure that new opcode has the same - // properties. - assert((Opc == X86::MOV8rm || Opc == X86::MOV16rm || Opc == X86::MOV8rr || - Opc == X86::MOV16rr) && - "Unexpected opcode."); + // These are the opcodes currently known to work with the code below, if + // something // else will be added we need to ensure that new opcode has the + // same properties. + if (Opc != X86::MOV8rm && Opc != X86::MOV16rm && Opc != X86::MOV8rr && + Opc != X86::MOV16rr) + return false; bool IsDefined = false; for (auto &MO: OrigMI->implicit_operands()) { @@ -326,6 +332,33 @@ MachineInstr *FixupBWInstPass::tryReplaceCopy(MachineInstr *MI) const { return MIB; } +MachineInstr *FixupBWInstPass::tryReplaceExtend(unsigned New32BitOpcode, + MachineInstr *MI) const { + Register NewDestReg; + if (!getSuperRegDestIfDead(MI, NewDestReg)) + return nullptr; + + // Don't interfere with formation of CBW instructions which should be a + // shorter encoding than even the MOVSX32rr8. It's also immunte to partial + // merge issues on Intel CPUs. + if (MI->getOpcode() == X86::MOVSX16rr8 && + MI->getOperand(0).getReg() == X86::AX && + MI->getOperand(1).getReg() == X86::AL) + return nullptr; + + // Safe to change the instruction. + MachineInstrBuilder MIB = + BuildMI(*MF, MI->getDebugLoc(), TII->get(New32BitOpcode), NewDestReg); + + unsigned NumArgs = MI->getNumOperands(); + for (unsigned i = 1; i < NumArgs; ++i) + MIB.add(MI->getOperand(i)); + + MIB.setMemRefs(MI->memoperands()); + + return MIB; +} + MachineInstr *FixupBWInstPass::tryReplaceInstr(MachineInstr *MI, MachineBasicBlock &MBB) const { // See if this is an instruction of the type we are currently looking for. @@ -355,6 +388,15 @@ MachineInstr *FixupBWInstPass::tryReplaceInstr(MachineInstr *MI, // of the register. return tryReplaceCopy(MI); + case X86::MOVSX16rr8: + return tryReplaceExtend(X86::MOVSX32rr8, MI); + case X86::MOVSX16rm8: + return tryReplaceExtend(X86::MOVSX32rm8, MI); + case X86::MOVZX16rr8: + return tryReplaceExtend(X86::MOVZX32rr8, MI); + case X86::MOVZX16rm8: + return tryReplaceExtend(X86::MOVZX32rm8, MI); + default: // nothing to do here. break; diff --git a/llvm/test/CodeGen/X86/fast-isel-divrem.ll b/llvm/test/CodeGen/X86/fast-isel-divrem.ll index 3e649ca..45b9d6a 100644 --- a/llvm/test/CodeGen/X86/fast-isel-divrem.ll +++ b/llvm/test/CodeGen/X86/fast-isel-divrem.ll @@ -8,7 +8,7 @@ entry: } ; CHECK-LABEL: test_sdiv8: -; CHECK: movsbw +; CHECK: movsbl ; CHECK: idivb define i8 @test_srem8(i8 %dividend, i8 %divisor) nounwind { @@ -18,7 +18,7 @@ entry: } ; CHECK-LABEL: test_srem8: -; CHECK: movsbw +; CHECK: movsbl ; CHECK: idivb define i8 @test_udiv8(i8 %dividend, i8 %divisor) nounwind { @@ -28,7 +28,7 @@ entry: } ; CHECK-LABEL: test_udiv8: -; CHECK: movzbw +; CHECK: movzbl ; CHECK: divb define i8 @test_urem8(i8 %dividend, i8 %divisor) nounwind { @@ -38,7 +38,7 @@ entry: } ; CHECK-LABEL: test_urem8: -; CHECK: movzbw +; CHECK: movzbl ; CHECK: divb define i16 @test_sdiv16(i16 %dividend, i16 %divisor) nounwind { -- 2.7.4