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

Joel Stanley jstanley at cs.uiuc.edu
Fri Apr 11 00:21:01 PDT 2003


Changes in directory llvm/lib/Reoptimizer/Inst:

InstManip.cpp updated: 1.4 -> 1.5
InstManip.h updated: 1.4 -> 1.5
Phases.cpp updated: 1.8 -> 1.9

---
Log message:

Implemented remainder of code generation for phase 3 invocation; added
Phase3Info class for passing information between phase 2 and phase 3.


---
Diffs of the changes:

Index: llvm/lib/Reoptimizer/Inst/InstManip.cpp
diff -u llvm/lib/Reoptimizer/Inst/InstManip.cpp:1.4 llvm/lib/Reoptimizer/Inst/InstManip.cpp:1.5
--- llvm/lib/Reoptimizer/Inst/InstManip.cpp:1.4	Thu Apr 10 18:23:58 2003
+++ llvm/lib/Reoptimizer/Inst/InstManip.cpp	Fri Apr 11 00:22:20 2003
@@ -11,6 +11,8 @@
 #include "llvm/Reoptimizer/BinInterface/bitmath.h"
 #include "InstManip.h"
 
+const unsigned InstManip::NOP_INST = 0x01000000;
+
 void InstManip::printRange(unsigned* start, unsigned* end) const
 {
     // Dumps contents (and corresponding disassembly) of memory range given by range
@@ -35,12 +37,16 @@
     // present) that occurs as the first instruction of the function.
     
     unsigned inst = vm->readInstrFrmVm(addr);
-    return RD_FLD(inst, INSTR_OP3) == OP3_SAVE ? addr + 4 : 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 InstManip::generateLoad64(uint64_t value,
-                               std::vector<unsigned>& snippet,
-                               TargetRegister reg) const
+void InstManip::generateLoad(uint64_t value,
+                             std::vector<unsigned>& snippet,
+                             TargetRegister reg) const
 {
     // When reg == REG_0, load the 64-bit value into %o0, using %o0 and %o1.
     // When reg == REG_1, load the 64-bit value into %o1, using %o1 and %o2.
@@ -79,6 +85,42 @@
     // add %o0, (lwr 10b of lwr wrd), %o0
     snippet.push_back(MK_ADD_R_I(destReg, destReg, LOW10(LOWWORD(value))));
 
-    assert(snippet.size() - initSize == getGenLoad64Size() &&
+    assert(snippet.size() - initSize == getGenLoadSize() &&
            "Unexpected number of instructions in code sequence for 64-bit value -> %destReg");
 }
+
+void InstManip::generateCall(uint64_t dest,
+                             uint64_t slotBase,
+                             std::vector<unsigned>& snippet)
+{
+    unsigned initSize = snippet.size();
+    
+    // Calculate address of call instruction from slotBase
+    uint64_t callInstAddr = slotBase + getInstWidth() * snippet.size();
+
+    // Add call instruction and nop (for call delay slot) to code snippet.
+    snippet.push_back(getCallInst(dest, callInstAddr));
+    snippet.push_back(NOP_INST);
+
+    assert(snippet.size() - initSize == getGenCallSize() &&
+           "Unexpected number of instructions in code sequence for call");
+}
+
+void InstManip::generateBranchAlways(uint64_t dest,
+                                     uint64_t slotBase,
+                                     std::vector<unsigned>& snippet,
+                                     bool annul) 
+{
+    unsigned initSize = snippet.size();
+    
+    // Calculate address of branch instruction from slotBase
+    uint64_t branchInstAddr = slotBase + getInstWidth() * snippet.size();
+
+    // Add branch instruction and nop (for branch delay slot) to code snippet.
+    snippet.push_back(getBranchAlways(dest, branchInstAddr, annul));
+    snippet.push_back(NOP_INST);
+
+    assert(snippet.size() - initSize == getGenBranchAlwaysSize() &&
+           "Unexpected number of instruction in code sequence for branch-always");
+}
+


Index: llvm/lib/Reoptimizer/Inst/InstManip.h
diff -u llvm/lib/Reoptimizer/Inst/InstManip.h:1.4 llvm/lib/Reoptimizer/Inst/InstManip.h:1.5
--- llvm/lib/Reoptimizer/Inst/InstManip.h:1.4	Thu Apr 10 18:23:58 2003
+++ llvm/lib/Reoptimizer/Inst/InstManip.h	Fri Apr 11 00:22:20 2003
@@ -15,7 +15,8 @@
 
 #include <vector>
 #include "llvm/Reoptimizer/BinInterface/sparcdis.h"
-#include "llvm/Reoptimizer/InstrUtils.h"
+#include "llvm/Reoptimizer/InstrUtils.h" // getCallInstr, getUndepJumpInstr, etc.
+
 class VirtualMem;
 
 class InstManip 
@@ -31,20 +32,36 @@
                     
     uint64_t        skipFunctionHdr(uint64_t addr, VirtualMem* vm) const;
                     
-    void            generateLoad64(uint64_t value,
-                                   std::vector<unsigned>& snippet,
-                                   TargetRegister reg = REG_0) const;
-                    
+    void            generateLoad(uint64_t value,
+                                 std::vector<unsigned>& snippet,
+                                 TargetRegister reg = REG_0) const;
+
+    void            generateCall(uint64_t dest,
+                                 uint64_t slotBase,
+                                 std::vector<unsigned>& snippet);
+
+    void            generateBranchAlways(uint64_t dest,
+                                         uint64_t slotBase,
+                                         std::vector<unsigned>& snippet,
+                                         bool annul = true);
+
     inline unsigned getBranchAlways(uint64_t dest, uint64_t pc, bool annulHigh = true) const;
-    inline unsigned getCall(uint64_t dest, uint64_t pc) const;
+    inline unsigned getCallInst(uint64_t dest, uint64_t pc) const;
     inline bool     isBranch(unsigned inst) const;
 
-    unsigned        getNOP() const           { return 0x01000000; }
-    unsigned        getGenLoad64Size() const { return 6; }
+    // These are functions so when InstManip is superclassed, they'd become virtual, etc.
+    // In the short term we could use class constants, but this is more clear.
+    
+    unsigned        getNOP() const                 { return 0x01000000; }
+    unsigned        getGenLoadSize() const         { return 6;          }
+    unsigned        getGenCallSize() const         { return 2;          }
+    unsigned        getGenBranchAlwaysSize() const { return 2;          }
+    unsigned        getInstWidth() const           { return 4;          }
 
   private:
     // Branch-always (annul bit high) instruction base (i.e. address not filled in yet)
     static const unsigned BRANCH_ALWAYS_BASE = 0x30480000;
+    static const unsigned NOP_INST;
 };
 
 void InstManip::printRange(uint64_t start, uint64_t end) const
@@ -74,7 +91,7 @@
     return getUndepJumpInstr(BRANCH_ALWAYS_BASE, dest, pc);
 }
 
