Fixing truncate. Previously we were emitting truncate from r16 to r8 as
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.

llvm-svn: 28164
diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
index c0c9704..20534be 100644
--- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -791,6 +791,44 @@
 #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);