From 919ce03da6dfabb0df63426a2d739505bf3d125a Mon Sep 17 00:00:00 2001 From: Christopher Lamb Date: Sun, 29 Jul 2007 01:24:57 +0000 Subject: [PATCH] Change the x86 backend to use extract_subreg for truncation operations. Passes DejaGnu, SingleSource and MultiSource. llvm-svn: 40578 --- lib/Target/X86/X86ATTAsmPrinter.cpp | 23 ---------- lib/Target/X86/X86CodeEmitter.cpp | 12 ----- lib/Target/X86/X86ISelDAGToDAG.cpp | 64 ++++++++++++++++----------- lib/Target/X86/X86InstrInfo.td | 8 ---- lib/Target/X86/X86InstrX86-64.td | 22 --------- lib/Target/X86/X86IntelAsmPrinter.cpp | 23 ---------- 6 files changed, 38 insertions(+), 114 deletions(-) diff --git a/lib/Target/X86/X86ATTAsmPrinter.cpp b/lib/Target/X86/X86ATTAsmPrinter.cpp index 4c707df1e39..f2f640a9905 100644 --- a/lib/Target/X86/X86ATTAsmPrinter.cpp +++ b/lib/Target/X86/X86ATTAsmPrinter.cpp @@ -580,29 +580,6 @@ void X86ATTAsmPrinter::printMachineInstruction(const MachineInstr *MI) { // See if a truncate instruction can be turned into a nop. switch (MI->getOpcode()) { default: break; - case X86::TRUNC_64to32: - case X86::TRUNC_64to16: - case X86::TRUNC_32to16: - case X86::TRUNC_32to8: - case X86::TRUNC_16to8: - case X86::TRUNC_32_to8: - case X86::TRUNC_16_to8: { - const MachineOperand &MO0 = MI->getOperand(0); - const MachineOperand &MO1 = MI->getOperand(1); - unsigned Reg0 = MO0.getReg(); - unsigned Reg1 = MO1.getReg(); - unsigned Opc = MI->getOpcode(); - if (Opc == X86::TRUNC_64to32) - Reg1 = getX86SubSuperRegister(Reg1, MVT::i32); - else if (Opc == X86::TRUNC_32to16 || Opc == X86::TRUNC_64to16) - Reg1 = getX86SubSuperRegister(Reg1, MVT::i16); - else - Reg1 = getX86SubSuperRegister(Reg1, MVT::i8); - O << TAI->getCommentString() << " TRUNCATE "; - if (Reg0 != Reg1) - O << "\n\t"; - break; - } case X86::PsMOVZX64rr32: O << TAI->getCommentString() << " ZERO-EXTEND " << "\n\t"; break; diff --git a/lib/Target/X86/X86CodeEmitter.cpp b/lib/Target/X86/X86CodeEmitter.cpp index 9d5180452bc..0a7beb251a7 100644 --- a/lib/Target/X86/X86CodeEmitter.cpp +++ b/lib/Target/X86/X86CodeEmitter.cpp @@ -448,12 +448,6 @@ bool Emitter::isX86_64ExtendedReg(const MachineOperand &MO) { return false; } -inline static bool isX86_64TruncToByte(unsigned oc) { - return (oc == X86::TRUNC_64to8 || oc == X86::TRUNC_32to8 || - oc == X86::TRUNC_16to8); -} - - inline static bool isX86_64NonExtLowByteReg(unsigned reg) { return (reg == X86::SPL || reg == X86::BPL || reg == X86::SIL || reg == X86::DIL); @@ -465,7 +459,6 @@ inline static bool isX86_64NonExtLowByteReg(unsigned reg) { unsigned Emitter::determineREX(const MachineInstr &MI) { unsigned REX = 0; const TargetInstrDescriptor *Desc = MI.getInstrDescriptor(); - unsigned Opcode = Desc->Opcode; // Pseudo instructions do not need REX prefix byte. if ((Desc->TSFlags & X86II::FormMask) == X86II::Pseudo) @@ -479,16 +472,11 @@ unsigned Emitter::determineREX(const MachineInstr &MI) { Desc->getOperandConstraint(1, TOI::TIED_TO) != -1; // If it accesses SPL, BPL, SIL, or DIL, then it requires a 0x40 REX prefix. - bool isTrunc8 = isX86_64TruncToByte(Opcode); unsigned i = isTwoAddr ? 1 : 0; for (unsigned e = NumOps; i != e; ++i) { const MachineOperand& MO = MI.getOperand(i); if (MO.isRegister()) { unsigned Reg = MO.getReg(); - // Trunc to byte are actually movb. The real source operand is the low - // byte of the register. - if (isTrunc8 && i == 1) - Reg = getX86SubSuperRegister(Reg, MVT::i8); if (isX86_64NonExtLowByteReg(Reg)) REX |= 0x40; } diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp index 5ea12aa9611..619567665a9 100644 --- a/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -1258,39 +1258,51 @@ SDNode *X86DAGToDAGISel::Select(SDOperand N) { 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; } } diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index 906e7b210b1..0f5a1dc29cc 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -388,14 +388,6 @@ def IMPLICIT_DEF_GR32 : I<0, Pseudo, (outs GR32:$dst), (ins), // Nop def NOOP : I<0x90, RawFrm, (outs), (ins), "nop", []>; -// Truncate -def TRUNC_32_to8 : I<0x88, MRMDestReg, (outs GR8:$dst), (ins GR32_:$src), - "mov{b} {${src:subreg8}, $dst|$dst, ${src:subreg8}", []>; -def TRUNC_16_to8 : I<0x88, MRMDestReg, (outs GR8:$dst), (ins GR16_:$src), - "mov{b} {${src:subreg8}, $dst|$dst, ${src:subreg8}}", []>; -def TRUNC_32to16 : I<0x89, MRMDestReg, (outs GR16:$dst), (ins GR32:$src), - "mov{w} {${src:subreg16}, $dst|$dst, ${src:subreg16}}", - [(set GR16:$dst, (trunc GR32:$src))]>; //===----------------------------------------------------------------------===// // Control Flow Instructions... diff --git a/lib/Target/X86/X86InstrX86-64.td b/lib/Target/X86/X86InstrX86-64.td index 16930b42519..ec0f4708294 100644 --- a/lib/Target/X86/X86InstrX86-64.td +++ b/lib/Target/X86/X86InstrX86-64.td @@ -1005,28 +1005,6 @@ let isTwoAddress = 1 in { // Alias Instructions //===----------------------------------------------------------------------===// -// Truncate -// In 64-mode, each 64-bit and 32-bit registers has a low 8-bit sub-register. -def TRUNC_64to8 : I<0x88, MRMDestReg, (outs GR8:$dst), (ins GR64:$src), - "mov{b} {${src:subreg8}, $dst|$dst, ${src:subreg8}", - [(set GR8:$dst, (trunc GR64:$src))]>; -def TRUNC_32to8 : I<0x88, MRMDestReg, (outs GR8:$dst), (ins GR32:$src), - "mov{b} {${src:subreg8}, $dst|$dst, ${src:subreg8}", - [(set GR8:$dst, (trunc GR32:$src))]>, - Requires<[In64BitMode]>; -def TRUNC_16to8 : I<0x88, MRMDestReg, (outs GR8:$dst), (ins GR16:$src), - "mov{b} {${src:subreg8}, $dst|$dst, ${src:subreg8}}", - [(set GR8:$dst, (trunc GR16:$src))]>, - Requires<[In64BitMode]>; - -def TRUNC_64to16 : I<0x89, MRMDestReg, (outs GR16:$dst), (ins GR64:$src), - "mov{w} {${src:subreg16}, $dst|$dst, ${src:subreg16}}", - [(set GR16:$dst, (trunc GR64:$src))]>; - -def TRUNC_64to32 : I<0x89, MRMDestReg, (outs GR32:$dst), (ins GR64:$src), - "mov{l} {${src:subreg32}, $dst|$dst, ${src:subreg32}}", - [(set GR32:$dst, (trunc GR64:$src))]>; - // Zero-extension // TODO: Remove this after proper i32 -> i64 zext support. def PsMOVZX64rr32: I<0x89, MRMDestReg, (outs GR64:$dst), (ins GR32:$src), diff --git a/lib/Target/X86/X86IntelAsmPrinter.cpp b/lib/Target/X86/X86IntelAsmPrinter.cpp index 60d7ed60029..72ba1b098bc 100644 --- a/lib/Target/X86/X86IntelAsmPrinter.cpp +++ b/lib/Target/X86/X86IntelAsmPrinter.cpp @@ -306,29 +306,6 @@ void X86IntelAsmPrinter::printMachineInstruction(const MachineInstr *MI) { // See if a truncate instruction can be turned into a nop. switch (MI->getOpcode()) { default: break; - case X86::TRUNC_64to32: - case X86::TRUNC_64to16: - case X86::TRUNC_32to16: - case X86::TRUNC_32to8: - case X86::TRUNC_16to8: - case X86::TRUNC_32_to8: - case X86::TRUNC_16_to8: { - const MachineOperand &MO0 = MI->getOperand(0); - const MachineOperand &MO1 = MI->getOperand(1); - unsigned Reg0 = MO0.getReg(); - unsigned Reg1 = MO1.getReg(); - unsigned Opc = MI->getOpcode(); - if (Opc == X86::TRUNC_64to32) - Reg1 = getX86SubSuperRegister(Reg1, MVT::i32); - else if (Opc == X86::TRUNC_32to16 || Opc == X86::TRUNC_64to16) - Reg1 = getX86SubSuperRegister(Reg1, MVT::i16); - else - Reg1 = getX86SubSuperRegister(Reg1, MVT::i8); - O << TAI->getCommentString() << " TRUNCATE "; - if (Reg0 != Reg1) - O << "\n\t"; - break; - } case X86::PsMOVZX64rr32: O << TAI->getCommentString() << " ZERO-EXTEND " << "\n\t"; break;