Commit bb8b55b1 authored by CVS to SVN Conversion's avatar CVS to SVN Conversion
Browse files

This commit was manufactured by cvs2svn to create branch 'release_12'.

llvm-svn: 12471
parent b38cc9c0
Loading
Loading
Loading
Loading
+0 −240
Original line number Diff line number Diff line
/* Title:   SparcRegClassInfo.h    -*- C++ -*-
   Author:  Ruchira Sasanka
   Date:    Aug 20, 01
   Purpose: Contains the description of integer register class of Sparc
*/


#ifndef SPARC_INT_REG_CLASS_H
#define SPARC_INT_REG_CLASS_H

#include "llvm/Target/RegInfo.h"
#include "llvm/CodeGen/IGNode.h"

//-----------------------------------------------------------------------------
// Integer Register Class
//-----------------------------------------------------------------------------


// Int register names in same order as enum in class SparcIntRegOrder

static string const IntRegNames[] = 
  {       "g1", "g2", "g3", "g4", "g5", "g6", "g7",
    "o0", "o1", "o2", "o3", "o4", "o5",       "o7",
    "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
    "i0", "i1", "i2", "i3", "i4", "i5", 
    "g0", "i6", "i7",  "o6" }; 



class SparcIntRegOrder{ 

 public:

  enum RegsInPrefOrder   // colors possible for a LR (in preferred order)
   { 
     // --- following colors are volatile across function calls
     // %g0 can't be used for coloring - always 0
                     
     g1, g2, g3, g4, g5, g6, g7,  //%g1-%g7  
     o0, o1, o2, o3, o4, o5, o7,  // %o0-%o5, 

     // %o6 is sp, 
     // all %0's can get modified by a call

     // --- following colors are NON-volatile across function calls
      
     l0, l1, l2, l3, l4, l5, l6, l7,    //  %l0-%l7
     i0, i1, i2, i3, i4, i5,            // %i0-%i5: i's need not be preserved 
      
     // %i6 is the fp - so not allocated
     // %i7 is the ret address - can be used if saved

     // max # of colors reg coloring  can allocate (NumOfAvailRegs)

     // --- following colors are not available for allocation within this phase
     // --- but can appear for pre-colored ranges 

     g0, i6, i7,  o6

 

   };

  // max # of colors reg coloring  can allocate
  static unsigned int const NumOfAvailRegs = g0;

  static unsigned int const StartOfNonVolatileRegs = l0;
  static unsigned int const StartOfAllRegs = g1;
  static unsigned int const NumOfAllRegs = o6 + 1; 


  static const string  getRegName(const unsigned reg) {
    assert( reg < NumOfAllRegs );
    return IntRegNames[reg];
  }

};



class SparcIntRegClass : public MachineRegClassInfo
{
 public:

  SparcIntRegClass(unsigned ID) 
    : MachineRegClassInfo(ID, 
			  SparcIntRegOrder::NumOfAvailRegs,
			  SparcIntRegOrder::NumOfAllRegs)
    {  }

  void colorIGNode(IGNode * Node, bool IsColorUsedArr[] ) const;

};

//-----------------------------------------------------------------------------
// Float Register Class
//-----------------------------------------------------------------------------

static string const FloatRegNames[] = 
  {    
    "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",  "f8",  "f9", 
    "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19",
    "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29",
    "f30", "f31", "f32", "f33", "f34", "f35", "f36", "f37", "f38", "f39",
    "f40", "f41", "f42", "f43", "f44", "f45", "f46", "f47", "f48", "f49",
    "f50", "f51", "f52", "f53", "f54", "f55", "f56", "f57", "f58", "f59",
    "f60", "f61", "f62", "f63"
  };


class SparcFloatRegOrder{ 

 public:

  enum RegsInPrefOrder {

    f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, 
    f10, f11, f12, f13, f14, f15, f16, f17, f18, f19,
    f20, f21, f22, f23, f24, f25, f26, f27, f28, f29,
    f30, f31, f32, f33, f34, f35, f36, f37, f38, f39,
    f40, f41, f42, f43, f44, f45, f46, f47, f48, f49,
    f50, f51, f52, f53, f54, f55, f56, f57, f58, f59,
    f60, f61, f62, f63

  };

  // there are 64 regs alltogether but only 32 regs can be allocated at
  // a time.

  static unsigned int const NumOfAvailRegs = 32;
  static unsigned int const NumOfAllRegs = 64;

  static unsigned int const StartOfNonVolatileRegs = f6;
  static unsigned int const StartOfAllRegs = f0;


  static const string  getRegName(const unsigned reg) {
    assert( reg < NumOfAllRegs );
    return FloatRegNames[reg];
  }



};



class SparcFloatRegClass : public MachineRegClassInfo
{
 private:

  int findFloatColor(const IGNode *const Node, unsigned Start,
		     unsigned End, bool IsColorUsedArr[] ) const;

 public:

  SparcFloatRegClass(unsigned ID) 
    : MachineRegClassInfo(ID, 
			  SparcFloatRegOrder::NumOfAvailRegs,
			  SparcFloatRegOrder::NumOfAllRegs)
    {  }

  void colorIGNode(IGNode * Node, bool IsColorUsedArr[] ) const;

};




//-----------------------------------------------------------------------------
// Int CC Register Class
// Only one integer cc register is available
//-----------------------------------------------------------------------------


class SparcIntCCRegClass : public MachineRegClassInfo
{
public:

  SparcIntCCRegClass(unsigned ID) 
    : MachineRegClassInfo(ID,1, 1) {  }

  inline void colorIGNode(IGNode * Node, bool IsColorUsedArr[] ) const {
    Node->setColor(0);    // only one int cc reg is available
  }

};



//-----------------------------------------------------------------------------
// Float CC Register Class
// Only 4 Float CC registers are available
//-----------------------------------------------------------------------------


static string const FloatCCRegNames[] = 
  {    
    "fcc0",  "fcc1",  "fcc2",  "fcc3"
  };


class SparcFloatCCRegOrder{ 

 public:

  enum RegsInPrefOrder {

    fcc0, fcc1, fcc2, fcc3
  };

  static const string  getRegName(const unsigned reg) {
    assert( reg < 4 );
    return FloatCCRegNames[reg];
  }

};



class SparcFloatCCRegClass : public MachineRegClassInfo
{
public:

  SparcFloatCCRegClass(unsigned ID) 
    : MachineRegClassInfo(ID, 4, 4) {  }

  void colorIGNode(IGNode * Node, bool IsColorUsedArr[] ) const {
    int c;
    for(c=0; c < 4  && IsColorUsedArr[c] ; ++c) ; // find color
    assert( (c < 4)  && "Can allocate only 4 float cc registers");
    Node->setColor(c);   
  }

};




#endif
+0 −334
Original line number Diff line number Diff line
//===-- InstSelectSimple.cpp - A simple instruction selector for SparcV8 --===//
// 
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
// 
//===----------------------------------------------------------------------===//
//
// This file defines a simple peephole instruction selector for the V8 target
//
//===----------------------------------------------------------------------===//

#include "SparcV8.h"
#include "SparcV8InstrInfo.h"
#include "llvm/Instructions.h"
#include "llvm/IntrinsicLowering.h"
#include "llvm/Pass.h"
#include "llvm/Constants.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/Support/InstVisitor.h"
#include "llvm/Support/CFG.h"
using namespace llvm;

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

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

    // MBBMap - Mapping between LLVM BB -> Machine BB
    std::map<const BasicBlock*, MachineBasicBlock*> MBBMap;

    V8ISel(TargetMachine &tm) : TM(tm), F(0), BB(0) {}

    /// runOnFunction - Top level implementation of instruction selection for
    /// the entire function.
    ///
    bool runOnFunction(Function &Fn);

    virtual const char *getPassName() const {
      return "SparcV8 Simple Instruction Selection";
    }

    /// visitBasicBlock - This method is called when we are visiting a new basic
    /// 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) {
      BB = MBBMap[&LLVM_BB];
    }

	void visitBinaryOperator(BinaryOperator &I);
    void visitReturnInst(ReturnInst &RI);

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

    /// LowerUnknownIntrinsicFunctionCalls - This performs a prepass over the
    /// function, lowering any calls to unknown intrinsic functions into the
    /// equivalent LLVM code.
    void LowerUnknownIntrinsicFunctionCalls(Function &F);
    void visitIntrinsicCall(Intrinsic::ID ID, CallInst &CI);

    /// copyConstantToRegister - Output the instructions required to put the
    /// specified constant into the specified register.
    ///
    void copyConstantToRegister(MachineBasicBlock *MBB,
                                MachineBasicBlock::iterator IP,
                                Constant *C, unsigned R);

    /// makeAnotherReg - This method returns the next register number we haven't
    /// yet used.
    ///
    /// Long values are handled somewhat specially.  They are always allocated
    /// as pairs of 32 bit integer values.  The register number returned is the
    /// lower 32 bits of the long value, and the regNum+1 is the upper 32 bits
    /// of the long value.
    ///
    unsigned makeAnotherReg(const Type *Ty) {
      assert(dynamic_cast<const SparcV8RegisterInfo*>(TM.getRegisterInfo()) &&
             "Current target doesn't have SparcV8 reg info??");
      const SparcV8RegisterInfo *MRI =
        static_cast<const SparcV8RegisterInfo*>(TM.getRegisterInfo());
      if (Ty == Type::LongTy || Ty == Type::ULongTy) {
        const TargetRegisterClass *RC = MRI->getRegClassForType(Type::IntTy);
        // Create the lower part
        F->getSSARegMap()->createVirtualRegister(RC);
        // Create the upper part.
        return F->getSSARegMap()->createVirtualRegister(RC)-1;
      }

      // Add the mapping of regnumber => reg class to MachineFunction
      const TargetRegisterClass *RC = MRI->getRegClassForType(Ty);
      return F->getSSARegMap()->createVirtualRegister(RC);
    }

    unsigned getReg(Value &V) { return getReg (&V); } // allow refs.
    unsigned getReg(Value *V) {
      // Just append to the end of the current bb.
      MachineBasicBlock::iterator It = BB->end();
      return getReg(V, BB, It);
    }
    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)) {
        copyConstantToRegister(MBB, IPt, C, Reg);
        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
        unsigned TmpReg = makeAnotherReg(V->getType());
        BuildMI (*MBB, IPt, V8::SETHIi, 1, TmpReg).addGlobalAddress (GV);
        BuildMI (*MBB, IPt, V8::ORri, 2, Reg).addReg (TmpReg)
          .addGlobalAddress (GV);
        RegMap.erase(V);  // Assign a new name to this address if ref'd again
      }

      return Reg;
    }

  };
}

FunctionPass *llvm::createSparcV8SimpleInstructionSelector(TargetMachine &TM) {
  return new V8ISel(TM);
}

enum TypeClass {
  cByte, cShort, cInt, cLong, cFloat, cDouble
};

static TypeClass getClass (const Type *T) {
  switch (T->getPrimitiveID ()) {
    case Type::UByteTyID:  case Type::SByteTyID:  return cByte;
    case Type::UShortTyID: case Type::ShortTyID:  return cShort;
    case Type::UIntTyID:   case Type::IntTyID:    return cInt;
    case Type::ULongTyID:  case Type::LongTyID:   return cLong;
    case Type::FloatTyID:                         return cFloat;
    case Type::DoubleTyID:                        return cDouble;
    default:
      assert (0 && "Type of unknown class passed to getClass?");
      return cByte;
  }
}

/// copyConstantToRegister - Output the instructions required to put the
/// specified constant into the specified register.
///
void V8ISel::copyConstantToRegister(MachineBasicBlock *MBB,
                                    MachineBasicBlock::iterator IP,
                                    Constant *C, unsigned R) {
  if (ConstantInt *CI = dyn_cast<ConstantInt> (C)) {
    unsigned Class = getClass(C->getType());
    switch (Class) {
      case cByte:
        BuildMI (*MBB, IP, V8::ORri, 2, R).addReg (V8::G0).addImm ((uint8_t) CI->getRawValue ());
        return;
      case cShort: {
        unsigned TmpReg = makeAnotherReg (C->getType ());
        BuildMI (*MBB, IP, V8::SETHIi, 1, TmpReg).addImm (((uint16_t) CI->getRawValue ()) >> 10);
        BuildMI (*MBB, IP, V8::ORri, 2, R).addReg (TmpReg).addImm (((uint16_t) CI->getRawValue ()) & 0x03ff);
        return;
      }
      case cInt: {
        unsigned TmpReg = makeAnotherReg (C->getType ());
        BuildMI (*MBB, IP, V8::SETHIi, 1, TmpReg).addImm (((uint32_t) CI->getRawValue ()) >> 10);
        BuildMI (*MBB, IP, V8::ORri, 2, R).addReg (TmpReg).addImm (((uint32_t) CI->getRawValue ()) & 0x03ff);
        return;
      }
      default:
        assert (0 && "Can't copy this kind of constant into register yet");
        return;
    }
  }

  assert (0 && "Can't copy this kind of constant into register yet");
}

