mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-03 09:21:13 +00:00
Change the x86 backend to use extract_subreg for truncation operations. Passes DejaGnu, SingleSource and MultiSource.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@40578 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
f9b90ea955
commit
2dc6dc619c
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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...
|
||||
|
@ -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),
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user