Fix problems linking against the reoptimizer; _llvm_regAllocState must have
[oota-llvm.git] / lib / Target / SparcV9 / RegAlloc / PhyRegAlloc.cpp
index f23a22c6c4401fb4fc10fb4c50581c3094b1041d..99917cdf0b46918d24a179a05e1871dd22e1640b 100644 (file)
 // 
 //===----------------------------------------------------------------------===//
 
+#include "AllocInfo.h"
+#include "IGNode.h"
 #include "PhyRegAlloc.h"
 #include "RegAllocCommon.h"
 #include "RegClass.h"
-#include "IGNode.h"
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/iOther.h"
+#include "llvm/Module.h"
+#include "llvm/Type.h"
+#include "llvm/Analysis/LoopInfo.h"
 #include "llvm/CodeGen/FunctionLiveVarInfo.h"
 #include "llvm/CodeGen/InstrSelection.h"
+#include "llvm/CodeGen/MachineCodeForInstruction.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineFunctionInfo.h"
 #include "llvm/CodeGen/MachineInstr.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/MachineInstrAnnot.h"
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/MachineFunctionInfo.h"
 #include "llvm/CodeGen/Passes.h"
-#include "llvm/Analysis/LoopInfo.h"
-#include "llvm/Target/TargetInstrInfo.h"
-#include "llvm/Type.h"
-#include "llvm/iOther.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Constants.h"
-#include "llvm/Module.h"
 #include "llvm/Support/InstIterator.h"
-#include "Support/STLExtras.h"
-#include "Support/SetOperations.h"
+#include "llvm/Target/TargetInstrInfo.h"
 #include "Support/CommandLine.h"
+#include "Support/SetOperations.h"
+#include "Support/STLExtras.h"
 #include <cmath>
 
 RegAllocDebugLevel_t DEBUG_RA;
 
