Changes in directory llvm/lib/Target/X86:
X86ATTAsmPrinter.cpp updated: 1.42 -> 1.43 X86ISelDAGToDAG.cpp updated: 1.57 -> 1.58 X86InstrInfo.td updated: 1.263 -> 1.264 X86IntelAsmPrinter.cpp updated: 1.41 -> 1.42 X86RegisterInfo.cpp updated: 1.149 -> 1.150 X86RegisterInfo.h updated: 1.37 -> 1.38 --- Log message: Better implementation of truncate. ISel matches it to a pseudo instruction that gets emitted as movl (for r32 to i16, i8) or a movw (for r16 to i8). And if the destination gets allocated a subregister of the source operand, then the instruction will not be emitted at all. --- Diffs of the changes: (+162 -240) X86ATTAsmPrinter.cpp | 136 ++++++++++++------------------------------------- X86ISelDAGToDAG.cpp | 39 -------------- X86InstrInfo.td | 11 +++ X86IntelAsmPrinter.cpp | 135 ++++++++++++------------------------------------ X86RegisterInfo.cpp | 76 +++++++++++++++++++++++++++ X86RegisterInfo.h | 5 + 6 files changed, 162 insertions(+), 240 deletions(-) Index: llvm/lib/Target/X86/X86ATTAsmPrinter.cpp diff -u llvm/lib/Target/X86/X86ATTAsmPrinter.cpp:1.42 llvm/lib/Target/X86/X86ATTAsmPrinter.cpp:1.43 --- llvm/lib/Target/X86/X86ATTAsmPrinter.cpp:1.42 Thu May 4 13:05:43 2006 +++ llvm/lib/Target/X86/X86ATTAsmPrinter.cpp Fri May 5 00:40:20 2006 @@ -108,13 +108,20 @@ const MachineOperand &MO = MI->getOperand(OpNo); const MRegisterInfo &RI = *TM.getRegisterInfo(); switch (MO.getType()) { - case MachineOperand::MO_Register: + case MachineOperand::MO_Register: { assert(MRegisterInfo::isPhysicalRegister(MO.getReg()) && "Virtual registers should not make it this far!"); O << '%'; - for (const char *Name = RI.get(MO.getReg()).Name; *Name; ++Name) + unsigned Reg = MO.getReg(); + if (Modifier && strncmp(Modifier, "trunc", strlen("trunc")) == 0) { + MVT::ValueType VT = (strcmp(Modifier,"trunc16") == 0) + ? MVT::i16 : MVT::i32; + Reg = getX86SubSuperRegister(Reg, VT); + } + for (const char *Name = RI.get(Reg).Name; *Name; ++Name) O << (char)tolower(*Name); return; + } case MachineOperand::MO_Immediate: if (!Modifier || strcmp(Modifier, "debug") != 0) @@ -263,116 +270,25 @@ const char Mode) { const MRegisterInfo &RI = *TM.getRegisterInfo(); unsigned Reg = MO.getReg(); - const char *Name = RI.get(Reg).Name; switch (Mode) { default: return true; // Unknown mode. case 'b': // Print QImode register - switch (Reg) { - default: return true; - case X86::AH: case X86::AL: case X86::AX: case X86::EAX: - Name = "al"; - break; - case X86::DH: case X86::DL: case X86::DX: case X86::EDX: - Name = "dl"; - break; - case X86::CH: case X86::CL: case X86::CX: case X86::ECX: - Name = "cl"; - break; - case X86::BH: case X86::BL: case X86::BX: case X86::EBX: - Name = "bl"; - break; - case X86::ESI: - Name = "sil"; - break; - case X86::EDI: - Name = "dil"; - break; - case X86::EBP: - Name = "bpl"; - break; - case X86::ESP: - Name = "spl"; - break; - } + Reg = getX86SubSuperRegister(Reg, MVT::i8); break; case 'h': // Print QImode high register - switch (Reg) { - default: return true; - case X86::AH: case X86::AL: case X86::AX: case X86::EAX: - Name = "al"; - break; - case X86::DH: case X86::DL: case X86::DX: case X86::EDX: - Name = "dl"; - break; - case X86::CH: case X86::CL: case X86::CX: case X86::ECX: - Name = "cl"; - break; - case X86::BH: case X86::BL: case X86::BX: case X86::EBX: - Name = "bl"; - break; - } + Reg = getX86SubSuperRegister(Reg, MVT::i8, true); break; case 'w': // Print HImode register - switch (Reg) { - default: return true; - case X86::AH: case X86::AL: case X86::AX: case X86::EAX: - Name = "ax"; - break; - case X86::DH: case X86::DL: case X86::DX: case X86::EDX: - Name = "dx"; - break; - case X86::CH: case X86::CL: case X86::CX: case X86::ECX: - Name = "cx"; - break; - case X86::BH: case X86::BL: case X86::BX: case X86::EBX: - Name = "bx"; - break; - case X86::ESI: - Name = "si"; - break; - case X86::EDI: - Name = "di"; - break; - case X86::EBP: - Name = "bp"; - break; - case X86::ESP: - Name = "sp"; - break; - } + Reg = getX86SubSuperRegister(Reg, MVT::i16); break; case 'k': // Print SImode register - switch (Reg) { - default: return true; - case X86::AH: case X86::AL: case X86::AX: case X86::EAX: - Name = "eax"; - break; - case X86::DH: case X86::DL: case X86::DX: case X86::EDX: - Name = "edx"; - break; - case X86::CH: case X86::CL: case X86::CX: case X86::ECX: - Name = "ecx"; - break; - case X86::BH: case X86::BL: case X86::BX: case X86::EBX: - Name = "ebx"; - break; - case X86::ESI: - Name = "esi"; - break; - case X86::EDI: - Name = "edi"; - break; - case X86::EBP: - Name = "ebp"; - break; - case X86::ESP: - Name = "esp"; - break; - } + Reg = getX86SubSuperRegister(Reg, MVT::i32); break; } - O << '%' << Name; + O << '%'; + for (const char *Name = RI.get(Reg).Name; *Name; ++Name) + O << (char)tolower(*Name); return false; } @@ -440,6 +356,26 @@ } } + // See if a truncate instruction can be turned into a nop. + switch (MI->getOpcode()) { + default: break; + case X86::TRUNC_R32_R16: + case X86::TRUNC_R32_R8: + case X86::TRUNC_R16_R8: { + const MachineOperand &MO0 = MI->getOperand(0); + 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); + else + Reg0 = getX86SubSuperRegister(Reg0, MVT::i32); + if (Reg0 == Reg1) + O << CommentString << " TRUNCATE "; + break; + } + } + // Call the autogenerated instruction printer routines. printInstruction(MI); } Index: llvm/lib/Target/X86/X86ISelDAGToDAG.cpp diff -u llvm/lib/Target/X86/X86ISelDAGToDAG.cpp:1.57 llvm/lib/Target/X86/X86ISelDAGToDAG.cpp:1.58 --- llvm/lib/Target/X86/X86ISelDAGToDAG.cpp:1.57 Sat Mar 25 00:47:10 2006 +++ llvm/lib/Target/X86/X86ISelDAGToDAG.cpp Fri May 5 00:40:20 2006 @@ -791,45 +791,6 @@ #endif return; } - - case ISD::TRUNCATE: { - unsigned Reg; - MVT::ValueType VT; - switch (Node->getOperand(0).getValueType()) { - default: assert(0 && "Unknown truncate!"); - case MVT::i16: Reg = X86::AX; Opc = X86::MOV16rr; VT = MVT::i16; break; - case MVT::i32: Reg = X86::EAX; Opc = X86::MOV32rr; VT = MVT::i32; break; - } - SDOperand Tmp0, Tmp1; - Select(Tmp0, Node->getOperand(0)); - Select(Tmp1, SDOperand(CurDAG->getTargetNode(Opc, VT, Tmp0), 0)); - SDOperand InFlag = SDOperand(0,0); - Result = CurDAG->getCopyToReg(CurDAG->getEntryNode(), Reg, Tmp1, InFlag); - SDOperand Chain = Result.getValue(0); - InFlag = Result.getValue(1); - - switch (NVT) { - default: assert(0 && "Unknown truncate!"); - case MVT::i8: Reg = X86::AL; Opc = X86::MOV8rr; VT = MVT::i8; break; - case MVT::i16: Reg = X86::AX; Opc = X86::MOV16rr; VT = MVT::i16; break; - } - - Result = CurDAG->getCopyFromReg(Chain, Reg, VT, InFlag); - if (N.Val->hasOneUse()) - Result = CurDAG->SelectNodeTo(N.Val, Opc, VT, Result); - else - Result = CodeGenMap[N] = - SDOperand(CurDAG->getTargetNode(Opc, VT, Result), 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); Index: llvm/lib/Target/X86/X86InstrInfo.td diff -u llvm/lib/Target/X86/X86InstrInfo.td:1.263 llvm/lib/Target/X86/X86InstrInfo.td:1.264 --- llvm/lib/Target/X86/X86InstrInfo.td:1.263 Thu Apr 27 03:40:39 2006 +++ llvm/lib/Target/X86/X86InstrInfo.td Fri May 5 00:40:20 2006 @@ -351,6 +351,17 @@ // Nop 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_R16 : I<0x89, MRMDestReg, (ops R16:$dst, R32:$src), + "mov{l} {$src, ${dst:trunc32}|${dst:trunc32}, $src}", + [(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... // Index: llvm/lib/Target/X86/X86IntelAsmPrinter.cpp diff -u llvm/lib/Target/X86/X86IntelAsmPrinter.cpp:1.41 llvm/lib/Target/X86/X86IntelAsmPrinter.cpp:1.42 --- llvm/lib/Target/X86/X86IntelAsmPrinter.cpp:1.41 Thu May 4 13:05:43 2006 +++ llvm/lib/Target/X86/X86IntelAsmPrinter.cpp Fri May 5 00:40:20 2006 @@ -101,9 +101,15 @@ const MRegisterInfo &RI = *TM.getRegisterInfo(); switch (MO.getType()) { case MachineOperand::MO_Register: - if (MRegisterInfo::isPhysicalRegister(MO.getReg())) - O << RI.get(MO.getReg()).Name; - else + if (MRegisterInfo::isPhysicalRegister(MO.getReg())) { + unsigned Reg = MO.getReg(); + if (Modifier && strncmp(Modifier, "trunc", strlen("trunc")) == 0) { + MVT::ValueType VT = (strcmp(Modifier,"trunc16") == 0) + ? MVT::i16 : MVT::i32; + Reg = getX86SubSuperRegister(Reg, VT); + } + O << RI.get(Reg).Name; + } else O << "reg" << MO.getReg(); return; @@ -240,116 +246,23 @@ const char Mode) { const MRegisterInfo &RI = *TM.getRegisterInfo(); unsigned Reg = MO.getReg(); - const char *Name = RI.get(Reg).Name; switch (Mode) { default: return true; // Unknown mode. case 'b': // Print QImode register - switch (Reg) { - default: return true; - case X86::AH: case X86::AL: case X86::AX: case X86::EAX: - Name = "AL"; - break; - case X86::DH: case X86::DL: case X86::DX: case X86::EDX: - Name = "DL"; - break; - case X86::CH: case X86::CL: case X86::CX: case X86::ECX: - Name = "CL"; - break; - case X86::BH: case X86::BL: case X86::BX: case X86::EBX: - Name = "BL"; - break; - case X86::ESI: - Name = "SIL"; - break; - case X86::EDI: - Name = "DIL"; - break; - case X86::EBP: - Name = "BPL"; - break; - case X86::ESP: - Name = "SPL"; - break; - } + Reg = getX86SubSuperRegister(Reg, MVT::i8); break; case 'h': // Print QImode high register - switch (Reg) { - default: return true; - case X86::AH: case X86::AL: case X86::AX: case X86::EAX: - Name = "AL"; - break; - case X86::DH: case X86::DL: case X86::DX: case X86::EDX: - Name = "DL"; - break; - case X86::CH: case X86::CL: case X86::CX: case X86::ECX: - Name = "CL"; - break; - case X86::BH: case X86::BL: case X86::BX: case X86::EBX: - Name = "BL"; - break; - } + Reg = getX86SubSuperRegister(Reg, MVT::i8, true); break; case 'w': // Print HImode register - switch (Reg) { - default: return true; - case X86::AH: case X86::AL: case X86::AX: case X86::EAX: - Name = "AX"; - break; - case X86::DH: case X86::DL: case X86::DX: case X86::EDX: - Name = "DX"; - break; - case X86::CH: case X86::CL: case X86::CX: case X86::ECX: - Name = "CX"; - break; - case X86::BH: case X86::BL: case X86::BX: case X86::EBX: - Name = "BX"; - break; - case X86::ESI: - Name = "SI"; - break; - case X86::EDI: - Name = "DI"; - break; - case X86::EBP: - Name = "BP"; - break; - case X86::ESP: - Name = "SP"; - break; - } + Reg = getX86SubSuperRegister(Reg, MVT::i16); break; case 'k': // Print SImode register - switch (Reg) { - default: return true; - case X86::AH: case X86::AL: case X86::AX: case X86::EAX: - Name = "EAX"; - break; - case X86::DH: case X86::DL: case X86::DX: case X86::EDX: - Name = "EDX"; - break; - case X86::CH: case X86::CL: case X86::CX: case X86::ECX: - Name = "ECX"; - break; - case X86::BH: case X86::BL: case X86::BX: case X86::EBX: - Name = "EBX"; - break; - case X86::ESI: - Name = "ESI"; - break; - case X86::EDI: - Name = "EDI"; - break; - case X86::EBP: - Name = "EBP"; - break; - case X86::ESP: - Name = "ESP"; - break; - } + Reg = getX86SubSuperRegister(Reg, MVT::i32); break; } - O << Name; + O << '%' << RI.get(Reg).Name; return false; } @@ -392,6 +305,26 @@ void X86IntelAsmPrinter::printMachineInstruction(const MachineInstr *MI) { ++EmittedInsts; + // See if a truncate instruction can be turned into a nop. + switch (MI->getOpcode()) { + default: break; + case X86::TRUNC_R32_R16: + case X86::TRUNC_R32_R8: + case X86::TRUNC_R16_R8: { + const MachineOperand &MO0 = MI->getOperand(0); + 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); + else + Reg0 = getX86SubSuperRegister(Reg0, MVT::i32); + if (Reg0 == Reg1) + O << CommentString << " TRUNCATE "; + break; + } + } + // Call the autogenerated instruction printer routines. printInstruction(MI); } Index: llvm/lib/Target/X86/X86RegisterInfo.cpp diff -u llvm/lib/Target/X86/X86RegisterInfo.cpp:1.149 llvm/lib/Target/X86/X86RegisterInfo.cpp:1.150 --- llvm/lib/Target/X86/X86RegisterInfo.cpp:1.149 Thu May 4 13:16:01 2006 +++ llvm/lib/Target/X86/X86RegisterInfo.cpp Fri May 5 00:40:20 2006 @@ -811,5 +811,81 @@ return hasFP(MF) ? X86::EBP : X86::ESP; } +namespace llvm { +unsigned getX86SubSuperRegister(unsigned Reg, MVT::ValueType VT, bool High) { + switch (VT) { + default: return Reg; + case MVT::i8: + if (High) { + switch (Reg) { + default: return Reg; + case X86::AH: case X86::AL: case X86::AX: case X86::EAX: + return X86::AH; + case X86::DH: case X86::DL: case X86::DX: case X86::EDX: + return X86::DH; + case X86::CH: case X86::CL: case X86::CX: case X86::ECX: + return X86::CH; + case X86::BH: case X86::BL: case X86::BX: case X86::EBX: + return X86::BH; + } + } else { + switch (Reg) { + default: return Reg; + case X86::AH: case X86::AL: case X86::AX: case X86::EAX: + return X86::AL; + case X86::DH: case X86::DL: case X86::DX: case X86::EDX: + return X86::DL; + case X86::CH: case X86::CL: case X86::CX: case X86::ECX: + return X86::CL; + case X86::BH: case X86::BL: case X86::BX: case X86::EBX: + return X86::BL; + } + } + case MVT::i16: + switch (Reg) { + default: return Reg; + case X86::AH: case X86::AL: case X86::AX: case X86::EAX: + return X86::AX; + case X86::DH: case X86::DL: case X86::DX: case X86::EDX: + return X86::DX; + case X86::CH: case X86::CL: case X86::CX: case X86::ECX: + return X86::CX; + case X86::BH: case X86::BL: case X86::BX: case X86::EBX: + return X86::BX; + case X86::ESI: + return X86::SI; + case X86::EDI: + return X86::DI; + case X86::EBP: + return X86::BP; + case X86::ESP: + return X86::SP; + } + case MVT::i32: + switch (Reg) { + default: return true; + case X86::AH: case X86::AL: case X86::AX: case X86::EAX: + return X86::EAX; + case X86::DH: case X86::DL: case X86::DX: case X86::EDX: + return X86::EDX; + case X86::CH: case X86::CL: case X86::CX: case X86::ECX: + return X86::ECX; + case X86::BH: case X86::BL: case X86::BX: case X86::EBX: + return X86::EBX; + case X86::SI: + return X86::ESI; + case X86::DI: + return X86::EDI; + case X86::BP: + return X86::EBP; + case X86::SP: + return X86::ESP; + } + } + + return Reg; +} +} + #include "X86GenRegisterInfo.inc" Index: llvm/lib/Target/X86/X86RegisterInfo.h diff -u llvm/lib/Target/X86/X86RegisterInfo.h:1.37 llvm/lib/Target/X86/X86RegisterInfo.h:1.38 --- llvm/lib/Target/X86/X86RegisterInfo.h:1.37 Fri Apr 7 11:34:46 2006 +++ llvm/lib/Target/X86/X86RegisterInfo.h Fri May 5 00:40:20 2006 @@ -68,6 +68,11 @@ unsigned getFrameRegister(MachineFunction &MF) const; }; +// getX86SubSuperRegister - X86 utility function. It returns the sub or super +// register of a specific X86 register. +// e.g. getX86SubSuperRegister(X86::EAX, MVT::i16) return X86:AX +unsigned getX86SubSuperRegister(unsigned, MVT::ValueType, bool High=false); + } // End llvm namespace #endif _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits