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

Joel Stanley jstanley at cs.uiuc.edu
Fri May 30 10:26:12 PDT 2003


Changes in directory llvm/lib/Reoptimizer/Inst/lib:

PhaseInfo.h updated: 1.9 -> 1.9.2.1
Phases.cpp updated: 1.35 -> 1.35.2.1
SparcInstManip.cpp updated: 1.16 -> 1.16.2.1

---
Log message:

Implemented new dynamic-registration mechanism to split apart the notion of
instrumentation intervals/points and the metrics that are associated with them.
This allows new metrics to be associated with particular intervals at runtime
instead of at compile-time, which means that the runtime system is free to
register new metrics on the fly.


---
Diffs of the changes:

Index: llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h
diff -u llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h:1.9 llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h:1.9.2.1
--- llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h:1.9	Sun May 18 15:33:46 2003
+++ llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h	Fri May 30 10:25:33 2003
@@ -26,13 +26,19 @@
 
 typedef std::pair<uint64_t, uint64_t> AddressRange;
 
+typedef struct InstInfoNode {
+    unsigned      paramSize;
+    void*         retVal;
+    void*         instFunc;
+    //InstInfoNode* next;
+};
+
 typedef struct GBTElem {
-    unsigned gbtType;
-    unsigned short* loadVar;
-    unsigned gbtStartIdx;
-    unsigned paramSize;
-    void*    retVal;
-    void*    instFunc;
+    unsigned      siteID;
+    unsigned      gbtType;
+    unsigned      short* loadVar;
+    unsigned      gbtStartIdx;
+    InstInfoNode* instInfoList;
 };
 
 class Phase3Info 


Index: llvm/lib/Reoptimizer/Inst/lib/Phases.cpp
diff -u llvm/lib/Reoptimizer/Inst/lib/Phases.cpp:1.35 llvm/lib/Reoptimizer/Inst/lib/Phases.cpp:1.35.2.1
--- llvm/lib/Reoptimizer/Inst/lib/Phases.cpp:1.35	Thu May 22 22:26:12 2003
+++ llvm/lib/Reoptimizer/Inst/lib/Phases.cpp	Fri May 30 10:25:33 2003
@@ -56,6 +56,7 @@
 #include <set>
 #include <stdlib.h>
 #include <vector>
+#include <list>
 
 #include "llvm/Reoptimizer/Inst/ElfReader.h"
 #include "llvm/Reoptimizer/MemoryManager.h"
@@ -146,11 +147,165 @@
     uint64_t    m_tag;         // Entry to look for in the GBT
 };
 
