Factory methods for FunctionPasses now return type FunctionPass *.
[oota-llvm.git] / lib / Target / X86 / InstSelectSimple.cpp
index a7c3c648c8b1a57217fc9051688e68e081e649f5..2cc4e8367dfbdb5114695d258fcc86a7f6ea3a64 100644 (file)
@@ -85,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 {
@@ -121,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);
@@ -218,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.
@@ -228,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);
     }
 
@@ -343,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;
@@ -362,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();
@@ -585,11 +582,8 @@ bool ISel::EmitComparisonGetSignedness(unsigned OpNum, Value *Op0, Value *Op1) {
   // Special case handling of: cmp R, i
   if (Class == cByte || Class == cShort || Class == cInt)
     if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
-      uint64_t Op1v;
-      if (ConstantSInt *CSI = dyn_cast<ConstantSInt>(CI))
-        Op1v = CSI->getValue();
-      else
-        Op1v = cast<ConstantUInt>(CI)->getValue();
+      uint64_t Op1v = cast<ConstantInt>(CI)->getRawValue();
+
       // Mask off any upper bits of the constant, if there are any...
       Op1v &= (1ULL << (8 << Class)) - 1;
 
@@ -652,6 +646,8 @@ bool ISel::EmitComparisonGetSignedness(unsigned OpNum, Value *Op0, Value *Op1) {
       BuildMI(BB, SetCCOpcodeTab[0][OpNum], 0, X86::AL);
       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...
@@ -687,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");
@@ -856,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: {
@@ -953,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);
@@ -978,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!");
   }
 }
@@ -1053,11 +1060,7 @@ void ISel::emitSimpleBinaryOperation(MachineBasicBlock *BB,
     assert(Class < 3 && "General code handles 64-bit integer types!");
     unsigned Opcode = OpcodeTab[OperatorClass][Class];
     unsigned Op0r = getReg(Op0, BB, IP);
-    uint64_t Op1v;
-    if (ConstantSInt *CSI = dyn_cast<ConstantSInt>(Op1C))
-      Op1v = CSI->getValue();
-    else
-      Op1v = cast<ConstantUInt>(Op1C)->getValue();
+    uint64_t Op1v = cast<ConstantInt>(Op1C)->getRawValue();
 
     // Mask off any upper bits of the constant, if there are any...
     Op1v &= (1ULL << (8 << Class)) - 1;
@@ -1139,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;
@@ -1167,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;
   }
@@ -1179,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     };
 
@@ -1193,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...
@@ -1425,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();
@@ -1525,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) {
@@ -1806,9 +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:
-        assert(0 &&"FIXME not implemented: cast FP to unsigned long long");
-        abort();
+      // 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!");
       }
 
@@ -2071,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;
@@ -2088,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);
 }