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

Joel Stanley jstanley at cs.uiuc.edu
Sun May 18 12:46:00 PDT 2003


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

InstManip.h updated: 1.17 -> 1.18
PhaseInfo.h updated: 1.7 -> 1.8
Phases.cpp updated: 1.31 -> 1.32
SparcInstManip.cpp updated: 1.11 -> 1.12
SparcInstManip.h updated: 1.11 -> 1.12
design.txt updated: 1.14 -> 1.15

---
Log message:

Phase-5 heap regions are working properly.


---
Diffs of the changes:

Index: llvm/lib/Reoptimizer/Inst/lib/InstManip.h
diff -u llvm/lib/Reoptimizer/Inst/lib/InstManip.h:1.17 llvm/lib/Reoptimizer/Inst/lib/InstManip.h:1.18
--- llvm/lib/Reoptimizer/Inst/lib/InstManip.h:1.17	Mon May 12 21:00:22 2003
+++ llvm/lib/Reoptimizer/Inst/lib/InstManip.h	Sun May 18 12:45:25 2003
@@ -54,7 +54,8 @@
     enum LogicalRegister {
         REG_0,
         REG_1,
-        REG_2
+        REG_2,
+        REG_7
     };
 
     // buildSlot - Fill the provided vector with the instructions that go into the slot
@@ -79,7 +80,7 @@
 
     virtual unsigned getSlotSize(Phase2* p2) const = 0;
     virtual unsigned getSlotSize(Phase3* p3, InstCandidate& cand) const = 0;
-    virtual unsigned getSlotSize(Phase4* p4, pp::GBTEntryType type) const = 0;
+    virtual unsigned getSlotSize(Phase4* p4) const = 0;
 
     // findCandidates - Build the vector of instruction candidates that occur in the
     // region defined by the given addresses. This is necessarily a platform-dependent


Index: llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h
diff -u llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h:1.7 llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h:1.8
--- llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h:1.7	Tue May 13 13:36:33 2003
+++ llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h	Sun May 18 12:45:25 2003
@@ -15,12 +15,13 @@
 
 #define DEBUG 1
 #if DEBUG
-#define VERBOSE 2
+// Maximum verbosity is level 5
+#define VERBOSE 4
 #define DEBUG_MSG(v, x) if(VERBOSE >= v) std::cerr << "[pp] " << x
 #define HEX(x) std::hex << x << std::dec
 #else
 #define DEBUG_MSG(v, x)
-#define HEX(x)
+#define HEX(x) ""
 #endif
 
 typedef std::pair<uint64_t, uint64_t> AddressRange;


Index: llvm/lib/Reoptimizer/Inst/lib/Phases.cpp
diff -u llvm/lib/Reoptimizer/Inst/lib/Phases.cpp:1.31 llvm/lib/Reoptimizer/Inst/lib/Phases.cpp:1.32
--- llvm/lib/Reoptimizer/Inst/lib/Phases.cpp:1.31	Wed May 14 07:43:04 2003
+++ llvm/lib/Reoptimizer/Inst/lib/Phases.cpp	Sun May 18 12:45:25 2003
@@ -61,15 +61,12 @@
 #include "llvm/Reoptimizer/MemoryManager.h"
 #include "llvm/Reoptimizer/TraceCache.h"
 #include "llvm/Reoptimizer/VirtualMem.h"
+#include "llvm/Reoptimizer/InstrUtils.h"
 
 #include "InstManip.h"
 #include "PhaseInfo.h"
 #include "SparcInstManip.h"
 
-// tmp
-#include "llvm/Reoptimizer/InstrUtils.h"
-// tmp
-
 using std::vector;
 using std::cerr;
 using std::endl;
@@ -193,11 +190,14 @@
         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