+// InstFunctionInfo is the class used to represent information (e.g., address of
+// return value, pointer-to-instrumentation function) about particular
+// registered instrumentation functions.  In the case of end-interval functions,
+// the link 'm_pStart' is filled in to refer to the InstFunctionInfo instance
+// that contains information about the corresponding start-interval function.
+
+class InstFunctionInfo 
+{
+  public:
+    InstFunctionInfo(void* pRetVal,
+                     void* pInstFunc,
+                     InstFunctionInfo* pStart = 0):
+        m_pRetVal(pRetVal), m_pInstFunc(pInstFunc), m_pStart(pStart)
+    {
+    }
+
+    InstFunctionInfo(): m_pRetVal(0), m_pInstFunc(0), m_pStart(0)
+    {
+    }
+
+    void invoke();
+
+  protected:
+    void*             m_pRetVal;
+    void*             m_pInstFunc;
+    InstFunctionInfo* m_pStart;   // Info about start-interval function
+};
+
+// InstSiteInfo instances contain information about the state of particular
+// instrumentation sites.  More specifically, it holds the instrumentation
+// status (e.g. whether or not the site has been handled by phase 4 yet) of the
+// sites as well as the list of (pointers to) the InstFunctionInfo instances
+// registered with a particular site.
+
+class InstSiteInfo 
+{
+  public:
+    InstSiteInfo():
+        m_branchInstalled(false),
+        m_instrumented(false)
+    {
+    }
+
+    // For start-interval sites only -- allocates memory for the return value of
+    // the instrumentation function (size of allocated memory is retValBytes).
+    // Returns a pointer to the InstFunctionInfo* that corresponds to the
+    // instrumentation function, or null if the function has already been
+    // registered.
+
+    InstFunctionInfo* push_back(unsigned retValBytes,
+                                void* func);
+
+    // For end-interval sites (w/ optional link to corresponding start); other
+    // site types should use this routine as well.  The provided retVal ptr is
+    // used as the return-value parameter of the instrumentation function.
+
+    void push_back(void* retVal,
+                   void* func,
+                   InstFunctionInfo* startInfo = 0);
+
+    void invokeFunctions();
+
+  protected:
+    bool                      m_branchInstalled;     // Installed branch to slot yet?
+    bool                      m_instrumented;        // Has phase 4 instrumented site?
+    uint64_t                  m_brInstallAddr;       // Address to install branch inst
+    unsigned                  m_branchInst;          // The branch inst to install
+    std::set<void*>           m_registeredFuncs;     // Set of func-ptrs registered here
+    vector<InstFunctionInfo*> m_instFuncInfos;       // Info for all registered funcs
+
+    friend void Phase4::transform();
+
+    void installBranch();
+
+    bool isRegistered(void* func) 
+    {
+        return m_registeredFuncs.find(func) != m_registeredFuncs.end();
+    }
+
+    void setInstrumented() { m_instrumented = true; }
+
+    void setBranchInst(uint64_t addr, unsigned branchInst)
+    {
+        m_brInstallAddr = addr;
+        m_branchInst = branchInst;
+    }
+};
+
+// InstInfo is the class that holds data about the instrumentation that gets
+// bound to instrumentation sites and intervals at runtime.  There should only
+// be on instance of this class (i.e., it is a singleton class).  The
+// implementation hides an STL map that maps the unique identifier associated
+// with an instrumentation interval/site to a pair of InstSiteInfo instances,
+// which contains the information about the instrumentations registered for the
+// given interval or point site.  In the case of intervals, the first element of
+// the pair is the InstSiteInfo instance that contains data about the start
+// site, whereas the second element of the pair contains data about the end
+// site.  For point sites, only the first element of the pair contains valid
+// data.
+
+class InstInfo 
+{
+  public:
+    typedef std::pair<InstSiteInfo, InstSiteInfo> SiteInfoPair;
+
+    static InstInfo* instance() 
+    {
+        if(!m_pInstance)
+            m_pInstance = new InstInfo;
+        return m_pInstance;
+    }
+
+    static InstSiteInfo* findSiteInfo(unsigned siteID, unsigned gbtType) 
+    {
+        SiteInfoPair* sip = instance()->findSiteInfo(siteID);
+        InstSiteInfo* siteInfo;
+
+        switch(gbtType) {
+            case pp::GBT_INTERVAL_START: siteInfo = &sip->first; break;
+            case pp::GBT_INTERVAL_END:   siteInfo = &sip->second; break;
+            default: assert(0 && "Unhandled gbtType encountered"); break;
+        }
+
+        return siteInfo;
+    }
+
+    SiteInfoPair* findSiteInfo(unsigned siteID)
+    {
+        SiteInfoMap::iterator i = m_siteInfoMap.find(siteID);
+        if(i == m_siteInfoMap.end())
+            return &m_siteInfoMap[siteID];
+        return &i->second;
+    }
+
+    void setVM(VirtualMem* vm) { m_pVM = vm;   }
+    VirtualMem* getVM() const  { return m_pVM; }
+
+  protected:
+    typedef std::map<unsigned, SiteInfoPair> SiteInfoMap;
+
+    InstInfo(): m_pVM(0)
+    {
+    }
+    
+    SiteInfoMap m_siteInfoMap;
+    VirtualMem* m_pVM;
+
+  private:
+    static InstInfo* m_pInstance;
+};
+
+InstInfo* InstInfo::m_pInstance = 0;
+
 //////////////// Phase 2 implementation ////////////////
 
 extern "C" void phase2() 
 {
     TraceCache* pTC = new TraceCache();
+    InstInfo::instance()->setVM(pTC->getVM());
     Phase2 ph(pTC, new SparcInstManip(pTC));
     ph.transform();
 }
