[llvm-commits] CVS: llvm/lib/Reoptimizer/Inst/InstManip.cpp InstManip.h Phases.cpp SparcInstManip.cpp SparcInstManip.h design.txt

Joel Stanley jstanley at cs.uiuc.edu
Wed Apr 30 11:30:01 PDT 2003


Changes in directory llvm/lib/Reoptimizer/Inst:

InstManip.cpp updated: 1.10 -> 1.11
InstManip.h updated: 1.11 -> 1.12
Phases.cpp updated: 1.16 -> 1.17
SparcInstManip.cpp updated: 1.1 -> 1.2
SparcInstManip.h updated: 1.1 -> 1.2
design.txt updated: 1.11 -> 1.12

---
Log message:

Another intermediary refactoring point -- in particular, most of the platform-dependent
behavior has been moved into the SparcInstManip class, etc.




---
Diffs of the changes:

Index: llvm/lib/Reoptimizer/Inst/InstManip.cpp
diff -u llvm/lib/Reoptimizer/Inst/InstManip.cpp:1.10 llvm/lib/Reoptimizer/Inst/InstManip.cpp:1.11
--- llvm/lib/Reoptimizer/Inst/InstManip.cpp:1.10	Tue Apr 29 22:08:03 2003
+++ llvm/lib/Reoptimizer/Inst/InstManip.cpp	Wed Apr 30 11:36:09 2003
@@ -7,6 +7,7 @@
 #include <iostream>
 #include <iomanip>
 
+#include "llvm/Reoptimizer/TraceCache.h"
 #include "llvm/Reoptimizer/VirtualMem.h"
 #include "InstManip.h"
 
@@ -40,12 +41,38 @@
     ostr << "}";
 }
 
-InstManip::InstManip(VirtualMem* vm):
-    m_pVM(vm)
+InstManip::InstManip(TraceCache* tc, unsigned sharedSize, unsigned instWidth):
+    m_pTC(tc),
+    m_pPhase3SpillRegion(0),
+    m_pCurrSpill(0),
+    m_sharedSize(sharedSize),
+    m_instWidth(instWidth)
 {
-    assert(vm && "InstManip requires valid VirtualMem instance");
+    assert(tc && "InstManip requires valid TraceCache instance");
 }
 
 InstManip::~InstManip()
 {
+    if(m_pPhase3SpillRegion)
+        delete [] m_pPhase3SpillRegion;
+}
+
+void InstManip::makePhase3SpillRegion(unsigned numFuncs) 
+{
+    // Heap-allocate a region of memory in which to spill shared registers before phase3
+    // invocations.  We allocate one unit of space (given by getSharedSize()) for each
+    // function that must be transformed.
+
+    m_pPhase3SpillRegion = new uint64_t[getSharedSize() * numFuncs];
+    m_pCurrSpill = m_pPhase3SpillRegion;
+}
+
+void InstManip::copySnippetToSlot(std::vector<unsigned>& snippet, uint64_t slotBase) 
+{
+    uint64_t currAddr = slotBase;
+    for(std::vector<unsigned>::iterator i = snippet.begin(),
+            e = snippet.end(); i != e; ++i) {
+        m_pTC->getVM()->writeInstToVM(currAddr, *i);
+        currAddr += getInstWidth();
+    }
 }


Index: llvm/lib/Reoptimizer/Inst/InstManip.h
diff -u llvm/lib/Reoptimizer/Inst/InstManip.h:1.11 llvm/lib/Reoptimizer/Inst/InstManip.h:1.12
--- llvm/lib/Reoptimizer/Inst/InstManip.h:1.11	Tue Apr 29 22:08:03 2003
+++ llvm/lib/Reoptimizer/Inst/InstManip.h	Wed Apr 30 11:36:09 2003
@@ -4,7 +4,11 @@
 //     fileid: InstManip.h
 //     purpose: InstManip is a (pure virtual) class that hdies platform-specific
 //     instruction manipulation behind a common interface, and provides clients with
-//     various instruction manipulation utilities. Only two relevant assumptions are made:
+//     various instruction manipulation utilities. Since the structure of the TraceCache
+//     "slots" for the various phases of the binary editing for performance
+//     instrumentation have structure and content that is platform-dependent, this class
+//     also hides the platform-specific details of the slot construction as well.  Only
+//     two relevant assumptions are made:
 //
 //     * The TraceCache objects (TraceCache, MemoryManager, VirtualMem, etc) from the
 //     Reoptimizer library work in an appropriate manner on the given platform.
@@ -21,14 +25,21 @@
 #include <vector>
 #include <algorithm>
 