bool V8ISel::runOnFunction(Function &Fn) {
  // First pass over the function, lower any unknown intrinsic functions
  // with the IntrinsicLowering class.
  LowerUnknownIntrinsicFunctionCalls(Fn);
  
  F = &MachineFunction::construct(&Fn, TM);
  
  // Create all of the machine basic blocks for the function...
  for (Function::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
    F->getBasicBlockList().push_back(MBBMap[I] = new MachineBasicBlock(I));
  
  BB = &F->front();
  
  // Set up a frame object for the return address.  This is used by the
  // llvm.returnaddress & llvm.frameaddress intrinisics.
  //ReturnAddressIndex = F->getFrameInfo()->CreateFixedObject(4, -4);
  
  // Copy incoming arguments off of the stack and out of fixed registers.
  //LoadArgumentsToVirtualRegs(Fn);
  
  // Instruction select everything except PHI nodes
  visit(Fn);
  
  // Select the PHI nodes
  //SelectPHINodes();
  
  RegMap.clear();
  MBBMap.clear();
  F = 0;
  // We always build a machine code representation for the function
  return true;
}


void V8ISel::visitReturnInst(ReturnInst &I) {
  if (I.getNumOperands () == 1) {
    unsigned RetValReg = getReg (I.getOperand (0));
    switch (getClass (I.getOperand (0)->getType ())) {
      case cByte:
      case cShort:
      case cInt:
        // Schlep it over into i0 (where it will become o0 after restore).
        BuildMI (BB, V8::ORrr, 2, V8::I0).addReg(V8::G0).addReg(RetValReg);
        break;
      default:
        visitInstruction (I);
        return;
    }
  } else if (I.getNumOperands () != 1) {
    visitInstruction (I);
  }
  // Just emit a 'retl' instruction to return.
  BuildMI(BB, V8::RETL, 0);
  return;
}

void V8ISel::visitBinaryOperator (BinaryOperator &I) {
  unsigned DestReg = getReg (I);
  unsigned Op0Reg = getReg (I.getOperand (0));
  unsigned Op1Reg = getReg (I.getOperand (1));

  unsigned ResultReg = makeAnotherReg (I.getType ());
  switch (I.getOpcode ()) {
    case Instruction::Add: 
      BuildMI (BB, V8::ADDrr, 2, ResultReg).addReg (Op0Reg).addReg (Op1Reg);
      break;
    case Instruction::Sub: 
      BuildMI (BB, V8::SUBrr, 2, ResultReg).addReg (Op0Reg).addReg (Op1Reg);
      break;
    case Instruction::Mul: {
      unsigned MulOpcode = I.getType ()->isSigned () ? V8::SMULrr : V8::UMULrr;
      BuildMI (BB, MulOpcode, 2, ResultReg).addReg (Op0Reg).addReg (Op1Reg);
      break;
    }
    default:
      visitInstruction (I);
      return;
  }

  switch (getClass (I.getType ())) {
    case cByte: 
      if (I.getType ()->isSigned ()) { // add byte
        BuildMI (BB, V8::ANDri, 2, DestReg).addReg (ResultReg).addZImm (0xff);
      } else { // add ubyte
        unsigned TmpReg = makeAnotherReg (I.getType ());
        BuildMI (BB, V8::SLLri, 2, TmpReg).addReg (ResultReg).addZImm (24);
        BuildMI (BB, V8::SRAri, 2, DestReg).addReg (TmpReg).addZImm (24);
      }
      break;
    case cShort:
      if (I.getType ()->isSigned ()) { // add short
        unsigned TmpReg = makeAnotherReg (I.getType ());
        BuildMI (BB, V8::SLLri, 2, TmpReg).addReg (ResultReg).addZImm (16);
        BuildMI (BB, V8::SRAri, 2, DestReg).addReg (TmpReg).addZImm (16);
      } else { // add ushort
        unsigned TmpReg = makeAnotherReg (I.getType ());
        BuildMI (BB, V8::SLLri, 2, TmpReg).addReg (ResultReg).addZImm (16);
        BuildMI (BB, V8::SRLri, 2, DestReg).addReg (TmpReg).addZImm (16);
      }
      break;
    case cInt:
      BuildMI (BB, V8::ORrr, 2, DestReg).addReg (V8::G0).addReg (ResultReg);
      break;
    default:
      visitInstruction (I);
      return;
  }
}


/// LowerUnknownIntrinsicFunctionCalls - This performs a prepass over the
/// function, lowering any calls to unknown intrinsic functions into the
/// equivalent LLVM code.
void V8ISel::LowerUnknownIntrinsicFunctionCalls(Function &F) {
  for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
    for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; )
      if (CallInst *CI = dyn_cast<CallInst>(I++))
        if (Function *F = CI->getCalledFunction())
          switch (F->getIntrinsicID()) {
          case Intrinsic::not_intrinsic: break;
          default:
            // All other intrinsic calls we must lower.
            Instruction *Before = CI->getPrev();
            TM.getIntrinsicLowering().LowerIntrinsicCall(CI);
            if (Before) {        // Move iterator to instruction after call
              I = Before;  ++I;
            } else {
              I = BB->begin();
            }
          }
}


