Get rid of a pseudo instruction and replace it with subreg based operation on real...
authorChristopher Lamb <christopher.lamb@gmail.com>
Thu, 13 Mar 2008 05:47:01 +0000 (05:47 +0000)
committerChristopher Lamb <christopher.lamb@gmail.com>
Thu, 13 Mar 2008 05:47:01 +0000 (05:47 +0000)
Note: the coalescer will have to be careful about this too, when it starts coalescing insert_subreg nodes.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@48329 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Target/TargetInstrInfo.h
lib/CodeGen/LowerSubregs.cpp
lib/Target/TargetSelectionDAG.td
lib/Target/X86/X86ATTAsmPrinter.cpp
lib/Target/X86/X86ISelDAGToDAG.cpp
lib/Target/X86/X86Instr64bit.td
lib/Target/X86/X86InstrInfo.cpp
lib/Target/X86/X86InstrInfo.h
lib/Target/X86/X86InstrInfo.td
lib/Target/X86/X86IntelAsmPrinter.cpp
utils/TableGen/DAGISelEmitter.cpp

index 75260878dd21f18ff2af865fac4982937b87c3f5..d19ca1242062ab23494a2070dc01390cd6c84abb 100644 (file)
@@ -51,6 +51,15 @@ public:
     EXTRACT_SUBREG = 4,
     INSERT_SUBREG = 5
   };
+  
+  // Target independent implict values for use with subreg insert. All targets
+  // that support insert_subreg support IMPL_VAL_UNDEF. Support for the other 
+  // values is target dependent.
+  enum ImplictVal {
+    IMPL_VAL_UNDEF = 0,
+    IMPL_VAL_ZERO  = 1,
+    LAST_IMPL_VAL  = 3
+  };
 
   unsigned getNumOpcodes() const { return NumOpcodes; }
 
@@ -120,7 +129,6 @@ public:
     return false;
   }
   
-  
   /// convertToThreeAddress - This method must be implemented by targets that
   /// set the M_CONVERTIBLE_TO_3_ADDR flag.  When this flag is set, the target
   /// may be able to convert a two-address instruction into one or more true
index 531713e47fbceb17bff4f8cf7827daae95a30e7f..8945dd57b1851df2bb7d446f831a96044abce415 100644 (file)
@@ -96,13 +96,10 @@ bool LowerSubregsInstructionPass::LowerInsert(MachineInstr *MI) {
          (MI->getOperand(2).isRegister() && MI->getOperand(2).isUse()) &&
           MI->getOperand(3).isImmediate() && "Invalid insert_subreg");
           
+  // Check if we're inserting into an implicit undef value.
+  bool isImplicit = MI->getOperand(1).isImmediate();
   unsigned DstReg = MI->getOperand(0).getReg();
-  unsigned SrcReg = 0;
-  // Check if we're inserting into an implicit value.
-  if (MI->getOperand(1).isImmediate())
-    SrcReg = DstReg;
-  else
-    SrcReg = MI->getOperand(1).getReg();
+  unsigned SrcReg = isImplicit ? DstReg : MI->getOperand(1).getReg();
   unsigned InsReg = MI->getOperand(2).getReg();
   unsigned SubIdx = MI->getOperand(3).getImm();     
 
