[llvm-commits] [parallel] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp Printer.cpp X86CodeEmitter.cpp X86InstrBuilder.h X86InstrInfo.td X86RegisterInfo.cpp X86TargetMachine.cpp X86TargetMachine.h

Misha Brukman brukman at cs.uiuc.edu
Wed Mar 10 19:02:00 PST 2004


Changes in directory llvm/lib/Target/X86:

InstSelectSimple.cpp updated: 1.149.2.1 -> 1.149.2.2
Printer.cpp updated: 1.76.2.1 -> 1.76.2.2
X86CodeEmitter.cpp updated: 1.46.2.1 -> 1.46.2.2
X86InstrBuilder.h updated: 1.9.4.1 -> 1.9.4.2
X86InstrInfo.td updated: 1.15.2.1 -> 1.15.2.2
X86RegisterInfo.cpp updated: 1.40.4.1 -> 1.40.4.2
X86TargetMachine.cpp updated: 1.44.2.1 -> 1.44.2.2
X86TargetMachine.h updated: 1.21.2.1 -> 1.21.2.2

---
Log message:

Merge from trunk.


---
Diffs of the changes:  (+306 -202)

Index: llvm/lib/Target/X86/InstSelectSimple.cpp
diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.149.2.1 llvm/lib/Target/X86/InstSelectSimple.cpp:1.149.2.2
--- llvm/lib/Target/X86/InstSelectSimple.cpp:1.149.2.1	Mon Mar  1 17:58:15 2004
+++ llvm/lib/Target/X86/InstSelectSimple.cpp	Wed Mar 10 19:01:46 2004
@@ -107,6 +107,7 @@
     /// LowerUnknownIntrinsicFunctionCalls - This performs a prepass over the
     /// function, lowering any calls to unknown intrinsic functions into the
     /// equivalent LLVM code.
+    ///
     void LowerUnknownIntrinsicFunctionCalls(Function &F);
 
     /// LoadArgumentsToVirtualRegs - Load all of the arguments to this function
@@ -198,8 +199,14 @@
     ///
     void promote32(unsigned targetReg, const ValueRecord &VR);
 
-    // getGEPIndex - This is used to fold GEP instructions into X86 addressing
-    // expressions.
+    /// getAddressingMode - Get the addressing mode to use to address the
+    /// specified value.  The returned value should be used with addFullAddress.
+    void getAddressingMode(Value *Addr, unsigned &BaseReg, unsigned &Scale,
+                           unsigned &IndexReg, unsigned &Disp);
+
+
+    /// getGEPIndex - This is used to fold GEP instructions into X86 addressing
+    /// expressions.
     void getGEPIndex(MachineBasicBlock *MBB, MachineBasicBlock::iterator IP,
                      std::vector<Value*> &GEPOps,
                      std::vector<const Type*> &GEPTypes, unsigned &BaseReg,
@@ -221,11 +228,13 @@
 
     /// emitCastOperation - Common code shared between visitCastInst and
     /// constant expression cast support.
+    ///
     void emitCastOperation(MachineBasicBlock *BB,MachineBasicBlock::iterator IP,
                            Value *Src, const Type *DestTy, unsigned TargetReg);
 
     /// emitSimpleBinaryOperation - Common code shared between visitSimpleBinary
     /// and constant expression support.
+    ///
     void emitSimpleBinaryOperation(MachineBasicBlock *BB,
                                    MachineBasicBlock::iterator IP,
                                    Value *Op0, Value *Op1,
@@ -238,6 +247,7 @@
 
     /// emitSetCCOperation - Common code shared between visitSetCondInst and
     /// constant expression support.
+    ///
     void emitSetCCOperation(MachineBasicBlock *BB,
                             MachineBasicBlock::iterator IP,
                             Value *Op0, Value *Op1, unsigned Opcode,
@@ -245,6 +255,7 @@
 
     /// emitShiftOperation - Common code shared between visitShiftInst and
     /// constant expression support.
+    ///
     void emitShiftOperation(MachineBasicBlock *MBB,
                             MachineBasicBlock::iterator IP,
                             Value *Op, Value *ShiftAmount, bool isLeftShift,
@@ -709,9 +720,13 @@
       ++NumFPKill;
     }
   }
+  // If we got this far, there is no need to insert the kill instruction.
+  return false;
+#else
+  return true;
+#endif
 }
 
-
 // canFoldSetCCIntoBranch - Return the setcc instruction if we can fold it into
 // the conditional branch instruction which is the only user of the cc
 // instruction.  This is the case if the conditional branch is the only user of
@@ -887,6 +902,7 @@
 
 /// emitSetCCOperation - Common code shared between visitSetCondInst and
 /// constant expression support.
+///
 void ISel::emitSetCCOperation(MachineBasicBlock *MBB,
                               MachineBasicBlock::iterator IP,
                               Value *Op0, Value *Op1, unsigned Opcode,
@@ -913,6 +929,7 @@
 
 /// promote32 - Emit instructions to turn a narrow operand into a 32-bit-wide
 /// operand, in the specified target register.
+///
 void ISel::promote32(unsigned targetReg, const ValueRecord &VR) {
   bool isUnsigned = VR.Ty->isUnsigned();
 
@@ -1221,6 +1238,7 @@
 /// LowerUnknownIntrinsicFunctionCalls - This performs a prepass over the
 /// function, lowering any calls to unknown intrinsic functions into the
 /// equivalent LLVM code.
+///
 void ISel::LowerUnknownIntrinsicFunctionCalls(Function &F) {
   for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
     for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; )
@@ -1400,15 +1418,67 @@
   }
 }
 
+static bool isSafeToFoldLoadIntoInstruction(LoadInst &LI, Instruction &User) {
+  if (LI.getParent() != User.getParent())
+    return false;
+  BasicBlock::iterator It = &LI;
+  // Check all of the instructions between the load and the user.  We should
+  // really use alias analysis here, but for now we just do something simple.
+  for (++It; It != BasicBlock::iterator(&User); ++It) {
+    switch (It->getOpcode()) {
+    case Instruction::Store:
+    case Instruction::Call:
+    case Instruction::Invoke:
+      return false;
+    }
+  }
+  return true;
+}
+
 
 /// visitSimpleBinary - Implement simple binary operators for integral types...
 /// OperatorClass is one of: 0 for Add, 1 for Sub, 2 for And, 3 for Or, 4 for
 /// Xor.
+///
 void ISel::visitSimpleBinary(BinaryOperator &B, unsigned OperatorClass) {
   unsigned DestReg = getReg(B);
   MachineBasicBlock::iterator MI = BB->end();
-  emitSimpleBinaryOperation(BB, MI, B.getOperand(0), B.getOperand(1),
-                            OperatorClass, DestReg);
+  Value *Op0 = B.getOperand(0), *Op1 = B.getOperand(1);
+
+  // Special case: op Reg, load [mem]
+  if (isa<LoadInst>(Op0) && !isa<LoadInst>(Op1))
+    if (!B.swapOperands())
+      std::swap(Op0, Op1);  // Make sure any loads are in the RHS.
+
+  unsigned Class = getClassB(B.getType());
+  if (isa<LoadInst>(Op1) && Class < cFP &&
+      isSafeToFoldLoadIntoInstruction(*cast<LoadInst>(Op1), B)) {
+
+    static const unsigned OpcodeTab[][3] = {
+      // Arithmetic operators
+      { X86::ADD8rm, X86::ADD16rm, X86::ADD32rm },  // ADD
+      { X86::SUB8rm, X86::SUB16rm, X86::SUB32rm },  // SUB
+      
+      // Bitwise operators
+      { X86::AND8rm, X86::AND16rm, X86::AND32rm },  // AND
+      { X86:: OR8rm, X86:: OR16rm, X86:: OR32rm },  // OR
+      { X86::XOR8rm, X86::XOR16rm, X86::XOR32rm },  // XOR
+    };
+  
+    assert(Class < cFP && "General code handles 64-bit integer types!");
+    unsigned Opcode = OpcodeTab[OperatorClass][Class];
+
+    unsigned BaseReg, Scale, IndexReg, Disp;
+    getAddressingMode(cast<LoadInst>(Op1)->getOperand(0), BaseReg,
+                      Scale, IndexReg, Disp);
+
+    unsigned Op0r = getReg(Op0);
+    addFullAddress(BuildMI(BB, Opcode, 2, DestReg).addReg(Op0r),
+                   BaseReg, Scale, IndexReg, Disp);
+    return;
+  }
+
+  emitSimpleBinaryOperation(BB, MI, Op0, Op1, OperatorClass, DestReg);
 }
 
 /// emitSimpleBinaryOperation - Implement simple binary operators for integral
@@ -1450,83 +1520,82 @@
         return;
       }
 
