[llvm-commits] CVS: llvm/lib/Target/X86/X86ATTAsmPrinter.cpp X86ISelDAGToDAG.cpp X86InstrInfo.td X86IntelAsmPrinter.cpp X86RegisterInfo.cpp X86RegisterInfo.h
Evan Cheng
evan.cheng at apple.com
Thu May 4 22:40:32 PDT 2006
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
More information about the llvm-commits
mailing list