Restructure the mul/div/rem handling code to follow the pattern the other
[oota-llvm.git] / lib / Target / X86 / InstSelectSimple.cpp
index e735f94e7f6e4d4acfa6820838bc14cb138ca624..64a2d8f19a4885b4ad2720546c58bf202564a57a 100644 (file)
@@ -35,6 +35,43 @@ using namespace llvm;
 namespace {
   Statistic<>
   NumFPKill("x86-codegen", "Number of FP_REG_KILL instructions added");
+
+  /// TypeClass - Used by the X86 backend to group LLVM types by their basic X86
+  /// Representation.
+  ///
+  enum TypeClass {
+    cByte, cShort, cInt, cFP, cLong
+  };
+}
+
+/// getClass - Turn a primitive type into a "class" number which is based on the
+/// size of the type, and whether or not it is floating point.
+///
+static inline TypeClass getClass(const Type *Ty) {
+  switch (Ty->getPrimitiveID()) {
+  case Type::SByteTyID:
+  case Type::UByteTyID:   return cByte;      // Byte operands are class #0
+  case Type::ShortTyID:
+  case Type::UShortTyID:  return cShort;     // Short operands are class #1
+  case Type::IntTyID:
+  case Type::UIntTyID:
+  case Type::PointerTyID: return cInt;       // Int's and pointers are class #2
+
+  case Type::FloatTyID:
+  case Type::DoubleTyID:  return cFP;        // Floating Point is #3
+
+  case Type::LongTyID:
+  case Type::ULongTyID:   return cLong;      // Longs are class #4
+  default:
+    assert(0 && "Invalid type to getClass!");
+    return cByte;  // not reached
+  }
+}
+
+// getClassB - Just like getClass, but treat boolean values as bytes.
+static inline TypeClass getClassB(const Type *Ty) {
+  if (Ty == Type::BoolTy) return cByte;
+  return getClass(Ty);
 }
 
 namespace {
@@ -151,13 +188,6 @@ namespace {
     void visitSimpleBinary(BinaryOperator &B, unsigned OpcodeClass);
     void visitAdd(BinaryOperator &B) { visitSimpleBinary(B, 0); }
     void visitSub(BinaryOperator &B) { visitSimpleBinary(B, 1); }
-    void doMultiply(MachineBasicBlock *MBB, MachineBasicBlock::iterator MBBI,
-                    unsigned DestReg, const Type *DestTy,
-                    unsigned Op0Reg, unsigned Op1Reg);
-    void doMultiplyConst(MachineBasicBlock *MBB, 
-                         MachineBasicBlock::iterator MBBI,
-                         unsigned DestReg, const Type *DestTy,
-                         unsigned Op0Reg, unsigned Op1Val);
     void visitMul(BinaryOperator &B);
 
     void visitDiv(BinaryOperator &B) { visitDivRem(B); }
@@ -242,10 +272,21 @@ namespace {
                                    Value *Op0, Value *Op1,
                                    unsigned OperatorClass, unsigned TargetReg);
 
+    void emitMultiply(MachineBasicBlock *BB, MachineBasicBlock::iterator IP,
+                      Value *Op0, Value *Op1, unsigned TargetReg);
+
+    void doMultiply(MachineBasicBlock *MBB, MachineBasicBlock::iterator MBBI,
+                    unsigned DestReg, const Type *DestTy,
+                    unsigned Op0Reg, unsigned Op1Reg);
+    void doMultiplyConst(MachineBasicBlock *MBB, 
+                         MachineBasicBlock::iterator MBBI,
+                         unsigned DestReg, const Type *DestTy,
+                         unsigned Op0Reg, unsigned Op1Val);
+
     void emitDivRemOperation(MachineBasicBlock *BB,
                              MachineBasicBlock::iterator IP,
-                             unsigned Op0Reg, unsigned Op1Reg, bool isDiv,
-                             const Type *Ty, unsigned TargetReg);
+                             Value *Op0, Value *Op1, bool isDiv,
+                             unsigned TargetReg);
 
     /// emitSetCCOperation - Common code shared between visitSetCondInst and
     /// constant expression support.
@@ -315,22 +356,28 @@ namespace {
     }
     unsigned getReg(Value *V, MachineBasicBlock *MBB,
                     MachineBasicBlock::iterator IPt) {
-      unsigned &Reg = RegMap[V];
-      if (Reg == 0) {
-        Reg = makeAnotherReg(V->getType());
-        RegMap[V] = Reg;
-      }
-
       // If this operand is a constant, emit the code to copy the constant into
       // the register here...
       //
       if (Constant *C = dyn_cast<Constant>(V)) {
+        unsigned Reg = makeAnotherReg(V->getType());
         copyConstantToRegister(MBB, IPt, C, Reg);
-        RegMap.erase(V);  // Assign a new name to this constant if ref'd again
+        return Reg;
       } else if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
+        unsigned Reg = makeAnotherReg(V->getType());
         // Move the address of the global into the register
         BuildMI(*MBB, IPt, X86::MOV32ri, 1, Reg).addGlobalAddress(GV);
-        RegMap.erase(V);  // Assign a new name to this address if ref'd again
+        return Reg;
+      } else if (CastInst *CI = dyn_cast<CastInst>(V)) {
+        // Do not emit noop casts at all.
+        if (getClassB(CI->getType()) == getClassB(CI->getOperand(0)->getType()))
+          return getReg(CI->getOperand(0), MBB, IPt);
+      }
+
+      unsigned &Reg = RegMap[V];
+      if (Reg == 0) {
+        Reg = makeAnotherReg(V->getType());
+        RegMap[V] = Reg;
       }
 
       return Reg;
@@ -338,44 +385,6 @@ namespace {
   };
 }
 