-  if (!isa<ConstantInt>(Op1) || Class == cLong) {
-    static const unsigned OpcodeTab[][4] = {
-      // Arithmetic operators
-      { X86::ADD8rr, X86::ADD16rr, X86::ADD32rr, X86::FpADD },  // ADD
-      { X86::SUB8rr, X86::SUB16rr, X86::SUB32rr, X86::FpSUB },  // SUB
-      
-      // Bitwise operators
-      { X86::AND8rr, X86::AND16rr, X86::AND32rr, 0 },  // AND
-      { X86:: OR8rr, X86:: OR16rr, X86:: OR32rr, 0 },  // OR
-      { X86::XOR8rr, X86::XOR16rr, X86::XOR32rr, 0 },  // XOR
-    };
-    
-    bool isLong = false;
-    if (Class == cLong) {
-      isLong = true;
-      Class = cInt;          // Bottom 32 bits are handled just like ints
-    }
-    
-    unsigned Opcode = OpcodeTab[OperatorClass][Class];
-    assert(Opcode && "Floating point arguments to logical inst?");
+  // Special case: op Reg, <const>
+  if (Class != cLong && isa<ConstantInt>(Op1)) {
+    ConstantInt *Op1C = cast<ConstantInt>(Op1);
     unsigned Op0r = getReg(Op0, MBB, IP);
-    unsigned Op1r = getReg(Op1, MBB, IP);
-    BuildMI(*MBB, IP, Opcode, 2, DestReg).addReg(Op0r).addReg(Op1r);
-    
-    if (isLong) {        // Handle the upper 32 bits of long values...
-      static const unsigned TopTab[] = {
-        X86::ADC32rr, X86::SBB32rr, X86::AND32rr, X86::OR32rr, X86::XOR32rr
-      };
-      BuildMI(*MBB, IP, TopTab[OperatorClass], 2,
-          DestReg+1).addReg(Op0r+1).addReg(Op1r+1);
+
+    // xor X, -1 -> not X
+    if (OperatorClass == 4 && Op1C->isAllOnesValue()) {
+      static unsigned const NOTTab[] = { X86::NOT8r, X86::NOT16r, X86::NOT32r };
+      BuildMI(*MBB, IP, NOTTab[Class], 1, DestReg).addReg(Op0r);
+      return;
     }
-    return;
-  }
 
-  // Special case: op Reg, <const>
-  ConstantInt *Op1C = cast<ConstantInt>(Op1);
-  unsigned Op0r = getReg(Op0, MBB, IP);
+    // add X, -1 -> dec X
+    if (OperatorClass == 0 && Op1C->isAllOnesValue()) {
+      static unsigned const DECTab[] = { X86::DEC8r, X86::DEC16r, X86::DEC32r };
+      BuildMI(*MBB, IP, DECTab[Class], 1, DestReg).addReg(Op0r);
+      return;
+    }
 
-  // xor X, -1 -> not X
-  if (OperatorClass == 4 && Op1C->isAllOnesValue()) {
-    static unsigned const NOTTab[] = { X86::NOT8r, X86::NOT16r, X86::NOT32r };
-    BuildMI(*MBB, IP, NOTTab[Class], 1, DestReg).addReg(Op0r);
-    return;
-  }
+    // add X, 1 -> inc X
+    if (OperatorClass == 0 && Op1C->equalsInt(1)) {
+      static unsigned const DECTab[] = { X86::INC8r, X86::INC16r, X86::INC32r };
+      BuildMI(*MBB, IP, DECTab[Class], 1, DestReg).addReg(Op0r);
+      return;
+    }
+  
+    static const unsigned OpcodeTab[][3] = {
+      // Arithmetic operators
+      { X86::ADD8ri, X86::ADD16ri, X86::ADD32ri },  // ADD
+      { X86::SUB8ri, X86::SUB16ri, X86::SUB32ri },  // SUB
+    
+      // Bitwise operators
+      { X86::AND8ri, X86::AND16ri, X86::AND32ri },  // AND
+      { X86:: OR8ri, X86:: OR16ri, X86:: OR32ri },  // OR
+      { X86::XOR8ri, X86::XOR16ri, X86::XOR32ri },  // XOR
+    };
+  
+    assert(Class < cFP && "General code handles 64-bit integer types!");
+    unsigned Opcode = OpcodeTab[OperatorClass][Class];
 
-  // add X, -1 -> dec X
-  if (OperatorClass == 0 && Op1C->isAllOnesValue()) {
-    static unsigned const DECTab[] = { X86::DEC8r, X86::DEC16r, X86::DEC32r };
-    BuildMI(*MBB, IP, DECTab[Class], 1, DestReg).addReg(Op0r);
+    uint64_t Op1v = cast<ConstantInt>(Op1C)->getRawValue();
+    BuildMI(*MBB, IP, Opcode, 5, DestReg).addReg(Op0r).addImm(Op1v);
     return;
   }
 
-  // add X, 1 -> inc X
-  if (OperatorClass == 0 && Op1C->equalsInt(1)) {
-    static unsigned const DECTab[] = { X86::INC8r, X86::INC16r, X86::INC32r };
-    BuildMI(*MBB, IP, DECTab[Class], 1, DestReg).addReg(Op0r);
-    return;
-  }
-  
-  static const unsigned OpcodeTab[][3] = {
+  // Finally, handle the general case now.
+  static const unsigned OpcodeTab[][4] = {
     // Arithmetic operators
-    { X86::ADD8ri, X86::ADD16ri, X86::ADD32ri },  // ADD
-    { X86::SUB8ri, X86::SUB16ri, X86::SUB32ri },  // SUB
-    
+    { X86::ADD8rr, X86::ADD16rr, X86::ADD32rr, X86::FpADD },  // ADD
+    { X86::SUB8rr, X86::SUB16rr, X86::SUB32rr, X86::FpSUB },  // SUB
+      
     // Bitwise operators
-    { X86::AND8ri, X86::AND16ri, X86::AND32ri },  // AND
-    { X86:: OR8ri, X86:: OR16ri, X86:: OR32ri },  // OR
-    { X86::XOR8ri, X86::XOR16ri, X86::XOR32ri },  // XOR
+    { X86::AND8rr, X86::AND16rr, X86::AND32rr, 0 },  // AND
+    { X86:: OR8rr, X86:: OR16rr, X86:: OR32rr, 0 },  // OR
+    { X86::XOR8rr, X86::XOR16rr, X86::XOR32rr, 0 },  // XOR
   };
-  
-  assert(Class < 3 && "General code handles 64-bit integer types!");
+    
+  bool isLong = false;
+  if (Class == cLong) {
+    isLong = true;
+    Class = cInt;          // Bottom 32 bits are handled just like ints
+  }
+    
   unsigned Opcode = OpcodeTab[OperatorClass][Class];
-  uint64_t Op1v = cast<ConstantInt>(Op1C)->getRawValue();
-  
-  // Mask off any upper bits of the constant, if there are any...
-  Op1v &= (1ULL << (8 << Class)) - 1;
-  BuildMI(*MBB, IP, Opcode, 2, DestReg).addReg(Op0r).addImm(Op1v);
+  assert(Opcode && "Floating point arguments to logical inst?");
+  unsigned Op0r = getReg(Op0, MBB, IP);
+  unsigned Op1r = getReg(Op1, MBB, IP);
+  BuildMI(*MBB, IP, Opcode, 2, DestReg).addReg(Op0r).addReg(Op1r);
+    
+  if (isLong) {        // Handle the upper 32 bits of long values...
+    static const unsigned TopTab[] = {
+      X86::ADC32rr, X86::SBB32rr, X86::AND32rr, X86::OR32rr, X86::XOR32rr
+    };
+    BuildMI(*MBB, IP, TopTab[OperatorClass], 2,
+            DestReg+1).addReg(Op0r+1).addReg(Op1r+1);
+  }
 }
 
 /// doMultiply - Emit appropriate instructions to multiply together the
@@ -1895,31 +1964,66 @@
 }
 
 
-/// visitLoadInst - Implement LLVM load instructions in terms of the x86 'mov'
-/// instruction.  The load and store instructions are the only place where we
-/// need to worry about the memory layout of the target machine.
-///
-void ISel::visitLoadInst(LoadInst &I) {
-  unsigned DestReg = getReg(I);
-  unsigned BaseReg = 0, Scale = 1, IndexReg = 0, Disp = 0;
-  Value *Addr = I.getOperand(0);
+void ISel::getAddressingMode(Value *Addr, unsigned &BaseReg, unsigned &Scale,
+                             unsigned &IndexReg, unsigned &Disp) {
+  BaseReg = 0; Scale = 1; IndexReg = 0; Disp = 0;
   if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Addr)) {
     if (isGEPFoldable(BB, GEP->getOperand(0), GEP->op_begin()+1, GEP->op_end(),
                        BaseReg, Scale, IndexReg, Disp))
-      Addr = 0;  // Address is consumed!
+      return;
   } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Addr)) {
     if (CE->getOpcode() == Instruction::GetElementPtr)
       if (isGEPFoldable(BB, CE->getOperand(0), CE->op_begin()+1, CE->op_end(),
                         BaseReg, Scale, IndexReg, Disp))
-        Addr = 0;
+        return;
   }
 
