Skip to content
InstSelectSimple.cpp 47.5 KiB
Newer Older
//===-- InstSelectSimple.cpp - A simple instruction selector for x86 ------===//
//
// This file defines a simple peephole instruction selector for the x86 platform
//
//===----------------------------------------------------------------------===//

#include "X86.h"
#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"
Brian Gaeke's avatar
 
Brian Gaeke committed
#include "llvm/DerivedTypes.h"
#include "llvm/Constants.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
Chris Lattner's avatar
Chris Lattner committed
#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/InstVisitor.h"
#include "llvm/Target/MRegisterInfo.h"
#include <map>
Chris Lattner's avatar
Chris Lattner committed
/// BMI - A special BuildMI variant that takes an iterator to insert the
/// instruction at as well as a basic block.
Brian Gaeke's avatar
 
Brian Gaeke committed
/// this is the version for when you have a destination register in mind.
inline static MachineInstrBuilder BMI(MachineBasicBlock *MBB,
Chris Lattner's avatar
Chris Lattner committed
                                      MachineBasicBlock::iterator &I,
                                      MachineOpCode Opcode,
                                      unsigned NumOperands,
                                      unsigned DestReg) {
Chris Lattner's avatar
Chris Lattner committed
  assert(I >= MBB->begin() && I <= MBB->end() && "Bad iterator!");
Chris Lattner's avatar
Chris Lattner committed
  MachineInstr *MI = new MachineInstr(Opcode, NumOperands+1, true, true);
  I = MBB->insert(I, MI)+1;
Chris Lattner's avatar
Chris Lattner committed
  return MachineInstrBuilder(MI).addReg(DestReg, MOTy::Def);
}

Chris Lattner's avatar
Chris Lattner committed
/// BMI - A special BuildMI variant that takes an iterator to insert the
/// instruction at as well as a basic block.
Brian Gaeke's avatar
 
Brian Gaeke committed
inline static MachineInstrBuilder BMI(MachineBasicBlock *MBB,
Chris Lattner's avatar
Chris Lattner committed
                                      MachineBasicBlock::iterator &I,
                                      MachineOpCode Opcode,
                                      unsigned NumOperands) {
Chris Lattner's avatar
Chris Lattner committed
  assert(I > MBB->begin() && I <= MBB->end() && "Bad iterator!");
Chris Lattner's avatar
Chris Lattner committed
  MachineInstr *MI = new MachineInstr(Opcode, NumOperands, true, true);
  I = MBB->insert(I, MI)+1;
Chris Lattner's avatar
Chris Lattner committed
  return MachineInstrBuilder(MI);
}

namespace {
  struct ISel : public FunctionPass, InstVisitor<ISel> {
    TargetMachine &TM;
    MachineFunction *F;                    // The function we are compiling into
    MachineBasicBlock *BB;                 // The current MBB we are compiling

    unsigned CurReg;
    std::map<Value*, unsigned> RegMap;  // Mapping between Val's and SSA Regs

Chris Lattner's avatar
Chris Lattner committed
    // MBBMap - Mapping between LLVM BB -> Machine BB
    std::map<const BasicBlock*, MachineBasicBlock*> MBBMap;

    ISel(TargetMachine &tm)
      : TM(tm), F(0), BB(0), CurReg(MRegisterInfo::FirstVirtualRegister) {}