-class VirtualMem;
+class TraceCache;
+class Phase2;
+class Phase3;
+class InstCandidate;
+class Phase3Info;
+class Phase4Info;
 
 class InstManip 
 {
   public:
-    InstManip(VirtualMem* vm);
+    InstManip(TraceCache* vm, unsigned sharedSize, unsigned instWidth);
     virtual ~InstManip();
 
+    typedef std::pair<uint64_t, uint64_t> AddressRange;
+
     // Logical registers used by clients of this class, mapped to machine-specific IDs
     // by the logical -> actual register map.
     enum LogicalRegister {
@@ -37,19 +48,56 @@
         REG_2
     };
 
+    // buildSlot - Fill the provided vector with the instructions that go into the slot
+    // given by the Phase{3,4}Info instance. The proper function is distinguished by type
+    // in this manner because there are not really enough phases to warrant building the
+    // slot-building behavior into the Phase{3,4}Info classes themselves.
+
+    virtual void     buildSlot(Phase3Info* p3info,
+                               std::vector<unsigned>& snippet) = 0;
+
+    virtual void     buildSlot(Phase4Info* p4info,
+                               std::vector<unsigned>& snippet) = 0;
+
+    virtual unsigned getSlotSize(Phase2* p2) const = 0;
+    virtual unsigned getSlotSize(Phase3* p3, InstCandidate& cand) const = 0;
+
+    // getStartAddr - return the desired starting position in the function body. This is
+    // useful for skipping standard prologue code that occurs at the start of the function
+    // body.
+
+    virtual uint64_t getStartAddr(uint64_t funcStartAddr) const = 0;
+
+    virtual unsigned getBranchAlways(uint64_t dest, uint64_t pc, bool annulHigh = true) const = 0;
+    virtual bool     isBranch(unsigned inst) const = 0;
     virtual void     printRange(unsigned* start, unsigned* end) const = 0;
     virtual void     printInst(unsigned inst) const = 0;
-    virtual unsigned getInstWidth() const = 0;
+
+    ////
+
+    void             makePhase3SpillRegion(unsigned numFuncs);
+    uint64_t*        getCurrentSpill()     { return m_pCurrSpill;             }
+    void             advanceSpill()        { m_pCurrSpill += getSharedSize(); }
+    void             copySnippetToSlot(std::vector<unsigned>& snippet, uint64_t slotBase);
 
     inline void      printRange(uint64_t start, uint64_t end) const;
 
+    unsigned         getSharedSize() const { return m_sharedSize; }
+    unsigned         getInstWidth() const { return m_instWidth; }
+
   protected:
     InstManip() {}
     
     typedef std::map<LogicalRegister, unsigned> LogicalToActualRegMap;
 
     LogicalToActualRegMap  m_logicalToActualReg; // Maps logical -> actual register
-    VirtualMem*            m_pVM;
+    TraceCache*            m_pTC;
+
+    uint64_t*              m_pPhase3SpillRegion; // Base pointer to spill region for phase 3 invocations
+    uint64_t*              m_pCurrSpill;         // Current location in the phase 3 spill region
+
+    unsigned               m_sharedSize;         // # of shared registers that must be spilled
+    unsigned               m_instWidth;          // instruction width, in bytes
 };
 
 void InstManip::printRange(uint64_t start, uint64_t end) const


Index: llvm/lib/Reoptimizer/Inst/Phases.cpp
diff -u llvm/lib/Reoptimizer/Inst/Phases.cpp:1.16 llvm/lib/Reoptimizer/Inst/Phases.cpp:1.17
--- llvm/lib/Reoptimizer/Inst/Phases.cpp:1.16	Tue Apr 29 22:08:03 2003
+++ llvm/lib/Reoptimizer/Inst/Phases.cpp	Wed Apr 30 11:36:09 2003
@@ -81,6 +81,7 @@
 #include "ElfReader.h"
 //#include "InstManip.h"
 #include "SparcInstManip.h"
+#include "PhaseInfo.h"
 
 using std::vector;
 using std::cerr;
@@ -101,92 +102,6 @@
 
 typedef std::pair<uint64_t, uint64_t> AddressRange;
 
-class Phase3Info 
-{
-  public:
-    Phase3Info(const AddressRange& addressRange,
-               unsigned origInst,
-               uint64_t replaceAddr,
-               uint64_t slotDescriptor,
-               unsigned slotSize,
-               TraceCache* pTraceCache,
-               SparcInstManip* pInstManip):
-        m_addrRange(addressRange),
-        m_origInst(origInst),
-        m_replaceAddr(replaceAddr),
-        m_slotDescriptor(slotDescriptor),
-        m_slotSize(slotSize),
-        m_pTraceCache(pTraceCache),
-        m_pInstManip(pInstManip)
-    {
-    }
-
-    void print(std::ostream& ostr) 
-    {
-        ostr << std::hex << "Phase3Info instance: {" << endl
-             << "  Function address range: [" << m_addrRange.first << ", "
-             << m_addrRange.second << "]" << endl
-             << "  To replace: [" << m_origInst << " @ "
-             << m_replaceAddr << "]" << endl
-             << "}" << endl;
-    }
-
-    uint64_t    getStartAddr() const   { return m_addrRange.first;  }
-    uint64_t    getEndAddr() const     { return m_addrRange.second; }
-    uint64_t    getOrigInst() const    { return m_origInst;         }
-    uint64_t    getReplaceAddr() const { return m_replaceAddr;      }  
-    uint64_t    getSlot() const        { return m_slotDescriptor;   }
-    uint64_t    getSlotSize() const    { return m_slotSize;         }
-    TraceCache* getTraceCache()        { return m_pTraceCache;      }
-    SparcInstManip* getIM()            { return m_pInstManip;       }
-
-  private:
-    Phase3Info() {}
-
-    AddressRange m_addrRange;      // Range of function for phase 3 to examine
-    unsigned     m_origInst;       // Instruction replaced by phase 2
-    uint64_t     m_replaceAddr;    // Address at which to restore original inst
-    uint64_t     m_slotDescriptor; // Slot created by phase 2
-    unsigned     m_slotSize;       // Size of slot created by phase 2
-    TraceCache*  m_pTraceCache;    // TraceCache instance used by phase 2
-    SparcInstManip* m_pInstManip;  // The InstManip instance to pass to the next phase
-};
-
-class Phase4Info
-{
-  public:
-    Phase4Info(const InstCandidate& candidate,
-               uint64_t slotDescriptor,
-               uint64_t slotSize,
-               TraceCache* pTraceCache,
-               SparcInstManip* pInstManip):
-        m_candidate(candidate),
-        m_slotDescriptor(slotDescriptor),
-        m_slotSize(slotSize),
-        m_pTraceCache(pTraceCache),
-        m_pInstManip(pInstManip)
-    {
-    }
-
-    const InstCandidate& getCandidate() const { return m_candidate;        }
-    uint64_t             getSlot() const      { return m_slotDescriptor;   }
-    uint64_t             getSlotSize() const  { return m_slotSize;         }
-    TraceCache*          getTraceCache()      { return m_pTraceCache;      }
-    SparcInstManip*      getIM()              { return m_pInstManip;       }
-
-  private:
-    Phase4Info() {}
-
-    InstCandidate m_candidate;      // Candidate responsible for this instance's creation
-    uint64_t      m_slotDescriptor; // Slot created by phase 3
-    unsigned      m_slotSize;       // Size of slot created by phase 3
-    TraceCache*   m_pTraceCache;    // TraceCache instance used by phases 2 and 3
-    SparcInstManip* m_pInstManip;   // The InstManip instance to pass to the next phase
-};
-
-void phase3(Phase3Info* p3info);
-void phase4(uint64_t tag, Phase4Info* p4info);
-
 // Phase2 is the class that is responsible for effecting the core of the phase 2
 // transformation; the global function phase2() is simply an C-linkage interface.  
 