-  if (Addr) {
-    // If it's not foldable, reset addr mode.
-    BaseReg = getReg(Addr);
-    Scale = 1; IndexReg = 0; Disp = 0;
+  // If it's not foldable, reset addr mode.
+  BaseReg = getReg(Addr);
+  Scale = 1; IndexReg = 0; Disp = 0;
+}
+
+
+/// visitLoadInst - Implement LLVM load instructions in terms of the x86 'mov'
+/// instruction.  The load and store instructions are the only place where we
+/// need to worry about the memory layout of the target machine.
+///
+void ISel::visitLoadInst(LoadInst &I) {
+  // Check to see if this load instruction is going to be folded into a binary
+  // instruction, like add.  If so, we don't want to emit it.  Wouldn't a real
+  // pattern matching instruction selector be nice?
+  if (I.hasOneUse() && getClassB(I.getType()) < cFP) {
+    Instruction *User = cast<Instruction>(I.use_back());
+    switch (User->getOpcode()) {
+    default: User = 0; break;
+    case Instruction::Add:
+    case Instruction::Sub:
+    case Instruction::And:
+    case Instruction::Or:
+    case Instruction::Xor:
+      break;
+    }
+
+    if (User) {
+      // Okay, we found a user.  If the load is the first operand and there is
+      // no second operand load, reverse the operand ordering.  Note that this
+      // can fail for a subtract (ie, no change will be made).
+      if (!isa<LoadInst>(User->getOperand(1)))
+        cast<BinaryOperator>(User)->swapOperands();
+      
+      // Okay, now that everything is set up, if this load is used by the second
+      // operand, and if there are no instructions that invalidate the load
+      // before the binary operator, eliminate the load.
+      if (User->getOperand(1) == &I &&
+          isSafeToFoldLoadIntoInstruction(I, *User))
+        return;   // Eliminate the load!
+    }
   }
 
+  unsigned DestReg = getReg(I);
+  unsigned BaseReg = 0, Scale = 1, IndexReg = 0, Disp = 0;
+  getAddressingMode(I.getOperand(0), BaseReg, Scale, IndexReg, Disp);
+
   unsigned Class = getClassB(I.getType());
   if (Class == cLong) {
     addFullAddress(BuildMI(BB, X86::MOV32rm, 4, DestReg),
@@ -1942,24 +2046,8 @@
 /// instruction.
 ///
 void ISel::visitStoreInst(StoreInst &I) {
-  unsigned BaseReg = 0, Scale = 1, IndexReg = 0, Disp = 0;
-  Value *Addr = I.getOperand(1);
-  if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Addr)) {
-    if (isGEPFoldable(BB, GEP->getOperand(0), GEP->op_begin()+1, GEP->op_end(),
-                       BaseReg, Scale, IndexReg, Disp))
-      Addr = 0;  // Address is consumed!
-  } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Addr)) {
-    if (CE->getOpcode() == Instruction::GetElementPtr)
-      if (isGEPFoldable(BB, CE->getOperand(0), CE->op_begin()+1, CE->op_end(),
-                        BaseReg, Scale, IndexReg, Disp))
-        Addr = 0;
-  }
-
-  if (Addr) {
-    // If it's not foldable, reset addr mode.
-    BaseReg = getReg(Addr);
-    Scale = 1; IndexReg = 0; Disp = 0;
-  }
+  unsigned BaseReg, Scale, IndexReg, Disp;
+  getAddressingMode(I.getOperand(1), BaseReg, Scale, IndexReg, Disp);
 
   const Type *ValTy = I.getOperand(0)->getType();
   unsigned Class = getClassB(ValTy);