    /// runOnFunction - Top level implementation of instruction selection for
    /// the entire function.
    ///
    bool runOnFunction(Function &Fn) {
      F = &MachineFunction::construct(&Fn, TM);
      // Create all of the machine basic blocks for the function...
Chris Lattner's avatar
Chris Lattner committed
      for (Function::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
        F->getBasicBlockList().push_back(MBBMap[I] = new MachineBasicBlock(I));

Chris Lattner's avatar
Chris Lattner committed
      BB = &F->front();
Chris Lattner's avatar
Chris Lattner committed

Chris Lattner's avatar
Chris Lattner committed
      // Instruction select everything except PHI nodes
Chris Lattner's avatar
Chris Lattner committed

      // Select the PHI nodes
      SelectPHINodes();

      RegMap.clear();
Chris Lattner's avatar
Chris Lattner committed
      MBBMap.clear();
      CurReg = MRegisterInfo::FirstVirtualRegister;
      return false;  // We never modify the LLVM itself.
    }

Chris Lattner's avatar
Chris Lattner committed
    virtual const char *getPassName() const {
      return "X86 Simple Instruction Selection";
    }

    /// visitBasicBlock - This method is called when we are visiting a new basic
Chris Lattner's avatar
Chris Lattner committed
    /// block.  This simply creates a new MachineBasicBlock to emit code into
    /// and adds it to the current MachineFunction.  Subsequent visit* for
    /// instructions will be invoked for all instructions in the basic block.
    ///
    void visitBasicBlock(BasicBlock &LLVM_BB) {
Chris Lattner's avatar
Chris Lattner committed
      BB = MBBMap[&LLVM_BB];
    /// LoadArgumentsToVirtualRegs - Load all of the arguments to this function
    /// from the stack into virtual registers.
    ///
    void LoadArgumentsToVirtualRegs(Function &F);
Chris Lattner's avatar
Chris Lattner committed

    /// SelectPHINodes - Insert machine code to generate phis.  This is tricky
    /// because we have to generate our sources into the source basic blocks,
    /// not the current one.
    ///
    void SelectPHINodes();

    // Visitation methods for various instructions.  These methods simply emit
    // fixed X86 code for each instruction.
    //
    void visitReturnInst(ReturnInst &RI);
    void visitBranchInst(BranchInst &BI);
    void visitCallInst(CallInst &I);
    void visitSimpleBinary(BinaryOperator &B, unsigned OpcodeClass);
Chris Lattner's avatar
Chris Lattner committed
    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 *resultType,
		    unsigned op0Reg, unsigned op1Reg);
    void visitMul(BinaryOperator &B);
    void visitDiv(BinaryOperator &B) { visitDivRem(B); }
    void visitRem(BinaryOperator &B) { visitDivRem(B); }
    void visitDivRem(BinaryOperator &B);

    // Bitwise operators
Chris Lattner's avatar
Chris Lattner committed
    void visitAnd(BinaryOperator &B) { visitSimpleBinary(B, 2); }
    void visitOr (BinaryOperator &B) { visitSimpleBinary(B, 3); }
    void visitXor(BinaryOperator &B) { visitSimpleBinary(B, 4); }

    // Binary comparison operators
Chris Lattner's avatar
Chris Lattner committed
    void visitSetCCInst(SetCondInst &I, unsigned OpNum);
    void visitSetEQ(SetCondInst &I) { visitSetCCInst(I, 0); }
    void visitSetNE(SetCondInst &I) { visitSetCCInst(I, 1); }
    void visitSetLT(SetCondInst &I) { visitSetCCInst(I, 2); }
    void visitSetGT(SetCondInst &I) { visitSetCCInst(I, 3); }
    void visitSetLE(SetCondInst &I) { visitSetCCInst(I, 4); }
    void visitSetGE(SetCondInst &I) { visitSetCCInst(I, 5); }

    // Memory Instructions
    void visitLoadInst(LoadInst &I);
    void visitStoreInst(StoreInst &I);
Brian Gaeke's avatar
 
Brian Gaeke committed
    void visitGetElementPtrInst(GetElementPtrInst &I);
    void visitAllocaInst(AllocaInst &I);

    // We assume that by this point, malloc instructions have been
    // lowered to calls, and dlsym will magically find malloc for us.
    void visitMallocInst(MallocInst &I) { visitInstruction (I); }
    void visitFreeInst(FreeInst &I) { visitInstruction(I); }
Brian Gaeke's avatar
 
Brian Gaeke committed
    
    void visitShiftInst(ShiftInst &I);
Chris Lattner's avatar
Chris Lattner committed
    void visitPHINode(PHINode &I) {}      // PHI nodes handled by second pass
    void visitCastInst(CastInst &I);

    void visitInstruction(Instruction &I) {
      std::cerr << "Cannot instruction select: " << I;
      abort();
    }

Brian Gaeke's avatar
 
Brian Gaeke committed
    /// promote32 - Make a value 32-bits wide, and put it somewhere.
    void promote32 (const unsigned targetReg, Value *v);
    
    // emitGEPOperation - Common code shared between visitGetElementPtrInst and
    // constant expression GEP support.
    //
Chris Lattner's avatar
Chris Lattner committed
    void emitGEPOperation(MachineBasicBlock *BB, MachineBasicBlock::iterator&IP,
Chris Lattner's avatar
Chris Lattner committed
                          Value *Src, User::op_iterator IdxBegin,
                          User::op_iterator IdxEnd, unsigned TargetReg);

    /// copyConstantToRegister - Output the instructions required to put the
    /// specified constant into the specified register.
    ///
    void copyConstantToRegister(MachineBasicBlock *MBB,
                                MachineBasicBlock::iterator &MBBI,
                                Constant *C, unsigned Reg);
Brian Gaeke's avatar
 
Brian Gaeke committed
    /// makeAnotherReg - This method returns the next register number
    /// we haven't yet used.
    unsigned makeAnotherReg(const Type *Ty) {
      // Add the mapping of regnumber => reg class to MachineFunction
Chris Lattner's avatar
Chris Lattner committed
      const TargetRegisterClass *RC =
	TM.getRegisterInfo()->getRegClassForType(Ty);
      F->getSSARegMap()->addRegMap(CurReg, RC);
      return CurReg++;
Brian Gaeke's avatar
 
Brian Gaeke committed
    }

    /// getReg - This method turns an LLVM value into a register number.  This
    /// is guaranteed to produce the same register number for a particular value
    /// every time it is queried.
    ///
    unsigned getReg(Value &V) { return getReg(&V); }  // Allow references
Chris Lattner's avatar
Chris Lattner committed
    unsigned getReg(Value *V) {
      // Just append to the end of the current bb.
      MachineBasicBlock::iterator It = BB->end();
      return getReg(V, BB, It);
    }
Brian Gaeke's avatar
 
Brian Gaeke committed
    unsigned getReg(Value *V, MachineBasicBlock *MBB,
Chris Lattner's avatar
Chris Lattner committed
                    MachineBasicBlock::iterator &IPt) {
      unsigned &Reg = RegMap[V];
        Reg = makeAnotherReg(V->getType());
Chris Lattner's avatar
Chris Lattner committed
      // If this operand is a constant, emit the code to copy the constant into
      // the register here...
      //
      if (Constant *C = dyn_cast<Constant>(V)) {
        copyConstantToRegister(MBB, IPt, C, Reg);
Chris Lattner's avatar
Chris Lattner committed
        RegMap.erase(V);  // Assign a new name to this constant if ref'd again
      } else if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
        // Move the address of the global into the register
Brian Gaeke's avatar
 
Brian Gaeke committed
        BMI(MBB, IPt, X86::MOVir32, 1, Reg).addReg(GV);
Chris Lattner's avatar
Chris Lattner committed
        RegMap.erase(V);  // Assign a new name to this address if ref'd again
/// TypeClass - Used by the X86 backend to group LLVM types by their basic X86
/// Representation.
///
enum TypeClass {
Chris Lattner's avatar
Chris Lattner committed
  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::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
Chris Lattner's avatar
Chris Lattner committed
  case Type::FloatTyID:
  case Type::DoubleTyID:  return cFP;        // Floating Point is #3
  case Type::ULongTyID:   //return cLong;      // Longs are class #3
    return cInt;          // FIXME: LONGS ARE TREATED AS INTS!
  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.
///
void ISel::copyConstantToRegister(MachineBasicBlock *MBB,
                                  MachineBasicBlock::iterator &IP,
                                  Constant *C, unsigned R) {
  if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
    if (CE->getOpcode() == Instruction::GetElementPtr) {
Brian Gaeke's avatar
Brian Gaeke committed
      emitGEPOperation(MBB, IP, CE->getOperand(0),
Chris Lattner's avatar
Chris Lattner committed
                       CE->op_begin()+1, CE->op_end(), R);
Brian Gaeke's avatar
 
Brian Gaeke committed
    std::cerr << "Offending expr: " << C << "\n";
Chris Lattner's avatar
Chris Lattner committed
    assert(0 && "Constant expressions not yet handled!\n");
Brian Gaeke's avatar
 
Brian Gaeke committed
  }
    unsigned Class = getClassB(C->getType());
Chris Lattner's avatar
Chris Lattner committed
    assert(Class <= cInt && "Type not handled yet!");

    static const unsigned IntegralOpcodeTab[] = {
      X86::MOVir8, X86::MOVir16, X86::MOVir32
    };

    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);
Brian Gaeke's avatar
 
Brian Gaeke committed
      BMI(MBB, IP, IntegralOpcodeTab[Class], 1, R).addSImm(CSI->getValue());
    } else {
      ConstantUInt *CUI = cast<ConstantUInt>(C);
Brian Gaeke's avatar
 
Brian Gaeke committed
      BMI(MBB, IP, IntegralOpcodeTab[Class], 1, R).addZImm(CUI->getValue());
Chris Lattner's avatar
Chris Lattner committed
  } else if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
    double Value = CFP->getValue();
    if (Value == +0.0)
      BMI(MBB, IP, X86::FLD0, 0, R);
    else if (Value == +1.0)
      BMI(MBB, IP, X86::FLD1, 0, R);
    else {
      std::cerr << "Cannot load constant '" << Value << "'!\n";
      assert(0);
    }

Chris Lattner's avatar
Chris Lattner committed
  } else if (isa<ConstantPointerNull>(C)) {
Brian Gaeke's avatar
 
Brian Gaeke committed
    // Copy zero (null pointer) to the register.
Brian Gaeke's avatar
 
Brian Gaeke committed
    BMI(MBB, IP, X86::MOVir32, 1, R).addZImm(0);
  } else if (ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(C)) {
Brian Gaeke's avatar
Brian Gaeke committed
    unsigned SrcReg = getReg(CPR->getValue(), MBB, IP);
Brian Gaeke's avatar
 
Brian Gaeke committed
    BMI(MBB, IP, X86::MOVrr32, 1, R).addReg(SrcReg);
Brian Gaeke's avatar
 
Brian Gaeke committed
    std::cerr << "Offending constant: " << C << "\n";
    assert(0 && "Type not handled yet!");
/// LoadArgumentsToVirtualRegs - Load all of the arguments to this function from
/// the stack into virtual registers.
///
void ISel::LoadArgumentsToVirtualRegs(Function &Fn) {
  // Emit instructions to load the arguments...  On entry to a function on the
  // X86, the stack frame looks like this:
  //
  // [ESP] -- return address
  // [ESP + 4] -- first argument (leftmost lexically) if four bytes in size
  // [ESP + 8] -- second argument, if four bytes in size
  //    ... 
  //
  unsigned ArgOffset = 0;
  MachineFrameInfo *MFI = F->getFrameInfo();

  for (Function::aiterator I = Fn.abegin(), E = Fn.aend(); I != E; ++I) {
    unsigned Reg = getReg(*I);
    
    ArgOffset += 4;  // Each argument takes at least 4 bytes on the stack...
    int FI;          // Frame object index

    switch (getClassB(I->getType())) {
    case cByte:
      FI = MFI->CreateFixedObject(1, ArgOffset);
      addFrameReference(BuildMI(BB, X86::MOVmr8, 4, Reg), FI);
      break;
    case cShort:
      FI = MFI->CreateFixedObject(2, ArgOffset);
      addFrameReference(BuildMI(BB, X86::MOVmr16, 4, Reg), FI);
      break;
    case cInt:
      FI = MFI->CreateFixedObject(4, ArgOffset);
      addFrameReference(BuildMI(BB, X86::MOVmr32, 4, Reg), FI);
      break;
    case cFP:
      unsigned Opcode;
      if (I->getType() == Type::FloatTy) {
	Opcode = X86::FLDr32;
	FI = MFI->CreateFixedObject(4, ArgOffset);
      } else {
	Opcode = X86::FLDr64;
	ArgOffset += 4;   // doubles require 4 additional bytes
	FI = MFI->CreateFixedObject(8, ArgOffset);
      }
      addFrameReference(BuildMI(BB, Opcode, 4, Reg), FI);
      break;
    default:
      assert(0 && "Unhandled argument type!");
    }
  }
}


Chris Lattner's avatar
Chris Lattner committed
/// SelectPHINodes - Insert machine code to generate phis.  This is tricky
/// because we have to generate our sources into the source basic blocks, not
/// the current one.
///
void ISel::SelectPHINodes() {
  const Function &LF = *F->getFunction();  // The LLVM function...
  for (Function::const_iterator I = LF.begin(), E = LF.end(); I != E; ++I) {
    const BasicBlock *BB = I;
    MachineBasicBlock *MBB = MBBMap[I];

    // Loop over all of the PHI nodes in the LLVM basic block...
    unsigned NumPHIs = 0;
    for (BasicBlock::const_iterator I = BB->begin();
         PHINode *PN = (PHINode*)dyn_cast<PHINode>(&*I); ++I) {
      // Create a new machine instr PHI node, and insert it.
      MachineInstr *MI = BuildMI(X86::PHI, PN->getNumOperands(), getReg(*PN));
      MBB->insert(MBB->begin()+NumPHIs++, MI); // Insert it at the top of the BB

      for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
        MachineBasicBlock *PredMBB = MBBMap[PN->getIncomingBlock(i)];

        // Get the incoming value into a virtual register.  If it is not already
        // available in a virtual register, insert the computation code into
        // PredMBB
	// FIXME: This should insert the code into the BOTTOM of the block, not
	// the top of the block.  This just makes for huge live ranges...
        MachineBasicBlock::iterator PI = PredMBB->begin();
        while ((*PI)->getOpcode() == X86::PHI) ++PI;
        
Chris Lattner's avatar
Chris Lattner committed
        MI->addRegOperand(getReg(PN->getIncomingValue(i), PredMBB, PI));
        MI->addMachineBasicBlockOperand(PredMBB);
/// SetCC instructions - Here we just emit boilerplate code to set a byte-sized
/// register, then move it to wherever the result should be. 
/// We handle FP setcc instructions by pushing them, doing a
/// compare-and-pop-twice, and then copying the concodes to the main
/// processor's concodes (I didn't make this up, it's in the Intel manual)
///
Chris Lattner's avatar
Chris Lattner committed
void ISel::visitSetCCInst(SetCondInst &I, unsigned OpNum) {
  // The arguments are already supposed to be of the same type.
Chris Lattner's avatar
Chris Lattner committed
  const Type *CompTy = I.getOperand(0)->getType();
  unsigned reg1 = getReg(I.getOperand(0));
  unsigned reg2 = getReg(I.getOperand(1));

  unsigned Class = getClass(CompTy);
  switch (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);
    break;
  case cShort:
    BuildMI (BB, X86::CMPrr16, 2).addReg (reg1).addReg (reg2);
    break;
  case cInt:
    BuildMI (BB, X86::CMPrr32, 2).addReg (reg1).addReg (reg2);
    break;

Chris Lattner's avatar
Chris Lattner committed
#if 0
Chris Lattner's avatar
Chris Lattner committed
    // Push the variables on the stack with fldl opcodes.
    // FIXME: assuming var1, var2 are in memory, if not, spill to
    // stack first
Chris Lattner's avatar
Chris Lattner committed
  case cFP:  // Floats
Brian Gaeke's avatar
 
Brian Gaeke committed
    BuildMI (BB, X86::FLDr32, 1).addReg (reg1);
    BuildMI (BB, X86::FLDr32, 1).addReg (reg2);
Chris Lattner's avatar
Chris Lattner committed
    break;
Chris Lattner's avatar
Chris Lattner committed
  case cFP (doubles):  // Doubles
Brian Gaeke's avatar
 
Brian Gaeke committed
    BuildMI (BB, X86::FLDr64, 1).addReg (reg1);
    BuildMI (BB, X86::FLDr64, 1).addReg (reg2);
Chris Lattner's avatar
Chris Lattner committed
    break;
Chris Lattner's avatar
Chris Lattner committed
#endif
Chris Lattner's avatar
Chris Lattner committed
  case cLong:
  default:
    visitInstruction(I);
  }

Chris Lattner's avatar
Chris Lattner committed
#if 0
Chris Lattner's avatar
Chris Lattner committed
  if (CompTy->isFloatingPoint()) {
    // (Non-trapping) compare and pop twice.
    BuildMI (BB, X86::FUCOMPP, 0);
    // Move fp status word (concodes) to ax.
    BuildMI (BB, X86::FNSTSWr8, 1, X86::AX);
    // Load real concodes from ax.
    BuildMI (BB, X86::SAHF, 1).addReg(X86::AH);
  }
Chris Lattner's avatar
Chris Lattner committed
#endif
  // Emit setOp instruction (extract concode; clobbers ax),
  // using the following mapping:
  // LLVM  -> X86 signed  X86 unsigned
  // -----    -----       -----
  // seteq -> sete        sete
  // setne -> setne       setne
  // setlt -> setl        setb
  // setgt -> setg        seta
  // setle -> setle       setbe
  // setge -> setge       setae
Chris Lattner's avatar
Chris Lattner committed

  static const unsigned OpcodeTab[2][6] = {
    {X86::SETEr, X86::SETNEr, X86::SETBr, X86::SETAr, X86::SETBEr, X86::SETAEr},
    {X86::SETEr, X86::SETNEr, X86::SETLr, X86::SETGr, X86::SETLEr, X86::SETGEr},
  BuildMI(BB, OpcodeTab[CompTy->isSigned()][OpNum], 0, getReg(I));
Brian Gaeke's avatar
Brian Gaeke committed
/// promote32 - Emit instructions to turn a narrow operand into a 32-bit-wide
/// operand, in the specified target register.
Chris Lattner's avatar
Chris Lattner committed
void ISel::promote32 (unsigned targetReg, Value *v) {
  unsigned vReg = getReg(v);
  bool isUnsigned = v->getType()->isUnsigned();
  switch (getClass(v->getType())) {
  case cByte:
    // Extend value into target register (8->32)
    if (isUnsigned)
      BuildMI(BB, X86::MOVZXr32r8, 1, targetReg).addReg(vReg);
    else
      BuildMI(BB, X86::MOVSXr32r8, 1, targetReg).addReg(vReg);
    break;
  case cShort:
    // Extend value into target register (16->32)
    if (isUnsigned)
      BuildMI(BB, X86::MOVZXr32r16, 1, targetReg).addReg(vReg);
    else
      BuildMI(BB, X86::MOVSXr32r16, 1, targetReg).addReg(vReg);
    break;
  case cInt:
    // Move value into target register (32->32)
    BuildMI(BB, X86::MOVrr32, 1, targetReg).addReg(vReg);
    break;
  default:
    assert(0 && "Unpromotable operand class in promote32");
  }
Brian Gaeke's avatar
Brian Gaeke committed
}
/// 'ret' instruction - Here we are interested in meeting the x86 ABI.  As such,
/// we have the following possibilities:
///
///   ret void: No return value, simply emit a 'ret' instruction
///   ret sbyte, ubyte : Extend value into EAX and return
///   ret short, ushort: Extend value into EAX and return
///   ret int, uint    : Move value into EAX and return
///   ret pointer      : Move value into EAX and return
Chris Lattner's avatar
Chris Lattner committed
///   ret long, ulong  : Move value into EAX/EDX and return
///   ret float/double : Top of FP stack
Chris Lattner's avatar
Chris Lattner committed
void ISel::visitReturnInst (ReturnInst &I) {
  if (I.getNumOperands() == 0) {
    BuildMI(BB, X86::RET, 0); // Just emit a 'ret' instruction
    return;
  }

  Value *RetVal = I.getOperand(0);
  switch (getClass(RetVal->getType())) {
  case cByte:   // integral return values: extend or move into EAX and return
  case cShort:
  case cInt:
    promote32(X86::EAX, RetVal);
    break;
  case cFP:                   // Floats & Doubles: Return in ST(0)
    BuildMI(BB, X86::FpMOV, 1, X86::ST0).addReg(getReg(RetVal));
    break;
  case cLong:
    // ret long: use EAX(least significant 32 bits)/EDX (most
    // significant 32)...
  default:
    visitInstruction (I);
  }
  // Emit a 'ret' instruction
Chris Lattner's avatar
Chris Lattner committed
  BuildMI(BB, X86::RET, 0);
/// visitBranchInst - Handle conditional and unconditional branches here.  Note
/// that since code layout is frozen at this point, that if we are trying to
/// jump to a block that is the immediate successor of the current block, we can
/// just make a fall-through. (but we don't currently).
///
Chris Lattner's avatar
Chris Lattner committed
void ISel::visitBranchInst(BranchInst &BI) {
  if (BI.isConditional()) {
    BasicBlock *ifTrue  = BI.getSuccessor(0);
    BasicBlock *ifFalse = BI.getSuccessor(1);

    // Compare condition with zero, followed by jump-if-equal to ifFalse, and
    // jump-if-nonequal to ifTrue
    unsigned condReg = getReg(BI.getCondition());
Chris Lattner's avatar
Chris Lattner committed
    BuildMI(BB, X86::CMPri8, 2).addReg(condReg).addZImm(0);
    BuildMI(BB, X86::JNE, 1).addPCDisp(BI.getSuccessor(0));
    BuildMI(BB, X86::JE, 1).addPCDisp(BI.getSuccessor(1));
  } else { // unconditional branch
    BuildMI(BB, X86::JMP, 1).addPCDisp(BI.getSuccessor(0));
  }
Brian Gaeke's avatar
Brian Gaeke committed
/// visitCallInst - Push args on stack and do a procedure call instruction.
Chris Lattner's avatar
Chris Lattner committed
void ISel::visitCallInst(CallInst &CI) {
  // Count how many bytes are to be pushed on the stack...
  unsigned NumBytes = 0;

  if (CI.getNumOperands() > 1) {
    for (unsigned i = 1, e = CI.getNumOperands(); i != e; ++i)
      switch (getClass(CI.getOperand(i)->getType())) {
      case cByte: case cShort: case cInt:
	NumBytes += 4;
	break;
      case cLong:
	NumBytes += 8;
	break;
      case cFP:
	NumBytes += CI.getOperand(i)->getType() == Type::FloatTy ? 4 : 8;
	break;
      default: assert(0 && "Unknown class!");
      }

    // Adjust the stack pointer for the new arguments...
    BuildMI(BB, X86::ADJCALLSTACKDOWN, 1).addZImm(NumBytes);

    // Arguments go on the stack in reverse order, as specified by the ABI.
    unsigned ArgOffset = 0;
    for (unsigned i = 1, e = CI.getNumOperands(); i != e; ++i) {
      Value *Arg = CI.getOperand(i);
      switch (getClass(Arg->getType())) {
      case cByte:
      case cShort: {
	// Promote arg to 32 bits wide into a temporary register...
	unsigned R = makeAnotherReg(Type::UIntTy);
	promote32(R, Arg);
	addRegOffset(BuildMI(BB, X86::MOVrm32, 5),
		     X86::ESP, ArgOffset).addReg(R);
	break;
      }
      case cInt:
	addRegOffset(BuildMI(BB, X86::MOVrm32, 5),
		     X86::ESP, ArgOffset).addReg(getReg(Arg));
	break;

      case cFP:
	if (Arg->getType() == Type::FloatTy) {
	  addRegOffset(BuildMI(BB, X86::FSTr32, 5),
		       X86::ESP, ArgOffset).addReg(getReg(Arg));
	} else {
	  assert(Arg->getType() == Type::DoubleTy && "Unknown FP type!");
	  ArgOffset += 4;
	  addRegOffset(BuildMI(BB, X86::FSTr32, 5),
		       X86::ESP, ArgOffset).addReg(getReg(Arg));
	}
	break;

      default:
	// FIXME: long/ulong/float/double args not handled.
	visitInstruction(CI);
	break;
      }
      ArgOffset += 4;
Brian Gaeke's avatar
Brian Gaeke committed
    }

  if (Function *F = CI.getCalledFunction()) {
    // Emit a CALL instruction with PC-relative displacement.
    BuildMI(BB, X86::CALLpcrel32, 1).addPCDisp(F);
  } else {
    unsigned Reg = getReg(CI.getCalledValue());
    BuildMI(BB, X86::CALLr32, 1).addReg(Reg);
  }
  BuildMI(BB, X86::ADJCALLSTACKUP, 1).addZImm(NumBytes);

  // If there is a return value, scavenge the result from the location the call
  // leaves it in...
  //
  if (CI.getType() != Type::VoidTy) {
Chris Lattner's avatar
Chris Lattner committed
    unsigned resultTypeClass = getClass(CI.getType());
Brian Gaeke's avatar
 
Brian Gaeke committed
    switch (resultTypeClass) {
    case cByte:
    case cShort:
    case cInt: {
      // Integral results are in %eax, or the appropriate portion
      // thereof.
      static const unsigned regRegMove[] = {
	X86::MOVrr8, X86::MOVrr16, X86::MOVrr32
      };
      static const unsigned AReg[] = { X86::AL, X86::AX, X86::EAX };
Chris Lattner's avatar
Chris Lattner committed
      BuildMI(BB, regRegMove[resultTypeClass], 1, getReg(CI))
	         .addReg(AReg[resultTypeClass]);
Brian Gaeke's avatar
 
Brian Gaeke committed
      break;
    }
Chris Lattner's avatar
Chris Lattner committed
    case cFP:     // Floating-point return values live in %ST(0)
      BuildMI(BB, X86::FpMOV, 1, getReg(CI)).addReg(X86::ST0);
      break;
    default:
      std::cerr << "Cannot get return value for call of type '"
                << *CI.getType() << "'\n";
      visitInstruction(CI);
    }
Chris Lattner's avatar
Chris Lattner committed
/// 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) {
  if (B.getType() == Type::BoolTy)  // FIXME: Handle bools for logicals
    visitInstruction(B);

  unsigned Class = getClass(B.getType());
Chris Lattner's avatar
Chris Lattner committed
  if (Class > cFP)  // FIXME: Handle longs
    visitInstruction(B);

  static const unsigned OpcodeTab[][4] = {
Chris Lattner's avatar
Chris Lattner committed
    // Arithmetic operators
Chris Lattner's avatar
Chris Lattner committed
    { X86::ADDrr8, X86::ADDrr16, X86::ADDrr32, X86::FpADD },  // ADD
    { X86::SUBrr8, X86::SUBrr16, X86::SUBrr32, X86::FpSUB },  // SUB
Chris Lattner's avatar
Chris Lattner committed

    // 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
  };
  
  unsigned Opcode = OpcodeTab[OperatorClass][Class];
Chris Lattner's avatar
Chris Lattner committed
  assert(Opcode && "Floating point arguments to logical inst?");
  unsigned Op0r = getReg(B.getOperand(0));
  unsigned Op1r = getReg(B.getOperand(1));
  BuildMI(BB, Opcode, 2, getReg(B)).addReg(Op0r).addReg(Op1r);
}

Brian Gaeke's avatar
 
Brian Gaeke committed
/// doMultiply - Emit appropriate instructions to multiply together
/// the registers op0Reg and op1Reg, and put the result in destReg.
/// The type of the result should be given as resultType.
void ISel::doMultiply(MachineBasicBlock *MBB, MachineBasicBlock::iterator &MBBI,
                      unsigned destReg, const Type *resultType,
                      unsigned op0Reg, unsigned op1Reg) {
Chris Lattner's avatar
Chris Lattner committed
  unsigned Class = getClass(resultType);
  switch (Class) {
  case cFP:              // Floating point multiply
    BuildMI(BB, X86::FpMUL, 2, destReg).addReg(op0Reg).addReg(op1Reg);
    return;
  default:
  case cLong:
    assert(0 && "doMultiply not implemented for this class yet!");
  case cByte:
  case cShort:
  case cInt:          // Small integerals, handled below...
    break;
  }
Brian Gaeke's avatar
 
Brian Gaeke committed
 
  static const unsigned Regs[]     ={ X86::AL    , X86::AX     , X86::EAX     };
  static const unsigned MulOpcode[]={ X86::MULrr8, X86::MULrr16, X86::MULrr32 };
  static const unsigned MovOpcode[]={ X86::MOVrr8, X86::MOVrr16, X86::MOVrr32 };
Chris Lattner's avatar
Chris Lattner committed
  unsigned Reg     = Regs[Class];
Brian Gaeke's avatar
 
Brian Gaeke committed
  // Emit a MOV to put the first operand into the appropriately-sized
  // subreg of EAX.
Brian Gaeke's avatar
 
Brian Gaeke committed
  BMI(MBB, MBBI, MovOpcode[Class], 1, Reg).addReg (op0Reg);
Brian Gaeke's avatar
 
Brian Gaeke committed
  // Emit the appropriate multiply instruction.
Brian Gaeke's avatar
 
Brian Gaeke committed
  BMI(MBB, MBBI, MulOpcode[Class], 1).addReg (op1Reg);
Brian Gaeke's avatar
 
Brian Gaeke committed
  // Emit another MOV to put the result into the destination register.
Brian Gaeke's avatar
 
Brian Gaeke committed
  BMI(MBB, MBBI, MovOpcode[Class], 1, destReg).addReg (Reg);
Brian Gaeke's avatar
 
Brian Gaeke committed
}

/// visitMul - Multiplies are not simple binary operators because they must deal
/// with the EAX register explicitly.
///
void ISel::visitMul(BinaryOperator &I) {
Chris Lattner's avatar
Chris Lattner committed
  unsigned DestReg = getReg(I);
  unsigned Op0Reg  = getReg(I.getOperand(0));
  unsigned Op1Reg  = getReg(I.getOperand(1));
Chris Lattner's avatar
Chris Lattner committed
  MachineBasicBlock::iterator MBBI = BB->end();
  doMultiply(BB, MBBI, DestReg, I.getType(), Op0Reg, Op1Reg);
/// visitDivRem - Handle division and remainder instructions... these
/// instruction both require the same instructions to be generated, they just
/// select the result from a different register.  Note that both of these
/// instructions work differently for signed and unsigned operands.
///
void ISel::visitDivRem(BinaryOperator &I) {
Chris Lattner's avatar
Chris Lattner committed
  unsigned Class     = getClass(I.getType());
  unsigned Op0Reg    = getReg(I.getOperand(0));
  unsigned Op1Reg    = getReg(I.getOperand(1));
  unsigned ResultReg = getReg(I);

  switch (Class) {
  case cFP:              // Floating point multiply
    if (I.getOpcode() == Instruction::Div)
      BuildMI(BB, X86::FpDIV, 2, ResultReg).addReg(Op0Reg).addReg(Op1Reg);
    else
      BuildMI(BB, X86::FpREM, 2, ResultReg).addReg(Op0Reg).addReg(Op1Reg);
    return;
  default:
  case cLong:
    assert(0 && "div/rem not implemented for this class yet!");
  case cByte:
  case cShort:
  case cInt:          // Small integerals, handled below...
    break;
  }

  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 ClrOpcode[]={ X86::XORrr8, X86::XORrr16, X86::XORrr32 };
  static const unsigned ExtRegs[]  ={ X86::AH    , X86::DX     , X86::EDX     };

  static const unsigned DivOpcode[][4] = {
    { X86::DIVrr8 , X86::DIVrr16 , X86::DIVrr32 , 0 },  // Unsigned division
    { X86::IDIVrr8, X86::IDIVrr16, X86::IDIVrr32, 0 },  // Signed division
  };
  bool isSigned   = I.getType()->isSigned();
  unsigned Reg    = Regs[Class];
  unsigned ExtReg = ExtRegs[Class];

  // Put the first operand into one of the A registers...
  BuildMI(BB, MovOpcode[Class], 1, Reg).addReg(Op0Reg);

  if (isSigned) {
    // Emit a sign extension instruction...
Chris Lattner's avatar
Chris Lattner committed
    BuildMI(BB, ExtOpcode[Class], 0);
  } else {
    // If unsigned, emit a zeroing instruction... (reg = xor reg, reg)
    BuildMI(BB, ClrOpcode[Class], 2, ExtReg).addReg(ExtReg).addReg(ExtReg);
  }

Chris Lattner's avatar
Chris Lattner committed
  // Emit the appropriate divide or remainder instruction...
  BuildMI(BB, DivOpcode[isSigned][Class], 1).addReg(Op1Reg);
  // Figure out which register we want to pick the result out of...
  unsigned DestReg = (I.getOpcode() == Instruction::Div) ? Reg : ExtReg;
  
  // Put the result into the destination register...
Chris Lattner's avatar
Chris Lattner committed
  BuildMI(BB, MovOpcode[Class], 1, ResultReg).addReg(DestReg);
/// Shift instructions: 'shl', 'sar', 'shr' - Some special cases here
/// for constant immediate shift values, and for constant immediate
/// shift values equal to 1. Even the general case is sort of special,
/// because the shift amount has to be in CL, not just any old register.
///
void ISel::visitShiftInst (ShiftInst &I) {
  unsigned Op0r = getReg (I.getOperand(0));
  unsigned DestReg = getReg(I);
  bool isLeftShift = I.getOpcode() == Instruction::Shl;
  bool isOperandSigned = I.getType()->isUnsigned();
  unsigned OperandClass = getClass(I.getType());

Chris Lattner's avatar
Chris Lattner committed
  if (OperandClass > cInt)
    visitInstruction(I); // Can't handle longs yet!
  if (ConstantUInt *CUI = dyn_cast<ConstantUInt> (I.getOperand (1)))
Chris Lattner's avatar
Chris Lattner committed
      // The shift amount is constant, guaranteed to be a ubyte. Get its value.
      assert(CUI->getType() == Type::UByteTy && "Shift amount not a ubyte?");
      unsigned char shAmt = CUI->getValue();

      static const unsigned ConstantOperand[][4] = {
        { X86::SHRir8, X86::SHRir16, X86::SHRir32, 0 },  // SHR
        { X86::SARir8, X86::SARir16, X86::SARir32, 0 },  // SAR
        { X86::SHLir8, X86::SHLir16, X86::SHLir32, 0 },  // SHL
        { X86::SHLir8, X86::SHLir16, X86::SHLir32, 0 },  // SAL = SHL
      const unsigned *OpTab = // Figure out the operand table to use
        ConstantOperand[isLeftShift*2+isOperandSigned];
      // Emit: <insn> reg, shamt  (shift-by-immediate opcode "ir" form.)
      BuildMI(BB, OpTab[OperandClass], 2, DestReg).addReg(Op0r).addZImm(shAmt);
    }
  else
    {
      // The shift amount is non-constant.
      //
      // In fact, you can only shift with a variable shift amount if
      // that amount is already in the CL register, so we have to put it
      // there first.
      //
      // Emit: move cl, shiftAmount (put the shift amount in CL.)
      BuildMI(BB, X86::MOVrr8, 1, X86::CL).addReg(getReg(I.getOperand(1)));
      static const unsigned NonConstantOperand[][4] = {
        { X86::SHRrr8, X86::SHRrr16, X86::SHRrr32, 0 },  // SHR
        { X86::SARrr8, X86::SARrr16, X86::SARrr32, 0 },  // SAR
        { X86::SHLrr8, X86::SHLrr16, X86::SHLrr32, 0 },  // SHL
        { X86::SHLrr8, X86::SHLrr16, X86::SHLrr32, 0 },  // SAL = SHL
      const unsigned *OpTab = // Figure out the operand table to use
        NonConstantOperand[isLeftShift*2+isOperandSigned];
      BuildMI(BB, OpTab[OperandClass], 1, DestReg).addReg(Op0r);
/// 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) {
  bool isLittleEndian  = TM.getTargetData().isLittleEndian();
  bool hasLongPointers = TM.getTargetData().getPointerSize() == 8;
Chris Lattner's avatar
Chris Lattner committed
  unsigned SrcAddrReg = getReg(I.getOperand(0));
  unsigned DestReg = getReg(I);
  unsigned Class = getClass(I.getType());
Chris Lattner's avatar
Chris Lattner committed
  switch (Class) {
  default: visitInstruction(I);   // FIXME: Handle longs...
  case cFP: {
    // FIXME: Handle endian swapping for FP values.
    unsigned Opcode = I.getType() == Type::FloatTy ? X86::FLDr32 : X86::FLDr64;
    addDirectMem(BuildMI(BB, Opcode, 4, DestReg), SrcAddrReg);
    return;
  }
  case cInt:      // Integers of various sizes handled below
  case cShort:
  case cByte: break;
  }

  // We need to adjust the input pointer if we are emulating a big-endian
  // long-pointer target.  On these systems, the pointer that we are interested
  // in is in the upper part of the eight byte memory image of the pointer.  It
  // also happens to be byte-swapped, but this will be handled later.
  //
  if (!isLittleEndian && hasLongPointers && isa<PointerType>(I.getType())) {
    unsigned R = makeAnotherReg(Type::UIntTy);
    BuildMI(BB, X86::ADDri32, 2, R).addReg(SrcAddrReg).addZImm(4);
    SrcAddrReg = R;
  }
  unsigned IReg = DestReg;
  if (!isLittleEndian) {  // If big endian we need an intermediate stage
    IReg = makeAnotherReg(I.getType());
    std::swap(IReg, DestReg);
  }
Chris Lattner's avatar
Chris Lattner committed

  static const unsigned Opcode[] = { X86::MOVmr8, X86::MOVmr16, X86::MOVmr32 };
  addDirectMem(BuildMI(BB, Opcode[Class], 4, DestReg), SrcAddrReg);
  if (!isLittleEndian) {
    // Emit the byte swap instruction...
Chris Lattner's avatar
Chris Lattner committed
    switch (Class) {
    case cByte:
      // No byteswap neccesary for 8 bit value...
      BuildMI(BB, X86::MOVrr8, 1, IReg).addReg(DestReg);
      break;
    case cInt:
      // Use the 32 bit bswap instruction to do a 32 bit swap...
      BuildMI(BB, X86::BSWAPr32, 1, IReg).addReg(DestReg);
      break;

    case cShort:
      // For 16 bit we have to use an xchg instruction, because there is no
      // 16-bit bswap.  XCHG is neccesarily not in SSA form, so we force things
      // into AX to do the xchg.
      //
      BuildMI(BB, X86::MOVrr16, 1, X86::AX).addReg(DestReg);
      BuildMI(BB, X86::XCHGrr8, 2).addReg(X86::AL, MOTy::UseAndDef)
                                  .addReg(X86::AH, MOTy::UseAndDef);
      BuildMI(BB, X86::MOVrr16, 1, DestReg).addReg(X86::AX);
      break;
    default: assert(0 && "Class not handled yet!");
    }
/// visitStoreInst - Implement LLVM store instructions in terms of the x86 'mov'
/// instruction.
///
void ISel::visitStoreInst(StoreInst &I) {
  bool isLittleEndian  = TM.getTargetData().isLittleEndian();
  bool hasLongPointers = TM.getTargetData().getPointerSize() == 8;
  unsigned ValReg = getReg(I.getOperand(0));
  unsigned AddressReg = getReg(I.getOperand(1));
Chris Lattner's avatar
Chris Lattner committed
  unsigned Class = getClass(I.getOperand(0)->getType());
  switch (Class) {
  default: visitInstruction(I);   // FIXME: Handle longs...
  case cFP: {
    // FIXME: Handle endian swapping for FP values.
    unsigned Opcode = I.getOperand(0)->getType() == Type::FloatTy ?
                            X86::FSTr32 : X86::FSTr64;
    addDirectMem(BuildMI(BB, Opcode, 1+4), AddressReg).addReg(ValReg);
    return;
  }
  case cInt:      // Integers of various sizes handled below
  case cShort:
  case cByte: break;
  }

  if (!isLittleEndian && hasLongPointers &&
      isa<PointerType>(I.getOperand(0)->getType())) {
    unsigned R = makeAnotherReg(Type::UIntTy);
    BuildMI(BB, X86::ADDri32, 2, R).addReg(AddressReg).addZImm(4);
    AddressReg = R;
  }

Chris Lattner's avatar
Chris Lattner committed
  if (!isLittleEndian && Class != cByte) {
    // Emit a byte swap instruction...