@@ -199,17 +114,16 @@
 
   private:
     Phase2() {}
-    inline unsigned getSlotSize() const;
     
     TraceCache*     m_pTraceCache;
     SparcInstManip*      m_pInstManip;
 
-    static uint64_t* sm_pSpillRegion; // Base pointer to the spill region for phase 3 invocations
-    static uint64_t* sm_pCurrSpill;   // Pointer to current location in the spill region
+    //static uint64_t* sm_pSpillRegion; // Base pointer to the spill region for phase 3 invocations
+    //static uint64_t* sm_pCurrSpill;   // Pointer to current location in the spill region
 };
 
-uint64_t* Phase2::sm_pSpillRegion = 0;
-uint64_t* Phase2::sm_pCurrSpill = 0;
+//uint64_t* Phase2::sm_pSpillRegion = 0;
+//uint64_t* Phase2::sm_pCurrSpill = 0;
 
 // Phase3 is the class that is responsible for making the "phase 3" transformation; the
 // global function phase3() is responsible for constructing one Phase3 instance per
@@ -227,7 +141,6 @@
     Phase3() {}
 
     void            processCandidates(vector<InstCandidate>& candidates);
-    inline unsigned getSlotSize(InstCandidate&) const;
 
     Phase3Info* m_pPhase3Info;
     TraceCache* m_pTraceCache;
@@ -249,8 +162,6 @@
   private:
     Phase4() {}
 
-    inline unsigned getSlotSize() const;
-
     Phase4Info* m_pPhase4Info;
     TraceCache* m_pTraceCache;
     SparcInstManip*  m_pInstManip;
@@ -262,7 +173,7 @@
 extern "C" void phase2() 
 {
     TraceCache* pTC = new TraceCache();
-    SparcInstManip* pIM = new SparcInstManip(pTC->getVM());
+    SparcInstManip* pIM = new SparcInstManip(pTC);
     Phase2 ph(pTC, pIM);
     ph.transform();
 }
@@ -295,12 +206,10 @@
 
     cerr << "There are " << funcs.size() << " functions to process." << endl << endl;
 
-    // Heap-allocate a region of memory in which to spill shared registers before phase3
-    // invocations.  We allocate one unit of space (given by InstManip::getSharedSize())
-    // for each function that we transform.
-
-    sm_pSpillRegion = new uint64_t[m_pInstManip->getSharedSize() * funcs.size()];
-    sm_pCurrSpill = sm_pSpillRegion;
+    m_pInstManip->makePhase3SpillRegion(funcs.size());
+    
+    //sm_pSpillRegion = new uint64_t[m_pInstManip->getSharedSize() * funcs.size()];
+    //sm_pCurrSpill = sm_pSpillRegion;
 
     for(vector<std::pair<std::string, AddressRange> >::iterator i = funcs.begin(),
             e = funcs.end(); i != e; ++i) {
@@ -317,17 +226,68 @@
 static void copySnippetToSlot(vector<unsigned>& snippet,
                               uint64_t slotBase,
                               VirtualMem* vm,
-                              InstManip& im) 
+                              InstManip* im) 
 {
     uint64_t currAddr = slotBase;
     for(vector<unsigned>::iterator i = snippet.begin(), e = snippet.end(); i != e; ++i) {
         vm->writeInstToVM(currAddr, *i);
-        currAddr += im.getInstWidth();
+        currAddr += im->getInstWidth();
     }
 }
 
