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.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@28164 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng 2006-05-08 08:01:26 +00:00
parent 023cfb6871
commit 403be7eafc
7 changed files with 100 additions and 25 deletions

View File

@ -115,7 +115,7 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
unsigned Reg = MO.getReg();
if (Modifier && strncmp(Modifier, "trunc", strlen("trunc")) == 0) {
MVT::ValueType VT = (strcmp(Modifier,"trunc16") == 0)
? MVT::i16 : MVT::i32;
? MVT::i16 : MVT::i8;
Reg = getX86SubSuperRegister(Reg, VT);
}
for (const char *Name = RI.get(Reg).Name; *Name; ++Name)
@ -366,12 +366,13 @@ void X86ATTAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
const MachineOperand &MO1 = MI->getOperand(1);
unsigned Reg0 = MO0.getReg();
unsigned Reg1 = MO1.getReg();
if (MI->getOpcode() == X86::TRUNC_R16_R8)
Reg0 = getX86SubSuperRegister(Reg0, MVT::i16);
if (MI->getOpcode() == X86::TRUNC_R32_R16)
Reg1 = getX86SubSuperRegister(Reg1, MVT::i16);
else
Reg0 = getX86SubSuperRegister(Reg0, MVT::i32);
if (Reg0 == Reg1)
O << CommentString << " TRUNCATE ";
Reg1 = getX86SubSuperRegister(Reg1, MVT::i8);
O << CommentString << " TRUNCATE ";
if (Reg0 != Reg1)
O << "\n\t";
break;
}
}

View File