-unsigned InstManip::getCall(uint64_t dest, uint64_t pc) const
+unsigned InstManip::getCallInst(uint64_t dest, uint64_t pc) const
 {
     // dest is the destination address to call, pc is the value of the program counter
     // when the call instruction is executed (i.e., the address of the branch
@@ -89,6 +106,3 @@
 }
 
 #endif // _INCLUDED_INSTMANIP_H
-
-
-


Index: llvm/lib/Reoptimizer/Inst/Phases.cpp
diff -u llvm/lib/Reoptimizer/Inst/Phases.cpp:1.8 llvm/lib/Reoptimizer/Inst/Phases.cpp:1.9
--- llvm/lib/Reoptimizer/Inst/Phases.cpp:1.8	Thu Apr 10 18:40:49 2003
+++ llvm/lib/Reoptimizer/Inst/Phases.cpp	Fri Apr 11 00:22:20 2003
@@ -15,15 +15,30 @@
 //           2a. Replace the first instruction in F with a branch to a new slot in the
 //           dummy function.
 //
-//           2b. Obtain a heap region to write the phase 3 call into.
-//           
-// 	     2c. At the new slot write the indirect jump to the heap region, followed by
-// 	     the original (replaced) instruction and branch brack to original code.
+// 	     2b. At the new slot write the call to phase 3, passing it a pointer to an
+// 	     info structure which contains the original (replaced) instruction, the
+// 	     address range of the function, etc.
 //
-//           2d. Write code to call phase 3 into the heap region, etc.
+//           2c. At the end of the new slot write the direct branch back to the original
+//           code.
 //
 // PHASE 3:
 //
+//       1. Replace the original (replaced) instruction at the proper location in the
+//       original code.
+//
+//       2. Delete any slots and/or heap frames which have been marked for deletion by
+//       earlier invocations of phase3/4.
+//
+//       3. Analyze the function and determine the load-volatile candidates.
+//
+//       4. For each load-volatile candidate,
+//
+//           4a.
+//
+//       5. Deallocate the parameter structure and mark the phase 2 slot for deletion by a
+//       later invocation of phase 3.
+//
 // PHASE 4:
 //
 
@@ -31,6 +46,7 @@
 #include <iostream>
 #include <iomanip>
 #include <vector>