+static uint64_t replaceInstWithBrToSlot(uint64_t srcAddr,
+                                        unsigned slotSize,
+                                        TraceCache* tc,
+                                        InstManip* im) 
+{
+    // Obtain a new slot of the given size
+    uint64_t slotBase = tc->getMemMgr()->getMemory(slotSize);
+    assert(slotBase && "Unable to obtain memory from MemoryManager instance");
+
+    // Replace instruction at srcAddr with branch to start of new slot
+    tc->getVM()->writeInstToVM(srcAddr, im->getBranchAlways(slotBase, srcAddr));
+
+    return slotBase;
+}
+
 void Phase2::transformFunction(AddressRange& range)
 {
+    // Obtain address of first replacable instruction in function and obtain a new slot
+    // from the TraceCache memory manager (i.e., a new slot in the dummy function). Hold
+    // onto the replaced instruction for later restoration.
+    
+    VirtualMem* vm = m_pTraceCache->getVM();
+    uint64_t repInstAddr = m_pInstManip->getStartAddr(range.first);
+    unsigned origInst = vm->readInstrFrmVm(repInstAddr);
+
+    assert(!m_pInstManip->isBranch(origInst) &&
+           "Unhandled case: branch instruction first in function body");
+
+    unsigned slotSize = m_pInstManip->getSlotSize(this);
+
+    // Replace instruction at repInstAddr with a branch to start of a new slot.
+    uint64_t slotBase = replaceInstWithBrToSlot(repInstAddr, slotSize, m_pTraceCache, m_pInstManip);
+
+    // Build the Phase3Info structure and generate the phase 3 slot. 
+
+    Phase3Info* p3info = new Phase3Info(range, origInst, repInstAddr,
+                                        slotBase, slotSize, m_pTraceCache, m_pInstManip);
+
+    vector<unsigned> snippet;
+    m_pInstManip->buildSlot(p3info, snippet);
+
+    // Dump snippet instructions:
+    cerr << "phase3 slot instructions:" << endl;
+    for(vector<unsigned>::iterator j = snippet.begin(), k = snippet.end(); j != k; ++j) {
+        m_pInstManip->printInst(*j);
+        cerr << endl;
+    }
+
+    // Copy the snippet code into the slot
+    copySnippetToSlot(snippet, slotBase, vm, m_pInstManip);
+    
+    // {{{ Old version of this function
+#if 0
     // Obtain address of first replacable instruction in function and obtain a new slot from
     // the TraceCache memory manager (i.e., a new slot in the dummy function).
     
@@ -350,11 +310,13 @@
     vector<unsigned> snippet;
     m_pInstManip->startCode(snippet);
 
+    uint64_t* pCurrSpill = m_pInstManip->getCurrentSpill();
+    
     m_pInstManip->generateSave();
-    m_pInstManip->generateSpillShared((uint64_t) sm_pCurrSpill);
+    m_pInstManip->generateSpillShared((uint64_t) pCurrSpill);
     m_pInstManip->generateLoad((uint64_t) p3info, InstManip::REG_0, InstManip::REG_1);
     m_pInstManip->generateCall((uint64_t) &phase3, slotBase);
-    m_pInstManip->generateRestoreShared((uint64_t) sm_pCurrSpill);
+    m_pInstManip->generateRestoreShared((uint64_t) pCurrSpill);
     m_pInstManip->generateBranchAlways(repInstAddr, slotBase, m_pInstManip->getRestoreInst());
 
     m_pInstManip->endCode();
@@ -369,13 +331,17 @@
     // Bump the current spill pointer to the next "spill slot" in the spill region used
     // before/after phase3() invocations.
 
-    sm_pCurrSpill += m_pInstManip->getSharedSize();
+    m_pInstManip->advanceSpill();
+    //sm_pCurrSpill += m_pInstManip->getSharedSize();
 
     // Copy the snippet code into the slot
     assert(snippet.size() == getSlotSize() && "Snippet size does not match slot size");
-    copySnippetToSlot(snippet, slotBase, vm, *m_pInstManip);
+    copySnippetToSlot(snippet, slotBase, vm, m_pInstManip);
+#endif
+    // }}}
 }
 
+#if 0
 unsigned Phase2::getSlotSize() const
 {
     // The following sum corresponds to the sizes consumed by the various regions of the
@@ -388,6 +354,7 @@
         m_pInstManip->getGenRestoreSharedSize() +
         m_pInstManip->getGenBranchAlwaysSize();
 }
+#endif
 
 //////////////// Phase3 implementation ////////////////
 
@@ -431,23 +398,43 @@
     delete m_pPhase3Info;
 }
 
