Fixing truncate. Previously we were emitting truncate from r16 to r8 as
authorEvan Cheng <evan.cheng@apple.com>
Mon, 8 May 2006 08:01:26 +0000 (08:01 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Mon, 8 May 2006 08:01:26 +0000 (08:01 +0000)
movw. That is we promote the destination operand to r16. So
        %CH = TRUNC_R16_R8 %BP
is emitted as
        movw %bp, %cx.

This is incorrect. If %cl is live, it would be clobbered.
Ideally we want to do the opposite, that is emitted it as
        movb ??, %ch
But this is not possible since %bp does not have a r8 sub-register.

We are now defining a new register class R16_ which is a subclass of R16
containing only those 16-bit registers that have r8 sub-registers (i.e.
AX - DX). We isel the truncate to two instructions, a MOV16to16_ to copy the
value to the R16_ class, followed by a TRUNC_R16_R8.

Due to bug 770, the register colaescer is not going to coalesce between R16 and
R16_. That will be fixed later so we can eliminate the MOV16to16_. Right now, it
can only be eliminated if we are lucky that source and destination registers are
the same.

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

lib/Target/X86/X86ATTAsmPrinter.cpp
lib/Target/X86/X86ISelDAGToDAG.cpp
lib/Target/X86/X86InstrInfo.cpp
lib/Target/X86/X86InstrInfo.td
lib/Target/X86/X86IntelAsmPrinter.cpp
lib/Target/X86/X86RegisterInfo.cpp
lib/Target/X86/X86RegisterInfo.td

index 326251ccc2ed6b437ca62786c78bf6e087b3a54f..7baa8f87178244774e8f193d1d2af6d76d376e56 100755 (executable)
@@ -115,7 +115,7 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
     unsigned Reg = MO.getReg();
     if (Modifier && strncmp(Modifier, "trunc", strlen("trunc")) == 0) {
       MVT::ValueType VT = (strcmp(Modifier,"trunc16") == 0)
-        ? MVT::i16 : MVT::i32;
+        ? MVT::i16 : MVT::i8;
       Reg = getX86SubSuperRegister(Reg, VT);
     }
     for (const char *Name = RI.get(Reg).Name; *Name; ++Name)
@@ -366,12 +366,13 @@ void X86ATTAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
     const MachineOperand &MO1 = MI->getOperand(1);
     unsigned Reg0 = MO0.getReg();
     unsigned Reg1 = MO1.getReg();
-    if (MI->getOpcode() == X86::TRUNC_R16_R8)
-      Reg0 = getX86SubSuperRegister(Reg0, MVT::i16);
+    if (MI->getOpcode() == X86::TRUNC_R32_R16)
+      Reg1 = getX86SubSuperRegister(Reg1, MVT::i16);
     else
-      Reg0 = getX86SubSuperRegister(Reg0, MVT::i32);
-    if (Reg0 == Reg1)
-      O << CommentString << " TRUNCATE ";
+      Reg1 = getX86SubSuperRegister(Reg1, MVT::i8);
+    O << CommentString << " TRUNCATE ";
+    if (Reg0 != Reg1)
+      O << "\n\t";
     break;
   }
   }
index c0c9704c04fbe2d95a7677baa7b940554dfc88ac..20534beb7514c8cf903f84d48f43499381ff845c 100644 (file)
@@ -791,6 +791,44 @@ void X86DAGToDAGISel::Select(SDOperand &Result, SDOperand N) {
 #endif
       return;
     }
+
+    case ISD::TRUNCATE: {
+      if (NVT == MVT::i8) {
+        unsigned Opc2;
+        MVT::ValueType VT;
+        switch (Node->getOperand(0).getValueType()) {
+        default: assert(0 && "Unknown truncate!");
+        case MVT::i16:
+          Opc = X86::MOV16to16_;
+          VT = MVT::i16;
+          Opc2 = X86::TRUNC_R16_R8;
+          break;
+        case MVT::i32:
+          Opc = X86::MOV32to32_;
+          VT = MVT::i32;
+          if (NVT == MVT::i16)
+            Opc2 = X86::TRUNC_R32_R16;
+          else
+            Opc2 = X86::TRUNC_R32_R8;
+          break;
+        }
+
+        SDOperand Tmp0, Tmp1;
+        Select(Tmp0, Node->getOperand(0));
+        Tmp1 = SDOperand(CurDAG->getTargetNode(Opc, VT, Tmp0), 0);
+        Result = CodeGenMap[N] =
+          SDOperand(CurDAG->getTargetNode(Opc2, NVT, Tmp1), 0);
+      
+#ifndef NDEBUG
+        DEBUG(std::cerr << std::string(Indent-2, ' '));
+        DEBUG(std::cerr << "== ");
+        DEBUG(Result.Val->dump(CurDAG));
+        DEBUG(std::cerr << "\n");
+        Indent -= 2;
+#endif
+        return;
+      }
+    }
   }
 
   SelectCode(Result, N);