-                      << "[" << HEX(i->second.first)
-                      << ", " << HEX(i->second.second) << "]...\n");
+            // FIXME XXX TODO Get rid of this 'if' statement
+            if(i->first == "fibs") {
+                DEBUG_MSG(1, "Transforming function " << i->first
+                          << "[" << HEX(i->second.first)
+                          << ", " << HEX(i->second.second) << "]...\n");
 
-            transformFunction(i->second);
+                transformFunction(i->second);
+            }
         }
     }
 
@@ -215,6 +215,7 @@
         vm->writeInstToVM(currAddr, *i);
         currAddr += im->getInstWidth();
     }
+    ::doFlush(slotBase, slotBase + im->getInstWidth() * snippet.size());
 }
 
 static uint64_t replaceInstWithBrToSlot(uint64_t srcAddr,
@@ -228,6 +229,7 @@
 
     // Replace instruction at srcAddr with branch to start of new slot
     tc->getVM()->writeInstToVM(srcAddr, im->getBranchAlways(slotBase, srcAddr));
+    ::doFlush(srcAddr, srcAddr + im->getInstWidth());
 
     return slotBase;
 }
@@ -267,8 +269,7 @@
 
     // Replace instruction at repInstAddr with a branch to start of a new slot.
     uint64_t slotBase = replaceInstWithBrToSlot(repInstAddr, slotSize, m_pTC, m_pIM);
-    //::doFlush(range.first, range.second);
-    
+
 #if 0
 #if VERBOSE > 3
     DEBUG_MSG(4, "printing function after writing branch-to-slot\n");
@@ -318,8 +319,8 @@
     // as well).
 
     m_pTC->getVM()->writeInstToVM(p3info->getReplaceAddr(), p3info->getOrigInst());
-//     ::doFlush(m_pPhase3Info->getReplaceAddr(),
-//               m_pPhase3Info->getReplaceAddr() + m_pIM->getInstWidth());
+    ::doFlush(m_pPhase3Info->getReplaceAddr(),
+              m_pPhase3Info->getReplaceAddr() + m_pIM->getInstWidth());
 }
 
 Phase3::~Phase3() 