@@ -2003,8 +2091,9 @@
 }
 
 
-/// visitCastInst - Here we have various kinds of copying with or without
-/// sign extension going on.
+/// visitCastInst - Here we have various kinds of copying with or without sign
+/// extension going on.
+///
 void ISel::visitCastInst(CastInst &CI) {
   Value *Op = CI.getOperand(0);
   // If this is a cast from a 32-bit integer to a Long type, and the only uses
@@ -2028,8 +2117,9 @@
   emitCastOperation(BB, MI, Op, CI.getType(), DestReg);
 }
 
-/// emitCastOperation - Common code shared between visitCastInst and
-/// constant expression cast support.
+/// emitCastOperation - Common code shared between visitCastInst and constant
+/// expression cast support.
+///
 void ISel::emitCastOperation(MachineBasicBlock *BB,
                              MachineBasicBlock::iterator IP,
                              Value *Src, const Type *DestTy,
@@ -2371,7 +2461,8 @@
   }
 }
 
-
+/// visitGetElementPtrInst - instruction-select GEP instructions
+///
 void ISel::visitGetElementPtrInst(GetElementPtrInst &I) {
   // If this GEP instruction will be folded into all of its users, we don't need
   // to explicitly calculate it!


Index: llvm/lib/Target/X86/Printer.cpp
diff -u llvm/lib/Target/X86/Printer.cpp:1.76.2.1 llvm/lib/Target/X86/Printer.cpp:1.76.2.2
--- llvm/lib/Target/X86/Printer.cpp:1.76.2.1	Mon Mar  1 17:58:15 2004
+++ llvm/lib/Target/X86/Printer.cpp	Wed Mar 10 19:01:46 2004
@@ -7,21 +7,23 @@
 // 
 //===----------------------------------------------------------------------===//
 //
-// This file contains a printer that converts from our internal
-// representation of machine-dependent LLVM code to Intel-format
-// assembly language. This printer is the output mechanism used
-// by `llc' and `lli -print-machineinstrs' on X86.
+// This file contains a printer that converts from our internal representation
+// of machine-dependent LLVM code to Intel-format assembly language. This
+// printer is the output mechanism used by `llc' and `lli -print-machineinstrs'
+// on X86.
 //
 //===----------------------------------------------------------------------===//
 
 #include "X86.h"
 #include "X86InstrInfo.h"
+#include "X86TargetMachine.h"
 #include "llvm/Constants.h"
 #include "llvm/DerivedTypes.h"
 #include "llvm/Module.h"
 #include "llvm/Assembly/Writer.h"
-#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineCodeEmitter.h"
 #include "llvm/CodeGen/MachineConstantPool.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
 #include "llvm/CodeGen/MachineInstr.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Support/Mangler.h"
@@ -38,6 +40,37 @@
   cl::opt<bool> EmitCygwin("enable-cygwin-compatible-output", cl::Hidden,
          cl::desc("Emit X86 assembly code suitable for consumption by cygwin"));
 
+  struct GasBugWorkaroundEmitter : public MachineCodeEmitter {
+      GasBugWorkaroundEmitter(std::ostream& o) 
+          : O(o), OldFlags(O.flags()), firstByte(true) {
+          O << std::hex;
+      }
+
+      ~GasBugWorkaroundEmitter() {
+          O.flags(OldFlags);
+          O << "\t# ";
+      }
+
+      virtual void emitByte(unsigned char B) {
+          if (!firstByte) O << "\n\t";
+          firstByte = false;
+          O << ".byte 0x" << (unsigned) B;
+      }
+
+      // These should never be called
+      virtual void emitWord(unsigned W) { assert(0); }
+      virtual uint64_t getGlobalValueAddress(GlobalValue *V) { assert(0); }
+      virtual uint64_t getGlobalValueAddress(const std::string &Name) { assert(0); }
+      virtual uint64_t getConstantPoolEntryAddress(unsigned Index) { assert(0); }
+      virtual uint64_t getCurrentPCValue() { assert(0); }
+      virtual uint64_t forceCompilationOf(Function *F) { assert(0); }
+
+  private:
+      std::ostream& O;
+      std::ios::fmtflags OldFlags;
+      bool firstByte;
+  };
+
   struct Printer : public MachineFunctionPass {
     /// Output stream on which we're printing assembly code.
     ///
@@ -635,6 +668,7 @@
       O << ", ";
       printOp(MI->getOperand(2));
     }
+    checkImplUses(Desc);
     O << "\n";
     return;
   }
