Factory methods for FunctionPasses now return type FunctionPass *.
[oota-llvm.git] / lib / Target / X86 / InstSelectSimple.cpp
index 6b2ba396805fd955ee2b950bd979d8e143e7de8c..2cc4e8367dfbdb5114695d258fcc86a7f6ea3a64 100644 (file)
@@ -8,12 +8,7 @@
 #include "X86InstrInfo.h"
 #include "X86InstrBuilder.h"
 #include "llvm/Function.h"
-#include "llvm/iTerminators.h"
-#include "llvm/iOperators.h"
-#include "llvm/iOther.h"
-#include "llvm/iPHINode.h"
-#include "llvm/iMemory.h"
-#include "llvm/Type.h"
+#include "llvm/Instructions.h"
 #include "llvm/DerivedTypes.h"
 #include "llvm/Constants.h"
 #include "llvm/Pass.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineConstantPool.h"
 #include "llvm/Target/TargetMachine.h"
-#include "llvm/Support/InstVisitor.h"
 #include "llvm/Target/MRegisterInfo.h"
-#include <map>
+#include "llvm/Support/InstVisitor.h"
 
 /// BMI - A special BuildMI variant that takes an iterator to insert the
 /// instruction at as well as a basic block.  This is the version for when you
 /// have a destination register in mind.
 inline static MachineInstrBuilder BMI(MachineBasicBlock *MBB,
                                       MachineBasicBlock::iterator &I,
-                                      MachineOpCode Opcode,
-                                      unsigned NumOperands,
+                                      int Opcode, unsigned NumOperands,
                                       unsigned DestReg) {
   assert(I >= MBB->begin() && I <= MBB->end() && "Bad iterator!");
   MachineInstr *MI = new MachineInstr(Opcode, NumOperands+1, true, true);
@@ -46,8 +39,7 @@ inline static MachineInstrBuilder BMI(MachineBasicBlock *MBB,
 /// instruction at as well as a basic block.
 inline static MachineInstrBuilder BMI(MachineBasicBlock *MBB,
                                       MachineBasicBlock::iterator &I,
-                                      MachineOpCode Opcode,
-                                      unsigned NumOperands) {
+                                      int Opcode, unsigned NumOperands) {
   assert(I >= MBB->begin() && I <= MBB->end() && "Bad iterator!");
   MachineInstr *MI = new MachineInstr(Opcode, NumOperands, true, true);
   I = MBB->insert(I, MI)+1;
@@ -93,7 +85,8 @@ namespace {
       RegMap.clear();
       MBBMap.clear();
       F = 0;
-      return false;  // We never modify the LLVM itself.
+      // We always build a machine code representation for the function
+      return true;
     }
 
     virtual const char *getPassName() const {
@@ -129,9 +122,11 @@ namespace {
     void visitBranchInst(BranchInst &BI);
 
     struct ValueRecord {
+      Value *Val;
       unsigned Reg;
       const Type *Ty;
-      ValueRecord(unsigned R, const Type *T) : Reg(R), Ty(T) {}
+      ValueRecord(unsigned R, const Type *T) : Val(0), Reg(R), Ty(T) {}
+      ValueRecord(Value *V) : Val(V), Reg(0), Ty(V->getType()) {}
     };
     void doCall(const ValueRecord &Ret, MachineInstr *CallMI,
                const std::vector<ValueRecord> &Args);
@@ -226,9 +221,12 @@ namespace {
     /// of the long value.
     ///
     unsigned makeAnotherReg(const Type *Ty) {
+      assert(dynamic_cast<const X86RegisterInfo*>(TM.getRegisterInfo()) &&
+             "Current target doesn't have X86 reg info??");
+      const X86RegisterInfo *MRI =
+        static_cast<const X86RegisterInfo*>(TM.getRegisterInfo());
       if (Ty == Type::LongTy || Ty == Type::ULongTy) {
-       const TargetRegisterClass *RC =
-         TM.getRegisterInfo()->getRegClassForType(Type::IntTy);
+       const TargetRegisterClass *RC = MRI->getRegClassForType(Type::IntTy);
        // Create the lower part
        F->getSSARegMap()->createVirtualRegister(RC);
        // Create the upper part.
@@ -236,8 +234,7 @@ namespace {
       }
 
       // Add the mapping of regnumber => reg class to MachineFunction
-      const TargetRegisterClass *RC =
-       TM.getRegisterInfo()->getRegClassForType(Ty);
+      const TargetRegisterClass *RC = MRI->getRegClassForType(Ty);
       return F->getSSARegMap()->createVirtualRegister(RC);
     }
 
@@ -351,12 +348,7 @@ void ISel::copyConstantToRegister(MachineBasicBlock *MBB,
 
     if (Class == cLong) {
       // Copy the value into the register pair.
-      uint64_t Val;
-      if (C->getType()->isSigned())
-       Val = cast<ConstantSInt>(C)->getValue();
-      else
-       Val = cast<ConstantUInt>(C)->getValue();
-
+      uint64_t Val = cast<ConstantInt>(C)->getRawValue();
       BMI(MBB, IP, X86::MOVir32, 1, R).addZImm(Val & 0xFFFFFFFF);
       BMI(MBB, IP, X86::MOVir32, 1, R+1).addZImm(Val >> 32);
       return;
@@ -370,12 +362,9 @@ void ISel::copyConstantToRegister(MachineBasicBlock *MBB,
 
     if (C->getType() == Type::BoolTy) {
       BMI(MBB, IP, X86::MOVir8, 1, R).addZImm(C == ConstantBool::True);
-    } else if (C->getType()->isSigned()) {
-      ConstantSInt *CSI = cast<ConstantSInt>(C);
-      BMI(MBB, IP, IntegralOpcodeTab[Class], 1, R).addZImm(CSI->getValue());
     } else {
-      ConstantUInt *CUI = cast<ConstantUInt>(C);
-      BMI(MBB, IP, IntegralOpcodeTab[Class], 1, R).addZImm(CUI->getValue());
+      ConstantInt *CI = cast<ConstantInt>(C);
+      BMI(MBB, IP, IntegralOpcodeTab[Class], 1, R).addZImm(CI->getRawValue());
     }
   } else if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
     double Value = CFP->getValue();
@@ -587,26 +576,44 @@ bool ISel::EmitComparisonGetSignedness(unsigned OpNum, Value *Op0, Value *Op1) {
   // The arguments are already supposed to be of the same type.
   const Type *CompTy = Op0->getType();
   bool isSigned = CompTy->isSigned();
-  unsigned reg1 = getReg(Op0);
-  unsigned reg2 = getReg(Op1);
-
   unsigned Class = getClassB(CompTy);
+  unsigned Op0r = getReg(Op0);
+
+  // Special case handling of: cmp R, i
+  if (Class == cByte || Class == cShort || Class == cInt)
+    if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
+      uint64_t Op1v = cast<ConstantInt>(CI)->getRawValue();
+
+      // Mask off any upper bits of the constant, if there are any...
+      Op1v &= (1ULL << (8 << Class)) - 1;
+
+      switch (Class) {
+      case cByte:  BuildMI(BB, X86::CMPri8, 2).addReg(Op0r).addZImm(Op1v);break;
+      case cShort: BuildMI(BB, X86::CMPri16,2).addReg(Op0r).addZImm(Op1v);break;
+      case cInt:   BuildMI(BB, X86::CMPri32,2).addReg(Op0r).addZImm(Op1v);break;
+      default:
+        assert(0 && "Invalid class!");
+      }
+      return isSigned;
+    }
+
+  unsigned Op1r = getReg(Op1);
   switch (Class) {
   default: assert(0 && "Unknown type class!");
     // 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.
   case cByte:
-    BuildMI(BB, X86::CMPrr8, 2).addReg(reg1).addReg(reg2);
+    BuildMI(BB, X86::CMPrr8, 2).addReg(Op0r).addReg(Op1r);
     break;
   case cShort:
-    BuildMI(BB, X86::CMPrr16, 2).addReg(reg1).addReg(reg2);
+    BuildMI(BB, X86::CMPrr16, 2).addReg(Op0r).addReg(Op1r);
     break;
   case cInt:
-    BuildMI(BB, X86::CMPrr32, 2).addReg(reg1).addReg(reg2);
+    BuildMI(BB, X86::CMPrr32, 2).addReg(Op0r).addReg(Op1r);
     break;
   case cFP:
-    BuildMI(BB, X86::FpUCOM, 2).addReg(reg1).addReg(reg2);
+    BuildMI(BB, X86::FpUCOM, 2).addReg(Op0r).addReg(Op1r);
     BuildMI(BB, X86::FNSTSWr8, 0);
     BuildMI(BB, X86::SAHF, 1);
     isSigned = false;   // Compare with unsigned operators
@@ -617,8 +624,8 @@ bool ISel::EmitComparisonGetSignedness(unsigned OpNum, Value *Op0, Value *Op1) {
       unsigned LoTmp = makeAnotherReg(Type::IntTy);
       unsigned HiTmp = makeAnotherReg(Type::IntTy);
       unsigned FinalTmp = makeAnotherReg(Type::IntTy);
-      BuildMI(BB, X86::XORrr32, 2, LoTmp).addReg(reg1).addReg(reg2);
-      BuildMI(BB, X86::XORrr32, 2, HiTmp).addReg(reg1+1).addReg(reg2+1);
+      BuildMI(BB, X86::XORrr32, 2, LoTmp).addReg(Op0r).addReg(Op1r);
+      BuildMI(BB, X86::XORrr32, 2, HiTmp).addReg(Op0r+1).addReg(Op1r+1);
       BuildMI(BB, X86::ORrr32,  2, FinalTmp).addReg(LoTmp).addReg(HiTmp);
       break;  // Allow the sete or setne to be generated from flags set by OR
     } else {
@@ -635,10 +642,12 @@ bool ISel::EmitComparisonGetSignedness(unsigned OpNum, Value *Op0, Value *Op1) {
       // classes!  Until then, hardcode registers so that we can deal with their
       // aliases (because we don't have conditional byte moves).
       //
-      BuildMI(BB, X86::CMPrr32, 2).addReg(reg1).addReg(reg2);
+      BuildMI(BB, X86::CMPrr32, 2).addReg(Op0r).addReg(Op1r);
       BuildMI(BB, SetCCOpcodeTab[0][OpNum], 0, X86::AL);
-      BuildMI(BB, X86::CMPrr32, 2).addReg(reg1+1).addReg(reg2+1);
+      BuildMI(BB, X86::CMPrr32, 2).addReg(Op0r+1).addReg(Op1r+1);
       BuildMI(BB, SetCCOpcodeTab[isSigned][OpNum], 0, X86::BL);
+      BuildMI(BB, X86::IMPLICIT_DEF, 0, X86::BH);
+      BuildMI(BB, X86::IMPLICIT_DEF, 0, X86::AH);
       BuildMI(BB, X86::CMOVErr16, 2, X86::BX).addReg(X86::BX).addReg(X86::AX);
       // NOTE: visitSetCondInst knows that the value is dumped into the BL
       // register at this point for long values...
@@ -674,24 +683,28 @@ void ISel::visitSetCondInst(SetCondInst &I) {
 /// operand, in the specified target register.
 void ISel::promote32(unsigned targetReg, const ValueRecord &VR) {
   bool isUnsigned = VR.Ty->isUnsigned();
+
+  // Make sure we have the register number for this value...
+  unsigned Reg = VR.Val ? getReg(VR.Val) : VR.Reg;
+
   switch (getClassB(VR.Ty)) {
   case cByte:
     // Extend value into target register (8->32)
     if (isUnsigned)
-      BuildMI(BB, X86::MOVZXr32r8, 1, targetReg).addReg(VR.Reg);
+      BuildMI(BB, X86::MOVZXr32r8, 1, targetReg).addReg(Reg);
     else
-      BuildMI(BB, X86::MOVSXr32r8, 1, targetReg).addReg(VR.Reg);
+      BuildMI(BB, X86::MOVSXr32r8, 1, targetReg).addReg(Reg);
     break;
   case cShort:
     // Extend value into target register (16->32)
     if (isUnsigned)
-      BuildMI(BB, X86::MOVZXr32r16, 1, targetReg).addReg(VR.Reg);
+      BuildMI(BB, X86::MOVZXr32r16, 1, targetReg).addReg(Reg);
     else
-      BuildMI(BB, X86::MOVSXr32r16, 1, targetReg).addReg(VR.Reg);
+      BuildMI(BB, X86::MOVSXr32r16, 1, targetReg).addReg(Reg);
     break;
   case cInt:
     // Move value into target register (32->32)
-    BuildMI(BB, X86::MOVrr32, 1, targetReg).addReg(VR.Reg);
+    BuildMI(BB, X86::MOVrr32, 1, targetReg).addReg(Reg);
     break;
   default:
     assert(0 && "Unpromotable operand class in promote32");
@@ -843,7 +856,7 @@ void ISel::doCall(const ValueRecord &Ret, MachineInstr *CallMI,
     // Arguments go on the stack in reverse order, as specified by the ABI.
     unsigned ArgOffset = 0;
     for (unsigned i = 0, e = Args.size(); i != e; ++i) {
-      unsigned ArgReg = Args[i].Reg;
+      unsigned ArgReg = Args[i].Val ? getReg(Args[i].Val) : Args[i].Reg;
       switch (getClassB(Args[i].Ty)) {
       case cByte:
       case cShort: {
@@ -940,8 +953,7 @@ void ISel::visitCallInst(CallInst &CI) {
 
   std::vector<ValueRecord> Args;
   for (unsigned i = 1, e = CI.getNumOperands(); i != e; ++i)
-    Args.push_back(ValueRecord(getReg(CI.getOperand(i)),
-                              CI.getOperand(i)->getType()));
+    Args.push_back(ValueRecord(CI.getOperand(i)));
 
   unsigned DestReg = CI.getType() != Type::VoidTy ? getReg(CI) : 0;
   doCall(ValueRecord(DestReg, CI.getType()), TheCall, Args);
@@ -965,6 +977,14 @@ void ISel::visitIntrinsicCall(LLVMIntrinsic::ID ID, CallInst &CI) {
     addDirectMem(BuildMI(BB, X86::MOVrm32, 5), TmpReg2).addReg(TmpReg1);
     return;
 
+  case LLVMIntrinsic::longjmp:
+    BuildMI(X86::CALLpcrel32, 1).addExternalSymbol("abort", true); 
+    return;
+
+  case LLVMIntrinsic::setjmp:
+    // Setjmp always returns zero...
+    BuildMI(BB, X86::MOVir32, 1, getReg(CI)).addZImm(0);
+    return;
   default: assert(0 && "Unknown intrinsic for X86!");
   }
 }
@@ -991,36 +1011,60 @@ void ISel::emitSimpleBinaryOperation(MachineBasicBlock *BB,
                                      Value *Op0, Value *Op1,
                                      unsigned OperatorClass,unsigned TargetReg){
   unsigned Class = getClassB(Op0->getType());
+  if (!isa<ConstantInt>(Op1) || Class == cLong) {
+    static const unsigned OpcodeTab[][4] = {
+      // Arithmetic operators
+      { X86::ADDrr8, X86::ADDrr16, X86::ADDrr32, X86::FpADD },  // ADD
+      { X86::SUBrr8, X86::SUBrr16, X86::SUBrr32, X86::FpSUB },  // SUB
+      
+      // Bitwise operators
+      { X86::ANDrr8, X86::ANDrr16, X86::ANDrr32, 0 },  // AND
+      { X86:: ORrr8, X86:: ORrr16, X86:: ORrr32, 0 },  // OR
+      { X86::XORrr8, X86::XORrr16, X86::XORrr32, 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?");
+    unsigned Op0r = getReg(Op0, BB, IP);
+    unsigned Op1r = getReg(Op1, BB, IP);
+    BMI(BB, IP, Opcode, 2, TargetReg).addReg(Op0r).addReg(Op1r);
+    
+    if (isLong) {        // Handle the upper 32 bits of long values...
+      static const unsigned TopTab[] = {
+        X86::ADCrr32, X86::SBBrr32, X86::ANDrr32, X86::ORrr32, X86::XORrr32
+      };
+      BMI(BB, IP, TopTab[OperatorClass], 2,
+          TargetReg+1).addReg(Op0r+1).addReg(Op1r+1);
+    }
+  } else {
+    // Special case: op Reg, <const>
+    ConstantInt *Op1C = cast<ConstantInt>(Op1);
 
-  static const unsigned OpcodeTab[][4] = {
-    // Arithmetic operators
-    { X86::ADDrr8, X86::ADDrr16, X86::ADDrr32, X86::FpADD },  // ADD
-    { X86::SUBrr8, X86::SUBrr16, X86::SUBrr32, X86::FpSUB },  // SUB
+    static const unsigned OpcodeTab[][3] = {
+      // Arithmetic operators
+      { X86::ADDri8, X86::ADDri16, X86::ADDri32 },  // ADD
+      { X86::SUBri8, X86::SUBri16, X86::SUBri32 },  // SUB
+      
+      // Bitwise operators
+      { X86::ANDri8, X86::ANDri16, X86::ANDri32 },  // AND
+      { X86:: ORri8, X86:: ORri16, X86:: ORri32 },  // OR
+      { X86::XORri8, X86::XORri16, X86::XORri32 },  // XOR
+    };
 
-    // Bitwise operators
-    { X86::ANDrr8, X86::ANDrr16, X86::ANDrr32, 0 },  // AND
-    { X86:: ORrr8, X86:: ORrr16, X86:: ORrr32, 0 },  // OR
-    { X86::XORrr8, X86::XORrr16, X86::XORrr32, 0 },  // XOR
-  };
+    assert(Class < 3 && "General code handles 64-bit integer types!");
+    unsigned Opcode = OpcodeTab[OperatorClass][Class];
+    unsigned Op0r = getReg(Op0, BB, IP);
+    uint64_t Op1v = cast<ConstantInt>(Op1C)->getRawValue();
 
-  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?");
-  unsigned Op0r = getReg(Op0, BB, IP);
-  unsigned Op1r = getReg(Op1, BB, IP);
-  BMI(BB, IP, Opcode, 2, TargetReg).addReg(Op0r).addReg(Op1r);
-
-  if (isLong) {        // Handle the upper 32 bits of long values...
-    static const unsigned TopTab[] = {
-      X86::ADCrr32, X86::SBBrr32, X86::ANDrr32, X86::ORrr32, X86::XORrr32
-    };
-    BMI(BB, IP, TopTab[OperatorClass], 2,
-        TargetReg+1).addReg(Op0r+1).addReg(Op1r+1);
+    // Mask off any upper bits of the constant, if there are any...
+    Op1v &= (1ULL << (8 << Class)) - 1;
+    BMI(BB, IP, Opcode, 2, TargetReg).addReg(Op0r).addZImm(Op1v);
   }
 }
 
@@ -1028,8 +1072,6 @@ void ISel::emitSimpleBinaryOperation(MachineBasicBlock *BB,
 /// registers op0Reg and op1Reg, and put the result in DestReg.  The type of the
 /// result should be given as DestTy.
 ///
-/// FIXME: doMultiply should use one of the two address IMUL instructions!
-///
 void ISel::doMultiply(MachineBasicBlock *MBB, MachineBasicBlock::iterator &MBBI,
                       unsigned DestReg, const Type *DestTy,
                       unsigned op0Reg, unsigned op1Reg) {
@@ -1038,28 +1080,20 @@ void ISel::doMultiply(MachineBasicBlock *MBB, MachineBasicBlock::iterator &MBBI,
   case cFP:              // Floating point multiply
     BMI(BB, MBBI, X86::FpMUL, 2, DestReg).addReg(op0Reg).addReg(op1Reg);
     return;
+  case cInt:
+  case cShort:
+    BMI(BB, MBBI, Class == cInt ? X86::IMULr32 : X86::IMULr16, 2, DestReg)
+      .addReg(op0Reg).addReg(op1Reg);
+    return;
+  case cByte:
+    // Must use the MUL instruction, which forces use of AL...
+    BMI(MBB, MBBI, X86::MOVrr8, 1, X86::AL).addReg(op0Reg);
+    BMI(MBB, MBBI, X86::MULr8, 1).addReg(op1Reg);
+    BMI(MBB, MBBI, X86::MOVrr8, 1, DestReg).addReg(X86::AL);
+    return;
   default:
   case cLong: assert(0 && "doMultiply cannot operate on LONG values!");
-  case cByte:
-  case cShort:
-  case cInt:          // Small integerals, handled below...
-    break;
   }
-  static const unsigned Regs[]     ={ X86::AL    , X86::AX     , X86::EAX     };
-  static const unsigned MulOpcode[]={ X86::MULr8 , X86::MULr16 , X86::MULr32  };
-  static const unsigned MovOpcode[]={ X86::MOVrr8, X86::MOVrr16, X86::MOVrr32 };
-  unsigned Reg     = Regs[Class];
-
-  // Emit a MOV to put the first operand into the appropriately-sized
-  // subreg of EAX.
-  BMI(MBB, MBBI, MovOpcode[Class], 1, Reg).addReg(op0Reg);
-  
-  // Emit the appropriate multiply instruction.
-  BMI(MBB, MBBI, MulOpcode[Class], 1).addReg(op1Reg);
-
-  // Emit another MOV to put the result into the destination register.
-  BMI(MBB, MBBI, MovOpcode[Class], 1, DestReg).addReg(Reg);
 }
 
 /// visitMul - Multiplies are not simple binary operators because they must deal
@@ -1085,16 +1119,16 @@ void ISel::visitMul(BinaryOperator &I) {
     BuildMI(BB, X86::MOVrr32, 1, OverflowReg).addReg(X86::EDX); // AL*BL >> 32
 
     MachineBasicBlock::iterator MBBI = BB->end();
-    unsigned AHBLReg = makeAnotherReg(Type::UIntTy);
-    doMultiply(BB, MBBI, AHBLReg, Type::UIntTy, Op0Reg+1, Op1Reg); // AH*BL
+    unsigned AHBLReg = makeAnotherReg(Type::UIntTy);   // AH*BL
+    BMI(BB, MBBI, X86::IMULr32, 2, AHBLReg).addReg(Op0Reg+1).addReg(Op1Reg);
 
     unsigned AHBLplusOverflowReg = makeAnotherReg(Type::UIntTy);
     BuildMI(BB, X86::ADDrr32, 2,                         // AH*BL+(AL*BL >> 32)
            AHBLplusOverflowReg).addReg(AHBLReg).addReg(OverflowReg);
     
     MBBI = BB->end();
-    unsigned ALBHReg = makeAnotherReg(Type::UIntTy);
-    doMultiply(BB, MBBI, ALBHReg, Type::UIntTy, Op0Reg, Op1Reg+1); // AL*BH
+    unsigned ALBHReg = makeAnotherReg(Type::UIntTy); // AL*BH
+    BMI(BB, MBBI, X86::IMULr32, 2, ALBHReg).addReg(Op0Reg).addReg(Op1Reg+1);
     
     BuildMI(BB, X86::ADDrr32, 2,               // AL*BH + AH*BL + (AL*BL >> 32)
            DestReg+1).addReg(AHBLplusOverflowReg).addReg(ALBHReg);
@@ -1108,21 +1142,21 @@ void ISel::visitMul(BinaryOperator &I) {
 /// instructions work differently for signed and unsigned operands.
 ///
 void ISel::visitDivRem(BinaryOperator &I) {
-  unsigned Class     = getClass(I.getType());
-  unsigned Op0Reg    = getReg(I.getOperand(0));
-  unsigned Op1Reg    = getReg(I.getOperand(1));
-  unsigned ResultReg = getReg(I);
+  unsigned Class = getClass(I.getType());
+  unsigned Op0Reg, Op1Reg, ResultReg = getReg(I);
 
   switch (Class) {
   case cFP:              // Floating point divide
-    if (I.getOpcode() == Instruction::Div)
+    if (I.getOpcode() == Instruction::Div) {
+      Op0Reg = getReg(I.getOperand(0));
+      Op1Reg = getReg(I.getOperand(1));
       BuildMI(BB, X86::FpDIV, 2, ResultReg).addReg(Op0Reg).addReg(Op1Reg);
-    else {               // Floating point remainder...
+    else {               // Floating point remainder...
       MachineInstr *TheCall =
        BuildMI(X86::CALLpcrel32, 1).addExternalSymbol("fmod", true);
       std::vector<ValueRecord> Args;
-      Args.push_back(ValueRecord(Op0Reg, Type::DoubleTy));
-      Args.push_back(ValueRecord(Op1Reg, Type::DoubleTy));
+      Args.push_back(ValueRecord(I.getOperand(0)));
+      Args.push_back(ValueRecord(I.getOperand(1)));
       doCall(ValueRecord(ResultReg, Type::DoubleTy), TheCall, Args);
     }
     return;
@@ -1136,8 +1170,8 @@ void ISel::visitDivRem(BinaryOperator &I) {
       BuildMI(X86::CALLpcrel32, 1).addExternalSymbol(FnName[NameIdx], true);
 
     std::vector<ValueRecord> Args;
-    Args.push_back(ValueRecord(Op0Reg, Type::LongTy));
-    Args.push_back(ValueRecord(Op1Reg, Type::LongTy));
+    Args.push_back(ValueRecord(I.getOperand(0)));
+    Args.push_back(ValueRecord(I.getOperand(1)));
     doCall(ValueRecord(ResultReg, Type::LongTy), TheCall, Args);
     return;
   }
@@ -1148,7 +1182,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::CDQ     };
+  static const unsigned SarOpcode[]={ X86::SARir8, X86::SARir16, X86::SARir32 };
   static const unsigned ClrOpcode[]={ X86::XORrr8, X86::XORrr16, X86::XORrr32 };
   static const unsigned ExtRegs[]  ={ X86::AH    , X86::DX     , X86::EDX     };
 
@@ -1162,17 +1196,21 @@ void ISel::visitDivRem(BinaryOperator &I) {
   unsigned ExtReg = ExtRegs[Class];
 
   // Put the first operand into one of the A registers...
+  Op0Reg = getReg(I.getOperand(0));
   BuildMI(BB, MovOpcode[Class], 1, Reg).addReg(Op0Reg);
 
   if (isSigned) {
     // Emit a sign extension instruction...
-    BuildMI(BB, ExtOpcode[Class], 0);
+    unsigned ShiftResult = makeAnotherReg(I.getType());
+    BuildMI(BB, SarOpcode[Class], 2, ShiftResult).addReg(Op0Reg).addZImm(31);
+    BuildMI(BB, MovOpcode[Class], 1, ExtReg).addReg(ShiftResult);
   } else {
     // If unsigned, emit a zeroing instruction... (reg = xor reg, reg)
     BuildMI(BB, ClrOpcode[Class], 2, ExtReg).addReg(ExtReg).addReg(ExtReg);
   }
 
   // Emit the appropriate divide or remainder instruction...
+  Op1Reg = getReg(I.getOperand(1));
   BuildMI(BB, DivOpcode[isSigned][Class], 1).addReg(Op1Reg);
 
   // Figure out which register we want to pick the result out of...
@@ -1239,7 +1277,57 @@ void ISel::visitShiftInst(ShiftInst &I) {
        }
       }
     } else {
-      visitInstruction(I);  // FIXME: Implement long shift by non-constant
+      unsigned TmpReg = makeAnotherReg(Type::IntTy);
+
+      if (!isLeftShift && isSigned) {
+        // If this is a SHR of a Long, then we need to do funny sign extension
+        // stuff.  TmpReg gets the value to use as the high-part if we are
+        // shifting more than 32 bits.
+        BuildMI(BB, X86::SARir32, 2, TmpReg).addReg(SrcReg).addZImm(31);
+      } else {
+        // Other shifts use a fixed zero value if the shift is more than 32
+        // bits.
+        BuildMI(BB, X86::MOVir32, 1, TmpReg).addZImm(0);
+      }
+
+      // Initialize CL with the shift amount...
+      unsigned ShiftAmount = getReg(I.getOperand(1));
+      BuildMI(BB, X86::MOVrr8, 1, X86::CL).addReg(ShiftAmount);
+
+      unsigned TmpReg2 = makeAnotherReg(Type::IntTy);
+      unsigned TmpReg3 = makeAnotherReg(Type::IntTy);
+      if (isLeftShift) {
+        // TmpReg2 = shld inHi, inLo
+        BuildMI(BB, X86::SHLDrr32, 2, TmpReg2).addReg(SrcReg+1).addReg(SrcReg);
+        // TmpReg3 = shl  inLo, CL
+        BuildMI(BB, X86::SHLrr32, 1, TmpReg3).addReg(SrcReg);
+
+        // Set the flags to indicate whether the shift was by more than 32 bits.
+        BuildMI(BB, X86::TESTri8, 2).addReg(X86::CL).addZImm(32);
+
+        // DestHi = (>32) ? TmpReg3 : TmpReg2;
+        BuildMI(BB, X86::CMOVNErr32, 2, 
+                DestReg+1).addReg(TmpReg2).addReg(TmpReg3);
+        // DestLo = (>32) ? TmpReg : TmpReg3;
+        BuildMI(BB, X86::CMOVNErr32, 2, DestReg).addReg(TmpReg3).addReg(TmpReg);
+      } else {
+        // TmpReg2 = shrd inLo, inHi
+        BuildMI(BB, X86::SHRDrr32, 2, TmpReg2).addReg(SrcReg).addReg(SrcReg+1);
+        // TmpReg3 = s[ah]r  inHi, CL
+        BuildMI(BB, isSigned ? X86::SARrr32 : X86::SHRrr32, 1, TmpReg3)
+                       .addReg(SrcReg+1);
+
+        // Set the flags to indicate whether the shift was by more than 32 bits.
+        BuildMI(BB, X86::TESTri8, 2).addReg(X86::CL).addZImm(32);
+
+        // DestLo = (>32) ? TmpReg3 : TmpReg2;
+        BuildMI(BB, X86::CMOVNErr32, 2, 
+                DestReg).addReg(TmpReg2).addReg(TmpReg3);
+
+        // DestHi = (>32) ? TmpReg : TmpReg3;
+        BuildMI(BB, X86::CMOVNErr32, 2, 
+                DestReg+1).addReg(TmpReg3).addReg(TmpReg);
+      }
     }
     return;
   }
@@ -1344,7 +1432,7 @@ void ISel::visitLoadInst(LoadInst &I) {
   unsigned SrcAddrReg = getReg(I.getOperand(0));
   unsigned DestReg = getReg(I);
 
-  unsigned Class = getClass(I.getType());
+  unsigned Class = getClassB(I.getType());
   switch (Class) {
   case cFP: {
     MachineBasicBlock::iterator MBBI = BB->end();
@@ -1444,7 +1532,7 @@ void ISel::visitStoreInst(StoreInst &I) {
   unsigned ValReg      = getReg(I.getOperand(0));
   unsigned AddressReg  = getReg(I.getOperand(1));
 
-  unsigned Class = getClass(I.getOperand(0)->getType());
+  unsigned Class = getClassB(I.getOperand(0)->getType());
   switch (Class) {
   case cLong:
     if (isLittleEndian) {
@@ -1489,9 +1577,26 @@ void ISel::visitStoreInst(StoreInst &I) {
 /// 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
+  // of the case are GEP instructions, then the cast does not need to be
+  // generated explicitly, it will be folded into the GEP.
+  if (CI.getType() == Type::LongTy &&
+      (Op->getType() == Type::IntTy || Op->getType() == Type::UIntTy)) {
+    bool AllUsesAreGEPs = true;
+    for (Value::use_iterator I = CI.use_begin(), E = CI.use_end(); I != E; ++I)
+      if (!isa<GetElementPtrInst>(*I)) {
+        AllUsesAreGEPs = false;
+        break;
+      }        
+
+    // No need to codegen this cast if all users are getelementptr instrs...
+    if (AllUsesAreGEPs) return;
+  }
+
   unsigned DestReg = getReg(CI);
   MachineBasicBlock::iterator MI = BB->end();
-  emitCastOperation(BB, MI, CI.getOperand(0), CI.getType(), DestReg);
+  emitCastOperation(BB, MI, Op, CI.getType(), DestReg);
 }
 
 /// emitCastOperation - Common code shared between visitCastInst and
@@ -1508,10 +1613,28 @@ void ISel::emitCastOperation(MachineBasicBlock *BB,
   // Implement casts to bool by using compare on the operand followed by set if
   // not zero on the result.
   if (DestTy == Type::BoolTy) {
-    if (SrcClass == cFP || SrcClass == cLong)
-      abort();  // FIXME: implement cast (long & FP) to bool
-    
-    BMI(BB, IP, X86::CMPri8, 2).addReg(SrcReg).addZImm(0);
+    switch (SrcClass) {
+    case cByte:
+      BMI(BB, IP, X86::TESTrr8, 2).addReg(SrcReg).addReg(SrcReg);
+      break;
+    case cShort:
+      BMI(BB, IP, X86::TESTrr16, 2).addReg(SrcReg).addReg(SrcReg);
+      break;
+    case cInt:
+      BMI(BB, IP, X86::TESTrr32, 2).addReg(SrcReg).addReg(SrcReg);
+      break;
+    case cLong: {
+      unsigned TmpReg = makeAnotherReg(Type::IntTy);
+      BMI(BB, IP, X86::ORrr32, 2, TmpReg).addReg(SrcReg).addReg(SrcReg+1);
+      break;
+    }
+    case cFP:
+      assert(0 && "FIXME: implement cast FP to bool");
+      abort();
+    }
+
+    // If the zero flag is not set, then the value is true, set the byte to
+    // true.
     BMI(BB, IP, X86::SETNEr, 1, DestReg);
     return;
   }
@@ -1690,7 +1813,10 @@ void ISel::emitCastOperation(MachineBasicBlock *BB,
       case cByte:  StoreTy = Type::ShortTy; StoreClass = cShort; break;
       case cShort: StoreTy = Type::IntTy;   StoreClass = cInt;   break;
       case cInt:   StoreTy = Type::LongTy;  StoreClass = cLong;  break;
-      case cLong:  abort(); // FIXME: unsigned long long -> more complex
+      // The following treatment of cLong may not be perfectly right,
+      // but it survives chains of casts of the form
+      // double->ulong->double.
+      case cLong:  StoreTy = Type::LongTy;  StoreClass = cLong;  break;
       default: assert(0 && "Unknown store class!");
       }
 
@@ -1826,6 +1952,13 @@ void ISel::emitGEPOperation(MachineBasicBlock *MBB,
       // time.
       assert(idx->getType() == Type::LongTy && "Bad GEP array index!");
 
+      // Most GEP instructions use a [cast (int/uint) to LongTy] as their
+      // operand on X86.  Handle this case directly now...
+      if (CastInst *CI = dyn_cast<CastInst>(idx))
+        if (CI->getOperand(0)->getType() == Type::IntTy ||
+            CI->getOperand(0)->getType() == Type::UIntTy)
+          idx = CI->getOperand(0);
+
       // We want to add BaseReg to(idxReg * sizeof ElementType). First, we
       // must find the size of the pointed-to type (Not coincidentally, the next
       // type is the type of the elements in the array).
@@ -1946,8 +2079,6 @@ void ISel::visitMallocInst(MallocInst &I) {
     unsigned Op1Reg = getReg(I.getOperand(0));
     MachineBasicBlock::iterator MBBI = BB->end();
     doMultiply(BB, MBBI, Arg, Type::UIntTy, Op0Reg, Op1Reg);
-              
-              
   }
 
   std::vector<ValueRecord> Args;
@@ -1963,18 +2094,17 @@ void ISel::visitMallocInst(MallocInst &I) {
 ///
 void ISel::visitFreeInst(FreeInst &I) {
   std::vector<ValueRecord> Args;
-  Args.push_back(ValueRecord(getReg(I.getOperand(0)),
-                            I.getOperand(0)->getType()));
+  Args.push_back(ValueRecord(I.getOperand(0)));
   MachineInstr *TheCall = BuildMI(X86::CALLpcrel32,
                                  1).addExternalSymbol("free", true);
   doCall(ValueRecord(0, Type::VoidTy), TheCall, Args);
 }
    
 
-/// createSimpleX86InstructionSelector - This pass converts an LLVM function
+/// createX86SimpleInstructionSelector - This pass converts an LLVM function
 /// into a machine code representation is a very simple peep-hole fashion.  The
 /// generated code sucks but the implementation is nice and simple.
 ///
-Pass *createSimpleX86InstructionSelector(TargetMachine &TM) {
+FunctionPass *createX86SimpleInstructionSelector(TargetMachine &TM) {
   return new ISel(TM);
 }