@@ -118,13 +115,20 @@ bool LowerSubregsInstructionPass::LowerInsert(MachineInstr *MI) {
 
   DOUT << "subreg: CONVERTING: " << *MI;
        
+  // Check whether the implict subreg copy has side affects or not. Only copies
+  // into an undef value have no side affects, that is they can be eliminated
+  // without changing the semantics of the program.
+  bool copyHasSideAffects = isImplicit? 
+                  MI->getOperand(1).getImm() != TargetInstrInfo::IMPL_VAL_UNDEF
+                  : false; 
+       
   // If the inserted register is already allocated into a subregister
   // of the destination, we copy the subreg into the source
   // However, this is only safe if the insert instruction is the kill
   // of the source register
   bool revCopyOrder = TRI.isSubRegister(DstReg, InsReg);
-  if (revCopyOrder && InsReg != DstSubReg) {
-    if (MI->getOperand(1).isKill()) {
+  if (revCopyOrder && (InsReg != DstSubReg || copyHasSideAffects)) {
+    if (isImplicit || MI->getOperand(1).isKill()) {
       DstSubReg = TRI.getSubReg(SrcReg, SubIdx);
       // Insert sub-register copy
       const TargetRegisterClass *TRC1 = 0;
@@ -144,7 +148,7 @@ bool LowerSubregsInstructionPass::LowerInsert(MachineInstr *MI) {
     }
   }
 #ifndef NDEBUG
-  if (InsReg == DstSubReg) {
+  if (InsReg == DstSubReg && !copyHasSideAffects) {
      DOUT << "subreg: Eliminated subreg copy\n";
   }
 #endif
@@ -174,7 +178,7 @@ bool LowerSubregsInstructionPass::LowerInsert(MachineInstr *MI) {
   }
 #endif
 
-  if (!revCopyOrder && InsReg != DstSubReg) {
+  if (!revCopyOrder && (InsReg != DstSubReg || copyHasSideAffects)) {
     // Insert sub-register copy
     const TargetRegisterClass *TRC1 = 0;
     if (TargetRegisterInfo::isPhysicalRegister(InsReg)) {
index dc0fcb5443ea8b890df4a67fd1b2ae8931202493..73280f3f6fa93a00cbd1a339bf24931a41a39251 100644 (file)
@@ -919,5 +919,10 @@ def SDT_dwarf_loc : SDTypeProfile<0, 3,
                       [SDTCisInt<0>, SDTCisInt<1>, SDTCisInt<2>]>;
 def dwarf_loc : SDNode<"ISD::DEBUG_LOC", SDT_dwarf_loc,[SDNPHasChain]>;
 
-
+//===----------------------------------------------------------------------===//
+// Implict value insert subreg support.
+//
+// These should match the enum TargetInstrInfo::ImplictVal.
+def tii_impl_val_undef : PatLeaf<(i32 0)>;
+def tii_impl_val_zero  : PatLeaf<(i32 1)>;
 
index 4fef3827e3f8516241faab27c1c15cb56996e221..e51e065540e3c6bb7f61b3aa69c224ace61c87d1 100644 (file)
@@ -637,14 +637,6 @@ bool X86ATTAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
 void X86ATTAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
   ++EmittedInsts;
 
-  // See if a truncate instruction can be turned into a nop.
-  switch (MI->getOpcode()) {
-  default: break;
-  case X86::PsMOVZX64rr32:
-    O << TAI->getCommentString() << " ZERO-EXTEND " << "\n\t";
-    break;
-  }
-
   // Call the autogenerated instruction printer routines.
   printInstruction(MI);
 }
index d5601b74eab3673d10fa0f4b72dc45c9819ee954..bf233bfcbb459431c851f933662fdeab6819e8ed 100644 (file)
@@ -1533,14 +1533,9 @@ SDNode *X86DAGToDAGISel::Select(SDOperand N) {
       AddToISelQueue(N0);
       if (NVT == MVT::i64 || NVT == MVT::i32 || NVT == MVT::i16) {
         SDOperand SRIdx;
-        SDOperand ImplVal = CurDAG->getTargetConstant(X86::IMPL_VAL_UNDEF, 
-                                                      MVT::i32);
         switch(N0.getValueType()) {
         case MVT::i32:
           SRIdx = CurDAG->getTargetConstant(X86::SUBREG_32BIT, MVT::i32);
-          // x86-64 zero extends 32-bit inserts int 64-bit registers
-          if (Subtarget->is64Bit())
-            ImplVal = CurDAG->getTargetConstant(X86::IMPL_VAL_ZERO, MVT::i32);
           break;
         case MVT::i16:
           SRIdx = CurDAG->getTargetConstant(X86::SUBREG_16BIT, MVT::i32);
@@ -1552,6 +1547,8 @@ SDNode *X86DAGToDAGISel::Select(SDOperand N) {
         default: assert(0 && "Unknown any_extend!");
         }
         if (SRIdx.Val) {
+          SDOperand ImplVal = 
+              CurDAG->getTargetConstant(X86InstrInfo::IMPL_VAL_UNDEF, MVT::i32);
           SDNode *ResNode = CurDAG->getTargetNode(X86::INSERT_SUBREG,
                                                   NVT, ImplVal, N0, SRIdx);
 
index 3002b2c21082d20e2003bb397130fb5d282d656c..d5a9f0bc66f83873573eede17e91907f2ed5facf 100644 (file)
@@ -1089,22 +1089,6 @@ def Int_CVTTSS2SI64rm: RSSI<0x2C, MRMSrcMem, (outs GR64:$dst), (ins f32mem:$src)
 // Alias Instructions
 //===----------------------------------------------------------------------===//
 
-// Zero-extension
-// TODO: Remove this after proper i32 -> i64 zext support.
-def PsMOVZX64rr32: I<0x89, MRMDestReg, (outs GR64:$dst), (ins GR32:$src),
-                     "mov{l}\t{$src, ${dst:subreg32}|${dst:subreg32}, $src}",
-                     [(set GR64:$dst, (zext GR32:$src))]>;
-def PsMOVZX64rm32: I<0x8B, MRMSrcMem, (outs GR64:$dst), (ins i32mem:$src),
-                     "mov{l}\t{$src, ${dst:subreg32}|${dst:subreg32}, $src}",
-                     [(set GR64:$dst, (zextloadi64i32 addr:$src))]>;
-
-/// PsAND64rrFFFFFFFF - r = r & (2^32-1)
-def PsAND64rrFFFFFFFF
-  : I<0x89, MRMDestReg, (outs GR64:$dst), (ins GR64:$src),
-  "mov{l}\t{${src:subreg32}, ${dst:subreg32}|${dst:subreg32}, ${src:subreg32}}",
-      [(set GR64:$dst, (and GR64:$src, i64immFFFFFFFF))]>;
-
-
 // Alias instructions that map movr0 to xor. Use xorl instead of xorq; it's
 // equivalent due to implicit zero-extending, and it sometimes has a smaller
 // encoding.
@@ -1220,27 +1204,48 @@ def : Pat<(X86tcret (i64 texternalsym:$dst), imm:$off),
 def : Pat<(parallel (X86cmp GR64:$src1, 0), (implicit EFLAGS)),
           (TEST64rr GR64:$src1, GR64:$src1)>;
 
+
+
+// Zero-extension
+def : Pat<(i64 (zext GR32:$src)), (INSERT_SUBREG tii_impl_val_zero, 
+                                            GR32:$src, x86_subreg_32bit)>;
+
 // zextload bool -> zextload byte
 def : Pat<(zextloadi64i1 addr:$src), (MOVZX64rm8 addr:$src)>;
 
+def : Pat<(zextloadi64i32 addr:$src), (INSERT_SUBREG tii_impl_val_zero, 
+                                        (MOV32rm addr:$src), x86_subreg_32bit)>;
+
 // extload
 def : Pat<(extloadi64i1 addr:$src),  (MOVZX64rm8  addr:$src)>;
 def : Pat<(extloadi64i8 addr:$src),  (MOVZX64rm8  addr:$src)>;
 def : Pat<(extloadi64i16 addr:$src), (MOVZX64rm16 addr:$src)>;
-def : Pat<(extloadi64i32 addr:$src), (PsMOVZX64rm32 addr:$src)>;
+def : Pat<(extloadi64i32 addr:$src), (INSERT_SUBREG tii_impl_val_undef, 
+                                        (MOV32rm addr:$src), x86_subreg_32bit)>;
 
 // anyext -> zext
 def : Pat<(i64 (anyext GR8 :$src)), (MOVZX64rr8  GR8 :$src)>;
 def : Pat<(i64 (anyext GR16:$src)), (MOVZX64rr16 GR16:$src)>;
-def : Pat<(i64 (anyext GR32:$src)), (PsMOVZX64rr32 GR32:$src)>;
+def : Pat<(i64 (anyext GR32:$src)), (INSERT_SUBREG tii_impl_val_undef, 
+                                        GR32:$src, x86_subreg_32bit)>;
+
 def : Pat<(i64 (anyext (loadi8  addr:$src))), (MOVZX64rm8  addr:$src)>;
 def : Pat<(i64 (anyext (loadi16 addr:$src))), (MOVZX64rm16 addr:$src)>;
-def : Pat<(i64 (anyext (loadi32 addr:$src))), (PsMOVZX64rm32 addr:$src)>;
+def : Pat<(i64 (anyext (loadi32 addr:$src))), (INSERT_SUBREG tii_impl_val_undef, 
+                                                (MOV32rm addr:$src), 
+                                                  x86_subreg_32bit)>;
 
 //===----------------------------------------------------------------------===//
 // Some peepholes
 //===----------------------------------------------------------------------===//
 
+
+// r & (2^32-1) ==> mov32 + implicit zext
+def : Pat<(and GR64:$src, i64immFFFFFFFF), 
+          (INSERT_SUBREG tii_impl_val_zero, 
+            (MOV32rr (EXTRACT_SUBREG GR64:$src, x86_subreg_32bit)),
+            x86_subreg_32bit)>;
+
 // (shl x, 1) ==> (add x, x)
 def : Pat<(shl GR64:$src1, (i8 1)), (ADD64rr GR64:$src1, GR64:$src1)>;
 
index 8497fe3039ca3947553270b9b0d454ff984b9d86..ff666ff3c2794785740bb973cc37035d79c2d73a 100644 (file)
@@ -392,7 +392,6 @@ X86InstrInfo::X86InstrInfo(X86TargetMachine &tm)
     { X86::PSHUFDri,        X86::PSHUFDmi },
     { X86::PSHUFHWri,       X86::PSHUFHWmi },
     { X86::PSHUFLWri,       X86::PSHUFLWmi },
-    { X86::PsMOVZX64rr32,   X86::PsMOVZX64rm32 },
     { X86::RCPPSr,          X86::RCPPSm },
     { X86::RCPPSr_Int,      X86::RCPPSm_Int },
     { X86::RSQRTPSr,        X86::RSQRTPSm },
@@ -922,8 +921,9 @@ X86InstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
       // Build and insert into an implicit UNDEF value. This is OK because
       // well be shifting and then extracting the lower 16-bits. 
       MachineInstr *Ins = 
-       BuildMI(get(X86::INSERT_SUBREG),leaInReg).addImm(X86::IMPL_VAL_UNDEF)
-         .addReg(Src).addImm(X86::SUBREG_16BIT);
+       BuildMI(get(X86::INSERT_SUBREG),leaInReg)
+                    .addImm(X86InstrInfo::IMPL_VAL_UNDEF)
+                    .addReg(Src).addImm(X86::SUBREG_16BIT);
       
       NewMI = BuildMI(get(Opc), leaOutReg)
         .addReg(0).addImm(1 << ShAmt).addReg(leaInReg).addImm(0);
index e0d0342ae6ddf20db03d435e3474725ee0a52bdc..f4cdb706955e735bad53a4fb0995db1e4288a6ea 100644 (file)
@@ -45,15 +45,7 @@ namespace X86 {
     COND_S  = 15,
     COND_INVALID
   };
-  
-  // X86 specific implict values used for subregister inserts. 
-  // This can be used to model the fact that x86-64 by default
-  // inserts 32-bit values into 64-bit registers implicitly containing zeros.
-  enum ImplicitVal {
-    IMPL_VAL_UNDEF = 0,
-    IMPL_VAL_ZERO  = 1
-  };
-  
+    
   // Turn condition code into conditional branch opcode.
   unsigned GetCondBranchFromCond(CondCode CC);
   
index 4d03dba32dce9ca7fb10f02d21ed7989d6f01c0c..e32fb9c4b53b9e3a84dc610cc572f7c301727a10 100644 (file)
@@ -161,10 +161,6 @@ def i32i8imm  : Operand<i32>;
 // Branch targets have OtherVT type.
 def brtarget : Operand<OtherVT>;
 
-// These should match the enum X86::ImplicitVal
-def x86_impl_val_undef : PatLeaf<(i32 0)>;
-def x86_impl_val_zero  : PatLeaf<(i32 1)>;
-
 //===----------------------------------------------------------------------===//
 // X86 Complex Pattern Definitions.
 //
index 6c46b45456294219725a51ae2f33e4cc717caa6e..16d819a3d7c688ab6730961c0f58ac2389559472 100644 (file)
@@ -314,14 +314,6 @@ bool X86IntelAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
 void X86IntelAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
   ++EmittedInsts;
 
-  // See if a truncate instruction can be turned into a nop.
-  switch (MI->getOpcode()) {
-  default: break;
-  case X86::PsMOVZX64rr32:
-    O << TAI->getCommentString() << " ZERO-EXTEND " << "\n\t";
-    break;
-  }
-
   // Call the autogenerated instruction printer routines.
   printInstruction(MI);
 }
index 291a913c3791f239085bdb338a7d4d38955ab2ab..0c6afab4c99b7b1fb158ae8bb49b49a69a091792 100644 (file)
@@ -975,9 +975,9 @@ public:
         }
       }
 
-      // Generate MemOperandSDNodes nodes for each memory accesses covered by this
-      // pattern.
-      if (isRoot) {
+      // Generate MemOperandSDNodes nodes for each memory accesses covered by 
+      // this pattern.
+      if (II.isSimpleLoad | II.mayLoad | II.mayStore) {
         std::vector<std::string>::const_iterator mi, mie;
         for (mi = LSI.begin(), mie = LSI.end(); mi != mie; ++mi) {
           emitCode("SDOperand LSI_" + *mi + " = "
@@ -1880,14 +1880,9 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
      << "  SDOperand Tmp = CurDAG->getTargetConstant(C, MVT::i32);\n"
      << "  AddToISelQueue(N1);\n"
      << "  SDOperand Ops[] = { N0, N1, Tmp };\n"
-     << "  if (N0.getOpcode() == ISD::UNDEF) {\n"
-     << "    return CurDAG->getTargetNode(TargetInstrInfo::INSERT_SUBREG,\n"
-     << "                                 N.getValueType(), Ops+1, 2);\n"
-     << "  } else {\n"
-     << "    AddToISelQueue(N0);\n"
-     << "    return CurDAG->getTargetNode(TargetInstrInfo::INSERT_SUBREG,\n"
-     << "                                 N.getValueType(), Ops, 3);\n"
-     << "  }\n"
+     << "  AddToISelQueue(N0);\n"
+     << "  return CurDAG->getTargetNode(TargetInstrInfo::INSERT_SUBREG,\n"
+     << "                               N.getValueType(), Ops, 3);\n"
      << "}\n\n";
 
   OS << "// The main instruction selector code.\n"