llvm.org GIT mirror llvm / 8f7f712
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@28119 91177308-0d34-0410-b5e6-96231b3b80d8 Evan Cheng 14 years ago
6 changed file(s) with 165 addition(s) and 243 deletion(s). Raw diff Collapse all Expand all
107107 const MachineOperand &MO = MI->getOperand(OpNo);
108108 const MRegisterInfo &RI = *TM.getRegisterInfo();
109109 switch (MO.getType()) {
110 case MachineOperand::MO_Register:
110 case MachineOperand::MO_Register: {
111111 assert(MRegisterInfo::isPhysicalRegister(MO.getReg()) &&
112112 "Virtual registers should not make it this far!");
113113 O << '%';
114 for (const char *Name = RI.get(MO.getReg()).Name; *Name; ++Name)
114 unsigned Reg = MO.getReg();
115 if (Modifier && strncmp(Modifier, "trunc", strlen("trunc")) == 0) {
116 MVT::ValueType VT = (strcmp(Modifier,"trunc16") == 0)
117 ? MVT::i16 : MVT::i32;
118 Reg = getX86SubSuperRegister(Reg, VT);
119 }
120 for (const char *Name = RI.get(Reg).Name; *Name; ++Name)
115121 O << (char)tolower(*Name);
116122 return;
123 }
117124
118125 case MachineOperand::MO_Immediate:
119126 if (!Modifier || strcmp(Modifier, "debug") != 0)
262269 const char Mode) {
263270 const MRegisterInfo &RI = *TM.getRegisterInfo();
264271 unsigned Reg = MO.getReg();
265 const char *Name = RI.get(Reg).Name;
266272 switch (Mode) {
267273 default: return true; // Unknown mode.
268274 case 'b': // Print QImode register
269 switch (Reg) {
270 default: return true;
271 case X86::AH: case X86::AL: case X86::AX: case X86::EAX:
272 Name = "al";
273 break;
274 case X86::DH: case X86::DL: case X86::DX: case X86::EDX:
275 Name = "dl";
276 break;
277 case X86::CH: case X86::CL: case X86::CX: case X86::ECX:
278 Name = "cl";
279 break;
280 case X86::BH: case X86::BL: case X86::BX: case X86::EBX:
281 Name = "bl";
282 break;
283 case X86::ESI:
284 Name = "sil";
285 break;
286 case X86::EDI:
287 Name = "dil";
288 break;
289 case X86::EBP:
290 Name = "bpl";
291 break;
292 case X86::ESP:
293 Name = "spl";
294 break;
295 }
275 Reg = getX86SubSuperRegister(Reg, MVT::i8);
296276 break;
297277 case 'h': // Print QImode high register
298 switch (Reg) {
299 default: return true;
300 case X86::AH: case X86::AL: case X86::AX: case X86::EAX:
301 Name = "al";
302 break;
303 case X86::DH: case X86::DL: case X86::DX: case X86::EDX:
304 Name = "dl";
305 break;
306 case X86::CH: case X86::CL: case X86::CX: case X86::ECX:
307 Name = "cl";
308 break;
309 case X86::BH: case X86::BL: case X86::BX: case X86::EBX:
310 Name = "bl";
311 break;
312 }
278 Reg = getX86SubSuperRegister(Reg, MVT::i8, true);
313279 break;
314280 case 'w': // Print HImode register
315 switch (Reg) {
316 default: return true;
317 case X86::AH: case X86::AL: case X86::AX: case X86::EAX:
318 Name = "ax";
319 break;
320 case X86::DH: case X86::DL: case X86::DX: case X86::EDX:
321 Name = "dx";
322 break;
323 case X86::CH: case X86::CL: case X86::CX: case X86::ECX:
324 Name = "cx";
325 break;
326 case X86::BH: case X86::BL: case X86::BX: case X86::EBX:
327 Name = "bx";
328 break;
329 case X86::ESI:
330 Name = "si";
331 break;
332 case X86::EDI:
333 Name = "di";
334 break;
335 case X86::EBP:
336 Name = "bp";
337 break;
338 case X86::ESP:
339 Name = "sp";
340 break;
341 }
281 Reg = getX86SubSuperRegister(Reg, MVT::i16);
342282 break;
343283 case 'k': // Print SImode register
344 switch (Reg) {
345 default: return true;
346 case X86::AH: case X86::AL: case X86::AX: case X86::EAX:
347 Name = "eax";
348 break;
349 case X86::DH: case X86::DL: case X86::DX: case X86::EDX:
350 Name = "edx";
351 break;
352 case X86::CH: case X86::CL: case X86::CX: case X86::ECX:
353 Name = "ecx";
354 break;
355 case X86::BH: case X86::BL: case X86::BX: case X86::EBX:
356 Name = "ebx";
357 break;
358 case X86::ESI:
359 Name = "esi";
360 break;
361 case X86::EDI:
362 Name = "edi";
363 break;
364 case X86::EBP:
365 Name = "ebp";
366 break;
367 case X86::ESP:
368 Name = "esp";
369 break;
370 }
371 break;
372 }
373
374 O << '%' << Name;
284 Reg = getX86SubSuperRegister(Reg, MVT::i32);
285 break;
286 }
287
288 O << '%';
289 for (const char *Name = RI.get(Reg).Name; *Name; ++Name)
290 O << (char)tolower(*Name);
375291 return false;
376292 }
377293
439355 }
440356 }
441357
358 // See if a truncate instruction can be turned into a nop.
359 switch (MI->getOpcode()) {
360 default: break;
361 case X86::TRUNC_R32_R16:
362 case X86::TRUNC_R32_R8:
363 case X86::TRUNC_R16_R8: {
364 const MachineOperand &MO0 = MI->getOperand(0);
365 const MachineOperand &MO1 = MI->getOperand(1);
366 unsigned Reg0 = MO0.getReg();
367 unsigned Reg1 = MO1.getReg();
368 if (MI->getOpcode() == X86::TRUNC_R16_R8)
369 Reg0 = getX86SubSuperRegister(Reg0, MVT::i16);
370 else
371 Reg0 = getX86SubSuperRegister(Reg0, MVT::i32);
372 if (Reg0 == Reg1)
373 O << CommentString << " TRUNCATE ";
374 break;
375 }
376 }
377
442378 // Call the autogenerated instruction printer routines.
443379 printInstruction(MI);
444380 }
790790 #endif
791791 return;
792792 }
793
794 case ISD::TRUNCATE: {
795 unsigned Reg;
796 MVT::ValueType VT;
797 switch (Node->getOperand(0).getValueType()) {
798 default: assert(0 && "Unknown truncate!");
799 case MVT::i16: Reg = X86::AX; Opc = X86::MOV16rr; VT = MVT::i16; break;
800 case MVT::i32: Reg = X86::EAX; Opc = X86::MOV32rr; VT = MVT::i32; break;
801 }
802 SDOperand Tmp0, Tmp1;
803 Select(Tmp0, Node->getOperand(0));
804 Select(Tmp1, SDOperand(CurDAG->getTargetNode(Opc, VT, Tmp0), 0));
805 SDOperand InFlag = SDOperand(0,0);
806 Result = CurDAG->getCopyToReg(CurDAG->getEntryNode(), Reg, Tmp1, InFlag);
807 SDOperand Chain = Result.getValue(0);
808 InFlag = Result.getValue(1);
809
810 switch (NVT) {
811 default: assert(0 && "Unknown truncate!");
812 case MVT::i8: Reg = X86::AL; Opc = X86::MOV8rr; VT = MVT::i8; break;
813 case MVT::i16: Reg = X86::AX; Opc = X86::MOV16rr; VT = MVT::i16; break;
814 }
815
816 Result = CurDAG->getCopyFromReg(Chain, Reg, VT, InFlag);
817 if (N.Val->hasOneUse())
818 Result = CurDAG->SelectNodeTo(N.Val, Opc, VT, Result);
819 else
820 Result = CodeGenMap[N] =
821 SDOperand(CurDAG->getTargetNode(Opc, VT, Result), 0);
822
823 #ifndef NDEBUG
824 DEBUG(std::cerr << std::string(Indent-2, ' '));
825 DEBUG(std::cerr << "== ");
826 DEBUG(Result.Val->dump(CurDAG));
827 DEBUG(std::cerr << "\n");
828 Indent -= 2;
829 #endif
830 return;
831 }
832793 }
833794
834795 SelectCode(Result, N);
349349
350350 // Nop
351351 def NOOP : I<0x90, RawFrm, (ops), "nop", []>;
352
353 // Truncate
354 def TRUNC_R32_R8 : I<0x89, MRMDestReg, (ops R8:$dst, R32:$src),
355 "mov{l} {$src, ${dst:trunc32}|${dst:trunc32}, $src}",
356 [(set R8:$dst, (trunc R32:$src))]>;
357 def TRUNC_R32_R16 : I<0x89, MRMDestReg, (ops R16:$dst, R32:$src),
358 "mov{l} {$src, ${dst:trunc32}|${dst:trunc32}, $src}",
359 [(set R16:$dst, (trunc R32:$src))]>;
360 def TRUNC_R16_R8 : I<0x89, MRMDestReg, (ops R8:$dst, R16:$src),
361 "mov{w} {$src, ${dst:trunc16}|${dst:trunc16}, $src}",
362 [(set R8:$dst, (trunc R16:$src))]>;
352363
353364 //===----------------------------------------------------------------------===//
354365 // Control Flow Instructions...
100100 const MRegisterInfo &RI = *TM.getRegisterInfo();
101101 switch (MO.getType()) {
102102 case MachineOperand::MO_Register:
103 if (MRegisterInfo::isPhysicalRegister(MO.getReg()))
104 O << RI.get(MO.getReg()).Name;
105 else
103 if (MRegisterInfo::isPhysicalRegister(MO.getReg())) {
104 unsigned Reg = MO.getReg();
105 if (Modifier && strncmp(Modifier, "trunc", strlen("trunc")) == 0) {
106 MVT::ValueType VT = (strcmp(Modifier,"trunc16") == 0)
107 ? MVT::i16 : MVT::i32;
108 Reg = getX86SubSuperRegister(Reg, VT);
109 }
110 O << RI.get(Reg).Name;
111 } else
106112 O << "reg" << MO.getReg();
107113 return;
108114
239245 const char Mode) {
240246 const MRegisterInfo &RI = *TM.getRegisterInfo();
241247 unsigned Reg = MO.getReg();
242 const char *Name = RI.get(Reg).Name;
243248 switch (Mode) {
244249 default: return true; // Unknown mode.
245250 case 'b': // Print QImode register
246 switch (Reg) {
247 default: return true;
248 case X86::AH: case X86::AL: case X86::AX: case X86::EAX:
249 Name = "AL";
250 break;
251 case X86::DH: case X86::DL: case X86::DX: case X86::EDX:
252 Name = "DL";
253 break;
254 case X86::CH: case X86::CL: case X86::CX: case X86::ECX:
255 Name = "CL";
256 break;
257 case X86::BH: case X86::BL: case X86::BX: case X86::EBX:
258 Name = "BL";
259 break;
260 case X86::ESI:
261 Name = "SIL";
262 break;
263 case X86::EDI:
264 Name = "DIL";
265 break;
266 case X86::EBP:
267 Name = "BPL";
268 break;
269 case X86::ESP:
270 Name = "SPL";
271 break;
272 }
251 Reg = getX86SubSuperRegister(Reg, MVT::i8);
273252 break;
274253 case 'h': // Print QImode high register
275 switch (Reg) {
276 default: return true;
277 case X86::AH: case X86::AL: case X86::AX: case X86::EAX:
278 Name = "AL";
279 break;
280 case X86::DH: case X86::DL: case X86::DX: case X86::EDX:
281 Name = "DL";
282 break;
283 case X86::CH: case X86::CL: case X86::CX: case X86::ECX:
284 Name = "CL";
285 break;
286 case X86::BH: case X86::BL: case X86::BX: case X86::EBX:
287 Name = "BL";
288 break;
289 }
254 Reg = getX86SubSuperRegister(Reg, MVT::i8, true);
290255 break;
291256 case 'w': // Print HImode register
292 switch (Reg) {
293 default: return true;
294 case X86::AH: case X86::AL: case X86::AX: case X86::EAX:
295 Name = "AX";
296 break;
297 case X86::DH: case X86::DL: case X86::DX: case X86::EDX:
298 Name = "DX";
299 break;
300 case X86::CH: case X86::CL: case X86::CX: case X86::ECX:
301 Name = "CX";
302 break;
303 case X86::BH: case X86::BL: case X86::BX: case X86::EBX:
304 Name = "BX";
305 break;
306 case X86::ESI:
307 Name = "SI";
308 break;
309 case X86::EDI:
310 Name = "DI";
311 break;
312 case X86::EBP:
313 Name = "BP";
314 break;
315 case X86::ESP:
316 Name = "SP";
317 break;
318 }
257 Reg = getX86SubSuperRegister(Reg, MVT::i16);
319258 break;
320259 case 'k': // Print SImode register
321 switch (Reg) {
322 default: return true;
323 case X86::AH: case X86::AL: case X86::AX: case X86::EAX:
324 Name = "EAX";
325 break;
326 case X86::DH: case X86::DL: case X86::DX: case X86::EDX:
327 Name = "EDX";
328 break;
329 case X86::CH: case X86::CL: case X86::CX: case X86::ECX:
330 Name = "ECX";
331 break;
332 case X86::BH: case X86::BL: case X86::BX: case X86::EBX:
333 Name = "EBX";
334 break;
335 case X86::ESI:
336 Name = "ESI";
337 break;
338 case X86::EDI:
339 Name = "EDI";
340 break;
341 case X86::EBP:
342 Name = "EBP";
343 break;
344 case X86::ESP:
345 Name = "ESP";
346 break;
347 }
260 Reg = getX86SubSuperRegister(Reg, MVT::i32);
348261 break;
349262 }
350263
351 O << Name;
264 O << '%' << RI.get(Reg).Name;
352265 return false;
353266 }
354267
390303 ///
391304 void X86IntelAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
392305 ++EmittedInsts;
306
307 // See if a truncate instruction can be turned into a nop.
308 switch (MI->getOpcode()) {
309 default: break;
310 case X86::TRUNC_R32_R16:
311 case X86::TRUNC_R32_R8:
312 case X86::TRUNC_R16_R8: {
313 const MachineOperand &MO0 = MI->getOperand(0);
314 const MachineOperand &MO1 = MI->getOperand(1);
315 unsigned Reg0 = MO0.getReg();
316 unsigned Reg1 = MO1.getReg();
317 if (MI->getOpcode() == X86::TRUNC_R16_R8)
318 Reg0 = getX86SubSuperRegister(Reg0, MVT::i16);
319 else
320 Reg0 = getX86SubSuperRegister(Reg0, MVT::i32);
321 if (Reg0 == Reg1)
322 O << CommentString << " TRUNCATE ";
323 break;
324 }
325 }
393326
394327 // Call the autogenerated instruction printer routines.
395328 printInstruction(MI);
810810 return hasFP(MF) ? X86::EBP : X86::ESP;
811811 }
812812
813 namespace llvm {
814 unsigned getX86SubSuperRegister(unsigned Reg, MVT::ValueType VT, bool High) {
815 switch (VT) {
816 default: return Reg;
817 case MVT::i8:
818 if (High) {
819 switch (Reg) {
820 default: return Reg;
821 case X86::AH: case X86::AL: case X86::AX: case X86::EAX:
822 return X86::AH;
823 case X86::DH: case X86::DL: case X86::DX: case X86::EDX:
824 return X86::DH;
825 case X86::CH: case X86::CL: case X86::CX: case X86::ECX:
826 return X86::CH;
827 case X86::BH: case X86::BL: case X86::BX: case X86::EBX:
828 return X86::BH;
829 }
830 } else {
831 switch (Reg) {
832 default: return Reg;
833 case X86::AH: case X86::AL: case X86::AX: case X86::EAX:
834 return X86::AL;
835 case X86::DH: case X86::DL: case X86::DX: case X86::EDX:
836 return X86::DL;
837 case X86::CH: case X86::CL: case X86::CX: case X86::ECX:
838 return X86::CL;
839 case X86::BH: case X86::BL: case X86::BX: case X86::EBX:
840 return X86::BL;
841 }
842 }
843 case MVT::i16:
844 switch (Reg) {
845 default: return Reg;
846 case X86::AH: case X86::AL: case X86::AX: case X86::EAX:
847 return X86::AX;
848 case X86::DH: case X86::DL: case X86::DX: case X86::EDX:
849 return X86::DX;
850 case X86::CH: case X86::CL: case X86::CX: case X86::ECX:
851 return X86::CX;
852 case X86::BH: case X86::BL: case X86::BX: case X86::EBX:
853 return X86::BX;
854 case X86::ESI:
855 return X86::SI;
856 case X86::EDI:
857 return X86::DI;
858 case X86::EBP:
859 return X86::BP;
860 case X86::ESP:
861 return X86::SP;
862 }
863 case MVT::i32:
864 switch (Reg) {
865 default: return true;
866 case X86::AH: case X86::AL: case X86::AX: case X86::EAX:
867 return X86::EAX;
868 case X86::DH: case X86::DL: case X86::DX: case X86::EDX:
869 return X86::EDX;
870 case X86::CH: case X86::CL: case X86::CX: case X86::ECX:
871 return X86::ECX;
872 case X86::BH: case X86::BL: case X86::BX: case X86::EBX:
873 return X86::EBX;
874 case X86::SI:
875 return X86::ESI;
876 case X86::DI:
877 return X86::EDI;
878 case X86::BP:
879 return X86::EBP;
880 case X86::SP:
881 return X86::ESP;
882 }
883 }
884
885 return Reg;
886 }
887 }
888
813889 #include "X86GenRegisterInfo.inc"
814890
6767 unsigned getFrameRegister(MachineFunction &MF) const;
6868 };
6969
70 // getX86SubSuperRegister - X86 utility function. It returns the sub or super
71 // register of a specific X86 register.
72 // e.g. getX86SubSuperRegister(X86::EAX, MVT::i16) return X86:AX
73 unsigned getX86SubSuperRegister(unsigned, MVT::ValueType, bool High=false);
74
7075 } // End llvm namespace
7176
7277 #endif