index 31a4f6fe2e7e7f87e436ce0ddb9b0effbf0594d2..cc30bfe0639dcd3d50161dd356ec6266cf595f90 100644 (file)
@@ -28,6 +28,7 @@ bool X86InstrInfo::isMoveInstr(const MachineInstr& MI,
                                unsigned& destReg) const {
   MachineOpCode oc = MI.getOpcode();
   if (oc == X86::MOV8rr || oc == X86::MOV16rr || oc == X86::MOV32rr ||
+      oc == X86::MOV16to16_ || oc == X86::MOV32to32_ ||
       oc == X86::FpMOV  || oc == X86::MOVSSrr || oc == X86::MOVSDrr ||
       oc == X86::FsMOVAPSrr || oc == X86::FsMOVAPDrr ||
       oc == X86::MOVAPSrr || oc == X86::MOVAPDrr ||
index 73baba9a57e19239617dad0a2e29d7c5e6c4412c..6729e7db7b07db7df3bdb63bf799d9d5d7d83f80 100644 (file)
@@ -357,15 +357,13 @@ def IMPLICIT_DEF_R32  : I<0, Pseudo, (ops R32:$dst),
 def NOOP : I<0x90, RawFrm, (ops), "nop", []>;
 
 // Truncate
-def TRUNC_R32_R8  : I<0x89, MRMDestReg, (ops R8:$dst, R32:$src),
-                      "mov{l} {$src, ${dst:trunc32}|${dst:trunc32}, $src}",
-                      [(set R8:$dst, (trunc R32:$src))]>;
+def TRUNC_R32_R8  : I<0x88, MRMDestReg, (ops R8:$dst, R32_:$src),
+                      "mov{b} {${src:trunc8}, $dst|$dst, ${src:trunc8}", []>;
+def TRUNC_R16_R8  : I<0x88, MRMDestReg, (ops R8:$dst, R16_:$src),
+                      "mov{b} {${src:trunc8}, $dst|$dst, ${src:trunc8}}", []>;
 def TRUNC_R32_R16 : I<0x89, MRMDestReg, (ops R16:$dst, R32:$src),
-                      "mov{l} {$src, ${dst:trunc32}|${dst:trunc32}, $src}",
+                      "mov{w} {${src:trunc16}, $dst|$dst, ${src:trunc16}}",
                       [(set R16:$dst, (trunc R32:$src))]>;
-def TRUNC_R16_R8  : I<0x89, MRMDestReg, (ops R8:$dst, R16:$src),
-                      "mov{w} {$src, ${dst:trunc16}|${dst:trunc16}, $src}",
-                      [(set R8:$dst, (trunc R16:$src))]>;
 
 //===----------------------------------------------------------------------===//
 //  Control Flow Instructions...
@@ -2310,6 +2308,26 @@ def MOV32r0  : I<0x31, MRMInitReg,  (ops R32:$dst),
                  "xor{l} $dst, $dst",
                  [(set R32:$dst, 0)]>;
 
+// Basic operations on R16 / R32 subclasses R16_ and R32_ which contains only
+// those registers that have R8 sub-registers (i.e. AX - DX, EAX - EDX).
+def MOV16to16_ : I<0x89, MRMDestReg, (ops R16_:$dst, R16:$src),
+                "mov{w} {$src, $dst|$dst, $src}", []>, OpSize;
+def MOV32to32_ : I<0x89, MRMDestReg, (ops R32_:$dst, R32:$src),
+                "mov{l} {$src, $dst|$dst, $src}", []>;
+
+def MOV16_rr : I<0x89, MRMDestReg, (ops R16_:$dst, R16_:$src),
+                "mov{w} {$src, $dst|$dst, $src}", []>, OpSize;
+def MOV32_rr : I<0x89, MRMDestReg, (ops R32_:$dst, R32_:$src),
+                "mov{l} {$src, $dst|$dst, $src}", []>;
+def MOV16_rm : I<0x8B, MRMSrcMem, (ops R16_:$dst, i16mem:$src),
+                "mov{w} {$src, $dst|$dst, $src}", []>, OpSize;
+def MOV32_rm : I<0x8B, MRMSrcMem, (ops R32_:$dst, i32mem:$src),
+                "mov{l} {$src, $dst|$dst, $src}", []>;
+def MOV16_mr : I<0x89, MRMDestMem, (ops i16mem:$dst, R16_:$src),
+                "mov{w} {$src, $dst|$dst, $src}", []>, OpSize;
+def MOV32_mr : I<0x89, MRMDestMem, (ops i32mem:$dst, R32_:$src),
+                "mov{l} {$src, $dst|$dst, $src}", []>;
+
 //===----------------------------------------------------------------------===//
 // DWARF Pseudo Instructions
 //
index fc42797d6c7c78f40d93f97a610656e02c93822d..952f73206e92ad831625fb040044aa3c27e26fa3 100755 (executable)
@@ -89,7 +89,7 @@ void X86IntelAsmPrinter::printOp(const MachineOperand &MO,
       unsigned Reg = MO.getReg();
       if (Modifier && strncmp(Modifier, "trunc", strlen("trunc")) == 0) {
         MVT::ValueType VT = (strcmp(Modifier,"trunc16") == 0)
-          ? MVT::i16 : MVT::i32;
+          ? MVT::i16 : MVT::i8;
         Reg = getX86SubSuperRegister(Reg, VT);
       }
       O << RI.get(Reg).Name;
@@ -268,12 +268,13 @@ void X86IntelAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
     const MachineOperand &MO1 = MI->getOperand(1);
     unsigned Reg0 = MO0.getReg();
     unsigned Reg1 = MO1.getReg();
-    if (MI->getOpcode() == X86::TRUNC_R16_R8)
-      Reg0 = getX86SubSuperRegister(Reg0, MVT::i16);
+    if (MI->getOpcode() == X86::TRUNC_R32_R16)
+      Reg1 = getX86SubSuperRegister(Reg1, MVT::i16);
     else
-      Reg0 = getX86SubSuperRegister(Reg0, MVT::i32);
-    if (Reg0 == Reg1)
-      O << CommentString << " TRUNCATE ";
+      Reg1 = getX86SubSuperRegister(Reg1, MVT::i8);
+    O << CommentString << " TRUNCATE ";
+    if (Reg0 != Reg1)
+      O << "\n\t";
     break;
   }
   }
index dac71a02f120a82b638f92479e611e0b9704dce5..57e6b17e6aea357a9aa6d948ea2a48f50a532503 100644 (file)
@@ -52,10 +52,14 @@ void X86RegisterInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
   unsigned Opc;
   if (RC == &X86::R32RegClass) {
     Opc = X86::MOV32mr;
-  } else if (RC == &X86::R8RegClass) {
-    Opc = X86::MOV8mr;
   } else if (RC == &X86::R16RegClass) {
     Opc = X86::MOV16mr;
+  } else if (RC == &X86::R8RegClass) {
+    Opc = X86::MOV8mr;
+  } else if (RC == &X86::R32_RegClass) {
+    Opc = X86::MOV32_mr;
+  } else if (RC == &X86::R16_RegClass) {
+    Opc = X86::MOV16_mr;
   } else if (RC == &X86::RFPRegClass || RC == &X86::RSTRegClass) {
     Opc = X86::FpST64m;
   } else if (RC == &X86::FR32RegClass) {
@@ -78,10 +82,14 @@ void X86RegisterInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
   unsigned Opc;
   if (RC == &X86::R32RegClass) {
     Opc = X86::MOV32rm;
-  } else if (RC == &X86::R8RegClass) {
-    Opc = X86::MOV8rm;
   } else if (RC == &X86::R16RegClass) {
     Opc = X86::MOV16rm;
+  } else if (RC == &X86::R8RegClass) {
+    Opc = X86::MOV8rm;
+  } else if (RC == &X86::R32_RegClass) {
+    Opc = X86::MOV32_rm;
+  } else if (RC == &X86::R16_RegClass) {
+    Opc = X86::MOV16_rm;
   } else if (RC == &X86::RFPRegClass || RC == &X86::RSTRegClass) {
     Opc = X86::FpLD64m;
   } else if (RC == &X86::FR32RegClass) {
@@ -104,10 +112,14 @@ void X86RegisterInfo::copyRegToReg(MachineBasicBlock &MBB,
   unsigned Opc;
   if (RC == &X86::R32RegClass) {
     Opc = X86::MOV32rr;
-  } else if (RC == &X86::R8RegClass) {
-    Opc = X86::MOV8rr;
   } else if (RC == &X86::R16RegClass) {
     Opc = X86::MOV16rr;
+  } else if (RC == &X86::R8RegClass) {
+    Opc = X86::MOV8rr;
+  } else if (RC == &X86::R32_RegClass) {
+    Opc = X86::MOV32_rr;
+  } else if (RC == &X86::R16_RegClass) {
+    Opc = X86::MOV16_rr;
   } else if (RC == &X86::RFPRegClass || RC == &X86::RSTRegClass) {
     Opc = X86::FpMOV;
   } else if (RC == &X86::FR32RegClass) {
index 5b20c1c3922159257f87ed76e58b2f124ebe9909..64ac727883a74394a0d4ae8fcf0056d988973de3 100644 (file)
@@ -136,6 +136,10 @@ def R32 : RegisterClass<"X86", [i32], 32,
   }];
 }
 
+// R16, R32 subclasses which contain registers that have R8 sub-registers.
+def R16_ : RegisterClass<"X86", [i16], 16, [AX, CX, DX, BX]>;
+def R32_ : RegisterClass<"X86", [i32], 32, [EAX, ECX, EDX, EBX]>;
+
 // Scalar SSE2 floating point registers.
 def FR32 : RegisterClass<"X86", [f32], 32,
                          [XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7]>;