@@ -447,12 +448,11 @@
 
 void Phase4::transform()
 {
-
 #if VERBOSE > 0
     dumpGBT(cerr);
 #endif
     DEBUG_MSG(1, "tag is " << HEX(m_tag) << ", and ");
-
+    
     if(GBTElem* gbte = searchGBT(m_tag)) {
         DEBUG_MSG(1, "matches.\n");
 
@@ -469,9 +469,9 @@
                 e = cand.getInsts().end(); i != e; ++i)
             vm->writeInstToVM(i->first, m_pIM->getNOP());
 
-        // Obtain memory (& rewrite branch) to the phase 5 slot.
+        // Obtain memory (& rewrite branch) to the phase 5 jump slot.
         
-        unsigned slotSize = m_pIM->getSlotSize(this, (pp::GBTEntryType) gbte->gbtType);
+        unsigned slotSize = m_pIM->getSlotSize(this);
         uint64_t repAddr = cand.front().first;
         uint64_t slotBase = replaceInstWithBrToSlot(repAddr, slotSize, m_pTC, m_pIM);
 


Index: llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp
diff -u llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp:1.11 llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp:1.12
--- llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp:1.11	Wed May 14 07:43:04 2003
+++ llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp	Sun May 18 12:45:26 2003
@@ -56,12 +56,23 @@
 #include <iostream>
 #include <iomanip>
 
+#include <sys/mman.h> // mprotect()
+
+#include <stdio.h>
+void perror(const char* s);
+#include <errno.h>
+int errno;
+
+#include <unistd.h> // valloc()
+
 #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 "llvm/Reoptimizer/InstrUtils.h"
+
 #include "SparcInstManip.h"
 #include "PhaseInfo.h"
 
@@ -91,6 +102,7 @@
     m_logicalToActualReg[REG_0] = R_O0;
     m_logicalToActualReg[REG_1] = R_O1;
     m_logicalToActualReg[REG_2] = R_O2;
+    m_logicalToActualReg[REG_7] = R_O7;
 
     // Populate output->input register map. This is SparcV9 specific and corresponds to
     // the register mapping that occurs after a 'save' instruction is issued. Shared and
@@ -180,53 +192,60 @@
                                std::vector<unsigned>& snippet)
 {
     unsigned sharedSize = WORD_WIDTH * getSharedSize();
-    unsigned stkSize = STKFRM_MIN + sharedSize + WORD_WIDTH * 2;
+
+    // WORD_WIDTH * 3 belows occurs because we need two words for saving the values of the
+    // two scratch registers, and 1 word for saving the return address in the jump slot.
+    unsigned stkSize = STKFRM_MIN + sharedSize + WORD_WIDTH * 3;
 
     if(stkSize % STACK_ALIGN != 0) {
-        // Pad up to next multiple of STACK_ALIGN; assumes STACK_ALIGN = 2 * WORD_WIDTH
+        // Pad up to next multiple of STACK_ALIGN; assumes STACK_ALIGN % WORD_WIDTH == 0
         stkSize += WORD_WIDTH;
         assert(stkSize % STACK_ALIGN == 0 && "Alignment adjustment failed");
     }
     
-    DEBUG_MSG(2, "buildStartSlot stack offset is " << stkSize << endl);
+    DEBUG_MSG(2, "buildSlot(p5) stack offset is " << stkSize << endl);
 
-    // For start interval sites, heap-allocate enough memory for the return value of the
-    // instrumentation function.
+    unsigned retAddrStkOff = STKFRM_MIN + sharedSize + 2 * WORD_WIDTH;
+    unsigned* heapSlot = buildPhase5HeapSlot(gbte, sharedSize, retAddrStkOff);
+
+    // If we're dealing with a start-interval instrumentation function, heap-allocate
+    // its parameter memory
 
     if(gbte->gbtType == pp::GBT_INTERVAL_START) {
         assert(!gbte->retVal && "Expected null retVal value");
         gbte->retVal = static_cast<void*>(new char[gbte->paramSize]);
     }
 
-    // After the alloca, our stack region looks like:
+    ////////////////
+    // Construct the phase 5 jump slot
+
+    startCode(snippet);
+
+    // After the SP sub, our stack region looks like:
     //     sp + BIAS + stkSize -> +--------------------------------+
-    //                            |       alignment padding        |
+    //                            | alignment padding (if needed)  |
+    //                            +--------------------------------+
+    //                            | ret addr for use by heap slot  | } WORD_WIDTH
     //                            +--------------------------------+
     //                            | save area for clobbered regs   | } WORD_WIDTH * 2
     //                            +--------------------------------+
     //                            | spill region for shared regs   | } sharedSize
     //  sp + BIAS + STKFRM_MIN -> +--------------------------------+
-    //  
-    
-    startCode(snippet);
+    //
 
     generateSPSub(stkSize);
 
-    // "Manually" save REG_0, REG_1
+    // Save registers REG_{0,7} so we don't have to issue a 'save'
     generateStackStore(REG_0, STKFRM_MIN + sharedSize);
-    generateStackStore(REG_1, STKFRM_MIN + sharedSize + WORD_WIDTH);
-
-    generateSpillShared(STKFRM_MIN);
-
-    generateLoad((uint64_t) gbte, REG_0, REG_1); // REG_0 live to call
-    generateStackStore(REG_0, PARAM_0);
+    generateStackStore(REG_7, STKFRM_MIN + sharedSize + WORD_WIDTH);
 
-    generateCall((uint64_t) &phase5, slotBase);
-    generateRestoreShared(STKFRM_MIN);
+    // Address of jmpl instruction will be in REG_7 at entry to heapSlot.
+    // This means that REG_7 is live until its use in heapSlot.
+    generateLdJmpl((uint64_t) heapSlot, REG_0, REG_7);
 
-    // "Manually" restore REG_0, REG_1
+    // Restore registers REG_{0,7} so we don't have to issue a 'restore'
     generateStackLoad(REG_0, STKFRM_MIN + sharedSize);
-    generateStackLoad(REG_1, STKFRM_MIN + sharedSize + WORD_WIDTH);
+    generateStackLoad(REG_7, STKFRM_MIN + sharedSize + WORD_WIDTH);
 
     generateBranchAlways(instAddr + getInstWidth(), slotBase, getSPSub(-stkSize));
 
@@ -268,27 +287,129 @@
         GEN_BRANCH_ALWAYS_SIZE;
 }
 