-static uint64_t replaceInstWithBrToSlot(uint64_t srcAddr,
-                                        unsigned slotSize,
-                                        TraceCache* tc,
-                                        SparcInstManip& im) 
+void Phase3::processCandidates(vector<InstCandidate>& candidates) 
 {
-    // Obtain a new slot of the given size
-    uint64_t slotBase = tc->getMemMgr()->getMemory(slotSize);
-    assert(slotBase && "Unable to obtain memory from MemoryManager instance");
+    // For each load candidate, obtain a new slot and write the phase 4 slot region
+    // contents into it.
 
-    // Replace instruction at srcAddr with branch to start of new slot
-    tc->getVM()->writeInstToVM(srcAddr, im.getBranchAlways(slotBase, srcAddr));
+    for(vector<InstCandidate>::iterator i = candidates.begin(), e = candidates.end(); i != e; ++i) {
+        cerr << "Transforming " << *i << endl;
+        unsigned slotSize = m_pInstManip->getSlotSize(this, *i);
 
-    return slotBase;
-}
+        // Replace load candidate instruction with a branch to the start of a new slot.
+        uint64_t slotBase = replaceInstWithBrToSlot(i->front().first, slotSize,
+                                                    m_pTraceCache, m_pInstManip);
 
-void Phase3::processCandidates(vector<InstCandidate>& candidates) 
-{
+        // Build the Phase4Info structure and generate the phase 4 slot.
+
+        Phase4Info* p4info = new Phase4Info(*i, slotBase, slotSize, m_pTraceCache, m_pInstManip);
+
+        vector<unsigned> snippet;
+        m_pInstManip->buildSlot(p4info, snippet);
+
+        // Dump snippet instructions:
+        cerr << "phase4 slot instructions:" << endl;
+        for(vector<unsigned>::iterator j = snippet.begin(), k = snippet.end(); j != k; ++j) {
+            m_pInstManip->printInst(*j);
+            cerr << endl;
+        }
+
+        // Copy the snippet code into the slot
+        copySnippetToSlot(snippet, slotBase, m_pTraceCache->getVM(), m_pInstManip);
+
+        // just one candidate for now
+        break;
+    }
+
+    // {{{ Old version of this function
+
+#if 0
     // For each load candidate, obtain a new slot and write the phase 3 slot region
     // contents into it.  See diagram in comments at top of file for more info.
 
@@ -496,13 +483,17 @@
 
         // Copy the snippet code into the slot
         assert(snippet.size() == getSlotSize(*i) && "Snippet size does not match slot size");
-        copySnippetToSlot(snippet, slotBase, m_pTraceCache->getVM(), *m_pInstManip);
+        copySnippetToSlot(snippet, slotBase, m_pTraceCache->getVM(), m_pInstManip);
 
         // just one candidate for now
         break;
     }
+#endif
+
+    // }}}
 }
 
+#if 0
 unsigned Phase3::getSlotSize(InstCandidate& cand) const
 {
     // The following sum corresponds to the sizes consumed by the various regions of the
@@ -518,6 +509,7 @@
         m_pInstManip->getGenRestoreSharedSize() +
         m_pInstManip->getGenBranchAlwaysSize();
 }
