From: Brian Gaeke Date: Thu, 14 Nov 2002 22:32:30 +0000 (+0000) Subject: include/llvm/CodeGen/MachineInstrBuilder.h: Add addClobber() inline X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=6559bb96a9901af21c6037675f9508373773bd35;p=oota-llvm.git include/llvm/CodeGen/MachineInstrBuilder.h: Add addClobber() inline convenience method. Fix typo in comment. lib/Target/X86/InstSelectSimple.cpp: Explicitly specify some implicit uses. Use MOVZX/MOVSX instead of MOV instructions with sign extend instructions. Take out LEAVE instructions. 32-bit IDIV and DIV use CDQ, not CWQ (CWQ is a typo). Fix typo in comment and remove some FIXME comments. lib/Target/X86/Printer.cpp: Include X86InstrInfo.h and llvm/Function.h. Add some simple code to Printer::runOnFunction to iterate over MachineBasicBlocks and call X86InstrInfo::print(). lib/Target/X86/X86InstrInfo.def: Make some more instructions with implicit defs "Void". Add more sign/zero extending "move" insns (movsx, movzx). lib/Target/X86/X86RegisterInfo.def: Add EFLAGS as a register. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4707 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h index d594d1b025b..a360be6de3b 100644 --- a/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/include/llvm/CodeGen/MachineInstrBuilder.h @@ -34,13 +34,22 @@ struct MachineInstrBuilder { return *this; } - /// addReg - Add an LLVM value that is to be used as a register...x + /// addReg - Add an LLVM value that is to be used as a register... /// MachineInstrBuilder &addReg(Value *V, bool isDef = false, bool isDNU = false){ MI->addRegOperand(V, isDef, isDNU); return *this; } + /// addClobber - Assert that this MI is going to clobber a specific + /// register. Useful for instructions that always clobber certain hard regs. + /// (Same as addReg(RegNo, true) but shorter and more obvious). + /// + MachineInstrBuilder &addClobber(int RegNo) { + MI->addRegOperand(RegNo, true); + return *this; + } + /// addPCDisp - Add an LLVM value to be treated as a PC relative /// displacement... /// diff --git a/lib/Target/X86/InstSelectSimple.cpp b/lib/Target/X86/InstSelectSimple.cpp index f2540a520dd..1d2daf7bf46 100644 --- a/lib/Target/X86/InstSelectSimple.cpp +++ b/lib/Target/X86/InstSelectSimple.cpp @@ -211,33 +211,30 @@ ISel::visitSetCondInst (SetCondInst & I) break; } // (Non-trapping) compare and pop twice. - // FIXME: Result of comparison -> condition codes, not a register. BuildMI (BB, X86::FUCOMPP, 0); // Move fp status word (concodes) to ax. BuildMI (BB, X86::FNSTSWr8, 1, X86::AX); // Load real concodes from ax. - // FIXME: Once again, flags are not modeled. - BuildMI (BB, X86::SAHF, 0); + BuildMI (BB, X86::SAHF, 1, X86::EFLAGS).addReg(X86::AH); } else { // integer comparison // Emit: cmp , (do the comparison). We can // compare 8-bit with 8-bit, 16-bit with 16-bit, 32-bit with // 32-bit. - // FIXME: Result of comparison -> condition codes, not a register. switch (comparisonWidth) { case 1: BuildMI (BB, X86::CMPrr8, 2, - X86::NoReg).addReg (reg1).addReg (reg2); + X86::EFLAGS).addReg (reg1).addReg (reg2); break; case 2: BuildMI (BB, X86::CMPrr16, 2, - X86::NoReg).addReg (reg1).addReg (reg2); + X86::EFLAGS).addReg (reg1).addReg (reg2); break; case 4: BuildMI (BB, X86::CMPrr32, 2, - X86::NoReg).addReg (reg1).addReg (reg2); + X86::EFLAGS).addReg (reg1).addReg (reg2); break; case 8: default: @@ -297,15 +294,11 @@ ISel::visitSetCondInst (SetCondInst & I) case 1: BuildMI (BB, X86::MOVrr8, 1, resultReg).addReg (X86::AL); break; - // FIXME: What to do about implicit destination registers? - // E.g., you don't specify it, but CBW is more like AX = CBW(AL). case 2: - BuildMI (BB, X86::CBW, 0, X86::AX); - BuildMI (BB, X86::MOVrr16, 1, resultReg).addReg (X86::AX); + BuildMI (BB, X86::MOVZXr16r8, 1, resultReg).addReg (X86::AL); break; case 4: - BuildMI (BB, X86::CWDE, 0, X86::EAX); - BuildMI (BB, X86::MOVrr32, 1, resultReg).addReg (X86::EAX); + BuildMI (BB, X86::MOVZXr32r8, 1, resultReg).addReg (X86::AL); break; case 8: default: @@ -331,6 +324,7 @@ ISel::visitReturnInst (ReturnInst & I) { if (I.getNumOperands () == 1) { + bool unsignedReturnValue = I.getOperand(0)->getType()->isUnsigned(); unsigned val = getReg (I.getOperand (0)); unsigned operandSize = I.getOperand (0)->getType ()->getPrimitiveSize (); @@ -358,21 +352,22 @@ ISel::visitReturnInst (ReturnInst & I) { case 1: // ret sbyte, ubyte: Extend value into EAX and return - // MOV AL, - // CBW - BuildMI (BB, X86::MOVrr8, 1, X86::AL).addReg (val); - BuildMI (BB, X86::CBW, 0); + if (unsignedReturnValue) { + BuildMI (BB, X86::MOVZXr32r8, 1, X86::EAX).addReg (val); + } else { + BuildMI (BB, X86::MOVSXr32r8, 1, X86::EAX).addReg (val); + } break; case 2: // ret short, ushort: Extend value into EAX and return - // MOV AX, - // CWDE - BuildMI (BB, X86::MOVrr16, 1, X86::AX).addReg (val); - BuildMI (BB, X86::CWDE, 0); + if (unsignedReturnValue) { + BuildMI (BB, X86::MOVZXr32r16, 1, X86::EAX).addReg (val); + } else { + BuildMI (BB, X86::MOVSXr32r16, 1, X86::EAX).addReg (val); + } break; case 4: // ret int, uint, ptr: Move value into EAX and return - // MOV EAX, BuildMI (BB, X86::MOVrr32, 1, X86::EAX).addReg (val); break; case 8: @@ -387,8 +382,7 @@ ISel::visitReturnInst (ReturnInst & I) } } } - // Emit a 'leave' and a 'ret' - BuildMI (BB, X86::LEAVE, 0); + // Emit a 'ret' -- the 'leave' will be added by the reg allocator, I guess? BuildMI (BB, X86::RET, 0); } @@ -473,7 +467,7 @@ void ISel::visitDivRem(BinaryOperator &I) { static const unsigned Regs[] ={ X86::AL , X86::AX , X86::EAX }; static const unsigned MovOpcode[]={ X86::MOVrr8, X86::MOVrr16, X86::MOVrr32 }; - static const unsigned ExtOpcode[]={ X86::CBW , X86::CWD , X86::CWQ }; + static const unsigned ExtOpcode[]={ X86::CBW , X86::CWD , X86::CDQ }; static const unsigned ClrOpcode[]={ X86::XORrr8, X86::XORrr16, X86::XORrr32 }; static const unsigned ExtRegs[] ={ X86::AH , X86::DX , X86::EDX }; @@ -502,7 +496,7 @@ void ISel::visitDivRem(BinaryOperator &I) { // Figure out which register we want to pick the result out of... unsigned DestReg = (I.getOpcode() == Instruction::Div) ? Reg : ExtReg; - // Emit the appropriate multiple instruction... + // Emit the appropriate divide or remainder instruction... // FIXME: We need to mark that this modified AH, DX, or EDX also!! BuildMI(BB,DivOpcode[isSigned][Class], 2, DestReg).addReg(Reg).addReg(Op1Reg); diff --git a/lib/Target/X86/Printer.cpp b/lib/Target/X86/Printer.cpp index b320e2c1788..fdb444e54ee 100644 --- a/lib/Target/X86/Printer.cpp +++ b/lib/Target/X86/Printer.cpp @@ -6,7 +6,10 @@ //===----------------------------------------------------------------------===// #include "X86.h" +#include "X86InstrInfo.h" #include "llvm/Pass.h" +#include "llvm/Function.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/CodeGen/MachineFunction.h" #include @@ -21,17 +24,40 @@ namespace { }; } -bool Printer::runOnFunction(Function &F) { - MachineFunction &MF = MachineFunction::get(&F); - O << "x86 printing not implemented yet!\n"; - - // This should use the X86InstructionInfo::print method to print assembly - // for each instruction - return false; -} +/// runOnFunction - This uses the X86InstructionInfo::print method +/// to print assembly for each instruction. +bool Printer::runOnFunction (Function & F) +{ + static unsigned bbnumber = 0; + MachineFunction & MF = MachineFunction::get (&F); + const MachineInstrInfo & MII = TM.getInstrInfo (); + const X86InstrInfo & x86ii = dynamic_cast (MII); + + O << "# x86 printing not implemented yet!\n"; + // Print out labels for the function. + O << "\t.globl\t" << F.getName () << "\n"; + O << "\t.type\t" << F.getName () << ", @function\n"; + O << F.getName () << ":\n"; + // Print out code for the function. + for (MachineFunction::const_iterator bb_i = MF.begin (), bb_e = MF.end (); + bb_i != bb_e; ++bb_i) + { + // Print a label for the basic block. + O << ".BB" << bbnumber++ << ":\n"; + for (MachineBasicBlock::const_iterator i_i = bb_i->begin (), i_e = + bb_i->end (); i_i != i_e; ++i_i) + { + // Print the assembly for the instruction. + O << "\t"; + x86ii.print (*i_i, O); + } + } + // We didn't modify anything. + return false; +} /// createX86CodePrinterPass - Print out the specified machine code function to /// the specified stream. This function should work regardless of whether or diff --git a/lib/Target/X86/X86AsmPrinter.cpp b/lib/Target/X86/X86AsmPrinter.cpp index b320e2c1788..fdb444e54ee 100644 --- a/lib/Target/X86/X86AsmPrinter.cpp +++ b/lib/Target/X86/X86AsmPrinter.cpp @@ -6,7 +6,10 @@ //===----------------------------------------------------------------------===// #include "X86.h" +#include "X86InstrInfo.h" #include "llvm/Pass.h" +#include "llvm/Function.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/CodeGen/MachineFunction.h" #include @@ -21,17 +24,40 @@ namespace { }; } -bool Printer::runOnFunction(Function &F) { - MachineFunction &MF = MachineFunction::get(&F); - O << "x86 printing not implemented yet!\n"; - - // This should use the X86InstructionInfo::print method to print assembly - // for each instruction - return false; -} +/// runOnFunction - This uses the X86InstructionInfo::print method +/// to print assembly for each instruction. +bool Printer::runOnFunction (Function & F) +{ + static unsigned bbnumber = 0; + MachineFunction & MF = MachineFunction::get (&F); + const MachineInstrInfo & MII = TM.getInstrInfo (); + const X86InstrInfo & x86ii = dynamic_cast (MII); + + O << "# x86 printing not implemented yet!\n"; + // Print out labels for the function. + O << "\t.globl\t" << F.getName () << "\n"; + O << "\t.type\t" << F.getName () << ", @function\n"; + O << F.getName () << ":\n"; + // Print out code for the function. + for (MachineFunction::const_iterator bb_i = MF.begin (), bb_e = MF.end (); + bb_i != bb_e; ++bb_i) + { + // Print a label for the basic block. + O << ".BB" << bbnumber++ << ":\n"; + for (MachineBasicBlock::const_iterator i_i = bb_i->begin (), i_e = + bb_i->end (); i_i != i_e; ++i_i) + { + // Print the assembly for the instruction. + O << "\t"; + x86ii.print (*i_i, O); + } + } + // We didn't modify anything. + return false; +} /// createX86CodePrinterPass - Print out the specified machine code function to /// the specified stream. This function should work regardless of whether or diff --git a/lib/Target/X86/X86ISelSimple.cpp b/lib/Target/X86/X86ISelSimple.cpp index f2540a520dd..1d2daf7bf46 100644 --- a/lib/Target/X86/X86ISelSimple.cpp +++ b/lib/Target/X86/X86ISelSimple.cpp @@ -211,33 +211,30 @@ ISel::visitSetCondInst (SetCondInst & I) break; } // (Non-trapping) compare and pop twice. - // FIXME: Result of comparison -> condition codes, not a register. BuildMI (BB, X86::FUCOMPP, 0); // Move fp status word (concodes) to ax. BuildMI (BB, X86::FNSTSWr8, 1, X86::AX); // Load real concodes from ax. - // FIXME: Once again, flags are not modeled. - BuildMI (BB, X86::SAHF, 0); + BuildMI (BB, X86::SAHF, 1, X86::EFLAGS).addReg(X86::AH); } else { // integer comparison // Emit: cmp , (do the comparison). We can // compare 8-bit with 8-bit, 16-bit with 16-bit, 32-bit with // 32-bit. - // FIXME: Result of comparison -> condition codes, not a register. switch (comparisonWidth) { case 1: BuildMI (BB, X86::CMPrr8, 2, - X86::NoReg).addReg (reg1).addReg (reg2); + X86::EFLAGS).addReg (reg1).addReg (reg2); break; case 2: BuildMI (BB, X86::CMPrr16, 2, - X86::NoReg).addReg (reg1).addReg (reg2); + X86::EFLAGS).addReg (reg1).addReg (reg2); break; case 4: BuildMI (BB, X86::CMPrr32, 2, - X86::NoReg).addReg (reg1).addReg (reg2); + X86::EFLAGS).addReg (reg1).addReg (reg2); break; case 8: default: @@ -297,15 +294,11 @@ ISel::visitSetCondInst (SetCondInst & I) case 1: BuildMI (BB, X86::MOVrr8, 1, resultReg).addReg (X86::AL); break; - // FIXME: What to do about implicit destination registers? - // E.g., you don't specify it, but CBW is more like AX = CBW(AL). case 2: - BuildMI (BB, X86::CBW, 0, X86::AX); - BuildMI (BB, X86::MOVrr16, 1, resultReg).addReg (X86::AX); + BuildMI (BB, X86::MOVZXr16r8, 1, resultReg).addReg (X86::AL); break; case 4: - BuildMI (BB, X86::CWDE, 0, X86::EAX); - BuildMI (BB, X86::MOVrr32, 1, resultReg).addReg (X86::EAX); + BuildMI (BB, X86::MOVZXr32r8, 1, resultReg).addReg (X86::AL); break; case 8: default: @@ -331,6 +324,7 @@ ISel::visitReturnInst (ReturnInst & I) { if (I.getNumOperands () == 1) { + bool unsignedReturnValue = I.getOperand(0)->getType()->isUnsigned(); unsigned val = getReg (I.getOperand (0)); unsigned operandSize = I.getOperand (0)->getType ()->getPrimitiveSize (); @@ -358,21 +352,22 @@ ISel::visitReturnInst (ReturnInst & I) { case 1: // ret sbyte, ubyte: Extend value into EAX and return - // MOV AL, - // CBW - BuildMI (BB, X86::MOVrr8, 1, X86::AL).addReg (val); - BuildMI (BB, X86::CBW, 0); + if (unsignedReturnValue) { + BuildMI (BB, X86::MOVZXr32r8, 1, X86::EAX).addReg (val); + } else { + BuildMI (BB, X86::MOVSXr32r8, 1, X86::EAX).addReg (val); + } break; case 2: // ret short, ushort: Extend value into EAX and return - // MOV AX, - // CWDE - BuildMI (BB, X86::MOVrr16, 1, X86::AX).addReg (val); - BuildMI (BB, X86::CWDE, 0); + if (unsignedReturnValue) { + BuildMI (BB, X86::MOVZXr32r16, 1, X86::EAX).addReg (val); + } else { + BuildMI (BB, X86::MOVSXr32r16, 1, X86::EAX).addReg (val); + } break; case 4: // ret int, uint, ptr: Move value into EAX and return - // MOV EAX, BuildMI (BB, X86::MOVrr32, 1, X86::EAX).addReg (val); break; case 8: @@ -387,8 +382,7 @@ ISel::visitReturnInst (ReturnInst & I) } } } - // Emit a 'leave' and a 'ret' - BuildMI (BB, X86::LEAVE, 0); + // Emit a 'ret' -- the 'leave' will be added by the reg allocator, I guess? BuildMI (BB, X86::RET, 0); } @@ -473,7 +467,7 @@ void ISel::visitDivRem(BinaryOperator &I) { static const unsigned Regs[] ={ X86::AL , X86::AX , X86::EAX }; static const unsigned MovOpcode[]={ X86::MOVrr8, X86::MOVrr16, X86::MOVrr32 }; - static const unsigned ExtOpcode[]={ X86::CBW , X86::CWD , X86::CWQ }; + static const unsigned ExtOpcode[]={ X86::CBW , X86::CWD , X86::CDQ }; static const unsigned ClrOpcode[]={ X86::XORrr8, X86::XORrr16, X86::XORrr32 }; static const unsigned ExtRegs[] ={ X86::AH , X86::DX , X86::EDX }; @@ -502,7 +496,7 @@ void ISel::visitDivRem(BinaryOperator &I) { // Figure out which register we want to pick the result out of... unsigned DestReg = (I.getOpcode() == Instruction::Div) ? Reg : ExtReg; - // Emit the appropriate multiple instruction... + // Emit the appropriate divide or remainder instruction... // FIXME: We need to mark that this modified AH, DX, or EDX also!! BuildMI(BB,DivOpcode[isSigned][Class], 2, DestReg).addReg(Reg).addReg(Op1Reg); diff --git a/lib/Target/X86/X86InstrInfo.def b/lib/Target/X86/X86InstrInfo.def index 1a6f2f5fca9..5c4a963d165 100644 --- a/lib/Target/X86/X86InstrInfo.def +++ b/lib/Target/X86/X86InstrInfo.def @@ -99,14 +99,14 @@ I(SARrr32 , "sarl", 0, 0) // R32 >>= cl D3/7 I(SARir32 , "sarl", 0, 0) // R32 >>= imm8 C1/7 ib // Floating point loads -I(FLDr4 , "flds", 0, 0) // push float D9/0 -I(FLDr8 , "fldl ", 0, 0) // push double DD/0 +I(FLDr4 , "flds", 0, X86II::Void) // push float D9/0 +I(FLDr8 , "fldl ", 0, X86II::Void) // push double DD/0 // Floating point compares -I(FUCOMPP , "fucompp", 0, 0) // compare+pop2x DA E9 +I(FUCOMPP , "fucompp", 0, X86II::Void) // compare+pop2x DA E9 // Floating point flag ops -I(FNSTSWr8 , "fnstsw", 0, 0) // AX = fp flags DF E0 +I(FNSTSWr8 , "fnstsw", 0, X86II::Void) // AX = fp flags DF E0 // Condition code ops, incl. set if equal/not equal/... I(SAHF , "sahf", 0, 0) // flags = AH 9E @@ -126,11 +126,16 @@ I(CMPrr8 , "cmpb", 0, 0) // compare R8,R8 38/r I(CMPrr16 , "cmpw", 0, 0) // compare R16,R16 39/r I(CMPrr32 , "cmpl", 0, 0) // compare R32,R32 39/r -// Sign extenders -I(CBW , "cbw", 0, 0) // AH = signext(AL) 98 -I(CWD , "cwd", 0, 0) // DX = signext(AX) 99 -I(CWQ , "cwq", 0, 0) // EDX= signext(EAX) 99 -I(CWDE , "cwde", 0, 0) // EAX = extend AX 98 +// Sign extenders (first 3 are good for DIV/IDIV; the others are more general) +I(CBW , "cbw", 0, 0) // AX = signext(AL) 98 +I(CWD , "cwd", 0, 0) // DX:AX = signext(AX) 99 +I(CDQ , "cdq", 0, 0) // EDX:EAX = signext(EAX) 99 +I(MOVSXr16r8 , "movsx", 0, 0) // R32 = signext(R8) 0F BE /r +I(MOVSXr32r8 , "movsx", 0, 0) // R32 = signext(R8) 0F BE /r +I(MOVSXr32r16 , "movsx", 0, 0) // R32 = signext(R16) 0F BF /r +I(MOVZXr16r8 , "movzx", 0, 0) // R32 = zeroext(R8) 0F B6 /r +I(MOVZXr32r8 , "movzx", 0, 0) // R32 = zeroext(R8) 0F B6 /r +I(MOVZXr32r16 , "movzx", 0, 0) // R32 = zeroext(R16) 0F B7 /r // At this point, I is dead, so undefine the macro #undef I diff --git a/lib/Target/X86/X86RegisterInfo.def b/lib/Target/X86/X86RegisterInfo.def index 9bfff5a8084..df75fa35895 100644 --- a/lib/Target/X86/X86RegisterInfo.def +++ b/lib/Target/X86/X86RegisterInfo.def @@ -64,5 +64,10 @@ R(BH, "bh", MRF::INT8, 0) // Flags, Segment registers, etc... +// This is a slimy hack to make it possible to say that flags are clobbered... +// Ideally we'd model instructions based on which particular flag(s) they +// could clobber. +R(EFLAGS, "eflags", MRF::INT8, 0) + // We are now done with the R macro #undef R