@@ -656,6 +690,7 @@
       O << ", ";
       printOp(MI->getOperand(5));
     }
+    checkImplUses(Desc);
     O << "\n";
     return;
   }
@@ -768,82 +803,37 @@
 
     const MachineOperand &Op3 = MI->getOperand(3);
 
-    // Bug: The 80-bit FP store-pop instruction "fstp XWORD PTR [...]"
+    // gas bugs:
+    //
+    // The 80-bit FP store-pop instruction "fstp XWORD PTR [...]"
     // is misassembled by gas in intel_syntax mode as its 32-bit
     // equivalent "fstp DWORD PTR [...]". Workaround: Output the raw
     // opcode bytes instead of the instruction.
-    if (MI->getOpcode() == X86::FSTP80m) {
-      if ((MI->getOperand(0).getReg() == X86::ESP)
-	  && (MI->getOperand(1).getImmedValue() == 1)) {
-        if (Op3.isImmediate() && 
-            Op3.getImmedValue() >= -128 && Op3.getImmedValue() <= 127) {
-          // 1 byte disp.
-          O << ".byte 0xdb, 0x7c, 0x24, 0x" << std::hex
-            << ((unsigned)Op3.getImmedValue() & 255) << std::dec << "\t# ";
-        } else {
-          O << ".byte 0xdb, 0xbc, 0x24\n\t";
-          O << ".long ";
-          printOp(Op3);
-          O << "\t# ";
-	}
-      }
-    }
-
-    // Bug: The 80-bit FP load instruction "fld XWORD PTR [...]" is
+    //
+    // The 80-bit FP load instruction "fld XWORD PTR [...]" is
     // misassembled by gas in intel_syntax mode as its 32-bit
     // equivalent "fld DWORD PTR [...]". Workaround: Output the raw
     // opcode bytes instead of the instruction.
-    if (MI->getOpcode() == X86::FLD80m &&
-        MI->getOperand(0).getReg() == X86::ESP &&
-        MI->getOperand(1).getImmedValue() == 1) {
-      if (Op3.isImmediate() && Op3.getImmedValue() >= -128 &&
-          Op3.getImmedValue() <= 127) {   // 1 byte displacement
-        O << ".byte 0xdb, 0x6c, 0x24, 0x" << std::hex
-          << ((unsigned)Op3.getImmedValue() & 255) << std::dec << "\t# ";
-      } else {
-        O << ".byte 0xdb, 0xac, 0x24\n\t";
-        O << ".long ";
-        printOp(Op3);
-        O << "\t# ";
-      }
-    }
-
-    // Bug: gas intel_syntax mode treats "fild QWORD PTR [...]" as an
+    //
+    // gas intel_syntax mode treats "fild QWORD PTR [...]" as an
     // invalid opcode, saying "64 bit operations are only supported in
     // 64 bit modes." libopcodes disassembles it as "fild DWORD PTR
     // [...]", which is wrong. Workaround: Output the raw opcode bytes
     // instead of the instruction.