+#include <algorithm>
 
 #include "llvm/Reoptimizer/TraceCache.h"
 #include "llvm/Reoptimizer/VirtualMem.h"
@@ -43,7 +59,52 @@
 using std::cerr;
 using std::endl;
 
-void phase3(uint64_t value);
+typedef std::pair<uint64_t, uint64_t> AddressRange;
+
+class Phase3Info 
+{
+  public:
+    Phase3Info(const AddressRange& addressRange,
+               unsigned origInst,
+               uint64_t replaceAddr,
+               uint64_t slotDescriptor,
+               TraceCache* pTraceCache):
+        m_addrRange(addressRange),
+        m_origInst(origInst),
+        m_replaceAddr(replaceAddr),
+        m_slotDescriptor(slotDescriptor),
+        m_pTraceCache(pTraceCache)
+    {
+    }
+
+    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;   }   
+    TraceCache* getTraceCache()        { return m_pTraceCache;      }   
+
+  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
+    TraceCache*  m_pTraceCache;    // TraceCache instance used by phase 2
+};
+
+void phase3(Phase3Info* p3info);
 
 // 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.  
@@ -51,22 +112,29 @@
 class Phase2 
 {
   public:
+    Phase2(TraceCache* pTraceCache);
     void transform();
-    void transformFunction(std::pair<uint64_t, uint64_t>& range);
+    void transformFunction(AddressRange& range);
 
   private:
+    Phase2() {}
     inline unsigned getSlotSize() const;
     
-    TraceCache m_traceCache;
-    InstManip  m_instManip;
+    TraceCache*     m_pTraceCache;
+    InstManip       m_instManip;
 };
 
 extern "C" void phase2() 
 {
-    Phase2 ph;
+    Phase2 ph(new TraceCache());
     ph.transform();
 }
 
