[X86] Teach FixupBWInsts to turn MOVSX16rr8/MOVZX16rr8/MOVSX16rm8/MOVZX16rm8 into...
authorCraig Topper <craig.topper@intel.com>
Fri, 6 Sep 2019 19:14:49 +0000 (19:14 +0000)
committerCraig Topper <craig.topper@intel.com>
Fri, 6 Sep 2019 19:14:49 +0000 (19:14 +0000)
llvm-svn: 371240

llvm/lib/Target/X86/X86FixupBWInsts.cpp
llvm/test/CodeGen/X86/fast-isel-divrem.ll

index 4a5f05c..9f7c4af 100644 (file)
@@ -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;
index 3e649ca..45b9d6a 100644 (file)
@@ -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 {