@@ -192,7 +347,7 @@
         if(m_excludeSet.find(i->first) == m_excludeSet.end()) {
             // Function is not in exclude set, so go ahead and transform it
 
-            DEBUG_MSG(1, "Transforming function " << i->first
+            DEBUG_MSG(4, "Transforming function " << i->first
                       << "[" << HEX(i->second.first)
                       << ", " << HEX(i->second.second) << "]...\n");
             
@@ -217,11 +372,35 @@
     ::doFlush(slotBase, slotBase + im->getInstWidth() * snippet.size());
 }
 
+static uint64_t makeNewSlot(uint64_t srcAddr,
+                            unsigned slotSize,
+                            unsigned& branchInst,
+                            TraceCache* tc,
+                            InstManip* im)
+{
+    // Return a branch instruction to the new slot via branchInst.
+    uint64_t slotBase = tc->getMemMgr()->getMemory(slotSize);
+    assert(slotBase && "Unable to obtain memory from MemoryManager instance");
+
+    branchInst = im->getBranchAlways(slotBase, srcAddr);
+    return slotBase;
+}
+
 static uint64_t replaceInstWithBrToSlot(uint64_t srcAddr,
                                         unsigned slotSize,
                                         TraceCache* tc,
                                         InstManip* im) 
 {
+    unsigned branchInst;
+    uint64_t slotBase = makeNewSlot(srcAddr, slotSize, branchInst, tc, im);
+
+    // Replace instruction at srcAddr with branch to start of new slot
+    tc->getVM()->writeInstToVM(srcAddr, branchInst);
+    ::doFlush(srcAddr, srcAddr + im->getInstWidth());
+
+    return slotBase;
+
+#if 0
     // Obtain a new slot of the given size
     uint64_t slotBase = tc->getMemMgr()->getMemory(slotSize);
     assert(slotBase && "Unable to obtain memory from MemoryManager instance");
@@ -231,6 +410,7 @@
     ::doFlush(srcAddr, srcAddr + im->getInstWidth());
 
     return slotBase;
+#endif
 }
 
 static void dumpSnippet(vector<unsigned>& snippet, InstManip* im)
@@ -363,8 +543,8 @@
         vector<unsigned> snippet;
         m_pIM->buildSlot(p4info, snippet);
 
-        DEBUG_MSG(3, "phase4 slot instructions:\n");
-#if VERBOSE > 2
+        DEBUG_MSG(4, "phase4 slot instructions:\n");
+#if VERBOSE > 3
         dumpSnippet(snippet, m_pIM);
 #endif
 
@@ -460,29 +640,44 @@
                && "Unexpected number of instructions in candidate");
 
         // Write NOPs over the original instructions that were associated with the elected
-        // candidate.  No need to no-op over the candidate load instruction itself since
-        // we're about to write over it with a branch to the phase 5 slot.
+        // candidate.
 
         VirtualMem* vm = m_pTC->getVM();
