include/llvm/CodeGen/MachineInstrBuilder.h: Add addClobber() inline
authorBrian Gaeke <gaeke@uiuc.edu>
Thu, 14 Nov 2002 22:32:30 +0000 (22:32 +0000)
committerBrian Gaeke <gaeke@uiuc.edu>
Thu, 14 Nov 2002 22:32:30 +0000 (22:32 +0000)
 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

include/llvm/CodeGen/MachineInstrBuilder.h
lib/Target/X86/InstSelectSimple.cpp
lib/Target/X86/Printer.cpp
lib/Target/X86/X86AsmPrinter.cpp
lib/Target/X86/X86ISelSimple.cpp
lib/Target/X86/X86InstrInfo.def
lib/Target/X86/X86RegisterInfo.def

index d594d1b025be908860d7e620a5e50da9a3d38877..a360be6de3b9246f85e691e48d4cf2bd37545c4c 100644 (file)
@@ -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...
   ///
index f2540a520dd7511c8970c2280c26662ecb320bc4..1d2daf7bf46fcee314ccae6a44d2747c2f603831 100644 (file)
@@ -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 <var1>, <var2> (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, <val>
-             // 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, <val>
-             // 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, <val>
              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);
 
index b320e2c17886c4c6dbdbd7740beff9426748ff80..fdb444e54eef44a82a667d96df5776ccabadd136 100644 (file)
@@ -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 <iostream>
 
@@ -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 <const X86InstrInfo &> (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
index b320e2c17886c4c6dbdbd7740beff9426748ff80..fdb444e54eef44a82a667d96df5776ccabadd136 100644 (file)
@@ -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 <iostream>
 
@@ -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 <const X86InstrInfo &> (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
index f2540a520dd7511c8970c2280c26662ecb320bc4..1d2daf7bf46fcee314ccae6a44d2747c2f603831 100644 (file)
@@ -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 <var1>, <var2> (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, <val>
-             // 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, <val>
-             // 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, <val>
              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);
 
index 1a6f2f5fca937f61a6d11969aede30032b7cd362..5c4a963d165ecbbe26c750f3fd53b15f05e6cf37 100644 (file)
@@ -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
index 9bfff5a8084471061ab4e948ccd8a806681f5f8e..df75fa3589547ed677eab418e73e3dcc460f9347 100644 (file)
@@ -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