+/// The reoptimizer wants to be able to grovel through the register
+/// allocator's state after it has done its job. This is a hack.
+///
+PhyRegAlloc::SavedStateMapTy ExportedFnAllocState;
+const bool SaveStateToModule = true;
+
 static cl::opt<RegAllocDebugLevel_t, true>
 DRA_opt("dregalloc", cl::Hidden, cl::location(DEBUG_RA),
         cl::desc("enable register allocation debugging information"),
@@ -1129,97 +1137,99 @@ void PhyRegAlloc::allocateStackSpace4SpilledLRs() {
 }
 
 
-namespace {
-  /// AllocInfo - Structure representing one instruction's
-  /// operand's-worth of register allocation state. We create tables
-  /// made out of these data structures to generate mapping information
-  /// for this register allocator. (FIXME: This might move to a header
-  /// file at some point.)
-  ///
-  struct AllocInfo {
-    unsigned Instruction;
-    unsigned Operand;
-    unsigned AllocState;
-    int Placement;
-    AllocInfo (unsigned Instruction_, unsigned Operand_,
-               unsigned AllocState_, int Placement_) :
-      Instruction (Instruction_), Operand (Operand_),
-      AllocState (AllocState_), Placement (Placement_) { }
-    /// getConstantType - Return a StructType representing an AllocInfo
-    /// object.
-    ///
-    static StructType *getConstantType () {
-      std::vector<const Type *> TV;
-      TV.push_back (Type::UIntTy);
-      TV.push_back (Type::UIntTy);
-      TV.push_back (Type::UIntTy);
-      TV.push_back (Type::IntTy);
-      return StructType::get (TV);
-    }
-    /// toConstant - Convert this AllocInfo into an LLVM Constant of type
-    /// getConstantType(), and return the Constant.
-    ///
-    Constant *toConstant () const {
-      StructType *ST = getConstantType ();
-      std::vector<Constant *> CV;
-      CV.push_back (ConstantUInt::get (Type::UIntTy, Instruction));
-      CV.push_back (ConstantUInt::get (Type::UIntTy, Operand));
-      CV.push_back (ConstantUInt::get (Type::UIntTy, AllocState));
-      CV.push_back (ConstantSInt::get (Type::IntTy, Placement));
-      return ConstantStruct::get (ST, CV);
-    }
-  };
+void PhyRegAlloc::saveStateForValue (std::vector<AllocInfo> &state,
+                                     const Value *V, unsigned Insn, int Opnd) {
+  LiveRangeMapType::const_iterator HMI = LRI->getLiveRangeMap ()->find (V); 
+  LiveRangeMapType::const_iterator HMIEnd = LRI->getLiveRangeMap ()->end ();   
+  AllocInfo::AllocStateTy AllocState = AllocInfo::NotAllocated; 
+  int Placement = -1; 
+  if ((HMI != HMIEnd) && HMI->second) { 
+    LiveRange *L = HMI->second; 
+    assert ((L->hasColor () || L->isMarkedForSpill ()) 
+            && "Live range exists but not colored or spilled"); 
+    if (L->hasColor ()) { 
+      AllocState = AllocInfo::Allocated; 
+      Placement = MRI.getUnifiedRegNum (L->getRegClassID (), 
+                                        L->getColor ()); 
+    } else if (L->isMarkedForSpill ()) { 
+      AllocState = AllocInfo::Spilled; 
+      assert (L->hasSpillOffset () 
+              && "Live range marked for spill but has no spill offset"); 
+      Placement = L->getSpillOffFromFP (); 
+    } 
+  } 
+  state.push_back (AllocInfo (Insn, Opnd, AllocState, Placement)); 
 }
 
+
 /// Save the global register allocation decisions made by the register
 /// allocator so that they can be accessed later (sort of like "poor man's
 /// debug info").
 ///
 void PhyRegAlloc::saveState () {
-  std::vector<Constant *> &state = FnAllocState[Fn];
+  std::vector<AllocInfo> &state = FnAllocState[Fn];
   unsigned Insn = 0;
-  LiveRangeMapType::const_iterator HMIEnd = LRI->getLiveRangeMap ()->end ();   
-  for (const_inst_iterator II=inst_begin (Fn), IE=inst_end (Fn); II != IE; ++II)
+  for (const_inst_iterator II=inst_begin (Fn), IE=inst_end (Fn); II!=IE; ++II){
+    saveStateForValue (state, (*II), Insn, -1);
     for (unsigned i = 0; i < (*II)->getNumOperands (); ++i) {
       const Value *V = (*II)->getOperand (i);
-      // Don't worry about it unless it's something whose reg. we'll need.
-      if (!isa<Argument> (V) && !isa<Instruction> (V))
-        continue;
-      LiveRangeMapType::const_iterator HMI = LRI->getLiveRangeMap ()->find (V);
-      static const unsigned NotAllocated = 0, Allocated = 1, Spilled = 2;
-      unsigned AllocState = NotAllocated;
-      int Placement = -1;
-      if ((HMI != HMIEnd) && HMI->second) {
-        LiveRange *L = HMI->second;
-        assert ((L->hasColor () || L->isMarkedForSpill ())
-                && "Live range exists but not colored or spilled");
-        if (L->hasColor()) {
-          AllocState = Allocated;
-          Placement = MRI.getUnifiedRegNum (L->getRegClassID (),
-                                            L->getColor ());
-        } else if (L->isMarkedForSpill ()) {
-          AllocState = Spilled;
-          assert (L->hasSpillOffset ()
-                  && "Live range marked for spill but has no spill offset");
-          Placement = L->getSpillOffFromFP ();
-        }
-      }
-      state.push_back (AllocInfo (Insn, i, AllocState,
-                                  Placement).toConstant ());
+      // Don't worry about it unless it's something whose reg. we'll need. 
+      if (!isa<Argument> (V) && !isa<Instruction> (V)) 
+        continue; 
+      saveStateForValue (state, V, Insn, i);
     }
+    ++Insn;
+  }
 }
 
+
 /// Check the saved state filled in by saveState(), and abort if it looks
-/// wrong. Only used when debugging.
+/// wrong. Only used when debugging. FIXME: Currently it just prints out
+/// the state, which isn't quite as useful.
 ///
 void PhyRegAlloc::verifySavedState () {
-  /// not yet implemented
+  std::vector<AllocInfo> &state = FnAllocState[Fn];
+  unsigned Insn = 0;
+  for (const_inst_iterator II=inst_begin (Fn), IE=inst_end (Fn); II!=IE; ++II) {
+    const Instruction *I = *II;
+    MachineCodeForInstruction &Instrs = MachineCodeForInstruction::get (I);
+    std::cerr << "Instruction:\n" << "  " << *I << "\n"
+              << "MachineCodeForInstruction:\n";
+    for (unsigned i = 0, n = Instrs.size (); i != n; ++i)
+      std::cerr << "  " << *Instrs[i] << "\n";
+    std::cerr << "FnAllocState:\n";
+    for (unsigned i = 0; i < state.size (); ++i) {
+      AllocInfo &S = state[i];
+      if (Insn == S.Instruction) {
+        std::cerr << "  (Instruction " << S.Instruction
+                  << ", Operand " << S.Operand
+                  << ", AllocState " << S.allocStateToString ()
+                  << ", Placement " << S.Placement << ")\n";
+      }
+    }
+    std::cerr << "----------\n";
+    ++Insn;
+  }
 }
 
+
+/// Finish the job of saveState(), by collapsing FnAllocState into an LLVM
+/// Constant and stuffing it inside the Module. (NOTE: Soon, there will be
+/// other, better ways of storing the saved state; this one is cumbersome and
+/// does not work well with the JIT.)
+///
 bool PhyRegAlloc::doFinalization (Module &M) { 
   if (!SaveRegAllocState)
     return false; // Nothing to do here, unless we're saving state.
 
+  // If saving state into the module, just copy new elements to the
+  // correct global.
+  if (!SaveStateToModule) {
+    ExportedFnAllocState = FnAllocState;
+    // FIXME: should ONLY copy new elements in FnAllocState
+    return false;
+  }
+
   // Convert FnAllocState to a single Constant array and add it
   // to the Module.
   ArrayType *AT = ArrayType::get (AllocInfo::getConstantType (), 0);
@@ -1231,14 +1241,18 @@ bool PhyRegAlloc::doFinalization (Module &M) {
   std::vector<Constant *> allstate;
   for (Module::iterator I = M.begin (), E = M.end (); I != E; ++I) {
     Function *F = I;
+    if (F->isExternal ()) continue;
     if (FnAllocState.find (F) == FnAllocState.end ()) {
       allstate.push_back (ConstantPointerNull::get (PT));
     } else {
-      std::vector<Constant *> &state = FnAllocState[F];
+      std::vector<AllocInfo> &state = FnAllocState[F];
 
       // Convert state into an LLVM ConstantArray, and put it in a
       // ConstantStruct (named S) along with its size.
-      unsigned Size = state.size ();
+      std::vector<Constant *> stateConstants;
+      for (unsigned i = 0, s = state.size (); i != s; ++i)
+        stateConstants.push_back (state[i].toConstant ());
+      unsigned Size = stateConstants.size ();
       ArrayType *AT = ArrayType::get (AllocInfo::getConstantType (), Size);
       std::vector<const Type *> TV;
       TV.push_back (Type::UIntTy);
@@ -1246,7 +1260,7 @@ bool PhyRegAlloc::doFinalization (Module &M) {
       StructType *ST = StructType::get (TV);
       std::vector<Constant *> CV;
       CV.push_back (ConstantUInt::get (Type::UIntTy, Size));
-      CV.push_back (ConstantArray::get (AT, state));
+      CV.push_back (ConstantArray::get (AT, stateConstants));
       Constant *S = ConstantStruct::get (ST, CV);
 
       GlobalVariable *GV =
@@ -1254,8 +1268,8 @@ bool PhyRegAlloc::doFinalization (Module &M) {
                             GlobalValue::InternalLinkage, S,
                             F->getName () + ".regAllocState", &M);
 
-      // Have: { uint, [Size x { uint, uint, uint, int }] } *
-      // Cast it to: { uint, [0 x { uint, uint, uint, int }] } *
+      // Have: { uint, [Size x { uint, int, uint, int }] } *
+      // Cast it to: { uint, [0 x { uint, int, uint, int }] } *
       Constant *CE = ConstantExpr::getCast (ConstantPointerRef::get (GV), PT);
       allstate.push_back (CE);
     }
@@ -1263,7 +1277,7 @@ bool PhyRegAlloc::doFinalization (Module &M) {
 
   unsigned Size = allstate.size ();
   // Final structure type is:
-  // { uint, [Size x { uint, [0 x { uint, uint, uint, int }] } *] }
+  // { uint, [Size x { uint, [0 x { uint, int, uint, int }] } *] }
   std::vector<const Type *> TV2;
   TV2.push_back (Type::UIntTy);
   ArrayType *AT2 = ArrayType::get (PT, Size);
@@ -1272,7 +1286,7 @@ bool PhyRegAlloc::doFinalization (Module &M) {
   std::vector<Constant *> CV2;
   CV2.push_back (ConstantUInt::get (Type::UIntTy, Size));
   CV2.push_back (ConstantArray::get (AT2, allstate));
-  new GlobalVariable (ST2, true, GlobalValue::InternalLinkage,
+  new GlobalVariable (ST2, true, GlobalValue::ExternalLinkage,
                       ConstantStruct::get (ST2, CV2), "_llvm_regAllocState",
                       &M);
   return false; // No error.