-unsigned SparcInstManip::getSlotSize(Phase4* p4, pp::GBTEntryType type) const
+unsigned SparcInstManip::getSlotSize(Phase4* p4) const
 {
     // The following sum corresponds to the sizes consumed by the various regions of the
-    // the slot constructed by phase 4, called the phase 5 slot. See ASCII diagram of
-    // phase 5 slot contents for details.
+    // the slot constructed at phase 4, called the phase 5 jump slot. See ASCII diagram of
+    // phase 5 jump slot contents for details.
 
     (void) p4;
 
-    return GEN_SPSUB_SIZE +
+    return
+        GEN_SPSUB_SIZE +
         GEN_STKSTORE_SIZE +
         GEN_STKSTORE_SIZE +
-        GEN_SPL_STK_SIZE +
-        GEN_LOAD_SIZE +
         GEN_STKSTORE_SIZE +
-        GEN_CALL_SIZE +
-        GEN_UNSPL_STK_SIZE +
+        GEN_LDJMPL_SIZE +
+        GEN_STKLOAD_SIZE +
         GEN_STKLOAD_SIZE +
         GEN_STKLOAD_SIZE +
         GEN_BRANCH_ALWAYS_SIZE;
 }
 
+static void dumpHeapSlot(unsigned* heapSlot,
+                         unsigned size,
+                         SparcInstManip* im)
+{
+    // Dump actual instructions in memory
+    unsigned* curr = heapSlot;
+    unsigned* end = heapSlot + size;
+    for(; curr < end; ++curr) {
+        cerr << "[pp] Instruction at: " << HEX(curr) << ": ";
+        im->printInst(*curr);
+        cerr << endl;
+    }
+    DEBUG_MSG(3, "Done with heap region construction, moving on to jump slot\n");
+}
+
+static void copySnippetToHeapSlot(vector<unsigned>& snippet,
+                                  unsigned* heapSlot,
+                                  unsigned size)
+{
+    unsigned* curr = heapSlot;
+    for(unsigned i = 0, e = snippet.size(); i < e; ++i)
+        *curr++ = snippet[i];
+    assert(curr == heapSlot + size && "Size mismatch on heap-slot copy");
+
+    // flush; unlikely that we need to flush here, but it's *possible*
+    ::doFlush((uint64_t) heapSlot, (uint64_t)(heapSlot + size));
+}
+
+static void setPageBits(unsigned* pageBase,
+                        unsigned sizeBytes,
+                        int protBits)
+{
+    DEBUG_MSG(3, "Setting access bits on heap slot page(s)" << endl);
+
+    int rc = mprotect(pageBase, sizeBytes, protBits);
+    if(rc < 0) {
+        perror("Unable to set permissions on pageBase");
+        assert(0 && "setPageBits failed");
+    }
+}
+
+unsigned* SparcInstManip::buildPhase5HeapSlot(GBTElem* gbte,
+                                              unsigned sharedSize,
+                                              unsigned retAddrStkOff)
+{
+    // Grab memory for the phase 5 heap slot -- this is not freed, intentionally.  NB: We
+    // use valloc here to ensure that the heap region is aligned on page boundaries.  This
+    // is probably not portable, but it'll do for now.
+
+    unsigned numHeapBytes = getPhase5HeapSize() * sizeof(unsigned);
+    unsigned* heapSlot = (unsigned*) valloc(numHeapBytes);
+
+    assert(sizeof(unsigned) == getInstWidth() && "Unexpected instruction width");
+    assert(heapSlot && "Failed to obtain memory for phase 5 heap slot");
+    DEBUG_MSG(2, "heapSlot address is " << HEX(heapSlot) << endl);
+
+    ////////////////
+    // Construct the phase 5 heap slot
+
+    // NB: We save the return address of the jmp slot before the call so that we do not
+    // need to make our own stack frame.
+
+    vector<unsigned> heapcode;
+    startCode(heapcode);
+
+    generateSpillShared(STKFRM_MIN);
+    generateStackStore(REG_7, retAddrStkOff);
+    generateLoad((uint64_t) gbte, REG_0, REG_7); // REG_0 live to call
+    generateStackStore(REG_0, PARAM_0);
+    generateCall((uint64_t) &phase5, (uint64_t) heapSlot);
+    generateStackLoad(REG_7, retAddrStkOff);
+    generateRestoreShared(STKFRM_MIN);
+    generateJmpl(REG_7, REG_0 /* scratch */, WORD_WIDTH);
+
+    endCode();
+
+    copySnippetToHeapSlot(heapcode, heapSlot, getPhase5HeapSize());
+    setPageBits(heapSlot, numHeapBytes, PROT_READ | PROT_EXEC);
+
+#if VERBOSE > 2
+    DEBUG_MSG(3, "Dumping contents of heap-slot memory...\n");
+    dumpHeapSlot(heapSlot, getPhase5HeapSize(), this);
+#endif
+
+    return heapSlot;
+}
+
+unsigned SparcInstManip::getPhase5HeapSize() const
+{
+    // The following sum corresponds to the sizes consumed by the various regions of the
+    // the (heap-allocated) slot constructed during phase 4, called the phase 5 heap
+    // slot. See ASCII diagram of phase 5 heap slot contents for details.
+
+    return GEN_SPL_STK_SIZE +
+        GEN_STKSTORE_SIZE +
+        GEN_LOAD_SIZE +
+        GEN_STKSTORE_SIZE +
+        GEN_CALL_SIZE +
+        GEN_STKLOAD_SIZE +
+        GEN_UNSPL_STK_SIZE +
+        GEN_JMPL_SIZE;
+}
+
 void SparcInstManip::findCandidates(const std::pair<uint64_t, uint64_t>& range,
                                     vector<InstCandidate>& candidates) 
 {
@@ -350,7 +471,7 @@
     m_pCurrSnippet->push_back(MK_ADD_R_I(m_logicalToActualReg[reg], R_O6, offset + BIAS));
 
     assert(m_pCurrSnippet->size() - initSize == GEN_SPOFFSET_SIZE &&
-           "Unexpected number of instructions in code sequence for SP load");
+           "Unexpected number of instructions in code sequence for SP offset");
 }
 
 // generateSPSub - Generate code to allocate 'size' bytes on the stack