-    if (MI->getOpcode() == X86::FILD64m &&
-        MI->getOperand(0).getReg() == X86::ESP &&
-        MI->getOperand(1).getImmedValue() == 1) {
-      if (Op3.isImmediate() && Op3.getImmedValue() >= -128 &&
-          Op3.getImmedValue() <= 127) {   // 1 byte displacement
-        O << ".byte 0xdf, 0x6c, 0x24, 0x" << std::hex
-          << ((unsigned)Op3.getImmedValue() & 255) << std::dec << "\t# ";
-      } else {
-        O << ".byte 0xdf, 0xac, 0x24\n\t";
-        O << ".long ";
-        printOp(Op3);
-        O << std::dec << "\t# ";
-      }
+    //
+    // gas intel_syntax mode treats "fistp QWORD PTR [...]" as an
+    // invalid opcode, saying "64 bit operations are only supported in
+    // 64 bit modes." libopcodes disassembles it as "fistpll DWORD PTR
+    // [...]", which is wrong. Workaround: Output the raw opcode bytes
+    // instead of the instruction.
+    if (MI->getOpcode() == X86::FSTP80m ||
+        MI->getOpcode() == X86::FLD80m ||
+        MI->getOpcode() == X86::FILD64m ||
+        MI->getOpcode() == X86::FISTP64m) {
+        GasBugWorkaroundEmitter gwe(O);
+        X86::emitInstruction(gwe, (X86InstrInfo&)TM.getInstrInfo(), *MI);
     }
 
-    // Bug: gas intel_syntax mode treats "fistp QWORD PTR [...]" as
-    // an invalid opcode, saying "64 bit operations are only
-    // supported in 64 bit modes." libopcodes disassembles it as
-    // "fistpll DWORD PTR [...]", which is wrong. Workaround: Output
-    // "fistpll DWORD PTR " instead, which is what libopcodes is
-    // expecting to see.
-    if (MI->getOpcode() == X86::FISTP64m) {
-      O << "fistpll DWORD PTR ";
-      printMemReference(MI, 0);
-      if (MI->getNumOperands() == 5) {
-	O << ", ";
-	printOp(MI->getOperand(4));
-      }
-      O << "\t# ";
-    }
-    
     O << TII.getName(MI->getOpcode()) << " ";
     O << sizePtr(Desc) << " ";
     printMemReference(MI, 0);
@@ -851,10 +841,10 @@
       O << ", ";
       printOp(MI->getOperand(4));
     }
+    checkImplUses(Desc);
     O << "\n";
     return;
   }
-
   default:
     O << "\tUNKNOWN FORM:\t\t-"; MI->print(O, TM); break;
   }


Index: llvm/lib/Target/X86/X86CodeEmitter.cpp
diff -u llvm/lib/Target/X86/X86CodeEmitter.cpp:1.46.2.1 llvm/lib/Target/X86/X86CodeEmitter.cpp:1.46.2.2
--- llvm/lib/Target/X86/X86CodeEmitter.cpp:1.46.2.1	Mon Mar  1 17:58:15 2004
+++ llvm/lib/Target/X86/X86CodeEmitter.cpp	Wed Mar 10 19:01:46 2004
@@ -168,7 +168,6 @@
 }
 
 
-
 namespace {
   class Emitter : public MachineFunctionPass {
     const X86InstrInfo  *II;
@@ -176,7 +175,9 @@
     std::map<const BasicBlock*, unsigned> BasicBlockAddrs;
     std::vector<std::pair<const BasicBlock*, unsigned> > BBRefs;
   public:
-    Emitter(MachineCodeEmitter &mce) : II(0), MCE(mce) {}
+    explicit Emitter(MachineCodeEmitter &mce) : II(0), MCE(mce) {}
+    Emitter(MachineCodeEmitter &mce, const X86InstrInfo& ii)
+        : II(&ii), MCE(mce) {}
 
     bool runOnMachineFunction(MachineFunction &MF);
 
@@ -184,11 +185,12 @@
       return "X86 Machine Code Emitter";
     }
 
+    void emitInstruction(const MachineInstr &MI);
+
   private:
-    void emitBasicBlock(MachineBasicBlock &MBB);
-    void emitInstruction(MachineInstr &MI);
+    void emitBasicBlock(const MachineBasicBlock &MBB);
 
-    void emitPCRelativeBlockAddress(BasicBlock *BB);
+    void emitPCRelativeBlockAddress(const BasicBlock *BB);
     void emitMaybePCRelativeValue(unsigned Address, bool isPCRelative);
     void emitGlobalAddressForCall(GlobalValue *GV);
     void emitGlobalAddressForPtr(GlobalValue *GV);
@@ -203,6 +205,14 @@
   };
 }
 
+// This function is required by Printer.cpp to workaround gas bugs
+void llvm::X86::emitInstruction(MachineCodeEmitter& mce,
+                                const X86InstrInfo& ii,
+                                const MachineInstr& mi)
+{
+    Emitter(mce, ii).emitInstruction(mi);
+}
+
 /// addPassesToEmitMachineCode - Add passes to the specified pass manager to get
 /// machine code emitted.  This uses a MachineCodeEmitter object to handle
 /// actually outputting the machine code and resolving things like the address
@@ -237,11 +247,11 @@
   return false;
 }
 
-void Emitter::emitBasicBlock(MachineBasicBlock &MBB) {
+void Emitter::emitBasicBlock(const MachineBasicBlock &MBB) {
   if (uint64_t Addr = MCE.getCurrentPCValue())
     BasicBlockAddrs[MBB.getBasicBlock()] = Addr;
 
-  for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ++I)
+  for (MachineBasicBlock::const_iterator I = MBB.begin(), E = MBB.end(); I != E; ++I)
     emitInstruction(*I);
 }
 
