Change the x86 backend to use extract_subreg for truncation operations. Passes DejaGnu, SingleSource and MultiSource.

llvm-svn: 40578
This commit is contained in:
Christopher Lamb 2007-07-29 01:24:57 +00:00
parent f7a5da17d9
commit 5fecb80efa
6 changed files with 38 additions and 114 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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...

View File

@ -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),

View File

@ -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;