@@ -365,7 +486,7 @@
     m_pCurrSnippet->push_back(getSPSub(size));
 
     assert(m_pCurrSnippet->size() - initSize == GEN_SPSUB_SIZE &&
-           "Unexpected number of instructions in code sequence for SP add");
+           "Unexpected number of instructions in code sequence for SP sub");
 }
 
 void SparcInstManip::generateLoad(uint64_t value,
@@ -406,6 +527,45 @@
            "Unexpected number of instructions in code sequence for 64-bit value -> %dest");
 }
 
+void SparcInstManip::generateJmpl(LogicalRegister useForIndirect,
+                                     LogicalRegister returnAddrDest,
+                                     unsigned offset)
+{
+    assert(m_pCurrSnippet && "Invalid snippet for code generation");
+    unsigned initSize = m_pCurrSnippet->size();
+
+    m_pCurrSnippet->push_back(MK_JMPL_INDIRECT(m_logicalToActualReg[returnAddrDest],
+                                               m_logicalToActualReg[useForIndirect],
+                                               offset));
+
+    DEBUG_MSG(3, "JMPL instruction word is " << HEX(m_pCurrSnippet->back()) << endl);
+    m_pCurrSnippet->push_back(getNOP());
+
+    assert(m_pCurrSnippet->size() - initSize == GEN_JMPL_SIZE &&
+           "Unexpected number of instructions in code sequence for jmpl");
+}
+
+void SparcInstManip::generateLdJmpl(uint64_t destAddr,
+                                       LogicalRegister useForIndirect,
+                                       LogicalRegister returnAddrDest,
+                                       unsigned offset)
+{
+    // Generate code that loads the value of destAddr into useForIndirect, then jumps to
+    // [%useForIndirect + offset], storing the return address (i.e., the address of the
+    // jmpl instruction itself) in %returnAddrDest.
+    
+    assert(m_pCurrSnippet && "Invalid snippet for code generation");
+    unsigned initSize = m_pCurrSnippet->size();
+
+    // returnAddrDest is used as a scratch reg in the generateLoad
+    // After this call, %useForIndirect is live until after the jump
+    generateLoad(destAddr, useForIndirect, returnAddrDest);
+    generateJmpl(useForIndirect, returnAddrDest, offset);
+
+    assert(m_pCurrSnippet->size() - initSize == GEN_LDJMPL_SIZE &&
+           "Unexpected number of instructions in code sequence for ld & jmpl");
+}
+
 void SparcInstManip::generateAddressCopy(unsigned loadInst,
                                          LogicalRegister dest,
                                          bool afterSave)