+Phase2::Phase2(TraceCache* tc):
+    m_pTraceCache(tc)
+{
+}
+
 void Phase2::transform()
 {
     cerr << "============================== Begin Phase 2 ==============================\n";
@@ -77,12 +145,12 @@
     ElfReader elfReader(execName);
     
     std::string funcName;
-    std::pair<uint64_t, uint64_t> range;
+    AddressRange range;
 
     while(elfReader.GetNextFunction(funcName, range)) {
         if(funcName == "l16_fibs") {
             //cerr << "Printing information about function " << funcName << endl;
-            m_instManip.printRange(range.first, range.second);
+            //m_instManip.printRange(range.first, range.second);
 
             cerr << "Transforming function " << funcName << "..." << endl;
             transformFunction(range);
@@ -92,76 +160,104 @@
     cerr << "============================== End Phase 2 ==============================\n";    
 }
 
-void Phase2::transformFunction(std::pair<uint64_t, uint64_t>& range)
+
+static void copySnippetToSlot(vector<unsigned>& snippet,
+                              uint64_t slotBase,
+                              VirtualMem* vm,
+                              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();
+    }
+}
+
+void Phase2::transformFunction(AddressRange& range)
 {
     ////////////////
-    // 1. Replace the first instruction in F with a branch to a new slot (annulling bit
-    // should specify *not* to execute the branch delay slot).
+    // 1. Replace the first (replacable) instruction in F with a branch to a new slot
+    // (annulling bit should specify *not* to execute the branch delay slot) in the dummy
+    // function.
+    //
+    // 2. In the slot, write:
+    //
+    //   - The code to load the pointer to the heap-allocated Phase3Info instance.
     // 
-    // 2. At the new slot write first the code to call the phase 3 function with the
-    // address of of F as an argument, followed by the (replaced) instruction from the
-    // original code.
+    //   - The call to phase 3
     //
-    // 3. At the new slot write a branch back to immediately after the branch-to-slot
-    // instruction in the original code.
+    //   - The branch back to the location of the replaced instruction (phase 3 will
+    //   replace the instruction at runtime).
     //
 
-    // Obtain address of first replacable instruction in function
-    VirtualMem* vm = m_traceCache.getVM();
+    // 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).
+    
+    VirtualMem* vm = m_pTraceCache->getVM();
     uint64_t repInstAddr = m_instManip.skipFunctionHdr(range.first, vm);
+    uint64_t slotBase = m_pTraceCache->getMemMgr()->getMemory(getSlotSize());
+    assert(slotBase && "Unable to obtain memory from MemoryManger instance");
 
-    // Obtain new slot's base address, build unconditional-anulled branch to slot base,
-    // and write over original instruction (saving it for later use).
-
-    MemoryManager* mm = m_traceCache.getMemMgr();
-    uint64_t slotBase = mm->getMemory(getSlotSize());
-    unsigned origInstr = vm->readInstrFrmVm(repInstAddr);
-    assert(!m_instManip.isBranch(origInstr) && "Unhandled case: branch instruction first in function body");
-
-    // Replace the instruction at repInstAddr with a branch to the start of the slot
+    // Replace instruction at repInstAddr with a branch to start of slot.
+    unsigned origInst = vm->readInstrFrmVm(repInstAddr);
+    assert(!m_instManip.isBranch(origInst) &&
+           "Unhandled case: branch instruction first in function body");
     vm->writeInstToVM(repInstAddr, m_instManip.getBranchAlways(slotBase, repInstAddr));
-    
-    vector<unsigned> snippet;
 
-    // Pass the starting address of F as the argument to phase3
-    // Currently, just some 64-bit value for verification purposes...
-    m_instManip.generateLoad64(0xefefefefabababab, snippet);
-
-    // Build call to phase 3
-    uint64_t callInstAddr = slotBase + 4 * snippet.size();
-    snippet.push_back(m_instManip.getCall((uint64_t) &phase3, callInstAddr));
-    snippet.push_back(m_instManip.getNOP());
-
-    // Instruction from original code (now replaced with branch)
-    snippet.push_back(origInstr);
-
-    // Build unconditional branch to repInstAddr + 4; this ensures execution of the code
-    // is resumed after phase3 is called and performs its transformations.
-
-    uint64_t branchInstAddr = slotBase + 4 * snippet.size();
-    snippet.push_back(m_instManip.getBranchAlways(repInstAddr + 4, branchInstAddr));
-    snippet.push_back(m_instManip.getNOP());
+    // Generate a) code to load the address of the heap-allocated Phase3Info struct into a
+    // register, which will be used as a parameter to the phase3 call, b) the call to
+    // phase 3 itself, and c) the direct branch back to the original code.
 
-    // Copy the snippet code into the slot.
-    uint64_t currAddr = slotBase;
-    for(vector<unsigned>::iterator i = snippet.begin(), e = snippet.end(); i != e; ++i) {
-        vm->writeInstToVM(currAddr, *i);
-        currAddr += 4;
-    }
+    Phase3Info* p3info = new Phase3Info(range, origInst, repInstAddr, slotBase, m_pTraceCache);
+
+    vector<unsigned> snippet;
+    m_instManip.generateLoad((uint64_t) p3info, snippet);
+    m_instManip.generateCall((uint64_t) &phase3, slotBase, snippet);
+    m_instManip.generateBranchAlways(repInstAddr, slotBase, snippet);
+
+    // Copy the snippet code into the slot
+    assert(snippet.size() == getSlotSize() && "Snippet size does not match slot size");
+    copySnippetToSlot(snippet, slotBase, vm, &m_instManip);
 }
 
 unsigned Phase2::getSlotSize() const
 {
-    // Slot size is [size of code for loading 64-bit value] + call inst + delay slot +
-    // instruction from original code + branch (back to original code) inst + delay slot
-    // ===> [size of code for loading 64-bit value] + 5
-
-    return m_instManip.getGenLoad64Size() + 5;
+    // A slot used by phase 2 looks like:
+    // +------------------------------+
+    // | load parameter for phase 3   |
+    // |       call to phase 3        |
+    // |            nop               |
+    // |    branch back to orig code  |
+    // |            nop               |
+    // +------------------------------+
+
+    return m_instManip.getGenLoadSize() +
+        m_instManip.getGenCallSize() +
+        m_instManip.getGenBranchAlwaysSize();
 }
 
-void phase3(uint64_t value)
+void phase3(Phase3Info* p3info)
 {
-    printf("phase3 called!\n");
-    printf("value passed in is: %lx\n", value);
-    fflush(stdout);
+    assert(p3info && "phase3 requires valid Phase3Info ptr");
+    
+    cerr << "================ Begin Phase 3 [" << std::hex
+         << p3info->getStartAddr() << ", " << p3info->getEndAddr()
+         << "] ================\n";
+
+    // Restore the replaced instruction to its original location (thus effectively
+    // removing the branch to the slot created by phase 2 as well)
+
+    VirtualMem* vm = p3info->getTraceCache()->getVM();
+    vm->writeInstToVM(p3info->getReplaceAddr(), p3info->getOrigInst());
+
+    // TODO: Delete pending slots/heap frames.
+
+    // Deallocate the parameter structure and mark the phase 2 slot that corresponds to this
+    // invocation of phase 3 as deletable.
+
+    // TODO: Mark p3info->getSlot() as deleted
+    
+    delete p3info;
+
+    cerr << "============================== End Phase 3 ==============================\n";
 }





More information about the llvm-commits mailing list