-/// TypeClass - Used by the X86 backend to group LLVM types by their basic X86
-/// Representation.
-///
-enum TypeClass {
-  cByte, cShort, cInt, cFP, cLong
-};
-
-/// getClass - Turn a primitive type into a "class" number which is based on the
-/// size of the type, and whether or not it is floating point.
-///
-static inline TypeClass getClass(const Type *Ty) {
-  switch (Ty->getPrimitiveID()) {
-  case Type::SByteTyID:
-  case Type::UByteTyID:   return cByte;      // Byte operands are class #0
-  case Type::ShortTyID:
-  case Type::UShortTyID:  return cShort;     // Short operands are class #1
-  case Type::IntTyID:
-  case Type::UIntTyID:
-  case Type::PointerTyID: return cInt;       // Int's and pointers are class #2
-
-  case Type::FloatTyID:
-  case Type::DoubleTyID:  return cFP;        // Floating Point is #3
-
-  case Type::LongTyID:
-  case Type::ULongTyID:   return cLong;      // Longs are class #4
-  default:
-    assert(0 && "Invalid type to getClass!");
-    return cByte;  // not reached
-  }
-}
-
-// getClassB - Just like getClass, but treat boolean values as bytes.
-static inline TypeClass getClassB(const Type *Ty) {
-  if (Ty == Type::BoolTy) return cByte;
-  return getClass(Ty);
-}
-
-
 /// copyConstantToRegister - Output the instructions required to put the
 /// specified constant into the specified register.
 ///
@@ -402,21 +411,15 @@ void ISel::copyConstantToRegister(MachineBasicBlock *MBB,
                                 Class, R);
       return;
 
-    case Instruction::Mul: {
-      unsigned Op0Reg = getReg(CE->getOperand(0), MBB, IP);
-      unsigned Op1Reg = getReg(CE->getOperand(1), MBB, IP);
-      doMultiply(MBB, IP, R, CE->getType(), Op0Reg, Op1Reg);
+    case Instruction::Mul:
+      emitMultiply(MBB, IP, CE->getOperand(0), CE->getOperand(1), R);
       return;
-    }
+
     case Instruction::Div:
-    case Instruction::Rem: {
-      unsigned Op0Reg = getReg(CE->getOperand(0), MBB, IP);
-      unsigned Op1Reg = getReg(CE->getOperand(1), MBB, IP);
-      emitDivRemOperation(MBB, IP, Op0Reg, Op1Reg,
-                          CE->getOpcode() == Instruction::Div,
-                          CE->getType(), R);
+    case Instruction::Rem:
+      emitDivRemOperation(MBB, IP, CE->getOperand(0), CE->getOperand(1),
+                          CE->getOpcode() == Instruction::Div, R);
       return;
-    }
 
     case Instruction::SetNE:
     case Instruction::SetEQ:
@@ -511,39 +514,51 @@ void ISel::LoadArgumentsToVirtualRegs(Function &Fn) {
   MachineFrameInfo *MFI = F->getFrameInfo();
 
   for (Function::aiterator I = Fn.abegin(), E = Fn.aend(); I != E; ++I) {
-    unsigned Reg = getReg(*I);
-    
+    bool ArgLive = !I->use_empty();
+    unsigned Reg = ArgLive ? getReg(*I) : 0;
     int FI;          // Frame object index
+
     switch (getClassB(I->getType())) {
     case cByte:
-      FI = MFI->CreateFixedObject(1, ArgOffset);
-      addFrameReference(BuildMI(BB, X86::MOV8rm, 4, Reg), FI);
+      if (ArgLive) {
+        FI = MFI->CreateFixedObject(1, ArgOffset);
+        addFrameReference(BuildMI(BB, X86::MOV8rm, 4, Reg), FI);
+      }
       break;
     case cShort:
-      FI = MFI->CreateFixedObject(2, ArgOffset);
-      addFrameReference(BuildMI(BB, X86::MOV16rm, 4, Reg), FI);
+      if (ArgLive) {
+        FI = MFI->CreateFixedObject(2, ArgOffset);
+        addFrameReference(BuildMI(BB, X86::MOV16rm, 4, Reg), FI);
+      }
       break;
     case cInt:
-      FI = MFI->CreateFixedObject(4, ArgOffset);
-      addFrameReference(BuildMI(BB, X86::MOV32rm, 4, Reg), FI);
+      if (ArgLive) {
+        FI = MFI->CreateFixedObject(4, ArgOffset);
+        addFrameReference(BuildMI(BB, X86::MOV32rm, 4, Reg), FI);
+      }
       break;
     case cLong:
-      FI = MFI->CreateFixedObject(8, ArgOffset);
-      addFrameReference(BuildMI(BB, X86::MOV32rm, 4, Reg), FI);
-      addFrameReference(BuildMI(BB, X86::MOV32rm, 4, Reg+1), FI, 4);
+      if (ArgLive) {
+        FI = MFI->CreateFixedObject(8, ArgOffset);
+        addFrameReference(BuildMI(BB, X86::MOV32rm, 4, Reg), FI);
+        addFrameReference(BuildMI(BB, X86::MOV32rm, 4, Reg+1), FI, 4);
+      }
       ArgOffset += 4;   // longs require 4 additional bytes
       break;
     case cFP:
-      unsigned Opcode;
-      if (I->getType() == Type::FloatTy) {
-        Opcode = X86::FLD32m;
-        FI = MFI->CreateFixedObject(4, ArgOffset);
-      } else {
-        Opcode = X86::FLD64m;
-        FI = MFI->CreateFixedObject(8, ArgOffset);
-        ArgOffset += 4;   // doubles require 4 additional bytes
+      if (ArgLive) {
+        unsigned Opcode;
+        if (I->getType() == Type::FloatTy) {
+          Opcode = X86::FLD32m;
+          FI = MFI->CreateFixedObject(4, ArgOffset);
+        } else {
+          Opcode = X86::FLD64m;
+          FI = MFI->CreateFixedObject(8, ArgOffset);
+        }
+        addFrameReference(BuildMI(BB, Opcode, 4, Reg), FI);
       }
-      addFrameReference(BuildMI(BB, Opcode, 4, Reg), FI);
+      if (I->getType() == Type::DoubleTy)
+        ArgOffset += 4;   // doubles require 4 additional bytes
       break;
     default:
       assert(0 && "Unhandled argument type!");
@@ -756,7 +771,9 @@ static SetCondInst *canFoldSetCCIntoBranchOrSelect(Value *V) {
       Instruction *User = cast<Instruction>(SCI->use_back());
       if ((isa<BranchInst>(User) || isa<SelectInst>(User)) &&
           SCI->getParent() == User->getParent() &&
-          getClassB(SCI->getOperand(0)->getType()) != cLong)
+          (getClassB(SCI->getOperand(0)->getType()) != cLong ||
+           SCI->getOpcode() == Instruction::SetEQ ||
+           SCI->getOpcode() == Instruction::SetNE))
         return SCI;
     }
   return 0;
@@ -806,9 +823,9 @@ unsigned ISel::EmitComparison(unsigned OpNum, Value *Op0, Value *Op1,
   unsigned Op0r = getReg(Op0, MBB, IP);
 
   // 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();
+  if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
+    if (Class == cByte || Class == cShort || Class == cInt) {
+      unsigned Op1v = CI->getRawValue();
 
       // Mask off any upper bits of the constant, if there are any...
       Op1v &= (1ULL << (8 << Class)) - 1;
@@ -833,7 +850,52 @@ unsigned ISel::EmitComparison(unsigned OpNum, Value *Op0, Value *Op1,
 
       BuildMI(*MBB, IP, CMPTab[Class], 2).addReg(Op0r).addImm(Op1v);
       return OpNum;
+    } else {
+      assert(Class == cLong && "Unknown integer class!");
+      unsigned LowCst = CI->getRawValue();
+      unsigned HiCst = CI->getRawValue() >> 32;
+      if (OpNum < 2) {    // seteq, setne
+        unsigned LoTmp = Op0r;
+        if (LowCst != 0) {
+          LoTmp = makeAnotherReg(Type::IntTy);
+          BuildMI(*MBB, IP, X86::XOR32ri, 2, LoTmp).addReg(Op0r).addImm(LowCst);
+        }
+        unsigned HiTmp = Op0r+1;
+        if (HiCst != 0) {
+          HiTmp = makeAnotherReg(Type::IntTy);
+          BuildMI(*MBB, IP, X86::XOR32ri, 2,HiTmp).addReg(Op0r+1).addImm(HiCst);
+        }
+        unsigned FinalTmp = makeAnotherReg(Type::IntTy);
+        BuildMI(*MBB, IP, X86::OR32rr, 2, FinalTmp).addReg(LoTmp).addReg(HiTmp);
+        return OpNum;
+      } else {
+        // Emit a sequence of code which compares the high and low parts once
+        // each, then uses a conditional move to handle the overflow case.  For
+        // example, a setlt for long would generate code like this:
+        //
+        // AL = lo(op1) < lo(op2)   // Signedness depends on operands
+        // BL = hi(op1) < hi(op2)   // Always unsigned comparison
+        // dest = hi(op1) == hi(op2) ? AL : BL;
+        //
+
+        // FIXME: This would be much better if we had hierarchical register
+        // classes!  Until then, hardcode registers so that we can deal with
+        // their aliases (because we don't have conditional byte moves).
+        //
+        BuildMI(*MBB, IP, X86::CMP32ri, 2).addReg(Op0r).addImm(LowCst);
+        BuildMI(*MBB, IP, SetCCOpcodeTab[0][OpNum], 0, X86::AL);
+        BuildMI(*MBB, IP, X86::CMP32ri, 2).addReg(Op0r+1).addImm(HiCst);
+        BuildMI(*MBB, IP, SetCCOpcodeTab[CompTy->isSigned()][OpNum], 0,X86::BL);
+        BuildMI(*MBB, IP, X86::IMPLICIT_DEF, 0, X86::BH);
+        BuildMI(*MBB, IP, X86::IMPLICIT_DEF, 0, X86::AH);
+        BuildMI(*MBB, IP, X86::CMOVE16rr, 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...
+        return OpNum;
+      }
     }
+  }
 
   // Special case handling of comparison against +/- 0.0
   if (ConstantFP *CFP = dyn_cast<ConstantFP>(Op1))
@@ -1455,6 +1517,8 @@ void ISel::LowerUnknownIntrinsicFunctionCalls(Function &F) {
           case Intrinsic::frameaddress:
           case Intrinsic::memcpy:
           case Intrinsic::memset:
+          case Intrinsic::readport:
+          case Intrinsic::writeport:
             // We directly implement these intrinsics
             break;
           default:
@@ -1616,6 +1680,72 @@ void ISel::visitIntrinsicCall(Intrinsic::ID ID, CallInst &CI) {
     return;
   }
 
+  case Intrinsic::readport:
+    //
+    // First, determine that the size of the operand falls within the
+    // acceptable range for this architecture.
+    //
+    if ((CI.getOperand(1)->getType()->getPrimitiveSize()) != 2) {
+      std::cerr << "llvm.readport: Address size is not 16 bits\n";
+      exit (1);
+    }
+
+    //
+    // Now, move the I/O port address into the DX register and use the IN
+    // instruction to get the input data.
+    //
+    BuildMI(BB, X86::MOV16rr, 1, X86::DX).addReg(getReg(CI.getOperand(1)));
+    switch (CI.getCalledFunction()->getReturnType()->getPrimitiveSize()) {
+      case 1:
+        BuildMI(BB, X86::IN8, 0);
+        break;
+      case 2:
+        BuildMI(BB, X86::IN16, 0);
+        break;
+      case 4:
+        BuildMI(BB, X86::IN32, 0);
+        break;
+      default:
+        std::cerr << "Cannot do input on this data type";
+        exit (1);
+    }
+    return;
+
+  case Intrinsic::writeport:
+    //
+    // First, determine that the size of the operand falls within the
+    // acceptable range for this architecture.
+    //
+    //
+    if ((CI.getOperand(2)->getType()->getPrimitiveSize()) != 2) {
+      std::cerr << "llvm.writeport: Address size is not 16 bits\n";
+      exit (1);
+    }
+
+    //
+    // Now, move the I/O port address into the DX register and the value to
+    // write into the AL/AX/EAX register.
+    //
+    BuildMI(BB, X86::MOV16rr, 1, X86::DX).addReg(getReg(CI.getOperand(2)));
+    switch (CI.getOperand(1)->getType()->getPrimitiveSize()) {
+      case 1:
+        BuildMI(BB, X86::MOV8rr, 1, X86::AL).addReg(getReg(CI.getOperand(1)));
+        BuildMI(BB, X86::OUT8, 0);
+        break;
+      case 2:
+        BuildMI(BB, X86::MOV16rr, 1, X86::AX).addReg(getReg(CI.getOperand(1)));
+        BuildMI(BB, X86::OUT16, 0);
+        break;
+      case 4:
+        BuildMI(BB, X86::MOV32rr, 1, X86::EAX).addReg(getReg(CI.getOperand(1)));
+        BuildMI(BB, X86::OUT32, 0);
+        break;
+      default:
+        std::cerr << "Cannot do output on this data type";
+        exit (1);
+    }
+    return;
+
   default: assert(0 && "Error: unknown intrinsics should have been lowered!");
   }
 }
@@ -1698,36 +1828,27 @@ void ISel::emitSimpleBinaryOperation(MachineBasicBlock *MBB,
   unsigned Class = getClassB(Op0->getType());
 
   // sub 0, X -> neg X
-  if (OperatorClass == 1)
-    if (ConstantInt *CI = dyn_cast<ConstantInt>(Op0)) {
-      if (CI->isNullValue()) {
-        unsigned op1Reg = getReg(Op1, MBB, IP);
-        static unsigned const NEGTab[] = {
-          X86::NEG8r, X86::NEG16r, X86::NEG32r, 0, X86::NEG32r
-        };
-        BuildMI(*MBB, IP, NEGTab[Class], 1, DestReg).addReg(op1Reg);
-
-        if (Class == cLong) {
-          // We just emitted: Dl = neg Sl
-          // Now emit       : T  = addc Sh, 0
-          //                : Dh = neg T
-          unsigned T = makeAnotherReg(Type::IntTy);
-          BuildMI(*MBB, IP, X86::ADC32ri, 2, T).addReg(op1Reg+1).addImm(0);
-          BuildMI(*MBB, IP, X86::NEG32r, 1, DestReg+1).addReg(T);
-        }
-        return;
-      }
-    } else if (ConstantFP *CFP = dyn_cast<ConstantFP>(Op0))
-      if (CFP->isExactlyValue(-0.0)) {
-        // -0.0 - X === -X
-        unsigned op1Reg = getReg(Op1, MBB, IP);
-        BuildMI(*MBB, IP, X86::FCHS, 1, DestReg).addReg(op1Reg);
-        return;
+  if (ConstantInt *CI = dyn_cast<ConstantInt>(Op0))
+    if (OperatorClass == 1 && CI->isNullValue()) {
+      unsigned op1Reg = getReg(Op1, MBB, IP);
+      static unsigned const NEGTab[] = {
+        X86::NEG8r, X86::NEG16r, X86::NEG32r, 0, X86::NEG32r
+      };
+      BuildMI(*MBB, IP, NEGTab[Class], 1, DestReg).addReg(op1Reg);
+      
+      if (Class == cLong) {
+        // We just emitted: Dl = neg Sl
+        // Now emit       : T  = addc Sh, 0
+        //                : Dh = neg T
+        unsigned T = makeAnotherReg(Type::IntTy);
+        BuildMI(*MBB, IP, X86::ADC32ri, 2, T).addReg(op1Reg+1).addImm(0);
+        BuildMI(*MBB, IP, X86::NEG32r, 1, DestReg+1).addReg(T);
       }
+      return;
+    }
 
-  // Special case: op Reg, <const>
-  if (isa<ConstantInt>(Op1)) {
-    ConstantInt *Op1C = cast<ConstantInt>(Op1);
+  // Special case: op Reg, <const int>
+  if (ConstantInt *Op1C = dyn_cast<ConstantInt>(Op1)) {
     unsigned Op0r = getReg(Op0, MBB, IP);
 
     // xor X, -1 -> not X
@@ -1821,6 +1942,56 @@ void ISel::emitSimpleBinaryOperation(MachineBasicBlock *MBB,
     }
   }
 
+  // Special case: op Reg, <const fp>
+  if (ConstantFP *Op1C = dyn_cast<ConstantFP>(Op1))
+    if (!Op1C->isExactlyValue(+0.0) && !Op1C->isExactlyValue(+1.0)) {
+      assert(OperatorClass < 2 && "FP operations only support add/sub!");
+      
+      // Create a constant pool entry for this constant.
+      MachineConstantPool *CP = F->getConstantPool();
+      unsigned CPI = CP->getConstantPoolIndex(Op1C);
+      const Type *Ty = Op1->getType();
+
+      static const unsigned OpcodeTab[][2] = {
+        { X86::FADD32m, X86::FSUB32m },   // Float
+        { X86::FADD64m, X86::FSUB64m },   // Double
+      };
+
+      assert(Ty == Type::FloatTy || Ty == Type::DoubleTy && "Unknown FP type!");
+      unsigned Opcode = OpcodeTab[Ty != Type::FloatTy][OperatorClass];
+      unsigned Op0r = getReg(Op0, MBB, IP);
+      addConstantPoolReference(BuildMI(*MBB, IP, Opcode, 5,
+                                       DestReg).addReg(Op0r), CPI);
+      return;
+    }
+  
+  // Special case: R1 = sub <const fp>, R2
+  if (ConstantFP *CFP = dyn_cast<ConstantFP>(Op0))
+    if (OperatorClass == 1) {  // sub only
+      if (CFP->isExactlyValue(-0.0)) {
+        // -0.0 - X === -X
+        unsigned op1Reg = getReg(Op1, MBB, IP);
+        BuildMI(*MBB, IP, X86::FCHS, 1, DestReg).addReg(op1Reg);
+        return;
+      } else if (!CFP->isExactlyValue(+0.0) && !CFP->isExactlyValue(+1.0)) {
+        // R1 = sub CST, R2  -->  R1 = subr R2, CST
+
+        // Create a constant pool entry for this constant.
+        MachineConstantPool *CP = F->getConstantPool();
+        unsigned CPI = CP->getConstantPoolIndex(CFP);
+        const Type *Ty = CFP->getType();
+        
+        static const unsigned OpcodeTab[2] = { X86::FSUBR32m, X86::FSUBR64m };
+        
+        assert(Ty == Type::FloatTy||Ty == Type::DoubleTy && "Unknown FP type!");
+        unsigned Opcode = OpcodeTab[Ty != Type::FloatTy];
+        unsigned Op1r = getReg(Op1, MBB, IP);
+        addConstantPoolReference(BuildMI(*MBB, IP, Opcode, 5,
+                                         DestReg).addReg(Op1r), CPI);
+        return;
+      }
+    }
+
   // Finally, handle the general case now.
   static const unsigned OpcodeTab[][5] = {
     // Arithmetic operators
@@ -1889,12 +2060,26 @@ static unsigned ExactLog2(unsigned Val) {
   return Count+1;
 }
 
+
+/// doMultiplyConst - This function is specialized to efficiently codegen an 8,
+/// 16, or 32-bit integer multiply by a constant.
 void ISel::doMultiplyConst(MachineBasicBlock *MBB,
                            MachineBasicBlock::iterator IP,
                            unsigned DestReg, const Type *DestTy,
                            unsigned op0Reg, unsigned ConstRHS) {
+  static const unsigned MOVrrTab[] = {X86::MOV8rr, X86::MOV16rr, X86::MOV32rr};
+  static const unsigned MOVriTab[] = {X86::MOV8ri, X86::MOV16ri, X86::MOV32ri};
+
   unsigned Class = getClass(DestTy);
 
+  if (ConstRHS == 0) {
+    BuildMI(*MBB, IP, MOVriTab[Class], 1, DestReg).addImm(0);
+    return;
+  } else if (ConstRHS == 1) {
+    BuildMI(*MBB, IP, MOVrrTab[Class], 1, DestReg).addReg(op0Reg);
+    return;
+  }
+
   // If the element size is exactly a power of 2, use a shift to get it.
   if (unsigned Shift = ExactLog2(ConstRHS)) {
     switch (Class) {
@@ -1920,10 +2105,6 @@ void ISel::doMultiplyConst(MachineBasicBlock *MBB,
   }
 
   // Most general case, emit a normal multiply...
-  static const unsigned MOVriTab[] = {
-    X86::MOV8ri, X86::MOV16ri, X86::MOV32ri
-  };
-
   unsigned TmpReg = makeAnotherReg(DestTy);
   BuildMI(*MBB, IP, MOVriTab[Class], 1, TmpReg).addImm(ConstRHS);
   
@@ -1936,47 +2117,123 @@ void ISel::doMultiplyConst(MachineBasicBlock *MBB,
 /// with the EAX register explicitly.
 ///
 void ISel::visitMul(BinaryOperator &I) {
-  unsigned Op0Reg  = getReg(I.getOperand(0));
-  unsigned DestReg = getReg(I);
+  unsigned ResultReg = getReg(I);
+
+  MachineBasicBlock::iterator IP = BB->end();
+  emitMultiply(BB, IP, I.getOperand(0), I.getOperand(1), ResultReg);
+}
+
+void ISel::emitMultiply(MachineBasicBlock *MBB, MachineBasicBlock::iterator IP,
+                        Value *Op0, Value *Op1, unsigned DestReg) {
+  MachineBasicBlock &BB = *MBB;
+  TypeClass Class = getClass(Op0->getType());
 
   // Simple scalar multiply?
-  if (I.getType() != Type::LongTy && I.getType() != Type::ULongTy) {
-    if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(1))) {
-      unsigned Val = (unsigned)CI->getRawValue(); // Cannot be 64-bit constant
-      MachineBasicBlock::iterator MBBI = BB->end();
-      doMultiplyConst(BB, MBBI, DestReg, I.getType(), Op0Reg, Val);
+  switch (Class) {
+  case cByte:
+  case cShort:
+  case cInt:
+    if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
+      unsigned Op0Reg  = getReg(Op0, &BB, IP);
+      unsigned Val = (unsigned)CI->getRawValue(); // Isn't a 64-bit constant
+      doMultiplyConst(&BB, IP, DestReg, Op0->getType(), Op0Reg, Val);
     } else {
-      unsigned Op1Reg  = getReg(I.getOperand(1));
-      MachineBasicBlock::iterator MBBI = BB->end();
-      doMultiply(BB, MBBI, DestReg, I.getType(), Op0Reg, Op1Reg);
+      unsigned Op0Reg  = getReg(Op0, &BB, IP);
+      unsigned Op1Reg  = getReg(Op1, &BB, IP);
+      doMultiply(&BB, IP, DestReg, Op1->getType(), Op0Reg, Op1Reg);
     }
-  } else {
-    unsigned Op1Reg  = getReg(I.getOperand(1));
-
-    // Long value.  We have to do things the hard way...
-    // Multiply the two low parts... capturing carry into EDX
-    BuildMI(BB, X86::MOV32rr, 1, X86::EAX).addReg(Op0Reg);
-    BuildMI(BB, X86::MUL32r, 1).addReg(Op1Reg);  // AL*BL
+    return;
+  case cFP:
+    {
+      unsigned Op0Reg  = getReg(Op0, &BB, IP);
+      unsigned Op1Reg  = getReg(Op1, &BB, IP);
+      doMultiply(&BB, IP, DestReg, Op1->getType(), Op0Reg, Op1Reg);
+      return;
+    }
+  case cLong:
+    break;
+  }
 
-    unsigned OverflowReg = makeAnotherReg(Type::UIntTy);
-    BuildMI(BB, X86::MOV32rr, 1, DestReg).addReg(X86::EAX);     // AL*BL
-    BuildMI(BB, X86::MOV32rr, 1, OverflowReg).addReg(X86::EDX); // AL*BL >> 32
+  unsigned Op0Reg  = getReg(Op0, &BB, IP);
 
-    MachineBasicBlock::iterator MBBI = BB->end();
+  // Long value.  We have to do things the hard way...
+  if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
+    unsigned CLow = CI->getRawValue();
+    unsigned CHi  = CI->getRawValue() >> 32;
+    
+    if (CLow == 0) {
+      // If the low part of the constant is all zeros, things are simple.
+      BuildMI(BB, IP, X86::MOV32ri, 1, DestReg).addImm(0);
+      doMultiplyConst(&BB, IP, DestReg+1, Type::UIntTy, Op0Reg, CHi);
+      return;
+    }
+    
+    // Multiply the two low parts... capturing carry into EDX
+    unsigned OverflowReg = 0;
+    if (CLow == 1) {
+      BuildMI(BB, IP, X86::MOV32rr, 1, DestReg).addReg(Op0Reg);
+    } else {
+      unsigned Op1RegL = makeAnotherReg(Type::UIntTy);
+      OverflowReg = makeAnotherReg(Type::UIntTy);
+      BuildMI(BB, IP, X86::MOV32ri, 1, Op1RegL).addImm(CLow);
+      BuildMI(BB, IP, X86::MOV32rr, 1, X86::EAX).addReg(Op0Reg);
+      BuildMI(BB, IP, X86::MUL32r, 1).addReg(Op1RegL);  // AL*BL
+      
+      BuildMI(BB, IP, X86::MOV32rr, 1, DestReg).addReg(X86::EAX);   // AL*BL
+      BuildMI(BB, IP, X86::MOV32rr, 1,
+              OverflowReg).addReg(X86::EDX);                    // AL*BL >> 32
+    }
+    
     unsigned AHBLReg = makeAnotherReg(Type::UIntTy);   // AH*BL
-    BuildMI(*BB, MBBI, X86::IMUL32rr,2,AHBLReg).addReg(Op0Reg+1).addReg(Op1Reg);
-
-    unsigned AHBLplusOverflowReg = makeAnotherReg(Type::UIntTy);
-    BuildMI(*BB, MBBI, X86::ADD32rr, 2,                  // AH*BL+(AL*BL >> 32)
-            AHBLplusOverflowReg).addReg(AHBLReg).addReg(OverflowReg);
+    doMultiplyConst(&BB, IP, AHBLReg, Type::UIntTy, Op0Reg+1, CLow);
     
-    MBBI = BB->end();
-    unsigned ALBHReg = makeAnotherReg(Type::UIntTy); // AL*BH
-    BuildMI(*BB, MBBI, X86::IMUL32rr,2,ALBHReg).addReg(Op0Reg).addReg(Op1Reg+1);
+    unsigned AHBLplusOverflowReg;
+    if (OverflowReg) {
+      AHBLplusOverflowReg = makeAnotherReg(Type::UIntTy);
+      BuildMI(BB, IP, X86::ADD32rr, 2,                // AH*BL+(AL*BL >> 32)
+              AHBLplusOverflowReg).addReg(AHBLReg).addReg(OverflowReg);
+    } else {
+      AHBLplusOverflowReg = AHBLReg;
+    }
     
-    BuildMI(*BB, MBBI, X86::ADD32rr, 2,         // AL*BH + AH*BL + (AL*BL >> 32)
-            DestReg+1).addReg(AHBLplusOverflowReg).addReg(ALBHReg);
+    if (CHi == 0) {
+      BuildMI(BB, IP, X86::MOV32rr, 1, DestReg+1).addReg(AHBLplusOverflowReg);
+    } else {
+      unsigned ALBHReg = makeAnotherReg(Type::UIntTy); // AL*BH
+      doMultiplyConst(&BB, IP, ALBHReg, Type::UIntTy, Op0Reg, CHi);
+      
+      BuildMI(BB, IP, X86::ADD32rr, 2,      // AL*BH + AH*BL + (AL*BL >> 32)
+              DestReg+1).addReg(AHBLplusOverflowReg).addReg(ALBHReg);
+    }
+    return;
   }
+
+  // General 64x64 multiply
+
+  unsigned Op1Reg  = getReg(Op1, &BB, IP);
+  // Multiply the two low parts... capturing carry into EDX
+  BuildMI(BB, IP, X86::MOV32rr, 1, X86::EAX).addReg(Op0Reg);
+  BuildMI(BB, IP, X86::MUL32r, 1).addReg(Op1Reg);  // AL*BL
+  
+  unsigned OverflowReg = makeAnotherReg(Type::UIntTy);
+  BuildMI(BB, IP, X86::MOV32rr, 1, DestReg).addReg(X86::EAX);     // AL*BL
+  BuildMI(BB, IP, X86::MOV32rr, 1,
+          OverflowReg).addReg(X86::EDX); // AL*BL >> 32
+  
+  unsigned AHBLReg = makeAnotherReg(Type::UIntTy);   // AH*BL
+  BuildMI(BB, IP, X86::IMUL32rr, 2,
+          AHBLReg).addReg(Op0Reg+1).addReg(Op1Reg);
+  
+  unsigned AHBLplusOverflowReg = makeAnotherReg(Type::UIntTy);
+  BuildMI(BB, IP, X86::ADD32rr, 2,                // AH*BL+(AL*BL >> 32)
+          AHBLplusOverflowReg).addReg(AHBLReg).addReg(OverflowReg);
+  
+  unsigned ALBHReg = makeAnotherReg(Type::UIntTy); // AL*BH
+  BuildMI(BB, IP, X86::IMUL32rr, 2,
+          ALBHReg).addReg(Op0Reg).addReg(Op1Reg+1);
+  
+  BuildMI(BB, IP, X86::ADD32rr, 2,      // AL*BH + AH*BL + (AL*BL >> 32)
+          DestReg+1).addReg(AHBLplusOverflowReg).addReg(ALBHReg);
 }
 
 
@@ -1986,25 +2243,28 @@ void ISel::visitMul(BinaryOperator &I) {
 /// instructions work differently for signed and unsigned operands.
 ///
 void ISel::visitDivRem(BinaryOperator &I) {
-  unsigned Op0Reg = getReg(I.getOperand(0));
-  unsigned Op1Reg = getReg(I.getOperand(1));
   unsigned ResultReg = getReg(I);
 
   MachineBasicBlock::iterator IP = BB->end();
-  emitDivRemOperation(BB, IP, Op0Reg, Op1Reg, I.getOpcode() == Instruction::Div,
-                      I.getType(), ResultReg);
+  emitDivRemOperation(BB, IP, I.getOperand(0), I.getOperand(1),
+                      I.getOpcode() == Instruction::Div, ResultReg);
+                      
 }
 
 void ISel::emitDivRemOperation(MachineBasicBlock *BB,
                                MachineBasicBlock::iterator IP,
-                               unsigned Op0Reg, unsigned Op1Reg, bool isDiv,
-                               const Type *Ty, unsigned ResultReg) {
-  unsigned Class = getClass(Ty);
+                               Value *Op0, Value *Op1, bool isDiv,
+                               unsigned ResultReg) {
+  unsigned Class = getClass(Op0->getType());
   switch (Class) {
   case cFP:              // Floating point divide
     if (isDiv) {
+      unsigned Op0Reg = getReg(Op0, BB, IP);
+      unsigned Op1Reg = getReg(Op1, BB, IP);
       BuildMI(*BB, IP, X86::FpDIV, 2, ResultReg).addReg(Op0Reg).addReg(Op1Reg);
     } else {               // Floating point remainder...
+      unsigned Op0Reg = getReg(Op0, BB, IP);
+      unsigned Op1Reg = getReg(Op1, BB, IP);
       MachineInstr *TheCall =
         BuildMI(X86::CALLpcrel32, 1).addExternalSymbol("fmod", true);
       std::vector<ValueRecord> Args;
@@ -2016,8 +2276,9 @@ void ISel::emitDivRemOperation(MachineBasicBlock *BB,
   case cLong: {
     static const char *FnName[] =
       { "__moddi3", "__divdi3", "__umoddi3", "__udivdi3" };
-
-    unsigned NameIdx = Ty->isUnsigned()*2 + isDiv;
+    unsigned Op0Reg = getReg(Op0, BB, IP);
+    unsigned Op1Reg = getReg(Op1, BB, IP);
+    unsigned NameIdx = Op0->getType()->isUnsigned()*2 + isDiv;
     MachineInstr *TheCall =
       BuildMI(X86::CALLpcrel32, 1).addExternalSymbol(FnName[NameIdx], true);
 
@@ -2043,16 +2304,18 @@ void ISel::emitDivRemOperation(MachineBasicBlock *BB,
     { X86::IDIV8r, X86::IDIV16r, X86::IDIV32r, 0 },  // Signed division
   };
 
-  bool isSigned   = Ty->isSigned();
+  bool isSigned   = Op0->getType()->isSigned();
   unsigned Reg    = Regs[Class];
   unsigned ExtReg = ExtRegs[Class];
 
   // Put the first operand into one of the A registers...
+  unsigned Op0Reg = getReg(Op0, BB, IP);
+  unsigned Op1Reg = getReg(Op1, BB, IP);
   BuildMI(*BB, IP, MovOpcode[Class], 1, Reg).addReg(Op0Reg);
 
   if (isSigned) {
     // Emit a sign extension instruction...
-    unsigned ShiftResult = makeAnotherReg(Ty);
+    unsigned ShiftResult = makeAnotherReg(Op0->getType());
     BuildMI(*BB, IP, SarOpcode[Class], 2,ShiftResult).addReg(Op0Reg).addImm(31);
     BuildMI(*BB, IP, MovOpcode[Class], 1, ExtReg).addReg(ShiftResult);
   } else {
@@ -2128,13 +2391,20 @@ void ISel::emitShiftOperation(MachineBasicBlock *MBB,
       } else {                 // Shifting more than 32 bits
         Amount -= 32;
         if (isLeftShift) {
-          BuildMI(*MBB, IP, X86::SHL32ri, 2,
-              DestReg + 1).addReg(SrcReg).addImm(Amount);
-          BuildMI(*MBB, IP, X86::MOV32ri, 1,
-              DestReg).addImm(0);
+          if (Amount != 0) {
+            BuildMI(*MBB, IP, X86::SHL32ri, 2,
+                    DestReg + 1).addReg(SrcReg).addImm(Amount);
+          } else {
+            BuildMI(*MBB, IP, X86::MOV32rr, 1, DestReg+1).addReg(SrcReg);
+          }
+          BuildMI(*MBB, IP, X86::MOV32ri, 1, DestReg).addImm(0);
         } else {
-          unsigned Opcode = isSigned ? X86::SAR32ri : X86::SHR32ri;
-          BuildMI(*MBB, IP, Opcode, 2, DestReg).addReg(SrcReg+1).addImm(Amount);
+          if (Amount != 0) {
+            BuildMI(*MBB, IP, isSigned ? X86::SAR32ri : X86::SHR32ri, 2,
+                    DestReg).addReg(SrcReg+1).addImm(Amount);
+          } else {
+            BuildMI(*MBB, IP, X86::MOV32rr, 1, DestReg).addReg(SrcReg+1);
+          }
           BuildMI(*MBB, IP, X86::MOV32ri, 1, DestReg+1).addImm(0);
         }
       }
@@ -2346,6 +2616,11 @@ void ISel::visitStoreInst(StoreInst &I) {
 ///
 void ISel::visitCastInst(CastInst &CI) {
   Value *Op = CI.getOperand(0);
+
+  // Noop casts are not even emitted.
+  if (getClassB(CI.getType()) == getClassB(Op->getType()))
+    return;
+
   // 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.
@@ -2491,7 +2766,7 @@ void ISel::emitCastOperation(MachineBasicBlock *BB,
     // a larger signed value, then use FLD on the larger value.
     //
     const Type *PromoteType = 0;
-    unsigned PromoteOpcode;
+    unsigned PromoteOpcode = 0;
     unsigned RealDestReg = DestReg;
     switch (SrcTy->getPrimitiveID()) {
     case Type::BoolTyID:
@@ -2529,8 +2804,7 @@ void ISel::emitCastOperation(MachineBasicBlock *BB,
     
     if (PromoteType) {
       unsigned TmpReg = makeAnotherReg(PromoteType);
-      unsigned Opc = SrcTy->isSigned() ? X86::MOVSX16rr8 : X86::MOVZX16rr8;
-      BuildMI(*BB, IP, Opc, 1, TmpReg).addReg(SrcReg);
+      BuildMI(*BB, IP, PromoteOpcode, 1, TmpReg).addReg(SrcReg);
       SrcTy = PromoteType;
       SrcClass = getClass(PromoteType);
       SrcReg = TmpReg;