@@ -453,7 +613,7 @@
     snippet.push_back(MK_LDX_STACK(m_logicalToActualReg[dest], BIAS + stkOffset));
 
     assert(snippet.size() - initSize == GEN_STKSTORE_SIZE &&
-           "Unexpected number of instructions in code sequence for parameter store");
+           "Unexpected number of instructions in code sequence for parameter load");
 }
 
 
@@ -509,7 +669,7 @@
            "Unexpected number of instructions in code sequence for restore");
 }
 
-void SparcInstManip::generateSave()
+void SparcInstManip::generateSave(unsigned offset)
 {
     assert(m_pCurrSnippet && "Invalid snippet for code generation");
     vector<unsigned>& snippet = *m_pCurrSnippet;
@@ -517,7 +677,7 @@
     unsigned initSize = snippet.size();    
 
     // save %sp, -176, %sp
-    snippet.push_back(MK_SAVE_IMM(R_O6, R_O6, -176));
+    snippet.push_back(MK_SAVE_IMM(R_O6, R_O6, -offset));
 
     assert(snippet.size() - initSize == GEN_SAVE_SIZE &&
            "Unexpected number of instructions in code sequence for save");
@@ -551,7 +711,7 @@
     ::generateRestoreShared(*m_pCurrSnippet, R_O6, WORD_WIDTH, offset + BIAS);
 
     assert(m_pCurrSnippet->size() - initSize == GEN_UNSPL_STK_SIZE &&
-           "Unexpected number of instructions in code sequence for spill to stack");
+           "Unexpected number of instructions in code sequence for unspill from stack");
 }
 
 void SparcInstManip::generateRestoreShared(uint64_t restoreFromAddr,


Index: llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.h
diff -u llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.h:1.11 llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.h:1.12
--- llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.h:1.11	Tue May 13 14:43:03 2003
+++ llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.h	Sun May 18 12:45:26 2003
@@ -35,7 +35,7 @@
 
     virtual unsigned getSlotSize(Phase2* p2) const;
     virtual unsigned getSlotSize(Phase3* p3, InstCandidate& cand) const;
-    virtual unsigned getSlotSize(Phase4* p4, pp::GBTEntryType type) const;
+    virtual unsigned getSlotSize(Phase4* p4) const;
 
     virtual void     findCandidates(const std::pair<uint64_t, uint64_t>& range,
                                     std::vector<InstCandidate>& candidates);
@@ -51,6 +51,12 @@
     typedef std::map<unsigned, unsigned>               OutputToInputRegMap;
     typedef std::map<GBTElem*, std::vector<uint64_t> > GBTStackMap;
 
+    unsigned*        buildPhase5HeapSlot(GBTElem* gbte,
+                                         unsigned sharedSize,
+                                         unsigned retAddrStkOff);
+    
+    unsigned         getPhase5HeapSize() const;
+
     void             startCode(std::vector<unsigned>& snippet) { m_pCurrSnippet = &snippet; }
     void             endCode()                                 { m_pCurrSnippet = 0;        }
                      
@@ -66,6 +72,15 @@
     void             generateSPOffset(LogicalRegister reg, unsigned offset);
     void             generateSPSub(unsigned size);
 
+    void             generateJmpl(LogicalRegister useForIndirect,
+                                  LogicalRegister returnAddrDest,
+                                  unsigned offset = 0);
+
+    void             generateLdJmpl(uint64_t destAddr,
+                                    LogicalRegister useForIndirect,
+                                    LogicalRegister returnAddrDest,
+                                    unsigned offset = 0);
+    
     void             generateLoad(uint64_t value,
                                   LogicalRegister dest,
                                   LogicalRegister tmp);
@@ -73,7 +88,7 @@
     void             generateStackStore(LogicalRegister src, unsigned stkOffset);
     void             generateStackLoad(LogicalRegister dest, unsigned stkOffset);
     void             generateRestore();
-    void             generateSave();
+    void             generateSave(unsigned offset = STKFRM_MIN);
                      
     void             generateRestoreShared(uint64_t restoreFromAddr,
                                            LogicalRegister tmp1 = REG_0,
@@ -155,6 +170,8 @@
     static const unsigned GEN_UNSPL_STK_SIZE =     GEN_SPL_STK_SIZE;
     static const unsigned GEN_SPSUB_SIZE =         1;
     static const unsigned GEN_SPOFFSET_SIZE =      1;
+    static const unsigned GEN_JMPL_SIZE =          2;
+    static const unsigned GEN_LDJMPL_SIZE =        GEN_LOAD_SIZE + GEN_JMPL_SIZE;
 };
 
 unsigned SparcInstManip::getBranchAlways(uint64_t dest, uint64_t pc, bool annul) const


Index: llvm/lib/Reoptimizer/Inst/lib/design.txt
diff -u llvm/lib/Reoptimizer/Inst/lib/design.txt:1.14 llvm/lib/Reoptimizer/Inst/lib/design.txt:1.15
--- llvm/lib/Reoptimizer/Inst/lib/design.txt:1.14	Mon May 12 21:00:23 2003
+++ llvm/lib/Reoptimizer/Inst/lib/design.txt	Sun May 18 12:45:26 2003
@@ -1441,3 +1441,24 @@
 
 }}}
 
+{{{ Suggestion from Chris
+
+FYI: Chris suggested a very interesting idea regarding an alternative to the
+very hackish dummy function approach.  If we made a "custom" linker, we'd be
+able to rewrite the functions with sufficient padding at the end.  If this
+occurred, we wouldn't need the dummy function at all anymore -- phase 2 would
+simply write branches down into the padded region instead of into the dummy
+function, and we'd be guaranteed to be within the PC-relative maximum branch
+distance except in the (exceedingly rare) cases where the function size was
+*really* big (i.e. >= 64K).  The only problem here is that we don't always know
+how big the padded region has to be -- in reality, it'd have to be big enough to
+contain the resolve-candidate slot code for *each* candidate in the scanned
+code.  The candidates could be located by the "custom" linker, and the padded
+regions could be made to be big enough, but the executable growth has the
+potential to be significant.  This unknown-size issue isn't unique to this
+padded approach, however, and remains a problem in the dummy function anyway.
+Also, Chris remarked that any novel page-management mechanisms, etc., (for the
+code that is jumped to in newly-allocated pages) that I devise should perhaps be
+integrated into the LLVM JIT if they are suitable.
+
+}}}





More information about the llvm-commits mailing list