-        for(vector<std::pair<uint64_t, unsigned> >::const_iterator i = cand.getInsts().begin() + 1,
+        for(vector<std::pair<uint64_t, unsigned> >::const_iterator i = cand.getInsts().begin(),
                 e = cand.getInsts().end(); i != e; ++i)
             vm->writeInstToVM(i->first, m_pIM->getNOP());
 
-        // Obtain memory (& rewrite branch) to the phase 5 jump slot.
+        // Obtain new slot, the phase 5 jump slot.
         
         unsigned slotSize = m_pIM->getSlotSize(this);
         uint64_t repAddr = cand.front().first;
-        uint64_t slotBase = replaceInstWithBrToSlot(repAddr, slotSize, m_pTC, m_pIM);
+        unsigned branchInst;
+        uint64_t slotBase = makeNewSlot(repAddr, slotSize, branchInst, m_pTC, m_pIM);
 
         vector<unsigned> snippet;
         m_pIM->buildSlot(gbte, slotBase, repAddr, m_pPhase4Info->getRange(), snippet);
 
-        DEBUG_MSG(3, "phase 5 slot contents:\n");
-#if VERBOSE > 2
+        DEBUG_MSG(4, "phase 5 slot contents:\n");
+#if VERBOSE > 3
         dumpSnippet(snippet, m_pIM);
 #endif
 
         copySnippetToSlot(snippet, slotBase, m_pTC->getVM(), m_pIM);
+
+        // Grab the information about this particular site.
+
+        assert(gbte->gbtType == pp::GBT_INTERVAL_START ||
+               gbte->gbtType == pp::GBT_INTERVAL_END &&
+               "Unhandled gbtType encountered (must implement)");
+        
+        InstSiteInfo* siteInfo = InstInfo::findSiteInfo(gbte->siteID, gbte->gbtType);
+
+        // Take steps to install the branch; note that the InstSiteInfo instance
+        // knows whether or not to actually write the branch instruction, etc.
+
+        siteInfo->setInstrumented();
+        siteInfo->setBranchInst(repAddr, branchInst);
+        siteInfo->installBranch();
     }
     else {
         DEBUG_MSG(1, "does not match\n");
@@ -510,6 +705,12 @@
 
 void phase5(GBTElem* gbte)
 {
+    DEBUG_MSG(1, "================ Begin Phase 5 ================\n");    
+    InstSiteInfo* siteInfo = InstInfo::findSiteInfo(gbte->siteID, gbte->gbtType);
+    siteInfo->invokeFunctions();
+    DEBUG_MSG(1, "================ End Phase 5 ================\n");
+
+#if 0
     switch(gbte->gbtType){
         case pp::GBT_INTERVAL_START: {
             DEBUG_MSG(1, "--- phase 5 start site invocation ---\n");
@@ -533,4 +734,111 @@
     }
 
     DEBUG_MSG(1, "--- phase 5 invocation completed ---\n" << std::flush);
+#endif
+}
+
+//////////////// InstSiteInfo implementation ////////////////
+
+InstFunctionInfo* InstSiteInfo::push_back(unsigned retValBytes,
+                                          void* func)
+{
+    DEBUG_MSG(3, "Inside InstSiteInfo::push_back, registering func w/ address "
+              << HEX(func) << ", new retVal of size " << retValBytes << endl);
+
+    InstFunctionInfo* fi = 0;
+
+    if(!isRegistered(func)) {
+        DEBUG_MSG(3, "not yet registered, registering...\n");
+        void* retVal = static_cast<void*>(new char[retValBytes]);
+        m_registeredFuncs.insert(func);
+        fi = new InstFunctionInfo(retVal, func);
+        m_instFuncInfos.push_back(fi);
+        installBranch();
+    }
+    else
+        DEBUG_MSG(3, "WARNING: Attempt to register instrumentation at site that was already instrumented\n");
+
+    return fi;
+}
+
+void InstSiteInfo::push_back(void* retVal,
+                             void* func,
+                             InstFunctionInfo* startInfo)
+{
+    DEBUG_MSG(3, "Inside InstSiteInfo::push_back, registering func w/ address "
+              << HEX(func) << ", retVal addr " << HEX(retVal) << endl);
+
+    if(!isRegistered(func)) {
+        DEBUG_MSG(3, "not yet registered, registering...\n");
+        m_registeredFuncs.insert(func);
+        m_instFuncInfos.push_back(new InstFunctionInfo(retVal, func, startInfo));
+        installBranch();
+    }
+    else
+        DEBUG_MSG(3, "WARNING: Attempt to register instrumentation at site that was already instrumented\n");
+}
+
+void InstSiteInfo::invokeFunctions()
+{
+    assert(m_branchInstalled && m_instrumented && "Invoking functions not permitted");
+
+    for(int i = 0, e = m_instFuncInfos.size(); i < e; ++i) {
+        DEBUG_MSG(3, "Invoking function " << i << endl);
+        m_instFuncInfos[i]->invoke();
+    }
+}
+
+void InstSiteInfo::installBranch()
+{
+    if(!m_branchInstalled && m_instrumented && m_instFuncInfos.size() > 0) {
+        DEBUG_MSG(3, "(InstSiteInfo::installBranch) Installing branch...\n");
+        VirtualMem* vm = InstInfo::instance()->getVM();
+        vm->writeInstToVM(m_brInstallAddr, m_branchInst);
+        m_branchInstalled = true;
+    }
+    else
+        DEBUG_MSG(3, "(InstSiteInfo::installBranch) Not installing branch, it's not needed\n");
+}
+
+//////////////// InstFunctionInfo implementation ////////////////
+
+void InstFunctionInfo::invoke()
+{
+    DEBUG_MSG(3, "(InstFunctionInfo::invoke) retVal address is: " << HEX(m_pRetVal) << endl);
+    if(m_pStart) {
+        DEBUG_MSG(3, "End-interval inst func detected\n");
+        void (*instFunc)(void*, void*) = (void (*)(void*, void*)) m_pInstFunc;
+        instFunc(m_pRetVal, m_pStart->m_pRetVal);
+    }
+    else {
+        DEBUG_MSG(3, "Start-interval or non-end inst func detected\n");
+        void (*instFunc)(void*) = (void (*)(void*)) m_pInstFunc;
+        instFunc(m_pRetVal);
+    }
+        
+    DEBUG_MSG(3, "(InstFunctionInfo::invoke) instrumentation function returned\n");
+}
+
+//////////////// register{Interval,Point}Inst implementation ////////////////
+
+extern "C" void registerIntervalInst(unsigned siteID,
+                                     void* startFunc,
+                                     void* endFunc,
+                                     unsigned paramSize,
+                                     void* retVal)
+{
+    InstInfo::SiteInfoPair* sip = InstInfo::instance()->findSiteInfo(siteID);
+    assert(sip && "Unable to obtain SiteInfoPair");
+    
+    // Handle start function
+    DEBUG_MSG(3, "registerIntervalInst: Registering start function...\n");
+    InstFunctionInfo* fi = sip->first.push_back(paramSize, startFunc);
+
+    if(fi) {
+        // Handle end function
+        DEBUG_MSG(3, "registerIntervalInst: Registering end function...\n");
+        sip->second.push_back(retVal, endFunc, fi);
+    }
+    else
+        DEBUG_MSG(3, "WARNING: Register-start-function returned 0, which implies redundant registration");
 }


Index: llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp
diff -u llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp:1.16 llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp:1.16.2.1
--- llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp:1.16	Wed May 28 08:52:41 2003
+++ llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp	Fri May 30 10:25:34 2003
@@ -242,6 +242,7 @@
 
     DEBUG_MSG(2, "buildPhase5HeapSlot completed\n");
 
+#if 0
     // If we're dealing with a start-interval instrumentation function, heap-allocate
     // its parameter memory
 
@@ -249,6 +250,7 @@
         assert(!gbte->retVal && "Expected null retVal value");
         gbte->retVal = static_cast<void*>(new char[gbte->paramSize]);
     }
+#endif
 
     ////////////////
     // Construct the phase 5 jump slot
@@ -363,7 +365,7 @@
                         unsigned sizeBytes,
                         int protBits)
 {
-    DEBUG_MSG(3, "Setting access bits on heap slot page(s)" << endl);
+    DEBUG_MSG(4, "Setting access bits on heap slot page(s)" << endl);
 
     int rc = mprotect(pageBase, sizeBytes, protBits);
     if(rc < 0) {
@@ -416,10 +418,10 @@
 
     setPageBits(heapSlot, numHeapBytes, PROT_READ | PROT_WRITE | PROT_EXEC);
 
-#if VERBOSE > 2
-    DEBUG_MSG(3, "Dumping contents of heap-slot memory...\n");
+#if VERBOSE > 3
+    DEBUG_MSG(4, "Dumping contents of heap-slot memory...\n");
     dumpHeapSlot(heapSlot, getPhase5HeapSize(), this);
-    DEBUG_MSG(3, "Done with heap region construction, moving on to jump slot\n");
+    DEBUG_MSG(4, "Done with heap region construction, moving on to jump slot\n");
 #endif
 
     return heapSlot;
@@ -462,7 +464,7 @@
         return addr + getInstWidth();
     }
     else {
-        DEBUG_MSG(2, "WARNING: Non-save instruction at function entry\n");
+        DEBUG_MSG(4, "WARNING: Non-save instruction at function entry\n");
         return addr;
     }
     
@@ -569,7 +571,7 @@
                                                m_logicalToActualReg[useForIndirect],
                                                offset));
 
-    DEBUG_MSG(3, "JMPL instruction word is " << HEX(m_pCurrSnippet->back()) << endl);
+    DEBUG_MSG(4, "JMPL instruction word is " << HEX(m_pCurrSnippet->back()) << endl);
     m_pCurrSnippet->push_back(getNOP());
 
     assert(m_pCurrSnippet->size() - initSize == GEN_JMPL_SIZE &&





More information about the llvm-commits mailing list