+#endif
 
 void Phase3::transform()
 {


Index: llvm/lib/Reoptimizer/Inst/SparcInstManip.cpp
diff -u llvm/lib/Reoptimizer/Inst/SparcInstManip.cpp:1.1 llvm/lib/Reoptimizer/Inst/SparcInstManip.cpp:1.2
--- llvm/lib/Reoptimizer/Inst/SparcInstManip.cpp:1.1	Tue Apr 29 22:08:03 2003
+++ llvm/lib/Reoptimizer/Inst/SparcInstManip.cpp	Wed Apr 30 11:36:09 2003
@@ -7,27 +7,34 @@
 #include <iostream>
 #include <iomanip>
 
+#include "llvm/Reoptimizer/TraceCache.h"
 #include "llvm/Reoptimizer/VirtualMem.h"
+#include "llvm/Reoptimizer/MemoryManager.h"
 #include "llvm/Reoptimizer/BinInterface/sparc9.h"
 #include "llvm/Reoptimizer/BinInterface/bitmath.h"
 
 #include "SparcInstManip.h"
+#include "PhaseInfo.h"
 
 const unsigned SparcInstManip::NOP_INST = 0x01000000;
 const unsigned SparcInstManip::BRANCH_ALWAYS_BASE = 0x10480000;
 const unsigned SparcInstManip::BRANCH_ALWAYS_BASE_ANNUL = 0x30480000;
 const unsigned SparcInstManip::BIAS = 2047;
-uint64_t SparcInstManip::sm_phase3SpillRegion[SparcInstManip::SHARED_SIZE];
+uint64_t SparcInstManip::sm_phase4SpillRegion[SparcInstManip::SHARED_SIZE];
 
 using std::cout;
 using std::cerr;
 using std::endl;
+using std::vector;
 
-SparcInstManip::SparcInstManip(VirtualMem* vm):
-    InstManip(vm),
+void phase3(Phase3Info* p3info);
+void phase4(uint64_t tag, Phase4Info* p4info);
+
+SparcInstManip::SparcInstManip(TraceCache* tc):
+    InstManip(tc, SHARED_SIZE, INST_WIDTH),
     m_pCurrSnippet(0)
 {
-    assert(vm && "SparcInstManip requires valid VirtualMem instance");
+    assert(tc && "SparcInstManip requires valid TraceCache instance");
 
     // Populate logical->actual register map. Since this SparcInstManip class is
     // SparcV9-specific, we map to the values used by the BinInterface library and macros.
@@ -55,6 +62,110 @@
         m_outputToInputReg[i] = i;
 }
 
+void SparcInstManip::buildSlot(Phase3Info* p3info,
+                               std::vector<unsigned>& snippet)
+{
+    // Build phase 3 slot. See ASCII diagram of phase 3 slot contents for details.
+
+    assert(p3info && "buildSlot requires valid p3info ptr");
+
+    uint64_t slotBase = p3info->getSlot();
+    uint64_t spillAddr = (uint64_t) getCurrentSpill();
+    
+    startCode(snippet);
+
+    generateSave();
+    generateSpillShared(spillAddr);
+    generateLoad((uint64_t) p3info, REG_0, REG_1);
+    generateCall((uint64_t) &phase3, slotBase);
+    generateRestoreShared(spillAddr);
+    generateBranchAlways(p3info->getReplaceAddr(), slotBase, getRestoreInst());
+
+    endCode();
+    advanceSpill();
+    assert(snippet.size() == p3info->getSlotSize() && 
+           "Snippet size does not match expected slot size");
+}
+
+
+void SparcInstManip::buildSlot(Phase4Info* p4info,
+                               std::vector<unsigned>& snippet)
+{
+    // Build phase 4 slot. See ASCII diagram of phase 4 slot contents for details.
+
+    uint64_t slotBase = p4info->getSlot();
+    uint64_t spillAddr = (uint64_t) getPhase4SpillAddr();
+    const InstCandidate& cand = p4info->getCandidate();
+    
+    // NB: We pass parameters to the phase4 function in REG_0 and REG_1 on the assumption
+    // that the input parameters will be looked for there. However, it is possible that
+    // the input parameters will be taken from the parameter array at fixed offsets from
+    // the stack pointer.  Hence, we store the parameters there as well.
+
+    startCode(snippet);
+
+    generateSave();
+    generateAddressCopy(cand.front().second, REG_0, true); // REG_0 live to call
+    generateParamStore(REG_0, PARAM_0);
+    generateSpillShared(spillAddr, REG_1, REG_2);
+    generateLoad((uint64_t) p4info, REG_1, REG_2);         // REG_1 live to call
+    generateParamStore(REG_1, PARAM_1);
+    generateCall((uint64_t) &phase4, slotBase);
+    generateRestoreShared(spillAddr);
+    generateBranchAlways(cand.front().first, slotBase, getRestoreInst());
+
+    endCode();
+    assert(snippet.size() == p4info->getSlotSize() &&
+           "Snippet size does not match expected slot size");
+}
+
+unsigned SparcInstManip::getSlotSize(Phase2* p2) const
+{
+    // The following sum corresponds to the sizes consumed by the various regions of the
+    // the slot constructed by phase 2, called the phase 3 slot.  See ASCII diagram of
+    // phase 3 slot contents for details.
+
+    (void) p2;
+    
+    return getGenSaveSize() +
+        getGenSpillSharedSize() +
+        getGenLoadSize() +
+        getGenCallSize() +
+        getGenRestoreSharedSize() +
+        getGenBranchAlwaysSize();
+}
+
+unsigned SparcInstManip::getSlotSize(Phase3* p3, InstCandidate& cand) const
+{
+    // The following sum corresponds to the sizes consumed by the various regions of the
+    // the slot constructed by phase 3, called the phase 4 slot. See ASCII diagram of
+    // phase 4 slot contents for details.
+
+    (void) p3;
+    
+    return getGenSaveSize() +
+        getGenAddressCopySize(cand.front().second) +
+        getGenParamStoreSize() +
+        getGenSpillSharedSize() +
+        getGenLoadSize() +
+        getGenParamStoreSize() +
+        getGenCallSize() +
+        getGenRestoreSharedSize() +
+        getGenBranchAlwaysSize();
+}
+
+uint64_t SparcInstManip::getStartAddr(uint64_t addr) const
+{
+    // For SparcV9, skip the save instruction, if present.
+    
+    unsigned inst = m_pTC->getVM()->readInstrFrmVm(addr);
+    assert(RD_FLD(inst, INSTR_OP) == OP_2 &&
+           RD_FLD(inst, INSTR_OP3) == OP3_SAVE &&
+           "Unhandled case: non-save instruction in function header");
+    
+    return addr + getInstWidth();
+}
+
 void SparcInstManip::printRange(unsigned* start,
                            unsigned* end) const
 {
@@ -80,19 +191,6 @@
     fflush(stdout);
 }
 
-uint64_t SparcInstManip::skipFunctionHdr(uint64_t addr) const
-{
-    // For SparcV9, what we're calling the "function header" is the save instruction (if
-    // present) that occurs as the first instruction of the function.
-    
-    unsigned inst = m_pVM->readInstrFrmVm(addr);
-    assert(RD_FLD(inst, INSTR_OP) == OP_2 &&
-           RD_FLD(inst, INSTR_OP3) == OP3_SAVE &&
-           "Unhandled case: non-save instruction in function header");
-    
-    return addr + getInstWidth();
-}
-
 void SparcInstManip::generateLoad(uint64_t value,
                              LogicalRegister dest,
                              LogicalRegister tmp)
@@ -103,7 +201,7 @@
 
     assert(m_pCurrSnippet && "Invalid snippet for code generation");
     assert(dest != tmp && "Distinct logical registers required");
-    std::vector<unsigned>& snippet = *m_pCurrSnippet;
+    vector<unsigned>& snippet = *m_pCurrSnippet;
     
     unsigned initSize = snippet.size();
     unsigned destReg = m_logicalToActualReg[dest];
@@ -139,7 +237,7 @@
     // input registers.  
 
     assert(m_pCurrSnippet && "Invalid snippet for code generation");
-    std::vector<unsigned>& snippet = *m_pCurrSnippet;
+    vector<unsigned>& snippet = *m_pCurrSnippet;
 
     unsigned initSize = snippet.size();
     unsigned destReg = m_logicalToActualReg[dest];
@@ -171,7 +269,7 @@
                                    StackOffset off)
 {
     assert(m_pCurrSnippet && "Invalid snippet for code generation");
-    std::vector<unsigned>& snippet = *m_pCurrSnippet;
+    vector<unsigned>& snippet = *m_pCurrSnippet;
 
     unsigned initSize = snippet.size();
     unsigned srcReg = m_logicalToActualReg[src];
@@ -186,7 +284,7 @@
                              uint64_t slotBase)
 {
     assert(m_pCurrSnippet && "Invalid snippet for code generation");
-    std::vector<unsigned>& snippet = *m_pCurrSnippet;
+    vector<unsigned>& snippet = *m_pCurrSnippet;
 
     unsigned initSize = snippet.size();
     
@@ -210,7 +308,7 @@
 void SparcInstManip::generateRestore()
 {
     assert(m_pCurrSnippet && "Invalid snippet for code generation");
-    std::vector<unsigned>& snippet = *m_pCurrSnippet;
+    vector<unsigned>& snippet = *m_pCurrSnippet;
 
     unsigned initSize = snippet.size();
 
@@ -223,7 +321,7 @@
 void SparcInstManip::generateSave()
 {
     assert(m_pCurrSnippet && "Invalid snippet for code generation");
-    std::vector<unsigned>& snippet = *m_pCurrSnippet;
+    vector<unsigned>& snippet = *m_pCurrSnippet;
 
     unsigned initSize = snippet.size();    
 
@@ -244,7 +342,7 @@
     assert(m_pCurrSnippet && "Invalid snippet for code generation");
     assert(tmp1 != tmp2 && "Distinct logical registers required");
 
-    std::vector<unsigned>& snippet = *m_pCurrSnippet;
+    vector<unsigned>& snippet = *m_pCurrSnippet;
     unsigned initSize = snippet.size();
     unsigned tmpReg = m_logicalToActualReg[tmp1];
 
@@ -268,7 +366,7 @@
     assert(m_pCurrSnippet && "Invalid snippet for code generation");
     assert(tmp1 != tmp2 && "Distinct logical registers required");
 
-    std::vector<unsigned>& snippet = *m_pCurrSnippet;
+    vector<unsigned>& snippet = *m_pCurrSnippet;
     unsigned initSize = snippet.size();    
     unsigned tmpReg = m_logicalToActualReg[tmp1];
 
@@ -290,7 +388,7 @@
                                      unsigned delaySlotInstr)
 {
     assert(m_pCurrSnippet && "Invalid snippet for code generation");
-    std::vector<unsigned>& snippet = *m_pCurrSnippet;
+    vector<unsigned>& snippet = *m_pCurrSnippet;
 
     unsigned initSize = snippet.size();
     
@@ -306,8 +404,8 @@
 }
 
 void SparcInstManip::findCandidates(uint64_t start,
-                               uint64_t end,
-                               std::vector<InstCandidate>& candidates) 
+                                    uint64_t end,
+                                    vector<InstCandidate>& candidates) 
 {
     for(uint64_t currAddr = start; currAddr <= end; currAddr += getInstWidth()) {
         InstCandidate cand(this);
@@ -404,11 +502,11 @@
                 // Last schema-2 search: find the STB instruction that stores from the
                 // LDUB's destination register.
                         
-                unsigned ldubInst = m_pVM->readInstrFrmVm(stkLoadAddr);
+                unsigned ldubInst = m_pTC->getVM()->readInstrFrmVm(stkLoadAddr);
                 uint64_t stbAddr = findNextStore(stkLoadAddr, end, getLoadDest(ldubInst));
                 unsigned stbInst;
 
-                if(stbAddr && isSTB((stbInst = m_pVM->readInstrFrmVm(stbAddr)))) {
+                if(stbAddr && isSTB((stbInst = m_pTC->getVM()->readInstrFrmVm(stbAddr)))) {
                             
                     // All of the criteria have been met for Schema 2, the "stack transfer"
                     // pattern.
@@ -467,7 +565,7 @@
     // Address of potential candidate load is given by 'addr', maximum search address is
     // given by 'end'
     
-    unsigned inst = m_pVM->readInstrFrmVm(addr);
+    unsigned inst = m_pTC->getVM()->readInstrFrmVm(addr);
     
     if(isLoadHalfWord(inst)) {
         // Search forward until a sth/stb from inst's target register is encountered
@@ -475,7 +573,7 @@
 
             // If STB, take actions for schema 1, otherwise check for schema 2 conditions.
 
-            unsigned storeInst = m_pVM->readInstrFrmVm(storeAddr);
+            unsigned storeInst = m_pTC->getVM()->readInstrFrmVm(storeAddr);
             std::pair<uint64_t, unsigned> inst1(addr, inst);
             std::pair<uint64_t, unsigned> inst2(storeAddr, storeInst);
 
@@ -495,7 +593,7 @@
     // an instance cannot be found.
 
     for(uint64_t currAddr = addr; currAddr <= end; currAddr += getInstWidth()) {
-        unsigned inst = m_pVM->readInstrFrmVm(currAddr);
+        unsigned inst = m_pTC->getVM()->readInstrFrmVm(currAddr);
 
         if(isLoadByte(inst) && isFPRelative(inst) && getFPOffset(inst) == fpOffset)
             return currAddr;
@@ -513,7 +611,7 @@
     // 0 if such an instance cannot be found.
 
     for(uint64_t currAddr = addr; currAddr <= end; currAddr += getInstWidth()) {
-        unsigned inst = m_pVM->readInstrFrmVm(currAddr);
+        unsigned inst = m_pTC->getVM()->readInstrFrmVm(currAddr);
         if(isSTH(inst) || isSTB(inst) && getStoreSrc(inst) == srcReg)
             return currAddr;
     }


Index: llvm/lib/Reoptimizer/Inst/SparcInstManip.h
diff -u llvm/lib/Reoptimizer/Inst/SparcInstManip.h:1.1 llvm/lib/Reoptimizer/Inst/SparcInstManip.h:1.2
--- llvm/lib/Reoptimizer/Inst/SparcInstManip.h:1.1	Tue Apr 29 22:08:03 2003
+++ llvm/lib/Reoptimizer/Inst/SparcInstManip.h	Wed Apr 30 11:36:09 2003
@@ -17,7 +17,7 @@
 class SparcInstManip : public InstManip
 {
   public:
-    SparcInstManip(VirtualMem* vm);
+    SparcInstManip(TraceCache* vm);
 
     // Offsets in stack frame for function parameters
     enum StackOffset {
@@ -25,12 +25,23 @@
         PARAM_1 = 136
     };
 
+    // Overloaded functions
+    
+    virtual void     buildSlot(Phase3Info* p3info,
+                               std::vector<unsigned>& snippet);
+
+    virtual void     buildSlot(Phase4Info* p3info,
+                               std::vector<unsigned>& snippet);
+
+    virtual unsigned getSlotSize(Phase2* p2) const;
+    virtual unsigned getSlotSize(Phase3* p3, InstCandidate& cand) const;
+    virtual uint64_t getStartAddr(uint64_t funcStartAddr) const;
+    inline unsigned  getBranchAlways(uint64_t dest, uint64_t pc, bool annulHigh = true) const;
+    inline bool      isBranch(unsigned inst) const;
     virtual void     printRange(unsigned* start, unsigned* end) const;
     virtual void     printInst(unsigned inst) const;
 
     ////
-
-    uint64_t         skipFunctionHdr(uint64_t addr) const;
                      
     void             startCode(std::vector<unsigned>& snippet) { m_pCurrSnippet = &snippet; }
     void             endCode()                                 { m_pCurrSnippet = 0;        }
@@ -67,9 +78,7 @@
                                     std::vector<InstCandidate>& candidates);
                      
     unsigned         getRestoreInst() const;
-    inline unsigned  getBranchAlways(uint64_t dest, uint64_t pc, bool annulHigh = true) const;
     inline unsigned  getCallInst(uint64_t dest, uint64_t pc) const;
-    inline bool      isBranch(unsigned inst) const;
 
     // These are functions so when SparcInstManip is superclassed, they'd become virtual, etc.
     // In the short term we could use class constants, but this is more clear.
@@ -80,15 +89,13 @@
     unsigned         getGenBranchAlwaysSize() const   { return 2;                              }
     unsigned         getGenSaveSize() const           { return 1;                              }
     unsigned         getGenParamStoreSize() const     { return 1;                              }
-    unsigned         getGenSpillSharedSize() const    { return getGenLoadSize() + SHARED_SIZE; }
-    unsigned         getGenRestoreSharedSize() const  { return getGenLoadSize() + SHARED_SIZE; }
+    unsigned         getGenSpillSharedSize() const    { return getGenLoadSize() + getSharedSize(); }
+    unsigned         getGenRestoreSharedSize() const  { return getGenLoadSize() + getSharedSize(); }
     unsigned         getGenRestoreSize() const        { return 1;                              }
-    virtual unsigned getInstWidth() const             { return 4;                              }
-    unsigned         getSharedSize() const            { return SHARED_SIZE;                    }
 
     inline unsigned  getGenAddressCopySize(unsigned loadInst) const;
 
-    uint64_t getPhase3SpillAddr() { return (uint64_t) sm_phase3SpillRegion; }
+    uint64_t getPhase4SpillAddr() { return (uint64_t) sm_phase4SpillRegion; }
 
   private:
     SparcInstManip() {}
@@ -126,6 +133,9 @@
     // Size (in number of 64-bit words) required for storing shared registers
     static const unsigned SHARED_SIZE = 7;
 
+    // Instruction width (in bytes)
+    static const unsigned INST_WIDTH = 4;
+
     // Sparc-specific constant used in SP manipulations
     static const unsigned BIAS;
 
@@ -135,7 +145,7 @@
     // because only one activation of a phase 4 slot ever occurs at a given time (assuming
     // single-threaded execution).
 
-    static uint64_t                     sm_phase3SpillRegion[SHARED_SIZE];
+    static uint64_t                     sm_phase4SpillRegion[SHARED_SIZE];
 };
 
 unsigned SparcInstManip::getBranchAlways(uint64_t dest, uint64_t pc, bool annul) const


Index: llvm/lib/Reoptimizer/Inst/design.txt
diff -u llvm/lib/Reoptimizer/Inst/design.txt:1.11 llvm/lib/Reoptimizer/Inst/design.txt:1.12
--- llvm/lib/Reoptimizer/Inst/design.txt:1.11	Tue Apr 29 21:08:42 2003
+++ llvm/lib/Reoptimizer/Inst/design.txt	Wed Apr 30 11:36:09 2003
@@ -886,11 +886,8 @@
 
 {{{ TODO
 
-    - Get phase 2 allocation of spill space working, write spill code (to spill space) for
-      phase 3 invocation. (Currently NO spilling is being done, which is not safe)
-
-    - Ensure phase 3 writes proper spill code for phase 4 invocation. (One spill space
-    should be sufficient)
+    - Refactor for platform independence, or at least approximate closely a good refactoring.
+      - Suggest making a slot builder class as well -- pull out slot creation from InstManip.
 
     - Start table-of-stacks implementation for phase4 authorship of phase 5 slots.
 





More information about the llvm-commits mailing list