void V8ISel::visitIntrinsicCall(Intrinsic::ID ID, CallInst &CI) {
  unsigned TmpReg1, TmpReg2;
  switch (ID) {
  default: assert(0 && "Intrinsic not supported!");
  }
}

llvm/lib/Target/SparcV8/Makefile

deleted100644 → 0
+0 −46
Original line number Diff line number Diff line
##===- lib/Target/SparcV8/Makefile -------------------------*- Makefile -*-===##
# 
#                     The LLVM Compiler Infrastructure
#
# This file was developed by the LLVM research group and is distributed under
# the University of Illinois Open Source License. See LICENSE.TXT for details.
# 
##===----------------------------------------------------------------------===##
LEVEL = ../../..
LIBRARYNAME = sparcv8
include $(LEVEL)/Makefile.common

TDFILES := $(wildcard $(SourceDir)/*.td) $(SourceDir)/../Target.td
TDFILE  := $(SourceDir)/SparcV8.td

# Make sure that tblgen is run, first thing.
$(SourceDepend): SparcV8GenRegisterInfo.h.inc SparcV8GenRegisterNames.inc \
                 SparcV8GenRegisterInfo.inc SparcV8GenInstrNames.inc \
                 SparcV8GenInstrInfo.inc SparcV8GenInstrSelector.inc

SparcV8GenRegisterNames.inc:: $(TDFILES) $(TBLGEN)
	@echo "Building SparcV8.td register names with tblgen"
	$(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $(TDFILE) -gen-register-enums -o $@

SparcV8GenRegisterInfo.h.inc:: $(TDFILES) $(TBLGEN)
	@echo "Building SparcV8.td register information header with tblgen"
	$(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $(TDFILE) -gen-register-desc-header -o $@

SparcV8GenRegisterInfo.inc:: $(TDFILES) $(TBLGEN)
	@echo "Building SparcV8.td register information implementation with tblgen"
	$(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $(TDFILE) -gen-register-desc -o $@

SparcV8GenInstrNames.inc:: $(TDFILES) $(TBLGEN)
	@echo "Building SparcV8.td instruction names with tblgen"
	$(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $(TDFILE) -gen-instr-enums -o $@

SparcV8GenInstrInfo.inc:: $(TDFILES) $(TBLGEN)
	@echo "Building SparcV8.td instruction information with tblgen"
	$(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $(TDFILE) -gen-instr-desc -o $@

SparcV8GenInstrSelector.inc:: $(TDFILES) $(TBLGEN)
	@echo "Building SparcV8.td instruction selector with tblgen"
	$(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $(TDFILE) -gen-instr-selector -o $@

clean::
	$(VERB) rm -f *.inc
+0 −9
Original line number Diff line number Diff line

SparcV8 backend skeleton
------------------------

This directory will house a 32-bit SPARC V8 backend employing a expander-based
instruction selector.  Watch this space for more news coming soon!

$Date$

llvm/lib/Target/SparcV8/SparcV8.h

deleted100644 → 0
+0 −40
Original line number Diff line number Diff line
//===-- SparcV8.h - Top-level interface for SparcV8 representation -*- C++ -*-//
// 
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
// 
//===----------------------------------------------------------------------===//
//
// This file contains the entry points for global functions defined in the LLVM
// SparcV8 back-end.
//
//===----------------------------------------------------------------------===//

#ifndef TARGET_SPARCV8_H
#define TARGET_SPARCV8_H

#include <iosfwd>

namespace llvm {

  class FunctionPass;
  class TargetMachine;

  FunctionPass *createSparcV8SimpleInstructionSelector(TargetMachine &TM);
  FunctionPass *createSparcV8CodePrinterPass(std::ostream &OS,
                                             TargetMachine &TM);

} // end namespace llvm;

// Defines symbolic names for SparcV8 registers.  This defines a mapping from
// register name to register number.
//
#include "SparcV8GenRegisterNames.inc"

// Defines symbolic names for the SparcV8 instructions.
//
#include "SparcV8GenInstrNames.inc"

#endif
Loading