@ -791,6 +791,44 @@ void X86DAGToDAGISel::Select(SDOperand &Result, SDOperand N) {
#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);

View File

@ -28,6 +28,7 @@ bool X86InstrInfo::isMoveInstr(const MachineInstr& MI,
unsigned& destReg) const {
MachineOpCode oc = MI.getOpcode();
if (oc == X86::MOV8rr || oc == X86::MOV16rr || oc == X86::MOV32rr ||
oc == X86::MOV16to16_ || oc == X86::MOV32to32_ ||
oc == X86::FpMOV || oc == X86::MOVSSrr || oc == X86::MOVSDrr ||
oc == X86::FsMOVAPSrr || oc == X86::FsMOVAPDrr ||
oc == X86::MOVAPSrr || oc == X86::MOVAPDrr ||

View File

@ -357,15 +357,13 @@ def IMPLICIT_DEF_R32 : I<0, Pseudo, (ops R32:$dst),
def NOOP : I<0x90, RawFrm, (ops), "nop", []>;
// Truncate
def TRUNC_R32_R8 : I<0x89, MRMDestReg, (ops R8:$dst, R32:$src),
"mov{l} {$src, ${dst:trunc32}|${dst:trunc32}, $src}",
[(set R8:$dst, (trunc R32:$src))]>;
def TRUNC_R32_R8 : I<0x88, MRMDestReg, (ops R8:$dst, R32_:$src),
"mov{b} {${src:trunc8}, $dst|$dst, ${src:trunc8}", []>;
def TRUNC_R16_R8 : I<0x88, MRMDestReg, (ops R8:$dst, R16_:$src),
"mov{b} {${src:trunc8}, $dst|$dst, ${src:trunc8}}", []>;
def TRUNC_R32_R16 : I<0x89, MRMDestReg, (ops R16:$dst, R32:$src),
"mov{l} {$src, ${dst:trunc32}|${dst:trunc32}, $src}",
"mov{w} {${src:trunc16}, $dst|$dst, ${src:trunc16}}",
[(set R16:$dst, (trunc R32:$src))]>;
def TRUNC_R16_R8 : I<0x89, MRMDestReg, (ops R8:$dst, R16:$src),
"mov{w} {$src, ${dst:trunc16}|${dst:trunc16}, $src}",
[(set R8:$dst, (trunc R16:$src))]>;
//===----------------------------------------------------------------------===//
// Control Flow Instructions...
@ -2310,6 +2308,26 @@ def MOV32r0 : I<0x31, MRMInitReg, (ops R32:$dst),
"xor{l} $dst, $dst",
[(set R32:$dst, 0)]>;
// Basic operations on R16 / R32 subclasses R16_ and R32_ which contains only
// those registers that have R8 sub-registers (i.e. AX - DX, EAX - EDX).
def MOV16to16_ : I<0x89, MRMDestReg, (ops R16_:$dst, R16:$src),
"mov{w} {$src, $dst|$dst, $src}", []>, OpSize;
def MOV32to32_ : I<0x89, MRMDestReg, (ops R32_:$dst, R32:$src),
"mov{l} {$src, $dst|$dst, $src}", []>;
def MOV16_rr : I<0x89, MRMDestReg, (ops R16_:$dst, R16_:$src),
"mov{w} {$src, $dst|$dst, $src}", []>, OpSize;
def MOV32_rr : I<0x89, MRMDestReg, (ops R32_:$dst, R32_:$src),
"mov{l} {$src, $dst|$dst, $src}", []>;
def MOV16_rm : I<0x8B, MRMSrcMem, (ops R16_:$dst, i16mem:$src),
"mov{w} {$src, $dst|$dst, $src}", []>, OpSize;
def MOV32_rm : I<0x8B, MRMSrcMem, (ops R32_:$dst, i32mem:$src),
"mov{l} {$src, $dst|$dst, $src}", []>;
def MOV16_mr : I<0x89, MRMDestMem, (ops i16mem:$dst, R16_:$src),
"mov{w} {$src, $dst|$dst, $src}", []>, OpSize;
def MOV32_mr : I<0x89, MRMDestMem, (ops i32mem:$dst, R32_:$src),
"mov{l} {$src, $dst|$dst, $src}", []>;
//===----------------------------------------------------------------------===//
// DWARF Pseudo Instructions
//

View File

@ -89,7 +89,7 @@ void X86IntelAsmPrinter::printOp(const MachineOperand &MO,
unsigned Reg = MO.getReg();
if (Modifier && strncmp(Modifier, "trunc", strlen("trunc")) == 0) {
MVT::ValueType VT = (strcmp(Modifier,"trunc16") == 0)
? MVT::i16 : MVT::i32;
? MVT::i16 : MVT::i8;
Reg = getX86SubSuperRegister(Reg, VT);
}
O << RI.get(Reg).Name;
@ -268,12 +268,13 @@ void X86IntelAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
const MachineOperand &MO1 = MI->getOperand(1);
unsigned Reg0 = MO0.getReg();
unsigned Reg1 = MO1.getReg();
if (MI->getOpcode() == X86::TRUNC_R16_R8)
Reg0 = getX86SubSuperRegister(Reg0, MVT::i16);
if (MI->getOpcode() == X86::TRUNC_R32_R16)
Reg1 = getX86SubSuperRegister(Reg1, MVT::i16);
else
Reg0 = getX86SubSuperRegister(Reg0, MVT::i32);
if (Reg0 == Reg1)
O << CommentString << " TRUNCATE ";
Reg1 = getX86SubSuperRegister(Reg1, MVT::i8);
O << CommentString << " TRUNCATE ";
if (Reg0 != Reg1)
O << "\n\t";
break;
}
}

View File

@ -52,10 +52,14 @@ void X86RegisterInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
unsigned Opc;
if (RC == &X86::R32RegClass) {
Opc = X86::MOV32mr;
} else if (RC == &X86::R8RegClass) {
Opc = X86::MOV8mr;
} else if (RC == &X86::R16RegClass) {
Opc = X86::MOV16mr;
} else if (RC == &X86::R8RegClass) {
Opc = X86::MOV8mr;
} else if (RC == &X86::R32_RegClass) {
Opc = X86::MOV32_mr;
} else if (RC == &X86::R16_RegClass) {
Opc = X86::MOV16_mr;
} else if (RC == &X86::RFPRegClass || RC == &X86::RSTRegClass) {
Opc = X86::FpST64m;
} else if (RC == &X86::FR32RegClass) {
@ -78,10 +82,14 @@ void X86RegisterInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
unsigned Opc;
if (RC == &X86::R32RegClass) {
Opc = X86::MOV32rm;
} else if (RC == &X86::R8RegClass) {
Opc = X86::MOV8rm;
} else if (RC == &X86::R16RegClass) {
Opc = X86::MOV16rm;
} else if (RC == &X86::R8RegClass) {
Opc = X86::MOV8rm;
} else if (RC == &X86::R32_RegClass) {
Opc = X86::MOV32_rm;
} else if (RC == &X86::R16_RegClass) {
Opc = X86::MOV16_rm;
} else if (RC == &X86::RFPRegClass || RC == &X86::RSTRegClass) {
Opc = X86::FpLD64m;
} else if (RC == &X86::FR32RegClass) {
@ -104,10 +112,14 @@ void X86RegisterInfo::copyRegToReg(MachineBasicBlock &MBB,
unsigned Opc;
if (RC == &X86::R32RegClass) {
Opc = X86::MOV32rr;
} else if (RC == &X86::R8RegClass) {
Opc = X86::MOV8rr;
} else if (RC == &X86::R16RegClass) {
Opc = X86::MOV16rr;
} else if (RC == &X86::R8RegClass) {
Opc = X86::MOV8rr;
} else if (RC == &X86::R32_RegClass) {
Opc = X86::MOV32_rr;
} else if (RC == &X86::R16_RegClass) {
Opc = X86::MOV16_rr;
} else if (RC == &X86::RFPRegClass || RC == &X86::RSTRegClass) {
Opc = X86::FpMOV;
} else if (RC == &X86::FR32RegClass) {

View File

@ -136,6 +136,10 @@ def R32 : RegisterClass<"X86", [i32], 32,
}];
}
// R16, R32 subclasses which contain registers that have R8 sub-registers.
def R16_ : RegisterClass<"X86", [i16], 16, [AX, CX, DX, BX]>;
def R32_ : RegisterClass<"X86", [i32], 32, [EAX, ECX, EDX, EBX]>;
// Scalar SSE2 floating point registers.
def FR32 : RegisterClass<"X86", [f32], 32,
[XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7]>;