Change the x86 backend to use extract_subreg for truncation operations. Passes DejaGnu, SingleSource and MultiSource.
llvm-svn: 40578
diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
index 5ea12aa..6195676 100644
--- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -1258,39 +1258,51 @@
return NULL;
}
-
- case ISD::TRUNCATE: {
- if (!Subtarget->is64Bit() && 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_16_to8;
- break;
- case MVT::i32:
- Opc = X86::MOV32to32_;
- VT = MVT::i32;
- Opc2 = X86::TRUNC_32_to8;
- break;
- }
-
- AddToISelQueue(Node->getOperand(0));
- SDOperand Tmp =
- SDOperand(CurDAG->getTargetNode(Opc, VT, Node->getOperand(0)), 0);
- SDNode *ResNode = CurDAG->getTargetNode(Opc2, NVT, Tmp);
+ case ISD::TRUNCATE: {
+ SDOperand Tmp;
+ SDOperand Input = Node->getOperand(0);
+ AddToISelQueue(Node->getOperand(0));
+ switch (NVT) {
+ case MVT::i8:
+ Tmp = CurDAG->getTargetConstant(1, MVT::i32); // SubRegSet 1
+ // Ensure that the source register has an 8-bit subreg on 32-bit targets
+ if (!Subtarget->is64Bit()) {
+ unsigned Opc;
+ MVT::ValueType VT;
+ switch (Node->getOperand(0).getValueType()) {
+ default: assert(0 && "Unknown truncate!");
+ case MVT::i16:
+ Opc = X86::MOV16to16_;
+ VT = MVT::i16;
+ break;
+ case MVT::i32:
+ Opc = X86::MOV32to32_;
+ VT = MVT::i32;
+ break;
+ }
+ Input =
+ SDOperand(CurDAG->getTargetNode(Opc, VT, Node->getOperand(0)), 0);
+ }
+ break;
+ case MVT::i16:
+ Tmp = CurDAG->getTargetConstant(2, MVT::i32); // SubRegSet 2
+ break;
+ case MVT::i32:
+ Tmp = CurDAG->getTargetConstant(3, MVT::i32); // SubRegSet 3
+ break;
+ default: assert(0 && "Unknown truncate!");
+ }
+ SDNode *ResNode = CurDAG->getTargetNode(X86::EXTRACT_SUBREG,
+ NVT,
+ Input, Tmp);
#ifndef NDEBUG
DOUT << std::string(Indent-2, ' ') << "=> ";
DEBUG(ResNode->dump(CurDAG));
DOUT << "\n";
Indent -= 2;
#endif
- return ResNode;
- }
-
+ return ResNode;
break;
}
}