@@ -251,7 +261,7 @@
 /// (because this is a forward branch), it keeps track of the information
 /// necessary to resolve this address later (and emits a dummy value).
 ///
-void Emitter::emitPCRelativeBlockAddress(BasicBlock *BB) {
+void Emitter::emitPCRelativeBlockAddress(const BasicBlock *BB) {
   // FIXME: Emit backward branches directly
   BBRefs.push_back(std::make_pair(BB, MCE.getCurrentPCValue()));
   MCE.emitWord(0);   // Emit a dummy value
@@ -476,7 +486,7 @@
   }
 }
 
-void Emitter::emitInstruction(MachineInstr &MI) {
+void Emitter::emitInstruction(const MachineInstr &MI) {
   NumEmitted++;  // Keep track of the # of mi's emitted
 
   unsigned Opcode = MI.getOpcode();
@@ -516,7 +526,7 @@
   case X86II::RawFrm:
     MCE.emitByte(BaseOpcode);
     if (MI.getNumOperands() == 1) {
-      MachineOperand &MO = MI.getOperand(0);
+      const MachineOperand &MO = MI.getOperand(0);
       if (MO.isPCRelativeDisp()) {
         // Conditional branch... FIXME: this should use an MBB destination!
         emitPCRelativeBlockAddress(cast<BasicBlock>(MO.getVRegValue()));
@@ -536,7 +546,7 @@
   case X86II::AddRegFrm:
     MCE.emitByte(BaseOpcode + getX86RegNum(MI.getOperand(0).getReg()));
     if (MI.getNumOperands() == 2) {
-      MachineOperand &MO1 = MI.getOperand(1);
+      const MachineOperand &MO1 = MI.getOperand(1);
       if (Value *V = MO1.getVRegValueOrNull()) {
 	assert(sizeOfImm(Desc) == 4 && "Don't know how to emit non-pointer values!");
         emitGlobalAddressForPtr(cast<GlobalValue>(V));


Index: llvm/lib/Target/X86/X86InstrBuilder.h
diff -u llvm/lib/Target/X86/X86InstrBuilder.h:1.9.4.1 llvm/lib/Target/X86/X86InstrBuilder.h:1.9.4.2
--- llvm/lib/Target/X86/X86InstrBuilder.h:1.9.4.1	Mon Mar  1 17:58:15 2004
+++ llvm/lib/Target/X86/X86InstrBuilder.h	Wed Mar 10 19:01:46 2004
@@ -54,6 +54,7 @@
                                                  unsigned Scale,
                                                  unsigned IndexReg,
                                                  unsigned Disp) {
+  assert (Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8);
   return MIB.addReg(BaseReg).addZImm(Scale).addReg(IndexReg).addSImm(Disp);
 }
 


Index: llvm/lib/Target/X86/X86InstrInfo.td
diff -u llvm/lib/Target/X86/X86InstrInfo.td:1.15.2.1 llvm/lib/Target/X86/X86InstrInfo.td:1.15.2.2
--- llvm/lib/Target/X86/X86InstrInfo.td:1.15.2.1	Mon Mar  1 17:58:15 2004
+++ llvm/lib/Target/X86/X86InstrInfo.td	Wed Mar 10 19:01:46 2004
@@ -53,7 +53,7 @@
 def Mem16  : MemType<2>;
 def Mem32  : MemType<3>;
 def Mem64  : MemType<4>;
-def Mem80  : MemType<4>;
+def Mem80  : MemType<5>;
 def Mem128 : MemType<6>;
 
 // FPFormat - This specifies what form this FP instruction has.  This is used by
@@ -294,9 +294,12 @@
 
 // Conditional moves.  These are modelled as X = cmovXX Y, Z.  Eventually
 // register allocated to cmovXX XY, Z
-def CMOVE16rr : I<"cmove", 0x44, MRMSrcReg>, TB, OpSize;        // if ==, R16 = R16
-def CMOVNE32rr: I<"cmovne",0x45, MRMSrcReg>, TB;                // if !=, R32 = R32
-def CMOVS32rr : I<"cmovs", 0x48, MRMSrcReg>, TB;                // if signed, R32 = R32
+def CMOVE16rr : I   <"cmove", 0x44, MRMSrcReg>, TB, OpSize;        // if ==, R16 = R16
+def CMOVE16rm : Im16<"cmove", 0x44, MRMSrcMem>, TB, OpSize;        // if ==, R16 = [mem16]
+def CMOVNE32rr: I   <"cmovne",0x45, MRMSrcReg>, TB;                // if !=, R32 = R32
+def CMOVNE32rm: Im32<"cmovne",0x45, MRMSrcMem>, TB;                // if !=, R32 = [mem32]
+def CMOVS32rr : I   <"cmovs", 0x48, MRMSrcReg>, TB;                // if signed, R32 = R32
+def CMOVS32rm : Im32<"cmovs", 0x48, MRMSrcMem>, TB;                // if signed, R32 = [mem32]
 
 // unary instructions
 def NEG8r  : I   <"neg", 0xF6, MRM3r>;         // R8  = -R8  = 0-R8
@@ -397,6 +400,7 @@
 def XOR32mi8 : Im32i8<"xor", 0x83, MRM6m     >;            // [mem32] ^= imm8
 
 // Shift instructions
+// FIXME: provide shorter instructions when imm8 == 1
 def SHL8rCL  : I     <"shl", 0xD2, MRM4r     >        , UsesCL; // R8  <<= cl
 def SHL16rCL : I     <"shl", 0xD3, MRM4r     >, OpSize, UsesCL; // R16 <<= cl
 def SHL32rCL : I     <"shl", 0xD3, MRM4r     >        , UsesCL; // R32 <<= cl


Index: llvm/lib/Target/X86/X86RegisterInfo.cpp
diff -u llvm/lib/Target/X86/X86RegisterInfo.cpp:1.40.4.1 llvm/lib/Target/X86/X86RegisterInfo.cpp:1.40.4.2
--- llvm/lib/Target/X86/X86RegisterInfo.cpp:1.40.4.1	Mon Mar  1 17:58:15 2004
+++ llvm/lib/Target/X86/X86RegisterInfo.cpp	Wed Mar 10 19:01:46 2004
@@ -260,6 +260,9 @@
     case X86::MOV8rr:  NI = MakeRMInst(X86::MOV8rm , FrameIndex, MI); break;
     case X86::MOV16rr: NI = MakeRMInst(X86::MOV16rm, FrameIndex, MI); break;
     case X86::MOV32rr: NI = MakeRMInst(X86::MOV32rm, FrameIndex, MI); break;
+    case X86::CMOVE16rr:  NI = MakeRMInst(X86::CMOVE16rm , FrameIndex, MI); break;
+    case X86::CMOVNE32rr: NI = MakeRMInst(X86::CMOVNE32rm, FrameIndex, MI); break;
+    case X86::CMOVS32rr:  NI = MakeRMInst(X86::CMOVS32rm , FrameIndex, MI); break;
     case X86::ADD8rr:  NI = MakeRMInst(X86::ADD8rm , FrameIndex, MI); break;
     case X86::ADD16rr: NI = MakeRMInst(X86::ADD16rm, FrameIndex, MI); break;
     case X86::ADD32rr: NI = MakeRMInst(X86::ADD32rm, FrameIndex, MI); break;


Index: llvm/lib/Target/X86/X86TargetMachine.cpp
diff -u llvm/lib/Target/X86/X86TargetMachine.cpp:1.44.2.1 llvm/lib/Target/X86/X86TargetMachine.cpp:1.44.2.2
--- llvm/lib/Target/X86/X86TargetMachine.cpp:1.44.2.1	Mon Mar  1 17:58:15 2004
+++ llvm/lib/Target/X86/X86TargetMachine.cpp	Wed Mar 10 19:01:46 2004
@@ -25,8 +25,6 @@
 using namespace llvm;
 
 namespace {
-  cl::opt<bool> PrintCode("print-machineinstrs",
-			  cl::desc("Print generated machine code"));
   cl::opt<bool> NoPatternISel("disable-pattern-isel", cl::init(true),
                         cl::desc("Use the 'simple' X86 instruction selector"));
   cl::opt<bool> NoSSAPeephole("disable-ssa-peephole", cl::init(true),
@@ -79,18 +77,18 @@
     PM.add(createX86SSAPeepholeOptimizerPass());
 
   // Print the instruction selected machine code...
-  if (PrintCode)
+  if (PrintMachineCode)
     PM.add(createMachineFunctionPrinterPass(&std::cerr));
 
   // Perform register allocation to convert to a concrete x86 representation
   PM.add(createRegisterAllocator());
 
-  if (PrintCode)
+  if (PrintMachineCode)
     PM.add(createMachineFunctionPrinterPass(&std::cerr));
 
   PM.add(createX86FloatingPointStackifierPass());
 
-  if (PrintCode)
+  if (PrintMachineCode)
     PM.add(createMachineFunctionPrinterPass(&std::cerr));
 
   // Insert prolog/epilog code.  Eliminate abstract frame index references...
@@ -98,7 +96,7 @@
 
   PM.add(createX86PeepholeOptimizerPass());
 
-  if (PrintCode)  // Print the register-allocated code
+  if (PrintMachineCode)  // Print the register-allocated code
     PM.add(createX86CodePrinterPass(std::cerr, *this));
 
   if (!DisableOutput)
@@ -138,18 +136,18 @@
   // FIXME: Add SSA based peephole optimizer here.
 
   // Print the instruction selected machine code...
-  if (PrintCode)
+  if (PrintMachineCode)
     PM.add(createMachineFunctionPrinterPass(&std::cerr));
 
   // Perform register allocation to convert to a concrete x86 representation
   PM.add(createRegisterAllocator());
 
-  if (PrintCode)
+  if (PrintMachineCode)
     PM.add(createMachineFunctionPrinterPass(&std::cerr));
 
   PM.add(createX86FloatingPointStackifierPass());
 
-  if (PrintCode)
+  if (PrintMachineCode)
     PM.add(createMachineFunctionPrinterPass(&std::cerr));
 
   // Insert prolog/epilog code.  Eliminate abstract frame index references...
@@ -157,7 +155,7 @@
 
   PM.add(createX86PeepholeOptimizerPass());
 
-  if (PrintCode)  // Print the register-allocated code
+  if (PrintMachineCode)  // Print the register-allocated code
     PM.add(createX86CodePrinterPass(std::cerr, TM));
 }
 


Index: llvm/lib/Target/X86/X86TargetMachine.h
diff -u llvm/lib/Target/X86/X86TargetMachine.h:1.21.2.1 llvm/lib/Target/X86/X86TargetMachine.h:1.21.2.2
--- llvm/lib/Target/X86/X86TargetMachine.h:1.21.2.1	Mon Mar  1 17:58:15 2004
+++ llvm/lib/Target/X86/X86TargetMachine.h	Wed Mar 10 19:01:46 2004
@@ -53,6 +53,13 @@
   virtual bool addPassesToEmitAssembly(PassManager &PM, std::ostream &Out);
 };
 
+  // this is implemented in X86CodeEmitter.cpp
+  namespace X86 {
+    void emitInstruction(MachineCodeEmitter& mce,
+                         const X86InstrInfo& ii,
+                         const MachineInstr& MI);
+  }
+
 } // End llvm namespace
 
 #endif





More information about the llvm-commits mailing list