From jstanley at cs.uiuc.edu Tue Apr 8 22:35:01 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Tue Apr 8 22:35:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/Inst/ElfReader.cpp ElfReader.h Phase2.cpp Message-ID: <200304090336.WAA20534@cypher.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/Inst: ElfReader.cpp updated: 1.2 -> 1.3 ElfReader.h updated: 1.2 -> 1.3 Phase2.cpp updated: 1.1 -> 1.2 --- Log message: Significant functionality added to InstManip wrapper class. As of this version, phase2 works (on a particular example). Furthermore: - Slot created in dummy function via TraceCache utils. - Writes call to phase3, passing 64-bit value (will later be function address), branch back to original code, etc. - phase3 doesn't exist yet, and is just a dummy function. --- Diffs of the changes: Index: llvm/lib/Reoptimizer/Inst/ElfReader.cpp diff -u llvm/lib/Reoptimizer/Inst/ElfReader.cpp:1.2 llvm/lib/Reoptimizer/Inst/ElfReader.cpp:1.3 --- llvm/lib/Reoptimizer/Inst/ElfReader.cpp:1.2 Thu Apr 3 15:00:51 2003 +++ llvm/lib/Reoptimizer/Inst/ElfReader.cpp Tue Apr 8 22:35:57 2003 @@ -57,7 +57,6 @@ m_entrySize = m_symTab->sh_entsize; m_numEntries = m_symTab->sh_size / m_entrySize; assert(m_symTab->sh_size % m_entrySize == 0 && "Symtable size must be multiple of entry size"); - cerr << "Symbol table contains " << m_numEntries << " entries" << endl; // Seek to the start of the symbol table in the file if(lseek(m_execFD, m_symTab->sh_offset, SEEK_SET) < 0) @@ -67,8 +66,15 @@ } bool ElfReader::GetNextFunction(std::string& fname, - AddressRange& addressRange) + std::pair& range) { + // Locate next function (skipping non-function entries) in the symbol table if + // possible. If found, return true, yielding name & extents by reference. Return + // false otherwise. + // + // NB: Address range contains the (closed) memory interval [start,end] of the memory + // addresses corresponding to the function with function fname. + while(m_entriesProcessed < m_numEntries) { m_entriesProcessed++; @@ -79,11 +85,11 @@ rdcnt = read(m_execFD, &sym + rdcnt, m_entrySize); } while(rdcnt < m_entrySize); - // If it is a function, extract the information and return + // If it is a function, extract name, extents, and return if(STT_FUNC == (sym.st_info & 0xf)) { // Symbol type is lower 4 bits fname = m_strTab + sym.st_name; - addressRange.first = sym.st_value; - addressRange.second = sym.st_value + sym.st_size - 4; + range.first = sym.st_value; + range.second = sym.st_value + sym.st_size - 4; return true; } } @@ -103,7 +109,6 @@ if(SHT_SYMTAB == secHdr->sh_type) { // Found section marked as a symbol table - cerr << "Found symbol table!" << endl; assert(!m_symTab && "Should only be one symbol table in the image"); m_symTab = secHdr; } Index: llvm/lib/Reoptimizer/Inst/ElfReader.h diff -u llvm/lib/Reoptimizer/Inst/ElfReader.h:1.2 llvm/lib/Reoptimizer/Inst/ElfReader.h:1.3 --- llvm/lib/Reoptimizer/Inst/ElfReader.h:1.2 Thu Apr 3 15:00:51 2003 +++ llvm/lib/Reoptimizer/Inst/ElfReader.h Tue Apr 8 22:35:57 2003 @@ -16,9 +16,8 @@ ElfReader(const char* execName); ~ElfReader(); - typedef std::pair AddressRange; - - bool GetNextFunction(std::string& string, AddressRange& range); + bool GetNextFunction(std::string& string, + std::pair& range); private: ElfReader() {} Index: llvm/lib/Reoptimizer/Inst/Phase2.cpp diff -u llvm/lib/Reoptimizer/Inst/Phase2.cpp:1.1 llvm/lib/Reoptimizer/Inst/Phase2.cpp:1.2 --- llvm/lib/Reoptimizer/Inst/Phase2.cpp:1.1 Fri Apr 4 17:08:56 2003 +++ llvm/lib/Reoptimizer/Inst/Phase2.cpp Tue Apr 8 22:35:57 2003 @@ -30,56 +30,368 @@ #include #include +#include #include #include "ElfReader.h" -#include "../BinInterface/sparcdis.h" +#include "llvm/Reoptimizer/TraceCache.h" +#include "llvm/Reoptimizer/VirtualMem.h" +#include "llvm/Reoptimizer/InstrUtils.h" +#include "../BinInterface/sparcdis.h" // TODO: Move to proper include directory +#include "../BinInterface/sparc9.h" // TODO: Move to proper include directory +#include "../BinInterface/bitmath.h" // TODO: Move to proper include directory +#include "../TraceCache/MemoryManager.h" // TODO: Move to proper include directory using std::vector; using std::cerr; using std::endl; +typedef std::pair AddressRange; + +// InstManip is a wrapper class around any BinInterface macros/mechanisms, as well as the +// TraceCache "instruction utilities, all which are SparcV9-specific; this class exists +// both for conceptual clarity and to facilitate hiding the Sparc-specificity from the +// Phase2 actions (and thus making it easier to use the phase2 transformations on other +// platforms in the future; we should be able to change which instruction manipulator +// object is instantiated, after making the appropriate superclass, etc). + +class InstManip +{ + public: + void printRange(unsigned* start, unsigned* end); + inline void printRange(AddressRange& range); + inline void printRange(uint64_t start, uint64_t end); + + inline void printInst(unsigned inst); + inline void printInst(unsigned* instAddr); + + uint64_t skipFunctionHdr(uint64_t addr, VirtualMem* vm); + + void generateLoad64(uint64_t value, vector& snippet); + + unsigned getBranchAlways(uint64_t dest, uint64_t pc, bool annulHigh = true); + inline unsigned getCall(uint64_t dest, uint64_t pc); + + unsigned getNOP() const { return 0x01000000; } + unsigned getGenLoad64Size() const { return 6; } + + private: + //////////////// + // Instruction constants and field-extraction "macros", etc. + + // Branch-always (annul bit high) instruction base (i.e. address not filled in yet) + static const int wtf = 19; + + static const unsigned BRANCH_ALWAYS_BASE = 0x30480000; + + unsigned low10(unsigned value) { return value & 0x000003ff; } + unsigned high22(unsigned value) { return value >> 10; } + unsigned highWord(uint64_t value) { return (unsigned) (value >> 32); } + unsigned lowWord(uint64_t value) { return (unsigned) value; } +}; + +// 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. + +class Phase2 +{ + public: + void transform(); + void transformFunction(AddressRange& range); + + private: + inline unsigned getSlotSize() const; + + TraceCache m_traceCache; + InstManip m_instManip; +}; + extern "C" void phase2() { + Phase2 ph; + ph.transform(); +} + +void Phase2::transform() +{ cerr << "============================== Begin Phase 2 ==============================\n"; const char* execName = getexecname(); cerr << "Executable name is: " << execName << endl; ElfReader elfReader(execName); - + std::string funcName; - ElfReader::AddressRange range; + AddressRange range; while(elfReader.GetNextFunction(funcName, range)) { - if(funcName == "l16_fibs" || funcName == "l16_floogle") { - cerr << "Function name is: " << funcName << endl; - cerr << "\tAddress range is ["; - fprintf(stderr, "%lx, %lx]", range.first, range.second); - cerr << endl; - - cerr << "Dumping BinInterface-generated disasm:" << endl; - - for(unsigned* inst = (unsigned*) range.first, - *end = (unsigned*) range.second; inst <= end; ++inst){ - printf("%lx:\t%8x\t", (uint64_t) inst, *inst); - sparc_print(*inst); - printf("\n"); - fflush(stdout); - } - #if 0 - cerr << "First instruction in function: " << endl; - void* ptr = (void*) range.first; - unsigned inst = *((uint32_t*)((void*) range.first)); - fprintf(stderr, "%x\n", inst); - cerr << "Disassembly is: "; - sparc_print(inst); - fflush(stdout); + if(funcName == "l16_floogle") { + cerr << "Printing information about function " << funcName << endl; + m_instManip.printRange(range); + } #endif + if(funcName == "l16_fibs") { + //cerr << "Printing information about function " << funcName << endl; + //m_instManip.printRange(range); + + cerr << "Transforming function " << funcName << "..." << endl; + transformFunction(range); } } cerr << "============================== End Phase 2 ==============================\n"; +} + +void phase3(uint64_t value) +{ + printf("phase3 called!\n"); + printf("value passed in is: %lx\n", value); + fflush(stdout); +} + +#if 0 +static void generateLoad64(uint64_t value, vector& snippet) +{ + // Use %o0 and %o1 to load the 64-bit value 'value' into %o0. + // Place the generated instructions into instruction-vector 'snippet'. + + unsigned high32 = (unsigned) (value >> 32); + unsigned low32 = (unsigned) value; + unsigned low10 = high32 & 0x000003ff; + + snippet.push_back(0x11000000 | (high32 >> 10)); // sethi (upper 22b of upper wrd), %o0 + snippet.push_back(0x90122000 | low10); // or %o0, (lower 10b of upper wrd), %o0 + snippet.push_back(0x912a3020); // sllx %o0, 32, %o0 + low10 = low32 & 0x000003ff; + snippet.push_back(0x13000000 | (low32 >> 10)); // sethi (upper 22b of lwr wrd), %o1 + snippet.push_back(0x90120009); // or %o0, %o1, %o0 + snippet.push_back(0x90022000 | low10); // add %o0, (lwr 10b of lwr wrd), %o0 +} + +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). + // + // 2. At the new slot write first the replaced instruction followed by code to call + // the phase 3 function with the address of of F as an argument. + // + // 3. At the new slot write a branch back to immediately after the branch-to-slot + // instruction in the original code. + // + + // Obtain address of first replacable instruction in function + VirtualMem* vm = m_traceCache.getVM(); + uint64_t repInstAddr = m_instManip.skipFunctionHdr(range.first, vm); + + // 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(11); + + // 0x30480000 is branch-always-annul-high instruction (without imm offset) + unsigned branchToSlot = getUndepJumpInstr(0x30480000, slotBase, repInstAddr); + unsigned origInstr = vm->readInstrFrmVm(repInstAddr); + + if(isBranchInstr(origInstr)) + assert(0 && "Unhandled case: branch instruction first in function body"); + + vm->writeInstToVM(repInstAddr, branchToSlot); + + // Build instructions into snippet vector for later insertion. + vector snippet; + + // Pass the starting address of F as the argument to phase3 + m_instManip.generateLoad64(0xefefefefabababab, snippet); + + // Build call to phase3 + uint64_t phase3Addr = (uint64_t)(&phase3); + unsigned call = getCallInstr(phase3Addr, slotBase + 4 * snippet.size()); + snippet.push_back(call); // call phase3 + snippet.push_back(0x01000000); // nop + + // Insert the instruction from the original code which has now + // been replaced with a branch. + snippet.push_back(origInstr); // Inst from orig code (now replaced with branch) + + // Build unconditional branch to repInstAddr + 4; this ensures execution of the code + // is resumed after phase3 is called and performs its transformations. + unsigned branchBack = + getUndepJumpInstr(0x30480000, repInstAddr + 4, slotBase + 4 * snippet.size()); + snippet.push_back(branchBack); // branch to original code + snippet.push_back(0x01000000); // nop + + // Copy the snippet code into the slot. + uint64_t currAddr = slotBase; + for(vector::iterator i = snippet.begin(), e = snippet.end(); i != e; ++i) { + vm->writeInstToVM(currAddr, *i); + currAddr += 4; + } + +#if 0 + cerr << "Dumping inserted snippet..." << endl; + m_instManip.printRange(slotBase, currAddr - 4); + fflush(stdout); + cerr << "Done w/ transformFunction" << endl; +#endif +} +#endif + +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). + // + // 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. + // + // 3. At the new slot write a branch back to immediately after the branch-to-slot + // instruction in the original code. + // + + // Obtain address of first replacable instruction in function + VirtualMem* vm = m_traceCache.getVM(); + uint64_t repInstAddr = m_instManip.skipFunctionHdr(range.first, vm); + + // 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); + + if(isBranchInstr(origInstr)) + assert(0 && "Unhandled case: branch instruction first in function body"); + + // Replace the instruction at repInstAddr with a branch to the start of the slot + vm->writeInstToVM(repInstAddr, m_instManip.getBranchAlways(slotBase, repInstAddr)); + + vector snippet; + + // Pass the starting address of F as the argument to phase3 + 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()); + + // Copy the snippet code into the slot. + uint64_t currAddr = slotBase; + for(vector::iterator i = snippet.begin(), e = snippet.end(); i != e; ++i) { + vm->writeInstToVM(currAddr, *i); + currAddr += 4; + } +} + +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; +} + +//////////////// InstManip implementation //////////////// + +void InstManip::printRange(unsigned* start, unsigned* end) +{ + // Dumps contents (and corresponding disassembly) of memory range given by range + // to stdout. TODO: Parameterize by an ostream instance; cannot do this yet + // because BinInterface is hard-coded to use printf and must be changed. + + std::cout << "Sparc dissassembly of range [" + << start << ", " << end << "]:" << endl; + + for(; start <= end; ++start) { + std::cout << start << " | " + << std::hex << std::setw(8) << std::setfill('0') + << *start << " | "; + sparc_print(*start); + std::cout << endl; + } +} + +void InstManip::printRange(AddressRange& range) +{ + printRange((unsigned*) range.first, (unsigned*) range.second); +} + +void InstManip::printRange(uint64_t start, uint64_t end) +{ + printRange((unsigned*) start, (unsigned*) end); +} + +void InstManip::printInst(unsigned inst) +{ + sparc_print(inst); + fflush(stdout); +} + +void InstManip::printInst(unsigned* instAddr) +{ + sparc_print(*instAddr); + fflush(stdout); +} + +uint64_t InstManip::skipFunctionHdr(uint64_t addr, VirtualMem* vm) +{ + // 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 = vm->readInstrFrmVm(addr); + return RD_FLD(inst, INSTR_OP3) == OP3_SAVE ? addr + 4 : addr; +} + +void InstManip::generateLoad64(uint64_t value, vector& snippet) +{ + // Using %o0 and %o1, load the 64-bit value 'value' into %o0. The sequence of + // instructions to do this is placed in the provided instruction vector 'snippet'. + + unsigned initSize = snippet.size(); + snippet.push_back(0x11000000 | high22(highWord(value))); // sethi (upper 22b of upper wrd), %o0 + snippet.push_back(0x90122000 | low10(highWord(value))); // or %o0, (lower 10b of upper wrd), %o0 + snippet.push_back(0x912a3020); // sllx %o0, 32, %o0 + snippet.push_back(0x13000000 | high22(lowWord(value))); // sethi (upper 22b of lwr wrd), %o1 + snippet.push_back(0x90120009); // or %o0, %o1, %o0 + snippet.push_back(0x90022000 | low10(lowWord(value))); // add %o0, (lwr 10b of lwr wrd), %o0 + + assert(snippet.size() - initSize == getGenLoad64Size() && + "Unexpected number of instructions in code sequence for 64-bit value -> %o0"); +} + +unsigned InstManip::getBranchAlways(uint64_t dest, uint64_t pc, bool annul) +{ + // dest is the destination address, pc is the value of the program counter when the + // branch instruction is executed (i.e., the address of the branch instruction). NB: + // Only handles branch-always-annul-high at the moment + + assert(annul && "Unhandled case: annul bit low"); + return getUndepJumpInstr(BRANCH_ALWAYS_BASE, dest, pc); +} + +unsigned InstManip::getCall(uint64_t dest, uint64_t pc) +{ + // 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 + // instruction). + + return getCallInstr(dest, pc); } From jstanley at cs.uiuc.edu Tue Apr 8 22:37:01 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Tue Apr 8 22:37:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/Inst/Phase2.cpp Message-ID: <200304090337.WAA20633@cypher.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/Inst: Phase2.cpp updated: 1.2 -> 1.3 --- Log message: Cleanup. --- Diffs of the changes: Index: llvm/lib/Reoptimizer/Inst/Phase2.cpp diff -u llvm/lib/Reoptimizer/Inst/Phase2.cpp:1.2 llvm/lib/Reoptimizer/Inst/Phase2.cpp:1.3 --- llvm/lib/Reoptimizer/Inst/Phase2.cpp:1.2 Tue Apr 8 22:35:57 2003 +++ llvm/lib/Reoptimizer/Inst/Phase2.cpp Tue Apr 8 22:37:42 2003 @@ -125,12 +125,6 @@ AddressRange range; while(elfReader.GetNextFunction(funcName, range)) { -#if 0 - if(funcName == "l16_floogle") { - cerr << "Printing information about function " << funcName << endl; - m_instManip.printRange(range); - } -#endif if(funcName == "l16_fibs") { //cerr << "Printing information about function " << funcName << endl; //m_instManip.printRange(range); @@ -150,96 +144,6 @@ fflush(stdout); } -#if 0 -static void generateLoad64(uint64_t value, vector& snippet) -{ - // Use %o0 and %o1 to load the 64-bit value 'value' into %o0. - // Place the generated instructions into instruction-vector 'snippet'. - - unsigned high32 = (unsigned) (value >> 32); - unsigned low32 = (unsigned) value; - unsigned low10 = high32 & 0x000003ff; - - snippet.push_back(0x11000000 | (high32 >> 10)); // sethi (upper 22b of upper wrd), %o0 - snippet.push_back(0x90122000 | low10); // or %o0, (lower 10b of upper wrd), %o0 - snippet.push_back(0x912a3020); // sllx %o0, 32, %o0 - low10 = low32 & 0x000003ff; - snippet.push_back(0x13000000 | (low32 >> 10)); // sethi (upper 22b of lwr wrd), %o1 - snippet.push_back(0x90120009); // or %o0, %o1, %o0 - snippet.push_back(0x90022000 | low10); // add %o0, (lwr 10b of lwr wrd), %o0 -} - -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). - // - // 2. At the new slot write first the replaced instruction followed by code to call - // the phase 3 function with the address of of F as an argument. - // - // 3. At the new slot write a branch back to immediately after the branch-to-slot - // instruction in the original code. - // - - // Obtain address of first replacable instruction in function - VirtualMem* vm = m_traceCache.getVM(); - uint64_t repInstAddr = m_instManip.skipFunctionHdr(range.first, vm); - - // 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(11); - - // 0x30480000 is branch-always-annul-high instruction (without imm offset) - unsigned branchToSlot = getUndepJumpInstr(0x30480000, slotBase, repInstAddr); - unsigned origInstr = vm->readInstrFrmVm(repInstAddr); - - if(isBranchInstr(origInstr)) - assert(0 && "Unhandled case: branch instruction first in function body"); - - vm->writeInstToVM(repInstAddr, branchToSlot); - - // Build instructions into snippet vector for later insertion. - vector snippet; - - // Pass the starting address of F as the argument to phase3 - m_instManip.generateLoad64(0xefefefefabababab, snippet); - - // Build call to phase3 - uint64_t phase3Addr = (uint64_t)(&phase3); - unsigned call = getCallInstr(phase3Addr, slotBase + 4 * snippet.size()); - snippet.push_back(call); // call phase3 - snippet.push_back(0x01000000); // nop - - // Insert the instruction from the original code which has now - // been replaced with a branch. - snippet.push_back(origInstr); // Inst from orig code (now replaced with branch) - - // Build unconditional branch to repInstAddr + 4; this ensures execution of the code - // is resumed after phase3 is called and performs its transformations. - unsigned branchBack = - getUndepJumpInstr(0x30480000, repInstAddr + 4, slotBase + 4 * snippet.size()); - snippet.push_back(branchBack); // branch to original code - snippet.push_back(0x01000000); // nop - - // Copy the snippet code into the slot. - uint64_t currAddr = slotBase; - for(vector::iterator i = snippet.begin(), e = snippet.end(); i != e; ++i) { - vm->writeInstToVM(currAddr, *i); - currAddr += 4; - } - -#if 0 - cerr << "Dumping inserted snippet..." << endl; - m_instManip.printRange(slotBase, currAddr - 4); - fflush(stdout); - cerr << "Done w/ transformFunction" << endl; -#endif -} -#endif - void Phase2::transformFunction(AddressRange& range) { //////////////// @@ -274,6 +178,7 @@ vector 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 From jstanley at cs.uiuc.edu Tue Apr 8 23:31:00 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Tue Apr 8 23:31:00 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/Inst/InstManip.cpp InstManip.h Phase2.cpp Message-ID: <200304090432.XAA21830@cypher.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/Inst: InstManip.cpp added (r1.1) InstManip.h added (r1.1) Phase2.cpp updated: 1.3 -> 1.4 --- Log message: Factored out InstManip code into separate files. --- Diffs of the changes: Index: llvm/lib/Reoptimizer/Inst/Phase2.cpp diff -u llvm/lib/Reoptimizer/Inst/Phase2.cpp:1.3 llvm/lib/Reoptimizer/Inst/Phase2.cpp:1.4 --- llvm/lib/Reoptimizer/Inst/Phase2.cpp:1.3 Tue Apr 8 22:37:42 2003 +++ llvm/lib/Reoptimizer/Inst/Phase2.cpp Tue Apr 8 23:32:03 2003 @@ -33,63 +33,17 @@ #include #include -#include "ElfReader.h" #include "llvm/Reoptimizer/TraceCache.h" #include "llvm/Reoptimizer/VirtualMem.h" -#include "llvm/Reoptimizer/InstrUtils.h" -#include "../BinInterface/sparcdis.h" // TODO: Move to proper include directory -#include "../BinInterface/sparc9.h" // TODO: Move to proper include directory -#include "../BinInterface/bitmath.h" // TODO: Move to proper include directory #include "../TraceCache/MemoryManager.h" // TODO: Move to proper include directory +#include "ElfReader.h" +#include "InstManip.h" + using std::vector; using std::cerr; using std::endl; -typedef std::pair AddressRange; - -// InstManip is a wrapper class around any BinInterface macros/mechanisms, as well as the -// TraceCache "instruction utilities, all which are SparcV9-specific; this class exists -// both for conceptual clarity and to facilitate hiding the Sparc-specificity from the -// Phase2 actions (and thus making it easier to use the phase2 transformations on other -// platforms in the future; we should be able to change which instruction manipulator -// object is instantiated, after making the appropriate superclass, etc). - -class InstManip -{ - public: - void printRange(unsigned* start, unsigned* end); - inline void printRange(AddressRange& range); - inline void printRange(uint64_t start, uint64_t end); - - inline void printInst(unsigned inst); - inline void printInst(unsigned* instAddr); - - uint64_t skipFunctionHdr(uint64_t addr, VirtualMem* vm); - - void generateLoad64(uint64_t value, vector& snippet); - - unsigned getBranchAlways(uint64_t dest, uint64_t pc, bool annulHigh = true); - inline unsigned getCall(uint64_t dest, uint64_t pc); - - unsigned getNOP() const { return 0x01000000; } - unsigned getGenLoad64Size() const { return 6; } - - private: - //////////////// - // Instruction constants and field-extraction "macros", etc. - - // Branch-always (annul bit high) instruction base (i.e. address not filled in yet) - static const int wtf = 19; - - static const unsigned BRANCH_ALWAYS_BASE = 0x30480000; - - unsigned low10(unsigned value) { return value & 0x000003ff; } - unsigned high22(unsigned value) { return value >> 10; } - unsigned highWord(uint64_t value) { return (unsigned) (value >> 32); } - unsigned lowWord(uint64_t value) { return (unsigned) value; } -}; - // 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. @@ -97,7 +51,7 @@ { public: void transform(); - void transformFunction(AddressRange& range); + void transformFunction(std::pair& range); private: inline unsigned getSlotSize() const; @@ -122,12 +76,12 @@ ElfReader elfReader(execName); std::string funcName; - AddressRange range; + std::pair range; while(elfReader.GetNextFunction(funcName, range)) { if(funcName == "l16_fibs") { //cerr << "Printing information about function " << funcName << endl; - //m_instManip.printRange(range); + m_instManip.printRange(range.first, range.second); cerr << "Transforming function " << funcName << "..." << endl; transformFunction(range); @@ -144,7 +98,7 @@ fflush(stdout); } -void Phase2::transformFunction(AddressRange& range) +void Phase2::transformFunction(std::pair& range) { //////////////// // 1. Replace the first instruction in F with a branch to a new slot (annulling bit @@ -169,7 +123,7 @@ uint64_t slotBase = mm->getMemory(getSlotSize()); unsigned origInstr = vm->readInstrFrmVm(repInstAddr); - if(isBranchInstr(origInstr)) + if(m_instManip.isBranch(origInstr)) assert(0 && "Unhandled case: branch instruction first in function body"); // Replace the instruction at repInstAddr with a branch to the start of the slot @@ -212,91 +166,3 @@ return m_instManip.getGenLoad64Size() + 5; } - -//////////////// InstManip implementation //////////////// - -void InstManip::printRange(unsigned* start, unsigned* end) -{ - // Dumps contents (and corresponding disassembly) of memory range given by range - // to stdout. TODO: Parameterize by an ostream instance; cannot do this yet - // because BinInterface is hard-coded to use printf and must be changed. - - std::cout << "Sparc dissassembly of range [" - << start << ", " << end << "]:" << endl; - - for(; start <= end; ++start) { - std::cout << start << " | " - << std::hex << std::setw(8) << std::setfill('0') - << *start << " | "; - sparc_print(*start); - std::cout << endl; - } -} - -void InstManip::printRange(AddressRange& range) -{ - printRange((unsigned*) range.first, (unsigned*) range.second); -} - -void InstManip::printRange(uint64_t start, uint64_t end) -{ - printRange((unsigned*) start, (unsigned*) end); -} - -void InstManip::printInst(unsigned inst) -{ - sparc_print(inst); - fflush(stdout); -} - -void InstManip::printInst(unsigned* instAddr) -{ - sparc_print(*instAddr); - fflush(stdout); -} - -uint64_t InstManip::skipFunctionHdr(uint64_t addr, VirtualMem* vm) -{ - // 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 = vm->readInstrFrmVm(addr); - return RD_FLD(inst, INSTR_OP3) == OP3_SAVE ? addr + 4 : addr; -} - -void InstManip::generateLoad64(uint64_t value, vector& snippet) -{ - // Using %o0 and %o1, load the 64-bit value 'value' into %o0. The sequence of - // instructions to do this is placed in the provided instruction vector 'snippet'. - - unsigned initSize = snippet.size(); - snippet.push_back(0x11000000 | high22(highWord(value))); // sethi (upper 22b of upper wrd), %o0 - snippet.push_back(0x90122000 | low10(highWord(value))); // or %o0, (lower 10b of upper wrd), %o0 - snippet.push_back(0x912a3020); // sllx %o0, 32, %o0 - snippet.push_back(0x13000000 | high22(lowWord(value))); // sethi (upper 22b of lwr wrd), %o1 - snippet.push_back(0x90120009); // or %o0, %o1, %o0 - snippet.push_back(0x90022000 | low10(lowWord(value))); // add %o0, (lwr 10b of lwr wrd), %o0 - - assert(snippet.size() - initSize == getGenLoad64Size() && - "Unexpected number of instructions in code sequence for 64-bit value -> %o0"); -} - -unsigned InstManip::getBranchAlways(uint64_t dest, uint64_t pc, bool annul) -{ - // dest is the destination address, pc is the value of the program counter when the - // branch instruction is executed (i.e., the address of the branch instruction). NB: - // Only handles branch-always-annul-high at the moment - - assert(annul && "Unhandled case: annul bit low"); - return getUndepJumpInstr(BRANCH_ALWAYS_BASE, dest, pc); -} - -unsigned InstManip::getCall(uint64_t dest, uint64_t pc) -{ - // 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 - // instruction). - - return getCallInstr(dest, pc); -} - From brukman at cs.uiuc.edu Wed Apr 9 16:52:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed Apr 9 16:52:01 2003 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/ModuloScheduling/ModuloSchedGraph.cpp ModuloSchedGraph.h ModuloScheduling.cpp ModuloScheduling.h Message-ID: <200304092151.QAA09738@neo.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/ModuloScheduling: ModuloSchedGraph.cpp updated: 1.2 -> 1.3 ModuloSchedGraph.h updated: 1.2 -> 1.3 ModuloScheduling.cpp updated: 1.2 -> 1.3 ModuloScheduling.h updated: 1.2 -> 1.3 --- Log message: Made the code readable: * Lines must be wrapped at 80 chars. This is a hard limit. * Consistent style on functions, braces, if, for, etc. Code must be readable. No functional changes have been made, even though I added a new typedef. --- Diffs of the changes: Index: llvm/lib/CodeGen/ModuloScheduling/ModuloSchedGraph.cpp diff -u llvm/lib/CodeGen/ModuloScheduling/ModuloSchedGraph.cpp:1.2 llvm/lib/CodeGen/ModuloScheduling/ModuloSchedGraph.cpp:1.3 --- llvm/lib/CodeGen/ModuloScheduling/ModuloSchedGraph.cpp:1.2 Sun Apr 6 18:56:10 2003 +++ llvm/lib/CodeGen/ModuloScheduling/ModuloSchedGraph.cpp Wed Apr 9 16:51:34 2003 @@ -1,31 +1,24 @@ -#include -#include "ModuloSchedGraph.h" +//===- ModuloSchedGraph.cpp - Graph datastructure for Modulo Scheduling ---===// +// +// +//===----------------------------------------------------------------------===// + #include "llvm/CodeGen/InstrSelection.h" -#include "llvm/BasicBlock.h" #include "llvm/Function.h" -#include "llvm/iOther.h" -#include "Support/StringExtras.h" -#include "Support/STLExtras.h" -#include -//#include -#include "llvm/iOperators.h" -#include "llvm/iOther.h" -#include "llvm/iPHINode.h" -#include "llvm/iTerminators.h" -#include "llvm/iMemory.h" +#include "llvm/Instructions.h" #include "llvm/Type.h" #include "llvm/CodeGen/MachineCodeForInstruction.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/Target/TargetSchedInfo.h" +#include "Support/StringExtras.h" +#include "Support/STLExtras.h" +#include "ModuloSchedGraph.h" +#include +#include +//#include #define UNIDELAY 1 -#define min(a, b) ((a) < (b) ? (a) : (b)) -#define max(a, b) ((a) < (b) ? (b) : (a)) -using std::vector; -using std::pair; -//using std::hash_map; -using std::cerr; extern std::ostream modSched_os; extern ModuloSchedDebugLevel_t ModuloSchedDebugLevel; //*********************** Internal Data Structures *************************/ @@ -33,187 +26,177 @@ // The following two types need to be classes, not typedefs, so we can use // opaque declarations in SchedGraph.h // -struct RefVec: public vector< pair > { - typedef vector< pair >:: iterator iterator; - typedef vector< pair >::const_iterator const_iterator; +struct RefVec:public std::vector < std::pair < ModuloSchedGraphNode *, int >> { + typedef std::vector >::iterator iterator; + typedef std::vector >::const_iterator const_iterator; }; -struct RegToRefVecMap: public hash_map { - typedef hash_map:: iterator iterator; - typedef hash_map::const_iterator const_iterator; +struct RegToRefVecMap:public std::hash_map < int, RefVec > { + typedef std::hash_map::iterator iterator; + typedef std::hash_map::const_iterator const_iterator; }; -struct ValueToDefVecMap: public hash_map { - typedef hash_map:: iterator iterator; - typedef hash_map::const_iterator const_iterator; +struct ValueToDefVecMap:public std::hash_map < const Instruction *, RefVec > { + typedef std::hash_map::iterator iterator; + typedef std::hash_map::const_iterator const_iterator; }; - - // class Modulo SchedGraphNode /*ctor*/ ModuloSchedGraphNode::ModuloSchedGraphNode(unsigned int _nodeId, - const BasicBlock* _bb, - const Instruction* _inst, - int indexInBB, - const TargetMachine& target) - : - SchedGraphNodeCommon(_nodeId, _bb, indexInBB), - inst(_inst) -{ - if(inst) - { - //FIXME: find the latency - //currently setthe latency to zero - latency =0; - } - + const BasicBlock * _bb, + const Instruction * _inst, + int indexInBB, + const TargetMachine & target) +:SchedGraphNodeCommon(_nodeId, _bb, indexInBB), inst(_inst) +{ + if (inst) { + //FIXME: find the latency + //currently setthe latency to zero + latency = 0; + } } - -//class ModuloScheGraph +//class ModuloScheGraph -void -ModuloSchedGraph::addDummyEdges() +void ModuloSchedGraph::addDummyEdges() { assert(graphRoot->outEdges.size() == 0); - - for (const_iterator I=begin(); I != end(); ++I) - { - ModuloSchedGraphNode* node = (ModuloSchedGraphNode*)( (*I).second); - assert(node != graphRoot && node != graphLeaf); - if (node->beginInEdges() == node->endInEdges()) - (void) new SchedGraphEdge(graphRoot, node, SchedGraphEdge::CtrlDep, - SchedGraphEdge::NonDataDep, 0); - if (node->beginOutEdges() == node->endOutEdges()) - (void) new SchedGraphEdge(node, graphLeaf, SchedGraphEdge::CtrlDep, - SchedGraphEdge::NonDataDep, 0); - } + + for (const_iterator I = begin(); I != end(); ++I) { + ModuloSchedGraphNode *node = (ModuloSchedGraphNode *) ((*I).second); + assert(node != graphRoot && node != graphLeaf); + if (node->beginInEdges() == node->endInEdges()) + (void) new SchedGraphEdge(graphRoot, node, SchedGraphEdge::CtrlDep, + SchedGraphEdge::NonDataDep, 0); + if (node->beginOutEdges() == node->endOutEdges()) + (void) new SchedGraphEdge(node, graphLeaf, SchedGraphEdge::CtrlDep, + SchedGraphEdge::NonDataDep, 0); + } } -bool isDefinition(const Instruction* I) +bool isDefinition(const Instruction *I) { //if(TerminatorInst::classof(I)||FreeInst::classof(I) || StoreInst::classof(I) || CallInst::classof(I)) - if(!I->hasName()) + if (!I->hasName()) return false; else return true; } -void ModuloSchedGraph::addDefUseEdges(const BasicBlock* bb) +void ModuloSchedGraph::addDefUseEdges(const BasicBlock *bb) { //collect def instructions, store them in vector // const TargetInstrInfo& mii = target.getInstrInfo(); - const TargetInstrInfo& mii = target.getInstrInfo(); - - typedef std::vector DefVec; + const TargetInstrInfo & mii = target.getInstrInfo(); + + typedef std::vector < ModuloSchedGraphNode * >DefVec; DefVec defVec; - + //find those def instructions - for(BasicBlock::const_iterator I=bb->begin(), E=bb->end(); I !=E; I++) - if(I->getType() != Type::VoidTy) - { - defVec.push_back(this->getGraphNodeForInst(I)) ; - } - - for(unsigned int i=0; i < defVec.size();i++) - for(Value::use_const_iterator I=defVec[i]->getInst()->use_begin();I !=defVec[i]->getInst()->use_end() ;I++) + for (BasicBlock::const_iterator I = bb->begin(), E = bb->end(); I != E; ++I) { + if (I->getType() != Type::VoidTy) { + defVec.push_back(this->getGraphNodeForInst(I)); + } + } + + for (unsigned int i = 0; i < defVec.size(); i++) { + for (Value::use_const_iterator I = defVec[i]->getInst()->use_begin(); + I != defVec[i]->getInst()->use_end(); I++) { + //for each use of a def, add a flow edge from the def instruction to the ref instruction + + + const Instruction *value = defVec[i]->getInst(); + Instruction *inst = (Instruction *) (*I); + ModuloSchedGraphNode *node = NULL; + + for (BasicBlock::const_iterator I = bb->begin(), E = bb->end(); + I != E; ++I) + if ((const Instruction *) I == inst) { + node = (*this)[inst]; + break; + } + + assert(inst != NULL && " Use not an Instruction ?"); + + if (node == NULL) //inst is not an instruction in this block { - //for each use of a def, add a flow edge from the def instruction to the ref instruction + } else { + // Add a flow edge from the def instruction to the ref instruction - - const Instruction* value=defVec[i]->getInst(); - Instruction *inst=(Instruction*)(*I); - ModuloSchedGraphNode* node=NULL; - - for(BasicBlock::const_iterator I=bb->begin(), E=bb->end(); I !=E; I++) - if((const Instruction*)I == inst) - { - node=(*this)[inst]; - break; - } - - assert(inst != NULL &&" Use not an Instruction ?" ); - - if(node == NULL) //inst is not an instruction in this block - {} - else - { - //add a flow edge from the def instruction to the ref instruction - - //self loop will not happen in SSA form - assert(defVec[i] != node && "same node?"); - - - //this is a true dependence, so the delay is equal to the delay of the pred node. - int delay=0; - MachineCodeForInstruction& tempMvec= MachineCodeForInstruction::get(value); - for(unsigned j=0;j< tempMvec.size();j++) - { - MachineInstr* temp=tempMvec[j]; - //delay +=mii.minLatency(temp->getOpCode()); - delay = max(delay, mii.minLatency(temp->getOpCode())); - } - - SchedGraphEdge* trueEdge=new SchedGraphEdge(defVec[i],node,value, SchedGraphEdge::TrueDep,delay); - - //if the ref instruction is before the def instrution - //then the def instruction must be a phi instruction - //add an anti-dependence edge to from the ref instruction to the def instruction - if( node->getOrigIndexInBB() < defVec[i]->getOrigIndexInBB()) - { - assert(PHINode::classof(inst) && "the ref instruction befre def is not PHINode?"); - trueEdge->setIteDiff(1); - } - - } - - } -} + // self loop will not happen in SSA form + assert(defVec[i] != node && "same node?"); + + // This is a true dependence, so the delay is equal to the delay of the + // pred node. + int delay = 0; + MachineCodeForInstruction & tempMvec = + MachineCodeForInstruction::get(value); + for (unsigned j = 0; j < tempMvec.size(); j++) { + MachineInstr *temp = tempMvec[j]; + //delay +=mii.minLatency(temp->getOpCode()); + delay = std::max(delay, mii.minLatency(temp->getOpCode())); + } + + SchedGraphEdge *trueEdge = + new SchedGraphEdge(defVec[i], node, value, + SchedGraphEdge::TrueDep, delay); + + // if the ref instruction is before the def instrution + // then the def instruction must be a phi instruction + // add an anti-dependence edge to from the ref instruction to the def + // instruction + if (node->getOrigIndexInBB() < defVec[i]->getOrigIndexInBB()) { + assert(PHINode::classof(inst) + && "the ref instruction befre def is not PHINode?"); + trueEdge->setIteDiff(1); + } -void ModuloSchedGraph::addCDEdges(const BasicBlock* bb) -{ - //find the last instruction in the basic block - //see if it is an branch instruction. - //If yes, then add an edge from each node expcept the last node to the last node - - const Instruction* inst=&(bb->back()); - ModuloSchedGraphNode* lastNode=(*this)[inst]; - if( TerminatorInst::classof(inst)) - for(BasicBlock::const_iterator I=bb->begin(),E=bb->end(); I != E; I++) - { - if(inst != I) - { - ModuloSchedGraphNode* node = (*this)[I]; - //use latency of 0 - (void) new SchedGraphEdge(node,lastNode,SchedGraphEdge::CtrlDep, - SchedGraphEdge::NonDataDep,0); - } - } - - -} + } + } +} +void ModuloSchedGraph::addCDEdges(const BasicBlock * bb) { + // find the last instruction in the basic block + // see if it is an branch instruction. + // If yes, then add an edge from each node expcept the last node to the last + // node + const Instruction *inst = &(bb->back()); + ModuloSchedGraphNode *lastNode = (*this)[inst]; + if (TerminatorInst::classof(inst)) + for (BasicBlock::const_iterator I = bb->begin(), E = bb->end(); I != E; + I++) { + if (inst != I) { + ModuloSchedGraphNode *node = (*this)[I]; + //use latency of 0 + (void) new SchedGraphEdge(node, lastNode, SchedGraphEdge::CtrlDep, + SchedGraphEdge::NonDataDep, 0); + } + } +} -static const int SG_LOAD_REF = 0; +static const int SG_LOAD_REF = 0; static const int SG_STORE_REF = 1; -static const int SG_CALL_REF = 2; +static const int SG_CALL_REF = 2; static const unsigned int SG_DepOrderArray[][3] = { - { SchedGraphEdge::NonDataDep, - SchedGraphEdge::AntiDep, - SchedGraphEdge::AntiDep }, - { SchedGraphEdge::TrueDep, - SchedGraphEdge::OutputDep, - SchedGraphEdge::TrueDep | SchedGraphEdge::OutputDep }, - { SchedGraphEdge::TrueDep, - SchedGraphEdge::AntiDep | SchedGraphEdge::OutputDep, - SchedGraphEdge::TrueDep | SchedGraphEdge::AntiDep - | SchedGraphEdge::OutputDep } + {SchedGraphEdge::NonDataDep, + SchedGraphEdge::AntiDep, + SchedGraphEdge::AntiDep}, + {SchedGraphEdge::TrueDep, + SchedGraphEdge::OutputDep, + SchedGraphEdge::TrueDep | SchedGraphEdge::OutputDep}, + {SchedGraphEdge::TrueDep, + SchedGraphEdge::AntiDep | SchedGraphEdge::OutputDep, + SchedGraphEdge::TrueDep | SchedGraphEdge::AntiDep + | SchedGraphEdge::OutputDep} }; @@ -222,616 +205,666 @@ // Use latency 1 just to ensure that memory operations are ordered; // latency does not otherwise matter (true dependences enforce that). // -void -ModuloSchedGraph::addMemEdges(const BasicBlock* bb) -{ - - vector memNodeVec; +void ModuloSchedGraph::addMemEdges(const BasicBlock * bb) { + + std::vector memNodeVec; //construct the memNodeVec - - for( BasicBlock::const_iterator I=bb->begin(), E=bb->end();I != E; I++) - if(LoadInst::classof(I) ||StoreInst::classof(I) || CallInst::classof(I)) - { - ModuloSchedGraphNode* node =(*this)[(const Instruction*)I]; - memNodeVec.push_back(node); - } + for (BasicBlock::const_iterator I = bb->begin(), E = bb->end(); I != E; ++I) { + if (LoadInst::classof(I) || StoreInst::classof(I) + || CallInst::classof(I)) { + ModuloSchedGraphNode *node = (*this)[(const Instruction *) I]; + memNodeVec.push_back(node); + } + } + // Instructions in memNodeVec are in execution order within the basic block, // so simply look at all pairs i]>. // - for (unsigned im=0, NM=memNodeVec.size(); im < NM; im++) - { - const Instruction* fromInst = memNodeVec[im]->getInst(); - int fromType = CallInst::classof(fromInst)? SG_CALL_REF - : LoadInst::classof(fromInst)? SG_LOAD_REF - : SG_STORE_REF; - for (unsigned jm=im+1; jm < NM; jm++) - { - const Instruction* toInst=memNodeVec[jm]->getInst(); - int toType = CallInst::classof(toInst)? SG_CALL_REF - : LoadInst::classof(toInst)? SG_LOAD_REF - : SG_STORE_REF; - if (fromType != SG_LOAD_REF || toType != SG_LOAD_REF) - { - (void) new SchedGraphEdge(memNodeVec[im], memNodeVec[jm], - SchedGraphEdge::MemoryDep, - SG_DepOrderArray[fromType][toType], 1); - - SchedGraphEdge* edge=new SchedGraphEdge(memNodeVec[jm],memNodeVec[im], - SchedGraphEdge::MemoryDep, - SG_DepOrderArray[toType][fromType],1); - edge->setIteDiff(1); - - } - } - } -} + for (unsigned im = 0, NM = memNodeVec.size(); im < NM; im++) { + const Instruction *fromInst = memNodeVec[im]->getInst(); + int fromType = CallInst::classof(fromInst) ? SG_CALL_REF + : LoadInst::classof(fromInst) ? SG_LOAD_REF : SG_STORE_REF; + for (unsigned jm = im + 1; jm < NM; jm++) { + const Instruction *toInst = memNodeVec[jm]->getInst(); + int toType = CallInst::classof(toInst) ? SG_CALL_REF + : LoadInst::classof(toInst) ? SG_LOAD_REF : SG_STORE_REF; + if (fromType != SG_LOAD_REF || toType != SG_LOAD_REF) { + (void) new SchedGraphEdge(memNodeVec[im], memNodeVec[jm], + SchedGraphEdge::MemoryDep, + SG_DepOrderArray[fromType][toType], 1); + + SchedGraphEdge *edge = + new SchedGraphEdge(memNodeVec[jm], memNodeVec[im], + SchedGraphEdge::MemoryDep, + SG_DepOrderArray[toType][fromType], 1); + edge->setIteDiff(1); + + } + } + } +} -void ModuloSchedGraph::buildNodesforBB (const TargetMachine& target, - const BasicBlock* bb, - std::vector& memNode, - RegToRefVecMap& regToRefVecMap, - ValueToDefVecMap& valueToDefVecMap) +void ModuloSchedGraph::buildNodesforBB(const TargetMachine &target, + const BasicBlock *bb, + std::vector &memNode, + RegToRefVecMap ®ToRefVecMap, + ValueToDefVecMap &valueToDefVecMap) { //const TargetInstrInfo& mii=target.getInstrInfo(); - + //Build graph nodes for each LLVM instruction and gather def/use info. //Do both together in a single pass over all machine instructions. - - int i=0; - for(BasicBlock::const_iterator I=bb->begin(), E=bb->end(); I!=E; I++) - { - ModuloSchedGraphNode* node=new ModuloSchedGraphNode(getNumNodes(), bb,I,i, target); - i++; - this->noteModuloSchedGraphNodeForInst(I,node); - } - - //this function finds some info about instruction in basic block for later use - //findDefUseInfoAtInstr(target, node, memNode,regToRefVecMap,valueToDefVecMap); + int i = 0; + for (BasicBlock::const_iterator I = bb->begin(), E = bb->end(); I != E; + ++I) { + ModuloSchedGraphNode *node = + new ModuloSchedGraphNode(getNumNodes(), bb, I, i, target); + i++; + this->noteModuloSchedGraphNodeForInst(I, node); + } + //this function finds some info about instruction in basic block for later use + //findDefUseInfoAtInstr(target, node, + //memNode,regToRefVecMap,valueToDefVecMap); } -bool ModuloSchedGraph::isLoop(const BasicBlock* bb) -{ +bool ModuloSchedGraph::isLoop(const BasicBlock *bb) { //only if the last instruction in the basicblock is branch instruction and //there is at least an option to branch itself - - const Instruction* inst=&(bb->back()); - if( BranchInst::classof(inst)) - for(unsigned i=0;i < ((BranchInst*)inst)->getNumSuccessors();i++) - { - BasicBlock* sb=((BranchInst*)inst)->getSuccessor(i); - if(sb ==bb) return true; - } - + const Instruction *inst = &(bb->back()); + if (BranchInst::classof(inst)) { + for (unsigned i = 0; i < ((BranchInst *) inst)->getNumSuccessors(); + i++) { + BasicBlock *sb = ((BranchInst *) inst)->getSuccessor(i); + if (sb == bb) + return true; + } + } + return false; - + } -bool ModuloSchedGraph::isLoop() -{ + +bool ModuloSchedGraph::isLoop() { //only if the last instruction in the basicblock is branch instruction and //there is at least an option to branch itself - - assert(bbVec.size() ==1 &&"only 1 basicblock in a graph"); - const BasicBlock* bb=bbVec[0]; - const Instruction* inst=&(bb->back()); - if( BranchInst::classof(inst)) - for(unsigned i=0;i < ((BranchInst*)inst)->getNumSuccessors();i++) - { - BasicBlock* sb=((BranchInst*)inst)->getSuccessor(i); - if(sb ==bb) return true; - } - + + assert(bbVec.size() == 1 && "only 1 basicblock in a graph"); + const BasicBlock *bb = bbVec[0]; + const Instruction *inst = &(bb->back()); + if (BranchInst::classof(inst)) + for (unsigned i = 0; i < ((BranchInst *) inst)->getNumSuccessors(); + i++) { + BasicBlock *sb = ((BranchInst *) inst)->getSuccessor(i); + if (sb == bb) + return true; + } + return false; - + } -void ModuloSchedGraph::computeNodeASAP(const BasicBlock* bb) -{ +void ModuloSchedGraph::computeNodeASAP(const BasicBlock *bb) { - //FIXME: now assume the only backward edges come from the edges from other nodes to the phi Node - //so i will ignore all edges to the phi node; after this, there shall be no recurrence. - - unsigned numNodes=bb->size(); - for(unsigned i=2;i < numNodes+2;i++) - { - ModuloSchedGraphNode* node=getNode(i); - node->setPropertyComputed(false); - } - - for(unsigned i=2;i < numNodes+2; i++) - { - ModuloSchedGraphNode* node=getNode(i); - node->ASAP=0; - if(i==2 ||node->getNumInEdges() ==0) - { node->setPropertyComputed(true);continue;} - for(ModuloSchedGraphNode::const_iterator I=node->beginInEdges(), E=node->endInEdges();I !=E; I++) - { - SchedGraphEdge* edge=*I; - ModuloSchedGraphNode* pred=(ModuloSchedGraphNode*)(edge->getSrc()); - assert(pred->getPropertyComputed()&&"pred node property is not computed!"); - int temp=pred->ASAP + edge->getMinDelay() - edge->getIteDiff()*this->MII; - node->ASAP= max(node->ASAP,temp); - } + //FIXME: now assume the only backward edges come from the edges from other + //nodes to the phi Node so i will ignore all edges to the phi node; after + //this, there shall be no recurrence. + + unsigned numNodes = bb->size(); + for (unsigned i = 2; i < numNodes + 2; i++) { + ModuloSchedGraphNode *node = getNode(i); + node->setPropertyComputed(false); + } + + for (unsigned i = 2; i < numNodes + 2; i++) { + ModuloSchedGraphNode *node = getNode(i); + node->ASAP = 0; + if (i == 2 || node->getNumInEdges() == 0) { node->setPropertyComputed(true); + continue; + } + for (ModuloSchedGraphNode::const_iterator I = node->beginInEdges(), E = + node->endInEdges(); I != E; I++) { + SchedGraphEdge *edge = *I; + ModuloSchedGraphNode *pred = + (ModuloSchedGraphNode *) (edge->getSrc()); + assert(pred->getPropertyComputed() + && "pred node property is not computed!"); + int temp = + pred->ASAP + edge->getMinDelay() - + edge->getIteDiff() * this->MII; + node->ASAP = std::max(node->ASAP, temp); } + node->setPropertyComputed(true); + } } -void ModuloSchedGraph::computeNodeALAP(const BasicBlock* bb) -{ - - unsigned numNodes=bb->size(); - int maxASAP=0; - for(unsigned i=numNodes+1;i >= 2;i--) - { - ModuloSchedGraphNode* node=getNode(i); - node->setPropertyComputed(false); - //cerr<< " maxASAP= " <ASAP= "<< node->ASAP<<"\n"; - maxASAP=max(maxASAP,node->ASAP); - } +void ModuloSchedGraph::computeNodeALAP(const BasicBlock *bb) { + unsigned numNodes = bb->size(); + int maxASAP = 0; + for (unsigned i = numNodes + 1; i >= 2; i--) { + ModuloSchedGraphNode *node = getNode(i); + node->setPropertyComputed(false); + //cerr<< " maxASAP= " <ASAP= "<< node->ASAP<<"\n"; + maxASAP = std::max(maxASAP, node->ASAP); + } //cerr<<"maxASAP is "<= 2; i--) - { - ModuloSchedGraphNode* node=getNode(i); - node->ALAP=maxASAP; - for(ModuloSchedGraphNode::const_iterator I=node->beginOutEdges(), E=node->endOutEdges(); I!=E; I++) - { - SchedGraphEdge* edge= *I; - ModuloSchedGraphNode* succ=(ModuloSchedGraphNode*) (edge->getSink()); - if(PHINode::classof(succ->getInst()))continue; - assert(succ->getPropertyComputed()&&"succ node property is not computed!"); - int temp=succ->ALAP - edge->getMinDelay()+edge->getIteDiff()*this->MII; - node->ALAP =min(node->ALAP,temp); - } - node->setPropertyComputed(true); - + + for (unsigned i = numNodes + 1; i >= 2; i--) { + ModuloSchedGraphNode *node = getNode(i); + node->ALAP = maxASAP; + for (ModuloSchedGraphNode::const_iterator I = + node->beginOutEdges(), E = node->endOutEdges(); I != E; I++) { + SchedGraphEdge *edge = *I; + ModuloSchedGraphNode *succ = + (ModuloSchedGraphNode *) (edge->getSink()); + if (PHINode::classof(succ->getInst())) + continue; + assert(succ->getPropertyComputed() + && "succ node property is not computed!"); + int temp = + succ->ALAP - edge->getMinDelay() + + edge->getIteDiff() * this->MII; + node->ALAP = std::min(node->ALAP, temp); } + node->setPropertyComputed(true); + } } -void ModuloSchedGraph::computeNodeMov(const BasicBlock* bb) +void ModuloSchedGraph::computeNodeMov(const BasicBlock *bb) { - unsigned numNodes=bb->size(); - for(unsigned i =2;i < numNodes +2 ;i++) - { - ModuloSchedGraphNode* node=getNode(i); - node->mov=node->ALAP-node->ASAP; - assert(node->mov >=0 &&"move freedom for this node is less than zero? "); - } + unsigned numNodes = bb->size(); + for (unsigned i = 2; i < numNodes + 2; i++) { + ModuloSchedGraphNode *node = getNode(i); + node->mov = node->ALAP - node->ASAP; + assert(node->mov >= 0 + && "move freedom for this node is less than zero? "); + } } -void ModuloSchedGraph::computeNodeDepth(const BasicBlock* bb) +void ModuloSchedGraph::computeNodeDepth(const BasicBlock * bb) { - unsigned numNodes=bb->size(); - for(unsigned i=2;i < numNodes+2;i++) - { - ModuloSchedGraphNode* node=getNode(i); - node->setPropertyComputed(false); - } + unsigned numNodes = bb->size(); + for (unsigned i = 2; i < numNodes + 2; i++) { + ModuloSchedGraphNode *node = getNode(i); + node->setPropertyComputed(false); + } - for(unsigned i=2;i < numNodes+2; i++) - { - ModuloSchedGraphNode* node=getNode(i); - node->depth=0; - if(i==2 ||node->getNumInEdges() ==0) - { node->setPropertyComputed(true);continue;} - for(ModuloSchedGraphNode::const_iterator I=node->beginInEdges(), E=node->endInEdges();I !=E; I++) - { - SchedGraphEdge* edge=*I; - ModuloSchedGraphNode* pred=(ModuloSchedGraphNode*)(edge->getSrc()); - assert(pred->getPropertyComputed()&&"pred node property is not computed!"); - int temp=pred->depth + edge->getMinDelay(); - node->depth= max(node->depth,temp); - } + for (unsigned i = 2; i < numNodes + 2; i++) { + ModuloSchedGraphNode *node = getNode(i); + node->depth = 0; + if (i == 2 || node->getNumInEdges() == 0) { node->setPropertyComputed(true); + continue; + } + for (ModuloSchedGraphNode::const_iterator I = node->beginInEdges(), E = + node->endInEdges(); I != E; I++) { + SchedGraphEdge *edge = *I; + ModuloSchedGraphNode *pred = + (ModuloSchedGraphNode *) (edge->getSrc()); + assert(pred->getPropertyComputed() + && "pred node property is not computed!"); + int temp = pred->depth + edge->getMinDelay(); + node->depth = std::max(node->depth, temp); } + node->setPropertyComputed(true); + } } -void ModuloSchedGraph::computeNodeHeight(const BasicBlock* bb) +void ModuloSchedGraph::computeNodeHeight(const BasicBlock *bb) { - unsigned numNodes=bb->size(); - for(unsigned i=numNodes+1;i >= 2;i--) - { - ModuloSchedGraphNode* node=getNode(i); - node->setPropertyComputed(false); - } - - for(unsigned i=numNodes+1;i >= 2; i--) - { - ModuloSchedGraphNode* node=getNode(i); - node->height=0; - for(ModuloSchedGraphNode::const_iterator I=node->beginOutEdges(), E=node->endOutEdges(); I!=E; I++) - { - SchedGraphEdge* edge= *I; - ModuloSchedGraphNode* succ=(ModuloSchedGraphNode*)(edge->getSink()); - if(PHINode::classof(succ->getInst())) continue; - assert(succ->getPropertyComputed()&&"succ node property is not computed!"); - node->height=max(node->height, succ->height+edge->getMinDelay()); - - } - node->setPropertyComputed(true); - + unsigned numNodes = bb->size(); + for (unsigned i = numNodes + 1; i >= 2; i--) { + ModuloSchedGraphNode *node = getNode(i); + node->setPropertyComputed(false); + } + + for (unsigned i = numNodes + 1; i >= 2; i--) { + ModuloSchedGraphNode *node = getNode(i); + node->height = 0; + for (ModuloSchedGraphNode::const_iterator I = + node->beginOutEdges(), E = node->endOutEdges(); I != E; ++I) { + SchedGraphEdge *edge = *I; + ModuloSchedGraphNode *succ = + (ModuloSchedGraphNode *) (edge->getSink()); + if (PHINode::classof(succ->getInst())) + continue; + assert(succ->getPropertyComputed() + && "succ node property is not computed!"); + node->height = std::max(node->height, succ->height + edge->getMinDelay()); + } + node->setPropertyComputed(true); + + } } -void ModuloSchedGraph::computeNodeProperty(const BasicBlock* bb) +void ModuloSchedGraph::computeNodeProperty(const BasicBlock * bb) { - //FIXME: now assume the only backward edges come from the edges from other nodes to the phi Node - //so i will ignore all edges to the phi node; after this, there shall be no recurrence. - + //FIXME: now assume the only backward edges come from the edges from other + //nodes to the phi Node so i will ignore all edges to the phi node; after + //this, there shall be no recurrence. + this->computeNodeASAP(bb); this->computeNodeALAP(bb); this->computeNodeMov(bb); this->computeNodeDepth(bb); - this->computeNodeHeight(bb); + this->computeNodeHeight(bb); } //do not consider the backedge in these two functions: // i.e. don't consider the edge with destination in phi node -std::vector ModuloSchedGraph::predSet(std::vector set, unsigned backEdgeSrc, unsigned backEdgeSink) +std::vector +ModuloSchedGraph::predSet(std::vector set, + unsigned backEdgeSrc, + unsigned + backEdgeSink) { std::vector predS; - for(unsigned i=0; i < set.size(); i++) - { - ModuloSchedGraphNode* node = set[i]; - for(ModuloSchedGraphNode::const_iterator I=node->beginInEdges(), E=node->endInEdges(); I !=E; I++) - { - SchedGraphEdge* edge= *I; - if(edge->getSrc()->getNodeId() ==backEdgeSrc && edge->getSink()->getNodeId() == backEdgeSink) continue; - ModuloSchedGraphNode* pred= (ModuloSchedGraphNode*)(edge->getSrc()); - //if pred is not in the predSet, push it in vector - bool alreadyInset=false; - for(unsigned j=0; j < predS.size(); j++) - if(predS[j]->getNodeId() == pred->getNodeId() ) - {alreadyInset=true;break;} - - for(unsigned j=0; j < set.size(); j++) - if(set[j]->getNodeId() == pred->getNodeId() ) - {alreadyInset=true; break;} - - if(! alreadyInset) - predS.push_back(pred); - } + for (unsigned i = 0; i < set.size(); i++) { + ModuloSchedGraphNode *node = set[i]; + for (ModuloSchedGraphNode::const_iterator I = node->beginInEdges(), E = + node->endInEdges(); I != E; I++) { + SchedGraphEdge *edge = *I; + if (edge->getSrc()->getNodeId() == backEdgeSrc + && edge->getSink()->getNodeId() == backEdgeSink) + continue; + ModuloSchedGraphNode *pred = + (ModuloSchedGraphNode *) (edge->getSrc()); + //if pred is not in the predSet, push it in vector + bool alreadyInset = false; + for (unsigned j = 0; j < predS.size(); ++j) + if (predS[j]->getNodeId() == pred->getNodeId()) { + alreadyInset = true; + break; + } + + for (unsigned j = 0; j < set.size(); ++j) + if (set[j]->getNodeId() == pred->getNodeId()) { + alreadyInset = true; + break; + } + + if (!alreadyInset) + predS.push_back(pred); } + } return predS; } ModuloSchedGraph::NodeVec ModuloSchedGraph::predSet(NodeVec set) { //node number increases from 2 - return predSet(set,0, 0); + return predSet(set, 0, 0); } - -std::vector ModuloSchedGraph::predSet(ModuloSchedGraphNode* _node, unsigned backEdgeSrc, unsigned backEdgeSink) +std::vector +ModuloSchedGraph::predSet(ModuloSchedGraphNode *_node, + unsigned backEdgeSrc, unsigned backEdgeSink) { - std::vector set; set.push_back(_node); return predSet(set, backEdgeSrc, backEdgeSink); - } -std::vector ModuloSchedGraph::predSet(ModuloSchedGraphNode* _node) +std::vector +ModuloSchedGraph::predSet(ModuloSchedGraphNode * _node) { - return predSet(_node,0,0); + return predSet(_node, 0, 0); } -std::vector ModuloSchedGraph::succSet(std::vector set,unsigned src, unsigned sink) -{ - vector succS; - for(unsigned i=0; i < set.size(); i++) - { - ModuloSchedGraphNode* node = set[i]; - for(ModuloSchedGraphNode::const_iterator I=node->beginOutEdges(), E=node->endOutEdges(); I !=E; I++) - { - SchedGraphEdge* edge= *I; - if(edge->getSrc()->getNodeId() == src && edge->getSink()->getNodeId() == sink) continue; - ModuloSchedGraphNode* succ= (ModuloSchedGraphNode*)(edge->getSink()); - //if pred is not in the predSet, push it in vector - bool alreadyInset=false; - for(unsigned j=0; j < succS.size(); j++) - if(succS[j]->getNodeId() == succ->getNodeId() ) - {alreadyInset=true;break;} - - for(unsigned j=0; j < set.size(); j++) - if(set[j]->getNodeId() == succ->getNodeId() ) - {alreadyInset=true;break;} - if(! alreadyInset) - succS.push_back(succ); - } +std::vector +ModuloSchedGraph::succSet(std::vector set, + unsigned src, unsigned sink) +{ + std::vector succS; + for (unsigned i = 0; i < set.size(); i++) { + ModuloSchedGraphNode *node = set[i]; + for (ModuloSchedGraphNode::const_iterator I = + node->beginOutEdges(), E = node->endOutEdges(); I != E; I++) { + SchedGraphEdge *edge = *I; + if (edge->getSrc()->getNodeId() == src + && edge->getSink()->getNodeId() == sink) + continue; + ModuloSchedGraphNode *succ = + (ModuloSchedGraphNode *) (edge->getSink()); + //if pred is not in the predSet, push it in vector + bool alreadyInset = false; + for (unsigned j = 0; j < succS.size(); j++) + if (succS[j]->getNodeId() == succ->getNodeId()) { + alreadyInset = true; + break; + } + + for (unsigned j = 0; j < set.size(); j++) + if (set[j]->getNodeId() == succ->getNodeId()) { + alreadyInset = true; + break; + } + if (!alreadyInset) + succS.push_back(succ); } - return succS; + } + return succS; } ModuloSchedGraph::NodeVec ModuloSchedGraph::succSet(NodeVec set) { - return succSet(set,0,0); + return succSet(set, 0, 0); } -std::vector ModuloSchedGraph::succSet(ModuloSchedGraphNode* _node,unsigned src, unsigned sink) +std::vector +ModuloSchedGraph::succSet(ModuloSchedGraphNode *_node, + unsigned src, unsigned sink) { - std::vector set; + std::vectorset; set.push_back(_node); return succSet(set, src, sink); - - } -std::vector ModuloSchedGraph::succSet(ModuloSchedGraphNode* _node) +std::vector +ModuloSchedGraph::succSet(ModuloSchedGraphNode * _node) { return succSet(_node, 0, 0); } -SchedGraphEdge* ModuloSchedGraph::getMaxDelayEdge(unsigned srcId, unsigned sinkId) +SchedGraphEdge *ModuloSchedGraph::getMaxDelayEdge(unsigned srcId, + unsigned sinkId) { - - ModuloSchedGraphNode* node =getNode(srcId); - SchedGraphEdge* maxDelayEdge=NULL; - int maxDelay=-1; - for(ModuloSchedGraphNode::const_iterator I=node->beginOutEdges(), E=node->endOutEdges();I !=E; I++) - { - SchedGraphEdge* edge= *I; - if(edge->getSink()->getNodeId() == sinkId) - if(edge->getMinDelay() > maxDelay){ - maxDelayEdge=edge; - maxDelay=edge->getMinDelay(); - } - } - assert(maxDelayEdge != NULL&&"no edge between the srcId and sinkId?"); + ModuloSchedGraphNode *node = getNode(srcId); + SchedGraphEdge *maxDelayEdge = NULL; + int maxDelay = -1; + for (ModuloSchedGraphNode::const_iterator I = node->beginOutEdges(), E = + node->endOutEdges(); I != E; I++) { + SchedGraphEdge *edge = *I; + if (edge->getSink()->getNodeId() == sinkId) + if (edge->getMinDelay() > maxDelay) { + maxDelayEdge = edge; + maxDelay = edge->getMinDelay(); + } + } + assert(maxDelayEdge != NULL && "no edge between the srcId and sinkId?"); return maxDelayEdge; } void ModuloSchedGraph::dumpCircuits() { - modSched_os<<"dumping circuits for graph: "<<"\n"; - int j=-1; - while(circuits[++j][0] !=0){ - int k=-1; - while(circuits[j][++k] !=0) - modSched_os<< circuits[j][k]<<"\t"; - modSched_os<<"\n"; + modSched_os << "dumping circuits for graph: " << "\n"; + int j = -1; + while (circuits[++j][0] != 0) { + int k = -1; + while (circuits[j][++k] != 0) + modSched_os << circuits[j][k] << "\t"; + modSched_os << "\n"; } } -void ModuloSchedGraph::dumpSet(std::vector set) +void ModuloSchedGraph::dumpSet(std::vector < ModuloSchedGraphNode * >set) { - for(unsigned i=0;i < set.size() ; i++) - modSched_os<< set[i]->getNodeId()<<"\t"; - modSched_os<<"\n"; + for (unsigned i = 0; i < set.size(); i++) + modSched_os << set[i]->getNodeId() << "\t"; + modSched_os << "\n"; } -std::vector ModuloSchedGraph::vectorUnion(std::vector set1,std::vector set2 ) +std::vector +ModuloSchedGraph::vectorUnion(std::vector set1, + std::vector set2) { std::vector unionVec; - for(unsigned i=0;i ModuloSchedGraph::vectorConj(std::vector set1,std::vector set2 ) -{ - std::vector conjVec; - for(unsigned i=0;i +ModuloSchedGraph::vectorConj(std::vector set1, + std::vector set2) +{ + std::vector conjVec; + for (unsigned i = 0; i < set1.size(); i++) + for (unsigned j = 0; j < set2.size(); j++) + if (set1[i] == set2[j]) + conjVec.push_back(set1[i]); + return conjVec; } -ModuloSchedGraph::NodeVec ModuloSchedGraph::vectorSub(NodeVec set1, NodeVec set2) +ModuloSchedGraph::NodeVec ModuloSchedGraph::vectorSub(NodeVec set1, + NodeVec set2) { NodeVec newVec; - for(NodeVec::iterator I=set1.begin(); I != set1.end(); I++){ - bool inset=false; - for(NodeVec::iterator II=set2.begin(); II!=set2.end(); II++) - if( (*I)->getNodeId() ==(*II)->getNodeId()) - {inset=true;break;} - if(!inset) newVec.push_back(*I); + for (NodeVec::iterator I = set1.begin(); I != set1.end(); I++) { + bool inset = false; + for (NodeVec::iterator II = set2.begin(); II != set2.end(); II++) + if ((*I)->getNodeId() == (*II)->getNodeId()) { + inset = true; + break; + } + if (!inset) + newVec.push_back(*I); } return newVec; } - -void ModuloSchedGraph::orderNodes(){ + +void ModuloSchedGraph::orderNodes() { oNodes.clear(); - - std::vector set; - const BasicBlock* bb=bbVec[0]; + + std::vector < ModuloSchedGraphNode * >set; + const BasicBlock *bb = bbVec[0]; unsigned numNodes = bb->size(); - + //first order all the sets - int j=-1; - int totalDelay=-1; - int preDelay=-1; - while(circuits[++j][0] !=0){ - int k=-1; - preDelay=totalDelay; + int j = -1; + int totalDelay = -1; + int preDelay = -1; + while (circuits[++j][0] != 0) { + int k = -1; + preDelay = totalDelay; - while(circuits[j][++k] !=0){ - ModuloSchedGraphNode* node =getNode(circuits[j][k]); + while (circuits[j][++k] != 0) { + ModuloSchedGraphNode *node = getNode(circuits[j][k]); unsigned nextNodeId; - nextNodeId =circuits[j][k+1] !=0? circuits[j][k+1]:circuits[j][0]; - SchedGraphEdge* edge = getMaxDelayEdge(circuits[j][k], nextNodeId); + nextNodeId = + circuits[j][k + 1] != 0 ? circuits[j][k + 1] : circuits[j][0]; + SchedGraphEdge *edge = getMaxDelayEdge(circuits[j][k], nextNodeId); totalDelay += edge->getMinDelay(); } - if(preDelay != -1 && totalDelay > preDelay){ + if (preDelay != -1 && totalDelay > preDelay) { //swap circuits[j][] and cuicuits[j-1][] unsigned temp[MAXNODE]; - for(int k=0;k= ModuloSched_PrintScheduleProcess) - modSched_os<<"building the first set"<<"\n"; - int setSeq=-1; - int k=-1; + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os << "building the first set" << "\n"; + int setSeq = -1; + int k = -1; setSeq++; - while(circuits[setSeq][++k]!=0) + while (circuits[setSeq][++k] != 0) set.push_back(getNode(circuits[setSeq][k])); - if(circuits[setSeq][0]!=0){ - backEdgeSrc=circuits[setSeq][k-1]; - backEdgeSink=circuits[setSeq][0]; + if (circuits[setSeq][0] != 0) { + backEdgeSrc = circuits[setSeq][k - 1]; + backEdgeSink = circuits[setSeq][0]; } - if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess){ - modSched_os<<"the first set is:"; + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) { + modSched_os << "the first set is:"; dumpSet(set); } - //implement the ordering algorithm - enum OrderSeq{ bottom_up, top_down}; + enum OrderSeq { bottom_up, top_down }; OrderSeq order; std::vector R; - while(!set.empty()) - { - std::vector pset=predSet(oNodes); - std::vector sset=succSet(oNodes); - - if(!pset.empty() && !vectorConj(pset,set).empty()) - {R=vectorConj(pset,set);order=bottom_up;} - else if( !sset.empty() && !vectorConj(sset,set).empty()) - {R=vectorConj(sset,set);order=top_down;} - else - { - int maxASAP=-1; - int position=-1; - for(unsigned i=0;igetASAP(); - if(temp>maxASAP ) { - maxASAP=temp; - position=i; - } - } - R.push_back(set[position]); - order=bottom_up; - } - - while(!R.empty()){ - if(order== top_down){ - if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os<<"in top_down round"<<"\n"; - while(!R.empty()){ - int maxHeight=-1; - NodeVec::iterator chosenI; - for(NodeVec::iterator I=R.begin();I != R.end();I++){ - int temp=(*I)->height; - if( (temp > maxHeight) || ( temp == maxHeight && (*I)->mov <= (*chosenI)->mov ) ){ - - if((temp > maxHeight) || ( temp == maxHeight && (*I)->mov < (*chosenI)->mov )){ - maxHeight=temp; - chosenI=I; - continue; - } - //possible case: instruction A and B has the same height and mov, but A has dependence to B - //e.g B is the branch instruction in the end, or A is the phi instruction at the beginning - if((*I)->mov == (*chosenI)->mov) - for(ModuloSchedGraphNode::const_iterator oe=(*I)->beginOutEdges(), end=(*I)->endOutEdges();oe !=end; oe++){ - if((*oe)->getSink() == (*chosenI)){ - maxHeight=temp; - chosenI=I; - continue; - } - } - } - } - ModuloSchedGraphNode* mu= *chosenI; - oNodes.push_back(mu); - R.erase(chosenI); - std::vector succ_mu= succSet(mu,backEdgeSrc,backEdgeSink); - std::vector comm=vectorConj(succ_mu,set); - comm=vectorSub(comm,oNodes); - R = vectorUnion(comm, R); - } - order=bottom_up; - R= vectorConj(predSet(oNodes), set); - } else{ - if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os<<"in bottom up round"<<"\n"; - while(!R.empty()){ - int maxDepth=-1; - NodeVec::iterator chosenI; - for(NodeVec::iterator I=R.begin();I != R.end();I++){ - int temp=(*I)->depth; - if( (temp > maxDepth) || ( temp == maxDepth && (*I)->mov < (*chosenI)->mov )){ - maxDepth=temp; - chosenI=I; - } - } - ModuloSchedGraphNode* mu=*chosenI; - oNodes.push_back(mu); - R.erase(chosenI); - std::vector pred_mu= predSet(mu,backEdgeSrc,backEdgeSink); - std::vector comm=vectorConj(pred_mu,set); - comm=vectorSub(comm,oNodes); - R = vectorUnion(comm, R); - } - order=top_down; - R= vectorConj(succSet(oNodes), set); - } + while (!set.empty()) { + std::vector < ModuloSchedGraphNode * >pset = predSet(oNodes); + std::vector < ModuloSchedGraphNode * >sset = succSet(oNodes); + + if (!pset.empty() && !vectorConj(pset, set).empty()) { + R = vectorConj(pset, set); + order = bottom_up; + } else if (!sset.empty() && !vectorConj(sset, set).empty()) { + R = vectorConj(sset, set); + order = top_down; + } else { + int maxASAP = -1; + int position = -1; + for (unsigned i = 0; i < set.size(); i++) { + int temp = set[i]->getASAP(); + if (temp > maxASAP) { + maxASAP = temp; + position = i; + } } - if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess){ - modSched_os<<"order finished"<<"\n"; - modSched_os<<"dumping the ordered nodes: "<<"\n"; - dumpSet(oNodes); - dumpCircuits(); - } - //create a new set - //FIXME: the nodes between onodes and this circuit should also be include in this set - if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os<<"building the next set"<<"\n"; - set.clear(); - int k=-1; - setSeq++; - while(circuits[setSeq][++k]!=0) - set.push_back(getNode(circuits[setSeq][k])); - if(circuits[setSeq][0]!=0){ - backEdgeSrc=circuits[setSeq][k-1]; - backEdgeSink=circuits[setSeq][0]; - } - if(set.empty()){ - //no circuits any more - //collect all other nodes - if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os<<"no circuits any more, collect the rest nodes"<<"\n"; - for(unsigned i=2;igetNodeId() == i) - {inset=true;break;} - if(!inset)set.push_back(getNode(i)); - } + R.push_back(set[position]); + order = bottom_up; + } + + while (!R.empty()) { + if (order == top_down) { + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os << "in top_down round" << "\n"; + while (!R.empty()) { + int maxHeight = -1; + NodeVec::iterator chosenI; + for (NodeVec::iterator I = R.begin(); I != R.end(); I++) { + int temp = (*I)->height; + if ((temp > maxHeight) + || (temp == maxHeight && (*I)->mov <= (*chosenI)->mov)) { + + if ((temp > maxHeight) + || (temp == maxHeight && (*I)->mov < (*chosenI)->mov)) { + maxHeight = temp; + chosenI = I; + continue; + } + //possible case: instruction A and B has the same height and mov, + //but A has dependence to B e.g B is the branch instruction in the + //end, or A is the phi instruction at the beginning + if ((*I)->mov == (*chosenI)->mov) + for (ModuloSchedGraphNode::const_iterator oe = + (*I)->beginOutEdges(), end = (*I)->endOutEdges(); + oe != end; oe++) { + if ((*oe)->getSink() == (*chosenI)) { + maxHeight = temp; + chosenI = I; + continue; + } + } + } + } + ModuloSchedGraphNode *mu = *chosenI; + oNodes.push_back(mu); + R.erase(chosenI); + std::vector succ_mu = + succSet(mu, backEdgeSrc, backEdgeSink); + std::vector comm = + vectorConj(succ_mu, set); + comm = vectorSub(comm, oNodes); + R = vectorUnion(comm, R); + } + order = bottom_up; + R = vectorConj(predSet(oNodes), set); + } else { + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os << "in bottom up round" << "\n"; + while (!R.empty()) { + int maxDepth = -1; + NodeVec::iterator chosenI; + for (NodeVec::iterator I = R.begin(); I != R.end(); I++) { + int temp = (*I)->depth; + if ((temp > maxDepth) + || (temp == maxDepth && (*I)->mov < (*chosenI)->mov)) { + maxDepth = temp; + chosenI = I; + } + } + ModuloSchedGraphNode *mu = *chosenI; + oNodes.push_back(mu); + R.erase(chosenI); + std::vector pred_mu = + predSet(mu, backEdgeSrc, backEdgeSink); + std::vector comm = + vectorConj(pred_mu, set); + comm = vectorSub(comm, oNodes); + R = vectorUnion(comm, R); + } + order = top_down; + R = vectorConj(succSet(oNodes), set); } - if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess){ - modSched_os<<"next set is: "<<"\n"; - dumpSet(set); + } + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) { + modSched_os << "order finished" << "\n"; + modSched_os << "dumping the ordered nodes: " << "\n"; + dumpSet(oNodes); + dumpCircuits(); + } + //create a new set + //FIXME: the nodes between onodes and this circuit should also be include in + //this set + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os << "building the next set" << "\n"; + set.clear(); + int k = -1; + setSeq++; + while (circuits[setSeq][++k] != 0) + set.push_back(getNode(circuits[setSeq][k])); + if (circuits[setSeq][0] != 0) { + backEdgeSrc = circuits[setSeq][k - 1]; + backEdgeSink = circuits[setSeq][0]; + } + if (set.empty()) { + //no circuits any more + //collect all other nodes + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os << "no circuits any more, collect the rest nodes" << + "\n"; + for (unsigned i = 2; i < numNodes + 2; i++) { + bool inset = false; + for (unsigned j = 0; j < oNodes.size(); j++) + if (oNodes[j]->getNodeId() == i) { + inset = true; + break; + } + if (!inset) + set.push_back(getNode(i)); } - }//while(!set.empty()) - + } + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) { + modSched_os << "next set is: " << "\n"; + dumpSet(set); + } + } //while(!set.empty()) + } @@ -839,11 +872,11 @@ -void ModuloSchedGraph::buildGraph (const TargetMachine& target) +void ModuloSchedGraph::buildGraph(const TargetMachine & target) { - const BasicBlock* bb=bbVec[0]; + const BasicBlock *bb = bbVec[0]; - assert(bbVec.size() ==1 &&"only handling a single basic block here"); + assert(bbVec.size() == 1 && "only handling a single basic block here"); // Use this data structure to note all machine operands that compute // ordinary LLVM values. These must be computed defs (i.e., instructions). @@ -855,9 +888,9 @@ // We use this to add memory dependence edges without a second full walk. // // vector memVec; - vector memNodeVec; + std::vector < ModuloSchedGraphNode * >memNodeVec; - // Use this data structure to note any uses or definitions of + // Use this data structure to note any uses or definitions of // machine registers so we can add edges for those later without // extra passes over the nodes. // The vector holds an ordered list of references to the machine reg, @@ -866,17 +899,17 @@ // by the pair: . // RegToRefVecMap regToRefVecMap; - - // Make a dummy root node. We'll add edges to the real roots later. - graphRoot = new ModuloSchedGraphNode(0, NULL, NULL, -1,target); - graphLeaf = new ModuloSchedGraphNode(1, NULL, NULL, -1,target); - - //---------------------------------------------------------------- - // First add nodes for all the LLVM instructions in the basic block - // because this greatly simplifies identifying which edges to add. - // Do this one VM instruction at a time since the ModuloSchedGraphNode needs that. + + // Make a dummy root node. We'll add edges to the real roots later. + graphRoot = new ModuloSchedGraphNode(0, NULL, NULL, -1, target); + graphLeaf = new ModuloSchedGraphNode(1, NULL, NULL, -1, target); + + //---------------------------------------------------------------- + // First add nodes for all the LLVM instructions in the basic block because + // this greatly simplifies identifying which edges to add. Do this one VM + // instruction at a time since the ModuloSchedGraphNode needs that. // Also, remember the load/store instructions to add memory deps later. //---------------------------------------------------------------- @@ -886,429 +919,438 @@ //dump only the blocks which are from loops - if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) this->dump(bb); - if(!isLoop(bb)){ - modSched_os <<" dumping non-loop BB:\n"; + if (!isLoop(bb)) { + modSched_os << " dumping non-loop BB:\n"; dump(bb); } - if( isLoop(bb)) - { - buildNodesforBB(target, bb, memNodeVec, regToRefVecMap, valueToDefVecMap); - - this->addDefUseEdges(bb); - - this->addCDEdges(bb); - - this->addMemEdges(bb); - - //this->dump(); - - int ResII=this->computeResII(bb); - if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os << "ResII is " << ResII<<"\n";; - int RecII=this->computeRecII(bb); - if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os << "RecII is " <MII=max(ResII, RecII); - - this->computeNodeProperty(bb); - if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - this->dumpNodeProperty(); - - this->orderNodes(); - - if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - this->dump(); - //this->instrScheduling(); - - //this->dumpScheduling(); - - - } + if (isLoop(bb)) { + buildNodesforBB(target, bb, memNodeVec, regToRefVecMap, + valueToDefVecMap); + + this->addDefUseEdges(bb); + this->addCDEdges(bb); + this->addMemEdges(bb); + + //this->dump(); + + int ResII = this->computeResII(bb); + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os << "ResII is " << ResII << "\n";; + int RecII = this->computeRecII(bb); + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os << "RecII is " << RecII << "\n"; + + this->MII = std::max(ResII, RecII); + + this->computeNodeProperty(bb); + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + this->dumpNodeProperty(); + + this->orderNodes(); + + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + this->dump(); + //this->instrScheduling(); + + //this->dumpScheduling(); + } } -ModuloSchedGraphNode* ModuloSchedGraph::getNode (const unsigned nodeId) const -{ - for(const_iterator I=begin(), E=end();I !=E;I++) - if((*I).second->getNodeId() ==nodeId) - return (ModuloSchedGraphNode*)(*I).second; +ModuloSchedGraphNode *ModuloSchedGraph::getNode(const unsigned nodeId) const +{ + for (const_iterator I = begin(), E = end(); I != E; I++) + if ((*I).second->getNodeId() == nodeId) + return (ModuloSchedGraphNode *) (*I).second; return NULL; } -int ModuloSchedGraph::computeRecII(const BasicBlock* bb) +int ModuloSchedGraph::computeRecII(const BasicBlock *bb) { - int RecII=0; + int RecII = 0; //os<<"begining computerRecII()"<<"\n"; - //FIXME: only deal with circuits starting at the first node: the phi node nodeId=2; + //FIXME: only deal with circuits starting at the first node: the phi node + //nodeId=2; //search all elementary circuits in the dependance graph //assume maximum number of nodes is MAXNODE - + unsigned path[MAXNODE]; unsigned stack[MAXNODE][MAXNODE]; - for(int j=0;jsize(); - - int i=0; - path[i]=2; - - ModuloSchedGraphNode* initNode=getNode(path[0]); - unsigned initNodeId=initNode->getNodeId(); - ModuloSchedGraphNode* currentNode=initNode; - - while(currentNode != NULL) - { - unsigned currentNodeId=currentNode->getNodeId(); - // modSched_os<<"current node is "<beginOutEdges(), E=currentNode->endOutEdges(); I !=E; I++) - { - //modSched_os <<" searching in outgoint edges of node "<getSink()->getNodeId(); - bool inpath=false,instack=false; - int k; - - //modSched_os<<"nodeId is "< currentNodeId && !inpath && !instack) - {nextNode=(ModuloSchedGraphNode*) ((SchedGraphEdge*)*I)->getSink();break;} - - } - if(nextNode != NULL) - { - //modSched_os<<"find the next Node "<getNodeId()<<"\n"; - - - int j=0; - while( stack[i][j] !=0) j++; - stack[i][j]=nextNode->getNodeId(); - - - i++; - path[i]=nextNode->getNodeId(); - currentNode=nextNode; - } - else - { - //modSched_os<<"no expansion any more"<<"\n"; - //confirmCircuit(); - for(ModuloSchedGraphNode::const_iterator I=currentNode->beginOutEdges(), E=currentNode->endOutEdges() ; I != E; I++) - { - unsigned nodeId=((SchedGraphEdge*)*I)->getSink()->getNodeId(); - if(nodeId == initNodeId) - { - - int j=-1; - while(circuits[++j][0] !=0); - for(int k=0;k= ModuloSched_PrintScheduleProcess) - modSched_os<<"circuits found are: "<<"\n"; - int j=-1; - while(circuits[++j][0] !=0){ - int k=-1; - while(circuits[j][++k] !=0) - if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os<< circuits[j][k]<<"\t"; - if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os<<"\n"; - - - //for this circuit, compute the sum of all edge delay - int sumDelay=0; - k=-1; - while(circuits[j][++k] !=0) - { - //ModuloSchedGraphNode* node =getNode(circuits[j][k]); - unsigned nextNodeId; - nextNodeId =circuits[j][k+1] !=0? circuits[j][k+1]:circuits[j][0]; - - /* - for(ModuloSchedGraphNode::const_iterator I=node->beginOutEdges(), E=node->endOutEdges();I !=E; I++) - { - SchedGraphEdge* edge= *I; - if(edge->getSink()->getNodeId() == nextNodeId) - {sumDelay += edge->getMinDelay();break;} - } - */ - - sumDelay += getMaxDelayEdge(circuits[j][k],nextNodeId)->getMinDelay(); - - } - // assume we have distance 1, in this case the sumDelay is RecII - // this is correct for SSA form only - // - if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os<<"The total Delay in the circuit is " < sumDelay? RecII: sumDelay; - - } - return RecII; - } - + const unsigned numNodes = bb->size(); + + int i = 0; + path[i] = 2; + + ModuloSchedGraphNode *initNode = getNode(path[0]); + unsigned initNodeId = initNode->getNodeId(); + ModuloSchedGraphNode *currentNode = initNode; + + while (currentNode != NULL) { + unsigned currentNodeId = currentNode->getNodeId(); + // modSched_os<<"current node is "<beginOutEdges(), E = currentNode->endOutEdges(); + I != E; I++) { + //modSched_os <<" searching in outgoint edges of node + //"<getSink()->getNodeId(); + bool inpath = false, instack = false; + int k; + + //modSched_os<<"nodeId is "< currentNodeId && !inpath && !instack) { + nextNode = + (ModuloSchedGraphNode *) ((SchedGraphEdge *) * I)->getSink(); + break; + } } - + + if (nextNode != NULL) { + //modSched_os<<"find the next Node "<getNodeId()<<"\n"; + + int j = 0; + while (stack[i][j] != 0) + j++; + stack[i][j] = nextNode->getNodeId(); + + i++; + path[i] = nextNode->getNodeId(); + currentNode = nextNode; + } else { + //modSched_os<<"no expansion any more"<<"\n"; + //confirmCircuit(); + for (ModuloSchedGraphNode::const_iterator I = + currentNode->beginOutEdges(), E = currentNode->endOutEdges(); + I != E; I++) { + unsigned nodeId = ((SchedGraphEdge *) * I)->getSink()->getNodeId(); + if (nodeId == initNodeId) { + + int j = -1; + while (circuits[++j][0] != 0); + for (int k = 0; k < MAXNODE; k++) + circuits[j][k] = path[k]; + + } + } + //remove this node in the path and clear the corresponding entries in the + //stack + path[i] = 0; + int j = 0; + for (j = 0; j < MAXNODE; j++) + stack[i][j] = 0; + i--; + currentNode = getNode(path[i]); + } + if (i == 0) { + + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os << "circuits found are: " << "\n"; + int j = -1; + while (circuits[++j][0] != 0) { + int k = -1; + while (circuits[j][++k] != 0) + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os << circuits[j][k] << "\t"; + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os << "\n"; + + //for this circuit, compute the sum of all edge delay + int sumDelay = 0; + k = -1; + while (circuits[j][++k] != 0) { + //ModuloSchedGraphNode* node =getNode(circuits[j][k]); + unsigned nextNodeId; + nextNodeId = + circuits[j][k + 1] != + 0 ? circuits[j][k + 1] : circuits[j][0]; + + /* + for(ModuloSchedGraphNode::const_iterator I=node->beginOutEdges(), + E=node->endOutEdges();I !=E; I++) + { + SchedGraphEdge* edge= *I; + if(edge->getSink()->getNodeId() == nextNodeId) + {sumDelay += edge->getMinDelay();break;} + } + */ + + sumDelay += + getMaxDelayEdge(circuits[j][k], nextNodeId)->getMinDelay(); + + } + // assume we have distance 1, in this case the sumDelay is RecII + // this is correct for SSA form only + // + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os << "The total Delay in the circuit is " << sumDelay + << "\n"; + + RecII = RecII > sumDelay ? RecII : sumDelay; + + } + return RecII; + } + + } + return -1; } -void ModuloSchedGraph::addResourceUsage(std::vector >& ruVec, int rid){ - //modSched_os<<"\nadding a resouce , current resouceUsage vector size is "< > &ruVec, + int rid) +{ + //modSched_os<<"\nadding a resouce , current resouceUsage vector size is + //"< > &ru) +void ModuloSchedGraph::dumpResourceUsage(std::vector > &ru) { - TargetSchedInfo& msi = (TargetSchedInfo&)target.getSchedInfo(); - - std::vector > resourceNumVector = msi.resourceNumVector; - modSched_os <<"resourceID\t"<<"resourceNum"<<"\n"; - for(unsigned i=0;i> resourceNumVector = msi.resourceNumVector; + modSched_os << "resourceID\t" << "resourceNum" << "\n"; + for (unsigned i = 0; i < resourceNumVector.size(); i++) + modSched_os << resourceNumVector[i]. + first << "\t" << resourceNumVector[i].second << "\n"; + + modSched_os << " maxNumIssueTotal(issue slot in one cycle) = " << msi. + maxNumIssueTotal << "\n"; + modSched_os << "resourceID\t resourceUsage\t ResourceNum" << "\n"; + for (unsigned i = 0; i < ru.size(); i++) { + modSched_os << ru[i].first << "\t" << ru[i].second; + const unsigned resNum = msi.getCPUResourceNum(ru[i].first); + modSched_os << "\t" << resNum << "\n"; } } -int ModuloSchedGraph::computeResII(const BasicBlock* bb) -{ - - const TargetInstrInfo& mii = target.getInstrInfo(); - const TargetSchedInfo& msi = target.getSchedInfo(); - +int ModuloSchedGraph::computeResII(const BasicBlock * bb) +{ + + const TargetInstrInfo & mii = target.getInstrInfo(); + const TargetSchedInfo & msi = target.getSchedInfo(); + int ResII; - std::vector > resourceUsage; //pair - - //FIXME: number of functional units the target machine can provide should be get from Target - // here I temporary hardcode it - - for(BasicBlock::const_iterator I=bb->begin(),E=bb->end(); I !=E; I++) - { - if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess){ - modSched_os<<"machine instruction for llvm instruction( node "<getNodeId()<<")" <<"\n"; - modSched_os<<"\t"<<*I; + std::vector> resourceUsage; + //pair + + //FIXME: number of functional units the target machine can provide should be + //get from Target here I temporary hardcode it + + for (BasicBlock::const_iterator I = bb->begin(), E = bb->end(); I != E; + I++) { + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) { + modSched_os << "machine instruction for llvm instruction( node " << + getGraphNodeForInst(I)->getNodeId() << ")" << "\n"; + modSched_os << "\t" << *I; + } + MachineCodeForInstruction & tempMvec = + MachineCodeForInstruction::get(I); + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os << "size =" << tempMvec.size() << "\n"; + for (unsigned i = 0; i < tempMvec.size(); i++) { + MachineInstr *minstr = tempMvec[i]; + + unsigned minDelay = mii.minLatency(minstr->getOpCode()); + InstrRUsage rUsage = msi.getInstrRUsage(minstr->getOpCode()); + InstrClassRUsage classRUsage = + msi.getClassRUsage(mii.getSchedClass(minstr->getOpCode())); + unsigned totCycles = classRUsage.totCycles; + + std::vector> resources =rUsage.resourcesByCycle; + assert(totCycles == resources.size()); + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os << "resources Usage for this Instr(totCycles=" << + totCycles << ",mindLatency=" << mii.minLatency(minstr-> + getOpCode()) << + "): " << *minstr << "\n"; + for (unsigned j = 0; j < resources.size(); j++) { + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os << "cycle " << j << ": "; + for (unsigned k = 0; k < resources[j].size(); k++) { + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os << "\t" << resources[j][k]; + addResourceUsage(resourceUsage, resources[j][k]); + } + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os << "\n"; } - MachineCodeForInstruction& tempMvec= MachineCodeForInstruction::get(I); - if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os <<"size =" <getOpCode()); - InstrRUsage rUsage=msi.getInstrRUsage(minstr->getOpCode()); - InstrClassRUsage classRUsage=msi.getClassRUsage(mii.getSchedClass(minstr->getOpCode())); - unsigned totCycles= classRUsage.totCycles; - - std::vector > resources - =rUsage.resourcesByCycle; - assert(totCycles == resources.size()); - if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os <<"resources Usage for this Instr(totCycles=" << totCycles << ",mindLatency="<getOpCode())<<"): "<< *minstr <<"\n"; - for(unsigned j=0;j< resources.size();j++){ - if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os<<"cycle "<= ModuloSched_PrintScheduleProcess) - modSched_os<<"\t"<= ModuloSched_PrintScheduleProcess) - modSched_os<<"\n"; - } - } } - if(ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + } + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) this->dumpResourceUsage(resourceUsage); //compute ResII - ResII=0; - int issueSlots=msi.maxNumIssueTotal; - for(unsigned i=0;igetName() - << "' =========\n\n"; - for(const_iterator I=begin(); I != end(); ++I) + modSched_os << " ====== ModuloSched graphs for function `" << + method->getName() << "' =========\n\n"; + for (const_iterator I = begin(); I != end(); ++I) (*I)->dump(); - - modSched_os << "\n=========End graphs for funtion` "<getName() - << "' ==========\n\n"; + + modSched_os << "\n=========End graphs for funtion` " << method->getName() + << "' ==========\n\n"; } -void ModuloSchedGraph::dump(const BasicBlock* bb) +void ModuloSchedGraph::dump(const BasicBlock * bb) { - modSched_os<<"dumping basic block:"; - modSched_os<<(bb->hasName()?bb->getName(): "block") - <<" (" << bb << ")"<<"\n"; + modSched_os << "dumping basic block:"; + modSched_os << (bb->hasName()? bb->getName() : "block") + << " (" << bb << ")" << "\n"; } -void ModuloSchedGraph::dump(const BasicBlock* bb, std::ostream& os) +void ModuloSchedGraph::dump(const BasicBlock * bb, std::ostream & os) { - os<<"dumping basic block:"; - os<<(bb->hasName()?bb->getName(): "block") - <<" (" << bb << ")"<<"\n"; + os << "dumping basic block:"; + os << (bb->hasName()? bb->getName() : "block") + << " (" << bb << ")" << "\n"; } -void -ModuloSchedGraph::dump() const +void ModuloSchedGraph::dump() const { modSched_os << " ModuloSchedGraph for basic Blocks:"; - for(unsigned i=0, N =bbVec.size(); i< N; i++) - { - modSched_os<<(bbVec[i]->hasName()?bbVec[i]->getName(): "block") - <<" (" << bbVec[i] << ")" - << ((i==N-1)?"":", "); - } - - modSched_os <<"\n\n Actual Root nodes : "; - for (unsigned i=0, N=graphRoot->outEdges.size(); i < N; i++) + for (unsigned i = 0, N = bbVec.size(); i < N; i++) { + modSched_os << (bbVec[i]->hasName()? bbVec[i]->getName() : "block") + << " (" << bbVec[i] << ")" << ((i == N - 1) ? "" : ", "); + } + + modSched_os << "\n\n Actual Root nodes : "; + for (unsigned i = 0, N = graphRoot->outEdges.size(); i < N; i++) modSched_os << graphRoot->outEdges[i]->getSink()->getNodeId() - << ((i == N-1)? "" : ", "); + << ((i == N - 1) ? "" : ", "); modSched_os << "\n Graph Nodes:\n"; //for (const_iterator I=begin(); I != end(); ++I) //modSched_os << "\n" << *I->second; - unsigned numNodes=bbVec[0]->size(); - for(unsigned i=2;i< numNodes+2;i++) - { - ModuloSchedGraphNode* node= getNode(i); - modSched_os << "\n" << *node; - } + unsigned numNodes = bbVec[0]->size(); + for (unsigned i = 2; i < numNodes + 2; i++) { + ModuloSchedGraphNode *node = getNode(i); + modSched_os << "\n" << *node; + } modSched_os << "\n"; } -void -ModuloSchedGraph::dumpNodeProperty() const + +void ModuloSchedGraph::dumpNodeProperty() const { - const BasicBlock* bb=bbVec[0]; - unsigned numNodes=bb->size(); - for(unsigned i=2;i < numNodes+2;i++) - { - ModuloSchedGraphNode* node=getNode(i); - modSched_os<<"NodeId "<getNodeId()<<"\t"; - modSched_os<<"ASAP "<getASAP()<<"\t"; - modSched_os<<"ALAP "<getALAP()<<"\t"; - modSched_os<<"mov " <getMov() <<"\t"; - modSched_os<<"depth "<getDepth()<<"\t"; - modSched_os<<"height "<getHeight()<<"\t"; - modSched_os<<"\n"; - } + const BasicBlock *bb = bbVec[0]; + unsigned numNodes = bb->size(); + for (unsigned i = 2; i < numNodes + 2; i++) { + ModuloSchedGraphNode *node = getNode(i); + modSched_os << "NodeId " << node->getNodeId() << "\t"; + modSched_os << "ASAP " << node->getASAP() << "\t"; + modSched_os << "ALAP " << node->getALAP() << "\t"; + modSched_os << "mov " << node->getMov() << "\t"; + modSched_os << "depth " << node->getDepth() << "\t"; + modSched_os << "height " << node->getHeight() << "\t"; + modSched_os << "\n"; + } } -void ModuloSchedGraphSet::buildGraphsForMethod (const Function *F, const TargetMachine& target) +void ModuloSchedGraphSet::buildGraphsForMethod(const Function * F, + const TargetMachine & + target) { - for(Function::const_iterator BI = F->begin(); BI != F->end(); ++BI) - addGraph(new ModuloSchedGraph(BI,target)); + for (Function::const_iterator BI = F->begin(); BI != F->end(); ++BI) + addGraph(new ModuloSchedGraph(BI, target)); } -std::ostream &operator<<(std::ostream &os, const ModuloSchedGraphNode& node) +std::ostream & operator<<(std::ostream & os, + const ModuloSchedGraphNode & node) { os << std::string(8, ' ') - << "Node " << node.nodeId << " : " - << "latency = " << node.latency << "\n" << std::string(12, ' '); - - + << "Node " << node.nodeId << " : " + << "latency = " << node.latency << "\n" << std::string(12, ' '); if (node.getInst() == NULL) os << "(Dummy node)\n"; - else - { - os << *node.getInst() << "\n" << std::string(12, ' '); - os << node.inEdges.size() << " Incoming Edges:\n"; - for (unsigned i=0, N=node.inEdges.size(); i < N; i++) - os << std::string(16, ' ') << *node.inEdges[i]; - - os << std::string(12, ' ') << node.outEdges.size() - << " Outgoing Edges:\n"; - for (unsigned i=0, N=node.outEdges.size(); i < N; i++) - os << std::string(16, ' ') << *node.outEdges[i]; - } - + else { + os << *node.getInst() << "\n" << std::string(12, ' '); + os << node.inEdges.size() << " Incoming Edges:\n"; + for (unsigned i = 0, N = node.inEdges.size(); i < N; i++) + os << std::string(16, ' ') << *node.inEdges[i]; + + os << std::string(12, ' ') << node.outEdges.size() + << " Outgoing Edges:\n"; + for (unsigned i = 0, N = node.outEdges.size(); i < N; i++) + os << std::string(16, ' ') << *node.outEdges[i]; + } + return os; } Index: llvm/lib/CodeGen/ModuloScheduling/ModuloSchedGraph.h diff -u llvm/lib/CodeGen/ModuloScheduling/ModuloSchedGraph.h:1.2 llvm/lib/CodeGen/ModuloScheduling/ModuloSchedGraph.h:1.3 --- llvm/lib/CodeGen/ModuloScheduling/ModuloSchedGraph.h:1.2 Sun Apr 6 18:56:16 2003 +++ llvm/lib/CodeGen/ModuloScheduling/ModuloSchedGraph.h Wed Apr 9 16:51:34 2003 @@ -1,4 +1,4 @@ -//===- ModuloSchedGraph.h - Represent a collection of data structures ----*- C++ -*-===// +//===- ModuloSchedGraph.h - Modulo Scheduling Graph and Set -*- C++ -*-----===// // // This header defines the primative classes that make up a data structure // graph. @@ -7,82 +7,111 @@ #ifndef LLVM_CODEGEN_MODULO_SCHED_GRAPH_H #define LLVM_CODEGEN_MODULO_SCHED_GRAPH_H - -#include "Support/HashExtras.h" -#include "Support/GraphTraits.h" -#include "../InstrSched/SchedGraphCommon.h" + #include "llvm/Instruction.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetInstrInfo.h" +#include "Support/HashExtras.h" +#include "Support/GraphTraits.h" +#include "../InstrSched/SchedGraphCommon.h" #include -using std::pair; //for debug information selecton -enum ModuloSchedDebugLevel_t{ +enum ModuloSchedDebugLevel_t { ModuloSched_NoDebugInfo, ModuloSched_Disable, ModuloSched_PrintSchedule, ModuloSched_PrintScheduleProcess, }; -//===============------------------------------------------------------------------------ -///ModuloSchedGraphNode - Implement a data structure based on the SchedGraphNodeCommon -///this class stores informtion needed later to order the nodes in modulo scheduling -/// -class ModuloSchedGraphNode: public SchedGraphNodeCommon { +//===----------------------------------------------------------------------===// +// ModuloSchedGraphNode - Implement a data structure based on the +// SchedGraphNodeCommon this class stores informtion needed later to order the +// nodes in modulo scheduling +// +class ModuloSchedGraphNode:public SchedGraphNodeCommon { private: - //the corresponding instruction - const Instruction* inst; + // the corresponding instruction + const Instruction *inst; - //whether this node's property(ASAP,ALAP, ...) has been computed + // whether this node's property(ASAP,ALAP, ...) has been computed bool propertyComputed; - //ASAP: the earliest time the node could be scheduled - //ALAP: the latest time the node couldbe scheduled - //depth: the depth of the node - //height: the height of the node - //mov: the mobility function, computed as ALAP - ASAP - //scheTime: the scheduled time if this node has been scheduled - //earlyStart: the earliest time to be tried to schedule the node - //lateStart: the latest time to be tried to schedule the node + // ASAP: the earliest time the node could be scheduled + // ALAP: the latest time the node couldbe scheduled + // depth: the depth of the node + // height: the height of the node + // mov: the mobility function, computed as ALAP - ASAP + // scheTime: the scheduled time if this node has been scheduled + // earlyStart: the earliest time to be tried to schedule the node + // lateStart: the latest time to be tried to schedule the node int ASAP, ALAP, depth, height, mov; int schTime; - int earlyStart,lateStart; + int earlyStart, lateStart; public: - - //get the instruction - const Instruction* getInst() const { return inst;} + //get the instruction + const Instruction *getInst() const { + return inst; + } //get the instruction op-code name - const char* getInstOpcodeName() const{ return inst->getOpcodeName();} - - //get the instruction op-code - const unsigned getInstOpcode() const { return inst->getOpcode();} - + const char *getInstOpcodeName() const { + return inst->getOpcodeName(); + } + //get the instruction op-code + const unsigned getInstOpcode() const { + return inst->getOpcode(); + } //return whether the node is NULL - bool isNullNode() const{ return(inst== NULL);} - + bool isNullNode() const { + return (inst == NULL); + } //return whether the property of the node has been computed - bool getPropertyComputed() {return propertyComputed;} - + bool getPropertyComputed() { + return propertyComputed; + } //set the propertyComputed - void setPropertyComputed(bool _propertyComputed) {propertyComputed = _propertyComputed;} - + void setPropertyComputed(bool _propertyComputed) { + propertyComputed = _propertyComputed; + } + //get the corresponding property - int getASAP(){ return ASAP;} - int getALAP(){ return ALAP;} - int getMov() { return mov;} - int getDepth(){return depth;} - int getHeight(){return height;} - int getSchTime(){return schTime;} - int getEarlyStart(){return earlyStart;} - int getLateStart() { return lateStart;} - void setEarlyStart(int _earlyStart) {earlyStart= _earlyStart;} - void setLateStart(int _lateStart) {lateStart= _lateStart;} - void setSchTime(int _time){schTime=_time;} + int getASAP() { + return ASAP; + } + int getALAP() { + return ALAP; + } + int getMov() { + return mov; + } + int getDepth() { + return depth; + } + int getHeight() { + return height; + } + int getSchTime() { + return schTime; + } + int getEarlyStart() { + return earlyStart; + } + int getLateStart() { + return lateStart; + } + void setEarlyStart(int _earlyStart) { + earlyStart = _earlyStart; + } + void setLateStart(int _lateStart) { + lateStart = _lateStart; + } + void setSchTime(int _time) { + schTime = _time; + } - private: +private: friend class ModuloSchedGraph; friend class SchedGraphNode; @@ -93,43 +122,34 @@ //indexInBB: the corresponding instruction's index in the BasicBlock //target: the targetMachine ModuloSchedGraphNode(unsigned int _nodeId, - const BasicBlock* _bb, - const Instruction* _inst, - int indexInBB, - const TargetMachine& target); - - - friend std::ostream& operator<<(std::ostream& os,const ModuloSchedGraphNode& edge); - -}; - + const BasicBlock * _bb, + const Instruction * _inst, + int indexInBB, const TargetMachine &target); + friend std::ostream & operator<<(std::ostream & os, + const ModuloSchedGraphNode & edge); +}; //FIXME: these two value should not be used #define MAXNODE 100 #define MAXCC 100 - - //===----------------------------------------------------------------------===// /// ModuloSchedGraph- the data structure to store dependence between nodes /// it catches data dependence and constrol dependence /// -/// - -class ModuloSchedGraph: +class ModuloSchedGraph : public SchedGraphCommon, - protected hash_map -{ - -private: + protected hash_map { + +private: //iteration Interval int MII; - + //target machine - const TargetMachine& target; + const TargetMachine & target; //the circuits in the dependence graph unsigned circuits[MAXCC][MAXNODE]; @@ -140,20 +160,20 @@ typedef std::vector NodeVec; //the function to compute properties - void computeNodeASAP(const BasicBlock* bb); - void computeNodeALAP(const BasicBlock* bb); - void computeNodeMov(const BasicBlock* bb); - void computeNodeDepth(const BasicBlock* bb); - void computeNodeHeight(const BasicBlock* bb); + void computeNodeASAP(const BasicBlock * bb); + void computeNodeALAP(const BasicBlock * bb); + void computeNodeMov(const BasicBlock * bb); + void computeNodeDepth(const BasicBlock * bb); + void computeNodeHeight(const BasicBlock * bb); //the function to compute node property - void computeNodeProperty(const BasicBlock* bb); + void computeNodeProperty(const BasicBlock * bb); //the function to sort nodes void orderNodes(); - + //add the resource usage - void addResourceUsage(std::vector >&, int); +void addResourceUsage(std::vector>&, int); //debug functions: //dump circuits @@ -161,13 +181,13 @@ //dump the input set of nodes void dumpSet(std::vector set); //dump the input resource usage table - void dumpResourceUsage(std::vector >&); - - public: + void dumpResourceUsage(std::vector> &); + +public: //help functions - + //get the maxium the delay between two nodes - SchedGraphEdge* getMaxDelayEdge(unsigned srcId, unsigned sinkId); + SchedGraphEdge *getMaxDelayEdge(unsigned srcId, unsigned sinkId); //FIXME: //get the predessor Set of the set @@ -175,174 +195,171 @@ NodeVec predSet(NodeVec set); //get the predessor set of the node - NodeVec predSet(ModuloSchedGraphNode* node, unsigned,unsigned); - NodeVec predSet(ModuloSchedGraphNode* node); + NodeVec predSet(ModuloSchedGraphNode * node, unsigned, unsigned); + NodeVec predSet(ModuloSchedGraphNode * node); //get the successor set of the set NodeVec succSet(NodeVec set, unsigned, unsigned); NodeVec succSet(NodeVec set); - + //get the succssor set of the node - NodeVec succSet(ModuloSchedGraphNode* node,unsigned, unsigned); - NodeVec succSet(ModuloSchedGraphNode* node); + NodeVec succSet(ModuloSchedGraphNode * node, unsigned, unsigned); + NodeVec succSet(ModuloSchedGraphNode * node); //return the uniton of the two vectors - NodeVec vectorUnion(NodeVec set1,NodeVec set2 ); + NodeVec vectorUnion(NodeVec set1, NodeVec set2); //return the consjuction of the two vectors - NodeVec vectorConj(NodeVec set1,NodeVec set2 ); - + NodeVec vectorConj(NodeVec set1, NodeVec set2); + //return all nodes in set1 but not set2 NodeVec vectorSub(NodeVec set1, NodeVec set2); - typedef hash_map map_base; + typedef hash_map map_base; + public: using map_base::iterator; using map_base::const_iterator; - + public: //get target machine - const TargetMachine& getTarget(){return target;} - + const TargetMachine & getTarget() { + return target; + } //get the iteration interval - const int getMII(){return MII;} + const int getMII() { + return MII; + } //get the ordered nodes - const NodeVec& getONodes(){return oNodes;} + const NodeVec & getONodes() { + return oNodes; + } //get the number of nodes (including the root and leaf) //note: actually root and leaf is not used - const unsigned int getNumNodes() const {return size()+2;} - + const unsigned int getNumNodes() const { + return size() + 2; + } //return wether the BasicBlock 'bb' contains a loop - bool isLoop (const BasicBlock* bb); + bool isLoop(const BasicBlock * bb); //return this basibBlock contains a loop - bool isLoop (); - + bool isLoop(); + //return the node for the input instruction - ModuloSchedGraphNode* getGraphNodeForInst(const Instruction* inst) const{ + ModuloSchedGraphNode *getGraphNodeForInst(const Instruction * inst) const { const_iterator onePair = this->find(inst); - return (onePair != this->end())?(*onePair).second: NULL; + return (onePair != this->end()) ? (*onePair).second : NULL; } - - //Debugging support - //dump the graph - void dump() const; + //Debugging support//dump the graph void dump() const; //dump the basicBlock - void dump(const BasicBlock* bb); + void dump(const BasicBlock * bb); //dump the basicBlock into 'os' stream - void dump(const BasicBlock* bb, std::ostream& os); + void dump(const BasicBlock * bb, std::ostream & os); //dump the node property - void dumpNodeProperty() const ; - - private: - friend class ModuloSchedGraphSet; //give access to ctor + void dumpNodeProperty() const; - public: - /*ctr*/ - ModuloSchedGraph(const BasicBlock* bb, const TargetMachine& _target) - :SchedGraphCommon(bb), target(_target){ +private: + friend class ModuloSchedGraphSet; //give access to ctor + +public: + ModuloSchedGraph(const BasicBlock *bb, const TargetMachine &_target) + :SchedGraphCommon(bb), target(_target) { buildGraph(target); } - /*dtr*/ - ~ModuloSchedGraph(){ - for(const_iterator I=begin(); I!=end(); ++I) + ~ModuloSchedGraph() { + for (const_iterator I = begin(); I != end(); ++I) delete I->second; } - + //unorder iterators //return values are pair using map_base::begin; using map_base::end; + void noteModuloSchedGraphNodeForInst(const Instruction *inst, + ModuloSchedGraphNode *node) + { + assert((*this)[inst] == NULL); + (*this)[inst] = node; + } - - inline void noteModuloSchedGraphNodeForInst(const Instruction* inst, - ModuloSchedGraphNode* node) - { - assert((*this)[inst] ==NULL); - (*this)[inst]=node; - } - //Graph builder - - ModuloSchedGraphNode* getNode (const unsigned nodeId) const; + + ModuloSchedGraphNode *getNode(const unsigned nodeId) const; //build the graph from the basicBlock - void buildGraph (const TargetMachine& target); + void buildGraph(const TargetMachine & target); //Build nodes for BasicBlock - void buildNodesforBB (const TargetMachine& target, - const BasicBlock* bb, - NodeVec& memNode, - RegToRefVecMap& regToRefVecMap, - ValueToDefVecMap& valueToDefVecMap); + void buildNodesforBB(const TargetMachine &target, + const BasicBlock *bb, + NodeVec &memNode, + RegToRefVecMap ®ToRefVecMap, + ValueToDefVecMap &valueToDefVecMap); //find definitiona and use information for all nodes - void findDefUseInfoAtInstr (const TargetMachine& target, - ModuloSchedGraphNode* node, - NodeVec& memNode, - RegToRefVecMap& regToRefVecMap, - ValueToDefVecMap& valueToDefVecMap); + void findDefUseInfoAtInstr(const TargetMachine &target, + ModuloSchedGraphNode *node, + NodeVec &memNode, + RegToRefVecMap ®ToRefVecMap, + ValueToDefVecMap &valueToDefVecMap); //add def-use edge - void addDefUseEdges (const BasicBlock* bb); + void addDefUseEdges(const BasicBlock *bb); //add control dependence edges - void addCDEdges (const BasicBlock* bb); + void addCDEdges(const BasicBlock *bb); //add memory dependence dges - void addMemEdges (const BasicBlock* bb); + void addMemEdges(const BasicBlock *bb); //add dummy edges void addDummyEdges(); //computer source restrictoin II - int computeResII (const BasicBlock* bb); + int computeResII(const BasicBlock *bb); //computer recurrence II - int computeRecII (const BasicBlock* bb); + int computeRecII(const BasicBlock *bb); }; -///==================================- -//gragh set +//==================================- +// Graph set -class ModuloSchedGraphSet: - public std::vector -{ +class ModuloSchedGraphSet : public std::vector { private: - const Function* method; - + const Function *method; + public: typedef std::vector baseVector; using baseVector::iterator; using baseVector::const_iterator; - + public: - /*ctor*/ ModuloSchedGraphSet (const Function* function, const TargetMachine& target); - - /*dtor*/ ~ModuloSchedGraphSet (); - - //iterators + ModuloSchedGraphSet(const Function *function, const TargetMachine &target); + ~ModuloSchedGraphSet(); + + // Iterators using baseVector::begin; using baseVector::end; +// Debugging support +void dump() const; - //Debugging support - void dump() const; - private: - inline void addGraph(ModuloSchedGraph* graph){ - assert(graph !=NULL); + void addGraph(ModuloSchedGraph *graph) { + assert(graph != NULL); this->push_back(graph); } - - //Graph builder - void buildGraphsForMethod (const Function *F, const TargetMachine& target); -}; -#endif + // Graph builder + void buildGraphsForMethod(const Function *F, + const TargetMachine &target); +} + +#endif Index: llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.cpp diff -u llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.cpp:1.2 llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.cpp:1.3 --- llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.cpp:1.2 Sun Apr 6 18:56:16 2003 +++ llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.cpp Wed Apr 9 16:51:34 2003 @@ -1,561 +1,580 @@ - -//===- SPLInstrScheduling.cpp - Modulo Software Pipelining Instruction Scheduling support -------===// -// -// this file implements the llvm/CodeGen/ModuloScheduling.h interface +//===- ModuloScheduling.cpp - Modulo Software Pipelining ------------------===// // +// Implements the llvm/CodeGen/ModuloScheduling.h interface // //===----------------------------------------------------------------------===// -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineCodeForInstruction.h" //#include "llvm/CodeGen/MachineCodeForBasicBlock.h" //#include "llvm/CodeGen/MachineCodeForMethod.h" -#include "llvm/CodeGen/MachineFunction.h" //#include "llvm/Analysis/LiveVar/FunctionLiveVarInfo.h" // FIXME: Remove when modularized better -#include "llvm/Target/TargetMachine.h" #include "llvm/BasicBlock.h" +#include "llvm/Constants.h" #include "llvm/Instruction.h" +#include "llvm/iTerminators.h" +#include "llvm/iPHINode.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineCodeForInstruction.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/InstrSelection.h" +#include "llvm/Target/TargetSchedInfo.h" +#include "llvm/Target/TargetMachine.h" #include "Support/CommandLine.h" -#include #include "ModuloSchedGraph.h" #include "ModuloScheduling.h" -#include "llvm/Target/TargetSchedInfo.h" -#include "llvm/BasicBlock.h" -#include "llvm/iTerminators.h" -#include "llvm/iPHINode.h" -#include "llvm/Constants.h" +#include +#include #include //#include -#include -#include "llvm/CodeGen/InstrSelection.h" - -#define max(x,y) (x>y?x:y) -#define min(x,y) (x +static cl::opt SDL_opt("modsched", cl::Hidden, cl::location(ModuloSchedDebugLevel), cl::desc("enable modulo scheduling debugging information"), - cl::values( - clEnumValN(ModuloSched_NoDebugInfo, "n", "disable debug output"), - clEnumValN(ModuloSched_Disable, "off", "disable modulo scheduling"), - clEnumValN(ModuloSched_PrintSchedule, "psched", "print original and new schedule"), - clEnumValN(ModuloSched_PrintScheduleProcess,"pschedproc", "print how the new schdule is produced"), - 0)); + cl::values(clEnumValN + (ModuloSched_NoDebugInfo, "n", "disable debug output"), + clEnumValN(ModuloSched_Disable, "off", + "disable modulo scheduling"), + clEnumValN(ModuloSched_PrintSchedule, "psched", + "print original and new schedule"), + clEnumValN(ModuloSched_PrintScheduleProcess, "pschedproc", + "print how the new schdule is produced"), 0)); -filebuf modSched_fb; -ostream modSched_os(&modSched_fb); +std::filebuf modSched_fb; +std::ostream modSched_os(&modSched_fb); -//************************************************************ +// Computes the schedule and inserts epilogue and prologue +// +void ModuloScheduling::instrScheduling() +{ + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os << "*************** computing modulo schedule **************\n"; -///the method to compute schedule and instert epilogue and prologue -void ModuloScheduling::instrScheduling(){ - - if( ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os<<"*************************computing modulo schedule ************************\n"; - - - const TargetSchedInfo& msi=target.getSchedInfo(); + const TargetSchedInfo & msi = target.getSchedInfo(); //number of issue slots in the in each cycle - int numIssueSlots=msi.maxNumIssueTotal; - - + int numIssueSlots = msi.maxNumIssueTotal; //compute the schedule - bool success=false; - while(!success) - { - //clear memory from the last round and initialize if necessary - clearInitMem(msi); - - //compute schedule and coreSchedule with the current II - success=computeSchedule(); - - if(!success){ - II++; - if( ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os<<"increase II to "<= ModuloSched_PrintScheduleProcess) + modSched_os << "increase II to " << II << "\n"; } - + } + //print the final schedule if necessary - if( ModuloSchedDebugLevel >= ModuloSched_PrintSchedule) + if (ModuloSchedDebugLevel >= ModuloSched_PrintSchedule) dumpScheduling(); - //the schedule has been computed //create epilogue, prologue and kernel BasicBlock - + //find the successor for this BasicBlock - BasicBlock* succ_bb= getSuccBB(bb); - + BasicBlock *succ_bb = getSuccBB(bb); + //print the original BasicBlock if necessary - if( ModuloSchedDebugLevel >= ModuloSched_PrintSchedule){ - modSched_os<<"dumping the orginal block\n"; + if (ModuloSchedDebugLevel >= ModuloSched_PrintSchedule) { + modSched_os << "dumping the orginal block\n"; graph.dump(bb); } - //construction of prologue, kernel and epilogue - BasicBlock* kernel=bb->splitBasicBlock(bb->begin()); - BasicBlock* prologue= bb; - BasicBlock* epilogue=kernel->splitBasicBlock(kernel->begin()); - - - //construct prologue + BasicBlock *kernel = bb->splitBasicBlock(bb->begin()); + BasicBlock *prologue = bb; + BasicBlock *epilogue = kernel->splitBasicBlock(kernel->begin()); + + // Construct prologue constructPrologue(prologue); - //construct kernel - constructKernel(prologue,kernel,epilogue); + // Construct kernel + constructKernel(prologue, kernel, epilogue); - //construct epilogue - constructEpilogue(epilogue,succ_bb); + // Construct epilogue + constructEpilogue(epilogue, succ_bb); - //print the BasicBlocks if necessary - if( ModuloSchedDebugLevel >= ModuloSched_PrintSchedule){ - modSched_os<<"dumping the prologue block:\n"; + if (ModuloSchedDebugLevel >= ModuloSched_PrintSchedule) { + modSched_os << "dumping the prologue block:\n"; graph.dump(prologue); - modSched_os<<"dumping the kernel block\n"; + modSched_os << "dumping the kernel block\n"; graph.dump(kernel); - modSched_os<<"dumping the epilogue block\n"; + modSched_os << "dumping the epilogue block\n"; graph.dump(epilogue); } - -} - -//clear memory from the last round and initialize if necessary -void ModuloScheduling::clearInitMem(const TargetSchedInfo& msi){ - +} +// Clear memory from the last round and initialize if necessary +// +void ModuloScheduling::clearInitMem(const TargetSchedInfo & msi) +{ unsigned numIssueSlots = msi.maxNumIssueTotal; - //clear nodeScheduled from the last round - if( ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess){ - modSched_os<< "***** new round with II= "<= ModuloSched_PrintScheduleProcess) { + modSched_os << "***** new round with II= " << II << + " *******************\n"; + modSched_os << + " ************clear the vector nodeScheduled*************\n"; } nodeScheduled.clear(); - - - //clear resourceTable from the last round and reset it + + // clear resourceTable from the last round and reset it resourceTable.clear(); - for(unsigned i=0;i< II;i++) + for (unsigned i = 0; i < II; ++i) resourceTable.push_back(msi.resourceNumVector); - - - //clear the schdule and coreSchedule from the last round + + // clear the schdule and coreSchedule from the last round schedule.clear(); coreSchedule.clear(); - - //create a coreSchedule of size II*numIssueSlots - //each entry is NULL - while( coreSchedule.size() < II){ - std::vector* newCycle=new std::vector(); - for(unsigned k=0;k*newCycle = + new std::vector < ModuloSchedGraphNode * >(); + for (unsigned k = 0; k < numIssueSlots; ++k) newCycle->push_back(NULL); coreSchedule.push_back(*newCycle); - } + } } +// Compute schedule and coreSchedule with the current II +// +bool ModuloScheduling::computeSchedule() +{ -//compute schedule and coreSchedule with the current II -bool ModuloScheduling::computeSchedule(){ - - if( ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os <<"start to compute schedule \n"; - - //loop over the ordered nodes - for(NodeVec::const_iterator I=oNodes.begin();I!=oNodes.end();I++) - { - //try to schedule for node I - if( ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - dumpScheduling(); - ModuloSchedGraphNode* node=*I; - - //compute whether this node has successor(s) - bool succ=true; - - //compute whether this node has predessor(s) - bool pred=true; - - NodeVec schSucc=graph.vectorConj(nodeScheduled,graph.succSet(node)); - if(schSucc.empty()) - succ=false; - NodeVec schPred=graph.vectorConj(nodeScheduled,graph.predSet(node)); - if(schPred.empty()) - pred=false; - - //startTime: the earliest time we will try to schedule this node - //endTime: the latest time we will try to schedule this node - int startTime, endTime; - - //node's earlyStart: possible earliest time to schedule this node - //node's lateStart: possible latest time to schedule this node - node->setEarlyStart(-1); - node->setLateStart(9999); - - - //this node has predessor but no successor - if(!succ && pred){ - - //this node's earlyStart is it's predessor's schedule time + the edge delay - // - the iteration difference* II - for(unsigned i=0;igetNodeId(),node->getNodeId()); - int temp=predNode->getSchTime()+edge->getMinDelay() - edge->getIteDiff()*II; - node->setEarlyStart( max(node->getEarlyStart(),temp)); - } - startTime=node->getEarlyStart(); - endTime=node->getEarlyStart()+II-1; - } - - - //this node has successor but no predessor - if(succ && !pred){ - for(unsigned i=0;igetNodeId(),node->getNodeId()); - int temp=succNode->getSchTime() - edge->getMinDelay() + edge->getIteDiff()*II; - node->setLateStart(min(node->getEarlyStart(),temp)); - } - startTime=node->getLateStart()- II+1; - endTime=node->getLateStart(); - } - - //this node has both successors and predessors - if(succ && pred) - { - for(unsigned i=0;igetNodeId(),node->getNodeId()); - int temp=predNode->getSchTime()+edge->getMinDelay() - edge->getIteDiff()*II; - node->setEarlyStart(max(node->getEarlyStart(),temp)); - } - for(unsigned i=0;igetNodeId(),node->getNodeId()); - int temp=succNode->getSchTime() - edge->getMinDelay() + edge->getIteDiff()*II; - node->setLateStart(min(node->getEarlyStart(),temp)); - } - startTime=node->getEarlyStart(); - endTime=min(node->getLateStart(),node->getEarlyStart()+((int)II)-1); - } - - //this node has no successor or predessor - if(!succ && !pred){ - node->setEarlyStart(node->getASAP()); - startTime=node->getEarlyStart(); - endTime=node->getEarlyStart()+II -1; - } - - //try to schedule this node based on the startTime and endTime - if( ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os<<"scheduling the node "<<(*I)->getNodeId()<<"\n"; + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os << "start to compute schedule\n"; - bool success= this->ScheduleNode(node,startTime, endTime,nodeScheduled); - if(!success)return false; - } + // Loop over the ordered nodes + for (NodeVec::const_iterator I = oNodes.begin(); I != oNodes.end(); ++I) { + // Try to schedule for node I + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + dumpScheduling(); + ModuloSchedGraphNode *node = *I; + + // Compute whether this node has successor(s) + bool succ = true; + + // Compute whether this node has predessor(s) + bool pred = true; + + NodeVec schSucc = graph.vectorConj(nodeScheduled, graph.succSet(node)); + if (schSucc.empty()) + succ = false; + NodeVec schPred = graph.vectorConj(nodeScheduled, graph.predSet(node)); + if (schPred.empty()) + pred = false; + + //startTime: the earliest time we will try to schedule this node + //endTime: the latest time we will try to schedule this node + int startTime, endTime; + + //node's earlyStart: possible earliest time to schedule this node + //node's lateStart: possible latest time to schedule this node + node->setEarlyStart(-1); + node->setLateStart(9999); + + //this node has predessor but no successor + if (!succ && pred) { + // This node's earlyStart is it's predessor's schedule time + the edge + // delay - the iteration difference* II + for (unsigned i = 0; i < schPred.size(); i++) { + ModuloSchedGraphNode *predNode = schPred[i]; + SchedGraphEdge *edge = + graph.getMaxDelayEdge(predNode->getNodeId(), + node->getNodeId()); + int temp = + predNode->getSchTime() + edge->getMinDelay() - + edge->getIteDiff() * II; + node->setEarlyStart(std::max(node->getEarlyStart(), temp)); + } + startTime = node->getEarlyStart(); + endTime = node->getEarlyStart() + II - 1; + } + // This node has a successor but no predecessor + if (succ && !pred) { + for (unsigned i = 0; i < schSucc.size(); ++i) { + ModuloSchedGraphNode *succNode = schSucc[i]; + SchedGraphEdge *edge = + graph.getMaxDelayEdge(succNode->getNodeId(), + node->getNodeId()); + int temp = + succNode->getSchTime() - edge->getMinDelay() + + edge->getIteDiff() * II; + node->setLateStart(std::min(node->getEarlyStart(), temp)); + } + startTime = node->getLateStart() - II + 1; + endTime = node->getLateStart(); + } + // This node has both successors and predecessors + if (succ && pred) { + for (unsigned i = 0; i < schPred.size(); ++i) { + ModuloSchedGraphNode *predNode = schPred[i]; + SchedGraphEdge *edge = + graph.getMaxDelayEdge(predNode->getNodeId(), + node->getNodeId()); + int temp = + predNode->getSchTime() + edge->getMinDelay() - + edge->getIteDiff() * II; + node->setEarlyStart(std::max(node->getEarlyStart(), temp)); + } + for (unsigned i = 0; i < schSucc.size(); ++i) { + ModuloSchedGraphNode *succNode = schSucc[i]; + SchedGraphEdge *edge = + graph.getMaxDelayEdge(succNode->getNodeId(), + node->getNodeId()); + int temp = + succNode->getSchTime() - edge->getMinDelay() + + edge->getIteDiff() * II; + node->setLateStart(std::min(node->getEarlyStart(), temp)); + } + startTime = node->getEarlyStart(); + endTime = std::min(node->getLateStart(), + node->getEarlyStart() + ((int) II) - 1); + } + //this node has no successor or predessor + if (!succ && !pred) { + node->setEarlyStart(node->getASAP()); + startTime = node->getEarlyStart(); + endTime = node->getEarlyStart() + II - 1; + } + //try to schedule this node based on the startTime and endTime + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os << "scheduling the node " << (*I)->getNodeId() << "\n"; + + bool success = + this->ScheduleNode(node, startTime, endTime, nodeScheduled); + if (!success) + return false; + } return true; } -//get the successor of the BasicBlock -BasicBlock* ModuloScheduling::getSuccBB(BasicBlock* bb){ - - BasicBlock* succ_bb; - for(unsigned i=0;i < II; i++) - for(unsigned j=0;j< coreSchedule[i].size();j++) - if(coreSchedule[i][j]){ - const Instruction* ist=coreSchedule[i][j]->getInst(); - - //we can get successor from the BranchInst instruction - //assume we only have one successor (besides itself) here - if(BranchInst::classof(ist)){ - BranchInst* bi=(BranchInst*)ist; - assert(bi->isConditional()&&"the branchInst is not a conditional one"); - assert(bi->getNumSuccessors() ==2&&" more than two successors?"); - BasicBlock* bb1=bi->getSuccessor(0); - BasicBlock* bb2=bi->getSuccessor(1); - assert( (bb1 == bb|| bb2 == bb) && " None of its successor is itself?"); - if(bb1 == bb) succ_bb=bb2; - else succ_bb=bb1; - return succ_bb; - } +// Get the successor of the BasicBlock +// +BasicBlock *ModuloScheduling::getSuccBB(BasicBlock *bb) +{ + BasicBlock *succ_bb; + for (unsigned i = 0; i < II; ++i) + for (unsigned j = 0; j < coreSchedule[i].size(); ++j) + if (coreSchedule[i][j]) { + const Instruction *ist = coreSchedule[i][j]->getInst(); + + //we can get successor from the BranchInst instruction + //assume we only have one successor (besides itself) here + if (BranchInst::classof(ist)) { + BranchInst *bi = (BranchInst *) ist; + assert(bi->isConditional() && + "the branchInst is not a conditional one"); + assert(bi->getNumSuccessors() == 2 + && " more than two successors?"); + BasicBlock *bb1 = bi->getSuccessor(0); + BasicBlock *bb2 = bi->getSuccessor(1); + assert((bb1 == bb || bb2 == bb) && + " None of its successors is itself?"); + if (bb1 == bb) + succ_bb = bb2; + else + succ_bb = bb1; + return succ_bb; + } } - assert( 0 && "NO Successor?"); + assert(0 && "NO Successor?"); return NULL; } -//get the predecessor of the BasicBlock -BasicBlock* ModuloScheduling::getPredBB(BasicBlock* bb){ - - BasicBlock* pred_bb; - - for(unsigned i=0;i < II; i++) - for(unsigned j=0;j< coreSchedule[i].size();j++) - if(coreSchedule[i][j]){ - const Instruction* ist=coreSchedule[i][j]->getInst(); - - //we can get predecessor from the PHINode instruction - //assume we only have one predecessor (besides itself) here - if(PHINode::classof(ist)){ - PHINode* phi=(PHINode*) ist; - assert(phi->getNumIncomingValues() == 2 &&" the number of incoming value is not equal to two? "); - BasicBlock* bb1= phi->getIncomingBlock(0); - BasicBlock* bb2= phi->getIncomingBlock(1); - assert( (bb1 == bb || bb2 == bb) && " None of its predecessor is itself?"); - if(bb1 == bb) pred_bb=bb2; - else pred_bb=bb1; - return pred_bb; - } +// Get the predecessor of the BasicBlock +// +BasicBlock *ModuloScheduling::getPredBB(BasicBlock *bb) +{ + BasicBlock *pred_bb; + for (unsigned i = 0; i < II; ++i) + for (unsigned j = 0; j < coreSchedule[i].size(); ++j) + if (coreSchedule[i][j]) { + const Instruction *ist = coreSchedule[i][j]->getInst(); + + //we can get predecessor from the PHINode instruction + //assume we only have one predecessor (besides itself) here + if (PHINode::classof(ist)) { + PHINode *phi = (PHINode *) ist; + assert(phi->getNumIncomingValues() == 2 && + " the number of incoming value is not equal to two? "); + BasicBlock *bb1 = phi->getIncomingBlock(0); + BasicBlock *bb2 = phi->getIncomingBlock(1); + assert((bb1 == bb || bb2 == bb) && + " None of its predecessor is itself?"); + if (bb1 == bb) + pred_bb = bb2; + else + pred_bb = bb1; + return pred_bb; + } } assert(0 && " no predecessor?"); return NULL; } -//construct the prologue -void ModuloScheduling::constructPrologue(BasicBlock* prologue){ - - InstListType& prologue_ist = prologue->getInstList(); - vvNodeType& tempSchedule_prologue= *(new vector< std::vector >(schedule)); - +// Construct the prologue +// +void ModuloScheduling::constructPrologue(BasicBlock *prologue) +{ + + InstListType & prologue_ist = prologue->getInstList(); + vvNodeType & tempSchedule_prologue = + *(new vector < std::vector < ModuloSchedGraphNode * >>(schedule)); + //compute the schedule for prologue - unsigned round=0; - unsigned scheduleSize=schedule.size(); - while(round < scheduleSize/II){ + unsigned round = 0; + unsigned scheduleSize = schedule.size(); + while (round < scheduleSize / II) { round++; - for(unsigned i=0;i < scheduleSize ;i++){ - if(round*II + i >= scheduleSize) break; - for(unsigned j=0;j < schedule[i].size(); j++) - if(schedule[i][j]){ - assert( tempSchedule_prologue[round*II +i ][j] == NULL && "table not consitant with core table"); - - //move the schedule one iteration ahead and overlap with the original one - tempSchedule_prologue[round*II + i][j]=schedule[i][j]; - } + for (unsigned i = 0; i < scheduleSize; ++i) { + if (round * II + i >= scheduleSize) + break; + for (unsigned j = 0; j < schedule[i].size(); ++j) { + if (schedule[i][j]) { + assert(tempSchedule_prologue[round * II + i][j] == NULL && + "table not consitent with core table"); + // move the schedule one iteration ahead and overlap with the original + tempSchedule_prologue[round * II + i][j] = schedule[i][j]; + } + } } } - //clear the clone memory in the core schedule instructions + // Clear the clone memory in the core schedule instructions clearCloneMemory(); - - //fill in the prologue - for(unsigned i=0;i < ceil(1.0*scheduleSize/II -1)*II ;i++) - for(unsigned j=0;j < tempSchedule_prologue[i].size();j++) - if(tempSchedule_prologue[i][j]){ - //get the instruction - Instruction* orn=(Instruction*)tempSchedule_prologue[i][j]->getInst(); + // Fill in the prologue + for (unsigned i = 0; i < ceil(1.0 * scheduleSize / II - 1) * II; ++i) + for (unsigned j = 0; j < tempSchedule_prologue[i].size(); ++j) + if (tempSchedule_prologue[i][j]) { + + //get the instruction + Instruction *orn = + (Instruction *) tempSchedule_prologue[i][j]->getInst(); - //made a clone of it - Instruction* cln=cloneInstSetMemory(orn); + //made a clone of it + Instruction *cln = cloneInstSetMemory(orn); - //insert the instruction - prologue_ist.insert(prologue_ist.back(),cln ); + //insert the instruction + prologue_ist.insert(prologue_ist.back(), cln); - //if there is PHINode in the prologue, the incoming value from itself should be removed - //because it is not a loop any longer - if( PHINode::classof(cln)){ - PHINode* phi=(PHINode*)cln; - phi->removeIncomingValue(phi->getParent()); - } + //if there is PHINode in the prologue, the incoming value from itself + //should be removed because it is not a loop any longer + if (PHINode::classof(cln)) { + PHINode *phi = (PHINode *) cln; + phi->removeIncomingValue(phi->getParent()); + } } } -//construct the kernel BasicBlock -void ModuloScheduling::constructKernel(BasicBlock* prologue,BasicBlock* kernel,BasicBlock* epilogue){ +// Construct the kernel BasicBlock +// +void ModuloScheduling::constructKernel(BasicBlock *prologue, + BasicBlock *kernel, + BasicBlock *epilogue) +{ //*************fill instructions in the kernel**************** - InstListType& kernel_ist = kernel->getInstList(); - BranchInst* brchInst; - PHINode* phiInst, *phiCln; - - for(unsigned i=0;igetInst())){ - brchInst=(BranchInst*)coreSchedule[i][j]->getInst(); - continue; - } - - //we should take care of PHINode instruction differently with normal instructions - if( PHINode::classof(coreSchedule[i][j]->getInst())){ - phiInst= (PHINode*)coreSchedule[i][j]->getInst(); - Instruction* cln=cloneInstSetMemory(phiInst); - kernel_ist.insert(kernel_ist.back(),cln); - phiCln=(PHINode*)cln; - continue; - } - - //for normal instructions: made a clone and insert it in the kernel_ist - Instruction* cln=cloneInstSetMemory( (Instruction*)coreSchedule[i][j]->getInst()); - kernel_ist.insert(kernel_ist.back(),cln); - } - - //the two incoming BasicBlock for PHINode is the prologue and the kernel (itself) - phiCln->setIncomingBlock(0,prologue); - phiCln->setIncomingBlock(1,kernel); - - //the incoming value for the kernel (itself) is the new value which is computed in the kernel - Instruction* originalVal=(Instruction*)phiInst->getIncomingValue(1); + InstListType & kernel_ist = kernel->getInstList(); + BranchInst *brchInst; + PHINode *phiInst, *phiCln; + + for (unsigned i = 0; i < coreSchedule.size(); ++i) + for (unsigned j = 0; j < coreSchedule[i].size(); ++j) + if (coreSchedule[i][j]) { + + // Take care of branch instruction differently with normal instructions + if (BranchInst::classof(coreSchedule[i][j]->getInst())) { + brchInst = (BranchInst *) coreSchedule[i][j]->getInst(); + continue; + } + // Take care of PHINode instruction differently with normal instructions + if (PHINode::classof(coreSchedule[i][j]->getInst())) { + phiInst = (PHINode *) coreSchedule[i][j]->getInst(); + Instruction *cln = cloneInstSetMemory(phiInst); + kernel_ist.insert(kernel_ist.back(), cln); + phiCln = (PHINode *) cln; + continue; + } + //for normal instructions: made a clone and insert it in the kernel_ist + Instruction *cln = + cloneInstSetMemory((Instruction *) coreSchedule[i][j]-> + getInst()); + kernel_ist.insert(kernel_ist.back(), cln); + } + // The two incoming BasicBlock for PHINode is the prologue and the kernel + // (itself) + phiCln->setIncomingBlock(0, prologue); + phiCln->setIncomingBlock(1, kernel); + + // The incoming value for the kernel (itself) is the new value which is + // computed in the kernel + Instruction *originalVal = (Instruction *) phiInst->getIncomingValue(1); phiCln->setIncomingValue(1, originalVal->getClone()); - - //make a clone of the branch instruction and insert it in the end - BranchInst* cln=(BranchInst*)cloneInstSetMemory( brchInst); - kernel_ist.insert(kernel_ist.back(),cln); - - //delete the unconditional branch instruction, which is generated when splitting the basicBlock - kernel_ist.erase( --kernel_ist.end()); - - //set the first successor to itself - ((BranchInst*)cln)->setSuccessor(0, kernel); - //set the second successor to eiplogue - ((BranchInst*)cln)->setSuccessor(1,epilogue); + // Make a clone of the branch instruction and insert it in the end + BranchInst *cln = (BranchInst *) cloneInstSetMemory(brchInst); + kernel_ist.insert(kernel_ist.back(), cln); + + // delete the unconditional branch instruction, which is generated when + // splitting the basicBlock + kernel_ist.erase(--kernel_ist.end()); + + // set the first successor to itself + ((BranchInst *) cln)->setSuccessor(0, kernel); + // set the second successor to eiplogue + ((BranchInst *) cln)->setSuccessor(1, epilogue); //*****change the condition******* //get the condition instruction - Instruction* cond=(Instruction*)cln->getCondition(); + Instruction *cond = (Instruction *) cln->getCondition(); //get the condition's second operand, it should be a constant - Value* operand=cond->getOperand(1); + Value *operand = cond->getOperand(1); assert(ConstantSInt::classof(operand)); //change the constant in the condtion instruction - ConstantSInt* iteTimes=ConstantSInt::get(operand->getType(),((ConstantSInt*)operand)->getValue()-II+1); - cond->setOperand(1,iteTimes); + ConstantSInt *iteTimes = + ConstantSInt::get(operand->getType(), + ((ConstantSInt *) operand)->getValue() - II + 1); + cond->setOperand(1, iteTimes); } +// Construct the epilogue +// +void ModuloScheduling::constructEpilogue(BasicBlock *epilogue, + BasicBlock *succ_bb) +{ - - -//construct the epilogue -void ModuloScheduling::constructEpilogue(BasicBlock* epilogue, BasicBlock* succ_bb){ - //compute the schedule for epilogue - vvNodeType& tempSchedule_epilogue= *(new vector< std::vector >(schedule)); - unsigned scheduleSize=schedule.size(); - int round =0; - while(round < ceil(1.0*scheduleSize/II )-1 ){ + vvNodeType & tempSchedule_epilogue = + *(new vector < std::vector < ModuloSchedGraphNode * >>(schedule)); + unsigned scheduleSize = schedule.size(); + int round = 0; + while (round < ceil(1.0 * scheduleSize / II) - 1) { round++; - for( unsigned i=0;i < scheduleSize ; i++){ - if(i + round *II >= scheduleSize) break; - for(unsigned j=0;j < schedule[i].size();j++) - if(schedule[i + round*II ][j]){ - assert( tempSchedule_epilogue[i][j] == NULL && "table not consitant with core table"); - - //move the schdule one iteration behind and overlap - tempSchedule_epilogue[i][j]=schedule[i + round*II][j]; - } + for (unsigned i = 0; i < scheduleSize; i++) { + if (i + round * II >= scheduleSize) + break; + for (unsigned j = 0; j < schedule[i].size(); j++) + if (schedule[i + round * II][j]) { + assert(tempSchedule_epilogue[i][j] == NULL + && "table not consitant with core table"); + + //move the schdule one iteration behind and overlap + tempSchedule_epilogue[i][j] = schedule[i + round * II][j]; + } } } - + //fill in the epilogue - InstListType& epilogue_ist = epilogue->getInstList(); - for(unsigned i=II;i getInst(); - - //BranchInst and PHINode should be treated differently - //BranchInst:unecessary, simly omitted - //PHINode: omitted - if( !BranchInst::classof(inst) && ! PHINode::classof(inst) ){ - //make a clone instruction and insert it into the epilogue - Instruction* cln=cloneInstSetMemory(inst); - epilogue_ist.push_front(cln); - } + InstListType & epilogue_ist = epilogue->getInstList(); + for (unsigned i = II; i < scheduleSize; i++) + for (unsigned j = 0; j < tempSchedule_epilogue[i].size(); j++) + if (tempSchedule_epilogue[i][j]) { + Instruction *inst = + (Instruction *) tempSchedule_epilogue[i][j]->getInst(); + + //BranchInst and PHINode should be treated differently + //BranchInst:unecessary, simly omitted + //PHINode: omitted + if (!BranchInst::classof(inst) && !PHINode::classof(inst)) { + //make a clone instruction and insert it into the epilogue + Instruction *cln = cloneInstSetMemory(inst); + epilogue_ist.push_front(cln); + } } - //*************delete the original instructions****************// //to delete the original instructions, we have to make sure their use is zero - + //update original core instruction's uses, using its clone instread - for(unsigned i=0;i < II; i++) - for(unsigned j=0;j < coreSchedule[i].size() ;j++){ - if(coreSchedule[i][j]) - updateUseWithClone((Instruction*)coreSchedule[i][j]->getInst() ); + for (unsigned i = 0; i < II; i++) + for (unsigned j = 0; j < coreSchedule[i].size(); j++) { + if (coreSchedule[i][j]) + updateUseWithClone((Instruction *) coreSchedule[i][j]->getInst()); } - + //erase these instructions - for(unsigned i=0;i < II; i++) - for(unsigned j=0;j < coreSchedule[i].size();j++) - if(coreSchedule[i][j]){ - Instruction* ist=(Instruction*)coreSchedule[i][j]->getInst(); - ist->getParent()->getInstList().erase(ist); + for (unsigned i = 0; i < II; i++) + for (unsigned j = 0; j < coreSchedule[i].size(); j++) + if (coreSchedule[i][j]) { + Instruction *ist = (Instruction *) coreSchedule[i][j]->getInst(); + ist->getParent()->getInstList().erase(ist); } //**************************************************************// //finally, insert an unconditional branch instruction at the end epilogue_ist.push_back(new BranchInst(succ_bb)); - -} +} -//---------------------------------------------------------------------------------------------- -//this function replace the value(instruction) ist in other instructions with its latest clone -//i.e. after this function is called, the ist is not used anywhere and it can be erased. -//---------------------------------------------------------------------------------------------- -void ModuloScheduling::updateUseWithClone(Instruction* ist){ - - while(ist->use_size() >0){ - bool destroyed=false; - - //other instruction is using this value ist - assert(Instruction::classof(*ist->use_begin())); - Instruction *inst=(Instruction*)(* ist->use_begin()); - - for(unsigned i=0;igetNumOperands();i++) - if(inst->getOperand(i) == ist && ist->getClone()){ - //if the instruction is TmpInstruction, simly delete it because it has no parent - // and it does not belongs to any BasicBlock - if(TmpInstruction::classof(inst)) { - delete inst; - destroyed=true; - break; - } +//------------------------------------------------------------------------------ +//this function replace the value(instruction) ist in other instructions with +//its latest clone i.e. after this function is called, the ist is not used +//anywhere and it can be erased. +//------------------------------------------------------------------------------ +void ModuloScheduling::updateUseWithClone(Instruction * ist) +{ + while (ist->use_size() > 0) { + bool destroyed = false; - //otherwise, set the instruction's operand to the value's clone - inst->setOperand(i, ist->getClone()); + //other instruction is using this value ist + assert(Instruction::classof(*ist->use_begin())); + Instruction *inst = (Instruction *) (*ist->use_begin()); - //the use from the original value ist is destroyed - destroyed=true; - break; - } - if( !destroyed) - { - //if the use can not be destroyed , something is wrong - inst->dump(); - assert( 0 &&"this use can not be destroyed"); - } + for (unsigned i = 0; i < inst->getNumOperands(); i++) + if (inst->getOperand(i) == ist && ist->getClone()) { + // if the instruction is TmpInstruction, simly delete it because it has + // no parent and it does not belongs to any BasicBlock + if (TmpInstruction::classof(inst)) { + delete inst; + destroyed = true; + break; + } + + //otherwise, set the instruction's operand to the value's clone + inst->setOperand(i, ist->getClone()); + + //the use from the original value ist is destroyed + destroyed = true; + break; + } + if (!destroyed) { + //if the use can not be destroyed , something is wrong + inst->dump(); + assert(0 && "this use can not be destroyed"); + } } - + } @@ -563,218 +582,236 @@ //this function clear all clone mememoy //i.e. set all instruction's clone memory to NULL //***************************************************** -void ModuloScheduling::clearCloneMemory(){ -for(unsigned i=0; i < coreSchedule.size();i++) - for(unsigned j=0;jgetInst())->clearClone(); - +void ModuloScheduling::clearCloneMemory() +{ + for (unsigned i = 0; i < coreSchedule.size(); i++) + for (unsigned j = 0; j < coreSchedule[i].size(); j++) + if (coreSchedule[i][j]) + ((Instruction *) coreSchedule[i][j]->getInst())->clearClone(); + } -//******************************************************************************** -//this function make a clone of the instruction orn -//the cloned instruction will use the orn's operands' latest clone as its operands -//it is done this way because LLVM is in SSA form and we should use the correct value -// +//****************************************************************************** +// this function make a clone of the instruction orn the cloned instruction will +// use the orn's operands' latest clone as its operands it is done this way +// because LLVM is in SSA form and we should use the correct value //this fuction also update the instruction orn's latest clone memory -//********************************************************************************** -Instruction* ModuloScheduling::cloneInstSetMemory(Instruction* orn) { +//****************************************************************************** +Instruction *ModuloScheduling::cloneInstSetMemory(Instruction * orn) +{ + // make a clone instruction + Instruction *cln = orn->clone(); -//make a clone instruction - Instruction* cln=orn->clone(); - - - //update the operands - for(unsigned k=0;kgetNumOperands();k++){ - const Value* op=orn->getOperand(k); - if(Instruction::classof(op) && ((Instruction*)op)->getClone()){ - Instruction* op_inst=(Instruction*)op; + // update the operands + for (unsigned k = 0; k < orn->getNumOperands(); k++) { + const Value *op = orn->getOperand(k); + if (Instruction::classof(op) && ((Instruction *) op)->getClone()) { + Instruction *op_inst = (Instruction *) op; cln->setOperand(k, op_inst->getClone()); } } - //update clone memory + // update clone memory orn->setClone(cln); return cln; } -bool ModuloScheduling::ScheduleNode(ModuloSchedGraphNode* node,unsigned start, unsigned end, NodeVec& nodeScheduled) +bool ModuloScheduling::ScheduleNode(ModuloSchedGraphNode * node, + unsigned start, unsigned end, + NodeVec & nodeScheduled) { - - const TargetSchedInfo& msi=target.getSchedInfo(); - unsigned int numIssueSlots=msi.maxNumIssueTotal; - - if( ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os<<"startTime= "<= ModuloSched_PrintScheduleProcess) - modSched_os<< " now try cycle " <= ModuloSched_PrintScheduleProcess) - modSched_os <<"\t Trying slot "<= ModuloSched_PrintScheduleProcess) + modSched_os << "startTime= " << start << " endTime= " << end << "\n"; + bool isScheduled = false; + for (unsigned i = start; i <= end; i++) { + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os << " now try cycle " << i << ":" << "\n"; + for (unsigned j = 0; j < numIssueSlots; j++) { + unsigned int core_i = i % II; + unsigned int core_j = j; + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os << "\t Trying slot " << j << "..........."; //check the resouce table, make sure there is no resource conflicts - const Instruction* instr=node->getInst(); - MachineCodeForInstruction& tempMvec= MachineCodeForInstruction::get(instr); - bool resourceConflict=false; - const TargetInstrInfo &mii=msi.getInstrInfo(); - - if(coreSchedule.size() < core_i+1 || !coreSchedule[core_i][core_j]){ - //this->dumpResourceUsageTable(); - int latency=0; - for(unsigned k=0;k< tempMvec.size();k++) - { - MachineInstr* minstr=tempMvec[k]; - InstrRUsage rUsage=msi.getInstrRUsage(minstr->getOpCode()); - std::vector > resources - =rUsage.resourcesByCycle; - updateResourceTable(resources,i + latency); - latency +=max(mii.minLatency(minstr->getOpCode()),1) ; - } - - //this->dumpResourceUsageTable(); - - latency=0; - if( resourceTableNegative()){ - - //undo-update the resource table - for(unsigned k=0;k< tempMvec.size();k++){ - MachineInstr* minstr=tempMvec[k]; - InstrRUsage rUsage=msi.getInstrRUsage(minstr->getOpCode()); - std::vector > resources - =rUsage.resourcesByCycle; - undoUpdateResourceTable(resources,i + latency); - latency +=max(mii.minLatency(minstr->getOpCode()),1) ; - } - resourceConflict=true; - } - } - if( !resourceConflict && !coreSchedule[core_i][core_j]){ - if( ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess){ - modSched_os <<" OK!"<<"\n"; - modSched_os<<"Node "<getNodeId()<< " is scheduleed."<<"\n"; - } - //schedule[i][j]=node; - while(schedule.size() <= i){ - std::vector* newCycle=new std::vector(); - for(unsigned k=0;kpush_back(NULL); - schedule.push_back(*newCycle); - } - vector::iterator startIterator; - startIterator = schedule[i].begin(); - schedule[i].insert(startIterator+j,node); - startIterator = schedule[i].begin(); - schedule[i].erase(startIterator+j+1); - - //update coreSchedule - //coreSchedule[core_i][core_j]=node; - while(coreSchedule.size() <= core_i){ - std::vector* newCycle=new std::vector(); - for(unsigned k=0;kpush_back(NULL); - coreSchedule.push_back(*newCycle); - } - - startIterator = coreSchedule[core_i].begin(); - coreSchedule[core_i].insert(startIterator+core_j,node); - startIterator = coreSchedule[core_i].begin(); - coreSchedule[core_i].erase(startIterator+core_j+1); - - node->setSchTime(i); - isScheduled=true; - nodeScheduled.push_back(node); - - break; - } - else if( coreSchedule[core_i][core_j]) { - if( ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os <<" Slot not available "<<"\n"; - } - else{ - if( ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os <<" Resource conflicts"<<"\n"; + const Instruction *instr = node->getInst(); + MachineCodeForInstruction & tempMvec = + MachineCodeForInstruction::get(instr); + bool resourceConflict = false; + const TargetInstrInfo & mii = msi.getInstrInfo(); + + if (coreSchedule.size() < core_i + 1 + || !coreSchedule[core_i][core_j]) { + //this->dumpResourceUsageTable(); + int latency = 0; + for (unsigned k = 0; k < tempMvec.size(); k++) { + MachineInstr *minstr = tempMvec[k]; + InstrRUsage rUsage = msi.getInstrRUsage(minstr->getOpCode()); + std::vector < std::vector < resourceId_t > >resources + = rUsage.resourcesByCycle; + updateResourceTable(resources, i + latency); + latency += std::max(mii.minLatency(minstr->getOpCode()), 1); + } + + //this->dumpResourceUsageTable(); + + latency = 0; + if (resourceTableNegative()) { + + //undo-update the resource table + for (unsigned k = 0; k < tempMvec.size(); k++) { + MachineInstr *minstr = tempMvec[k]; + InstrRUsage rUsage = msi.getInstrRUsage(minstr->getOpCode()); + std::vector < std::vector < resourceId_t > >resources + = rUsage.resourcesByCycle; + undoUpdateResourceTable(resources, i + latency); + latency += std::max(mii.minLatency(minstr->getOpCode()), 1); + } + resourceConflict = true; + } + } + if (!resourceConflict && !coreSchedule[core_i][core_j]) { + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) { + modSched_os << " OK!" << "\n"; + modSched_os << "Node " << node-> + getNodeId() << " is scheduleed." << "\n"; + } + //schedule[i][j]=node; + while (schedule.size() <= i) { + std::vector < ModuloSchedGraphNode * >*newCycle = + new std::vector < ModuloSchedGraphNode * >(); + for (unsigned k = 0; k < numIssueSlots; k++) + newCycle->push_back(NULL); + schedule.push_back(*newCycle); + } + vector < ModuloSchedGraphNode * >::iterator startIterator; + startIterator = schedule[i].begin(); + schedule[i].insert(startIterator + j, node); + startIterator = schedule[i].begin(); + schedule[i].erase(startIterator + j + 1); + + //update coreSchedule + //coreSchedule[core_i][core_j]=node; + while (coreSchedule.size() <= core_i) { + std::vector < ModuloSchedGraphNode * >*newCycle = + new std::vector < ModuloSchedGraphNode * >(); + for (unsigned k = 0; k < numIssueSlots; k++) + newCycle->push_back(NULL); + coreSchedule.push_back(*newCycle); + } + + startIterator = coreSchedule[core_i].begin(); + coreSchedule[core_i].insert(startIterator + core_j, node); + startIterator = coreSchedule[core_i].begin(); + coreSchedule[core_i].erase(startIterator + core_j + 1); + + node->setSchTime(i); + isScheduled = true; + nodeScheduled.push_back(node); + + break; + } else if (coreSchedule[core_i][core_j]) { + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os << " Slot not available " << "\n"; + } else { + if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + modSched_os << " Resource conflicts" << "\n"; } } - if(isScheduled) break; + if (isScheduled) + break; } //assert(nodeScheduled &&"this node can not be scheduled?"); return isScheduled; } -void ModuloScheduling::updateResourceTable(std::vector > useResources, int startCycle){ - for(unsigned i=0;i< useResources.size();i++){ - int absCycle=startCycle+i; - int coreCycle=absCycle % II; - std::vector >& resourceRemained=resourceTable[coreCycle]; - std::vector& resourceUsed= useResources[i]; - for(unsigned j=0;j< resourceUsed.size();j++){ - for(unsigned k=0;k< resourceRemained.size();k++) - if((int)resourceUsed[j] == resourceRemained[k].first){ - resourceRemained[k].second--; - } + +void ModuloScheduling::updateResourceTable(Resources useResources, + int startCycle) +{ + for (unsigned i = 0; i < useResources.size(); i++) { + int absCycle = startCycle + i; + int coreCycle = absCycle % II; + std::vector > &resourceRemained = + resourceTable[coreCycle]; + std::vector < unsigned int >&resourceUsed = useResources[i]; + for (unsigned j = 0; j < resourceUsed.size(); j++) { + for (unsigned k = 0; k < resourceRemained.size(); k++) + if ((int) resourceUsed[j] == resourceRemained[k].first) { + resourceRemained[k].second--; + } } } } -void ModuloScheduling::undoUpdateResourceTable(std::vector > useResources, int startCycle){ - for(unsigned i=0;i< useResources.size();i++){ - int absCycle=startCycle+i; - int coreCycle=absCycle % II; - std::vector >& resourceRemained=resourceTable[coreCycle]; - std::vector& resourceUsed= useResources[i]; - for(unsigned j=0;j< resourceUsed.size();j++){ - for(unsigned k=0;k< resourceRemained.size();k++) - if((int)resourceUsed[j] == resourceRemained[k].first){ - resourceRemained[k].second++; - } +void ModuloScheduling::undoUpdateResourceTable(Resources useResources, + int startCycle) +{ + for (unsigned i = 0; i < useResources.size(); i++) { + int absCycle = startCycle + i; + int coreCycle = absCycle % II; + std::vector > &resourceRemained = + resourceTable[coreCycle]; + std::vector < unsigned int >&resourceUsed = useResources[i]; + for (unsigned j = 0; j < resourceUsed.size(); j++) { + for (unsigned k = 0; k < resourceRemained.size(); k++) + if ((int) resourceUsed[j] == resourceRemained[k].first) { + resourceRemained[k].second++; + } } } } //----------------------------------------------------------------------- -//Function: resouceTableNegative -//return value: -// return false if any element in the resouceTable is negative -// otherwise return true -//Purpose: -// this function is used to determine if an instruction is eligible for schedule at certain cycle -//--------------------------------------------------------------------------------------- +// Function: resourceTableNegative +// return value: +// return false if any element in the resouceTable is negative +// otherwise return true +// Purpose: + +// this function is used to determine if an instruction is eligible for +// schedule at certain cycle +//----------------------------------------------------------------------- + -bool ModuloScheduling::resourceTableNegative(){ - assert(resourceTable.size() == (unsigned)II&& "resouceTable size must be equal to II"); - bool isNegative=false; - for(unsigned i=0; i < resourceTable.size();i++) - for(unsigned j=0;j < resourceTable[i].size();j++){ - if(resourceTable[i][j].second <0) { - isNegative=true; - break; - } +bool ModuloScheduling::resourceTableNegative() +{ + assert(resourceTable.size() == (unsigned) II + && "resouceTable size must be equal to II"); + bool isNegative = false; + for (unsigned i = 0; i < resourceTable.size(); i++) + for (unsigned j = 0; j < resourceTable[i].size(); j++) { + if (resourceTable[i][j].second < 0) { + isNegative = true; + break; + } } return isNegative; } //---------------------------------------------------------------------- -//Function: dumpResouceUsageTable -//Purpose: -// print out ResouceTable for debug +// Function: dumpResouceUsageTable +// Purpose: +// print out ResouceTable for debug // //------------------------------------------------------------------------ -void ModuloScheduling::dumpResourceUsageTable(){ - modSched_os<<"dumping resource usage table"<<"\n"; - for(unsigned i=0;i< resourceTable.size();i++){ - for(unsigned j=0;j < resourceTable[i].size();j++) - modSched_os < > thisSchedule){ - - const TargetSchedInfo& msi=target.getSchedInfo(); - unsigned numIssueSlots=msi.maxNumIssueTotal; - for(unsigned i=0;i< numIssueSlots;i++) - modSched_os <<"\t#"; - modSched_os<<"\n"; - for(unsigned i=0;i < thisSchedule.size();i++) - { - modSched_os<<"cycle"<getNodeId()<<"\t"; - else - modSched_os<<"\t"; - modSched_os<<"\n"; - } - +void ModuloScheduling::dumpSchedule(vvNodeType thisSchedule) +{ + const TargetSchedInfo & msi = target.getSchedInfo(); + unsigned numIssueSlots = msi.maxNumIssueTotal; + for (unsigned i = 0; i < numIssueSlots; i++) + modSched_os << "\t#"; + modSched_os << "\n"; + for (unsigned i = 0; i < thisSchedule.size(); i++) { + modSched_os << "cycle" << i << ": "; + for (unsigned j = 0; j < thisSchedule[i].size(); j++) + if (thisSchedule[i][j] != NULL) + modSched_os << thisSchedule[i][j]->getNodeId() << "\t"; + else + modSched_os << "\t"; + modSched_os << "\n"; + } + } @@ -811,36 +847,36 @@ // //------------------------------------------------------- -void ModuloScheduling::dumpScheduling(){ - modSched_os<<"dump schedule:"<<"\n"; - const TargetSchedInfo& msi=target.getSchedInfo(); - unsigned numIssueSlots=msi.maxNumIssueTotal; - for(unsigned i=0;i< numIssueSlots;i++) - modSched_os <<"\t#"; - modSched_os<<"\n"; - for(unsigned i=0;i < schedule.size();i++) - { - modSched_os<<"cycle"<getNodeId()<<"\t"; - else - modSched_os<<"\t"; - modSched_os<<"\n"; - } - - modSched_os<<"dump coreSchedule:"<<"\n"; - for(unsigned i=0;i< numIssueSlots;i++) - modSched_os <<"\t#"; - modSched_os<<"\n"; - for(unsigned i=0;i < coreSchedule.size();i++){ - modSched_os<<"cycle"<getNodeId()<<"\t"; +void ModuloScheduling::dumpScheduling() +{ + modSched_os << "dump schedule:" << "\n"; + const TargetSchedInfo & msi = target.getSchedInfo(); + unsigned numIssueSlots = msi.maxNumIssueTotal; + for (unsigned i = 0; i < numIssueSlots; i++) + modSched_os << "\t#"; + modSched_os << "\n"; + for (unsigned i = 0; i < schedule.size(); i++) { + modSched_os << "cycle" << i << ": "; + for (unsigned j = 0; j < schedule[i].size(); j++) + if (schedule[i][j] != NULL) + modSched_os << schedule[i][j]->getNodeId() << "\t"; + else + modSched_os << "\t"; + modSched_os << "\n"; + } + + modSched_os << "dump coreSchedule:" << "\n"; + for (unsigned i = 0; i < numIssueSlots; i++) + modSched_os << "\t#"; + modSched_os << "\n"; + for (unsigned i = 0; i < coreSchedule.size(); i++) { + modSched_os << "cycle" << i << ": "; + for (unsigned j = 0; j < coreSchedule[i].size(); j++) + if (coreSchedule[i][j] != NULL) + modSched_os << coreSchedule[i][j]->getNodeId() << "\t"; else - modSched_os<<"\t"; - modSched_os<<"\n"; + modSched_os << "\t"; + modSched_os << "\n"; } } @@ -856,45 +892,46 @@ //--------------------------------------------------------------------------- namespace { - class ModuloSchedulingPass : public FunctionPass { - const TargetMachine ⌖ + class ModuloSchedulingPass:public FunctionPass { + const TargetMachine & target; public: - ModuloSchedulingPass(const TargetMachine &T) : target(T) {} - const char *getPassName() const { return "Modulo Scheduling"; } - + ModuloSchedulingPass(const TargetMachine &T):target(T) { + } const char *getPassName() const { + return "Modulo Scheduling"; + } // getAnalysisUsage - We use LiveVarInfo... - virtual void getAnalysisUsage(AnalysisUsage &AU) const { + virtual void getAnalysisUsage(AnalysisUsage &AU) const { //AU.addRequired(FunctionLiveVarInfo::ID); - } - bool runOnFunction(Function &F); + } bool runOnFunction(Function & F); }; -} // end anonymous namespace - +} // end anonymous namespace bool ModuloSchedulingPass::runOnFunction(Function &F) { - + //if necessary , open the output for debug purpose - if(ModuloSchedDebugLevel== ModuloSched_Disable) + if (ModuloSchedDebugLevel == ModuloSched_Disable) return false; - - if(ModuloSchedDebugLevel>= ModuloSched_PrintSchedule){ - modSched_fb.open("moduloSchedDebugInfo.output", ios::out); - modSched_os<<"******************Modula Scheduling debug information*************************"<<"\n "; + + if (ModuloSchedDebugLevel >= ModuloSched_PrintSchedule) { + modSched_fb.open("moduloSchedDebugInfo.output", std::ios::out); + modSched_os << + "******************Modula Scheduling debug information****************" + << "\n "; } - - ModuloSchedGraphSet* graphSet = new ModuloSchedGraphSet(&F,target); + + ModuloSchedGraphSet *graphSet = new ModuloSchedGraphSet(&F, target); ModuloSchedulingSet ModuloSchedulingSet(*graphSet); - - if(ModuloSchedDebugLevel>= ModuloSched_PrintSchedule) + + if (ModuloSchedDebugLevel >= ModuloSched_PrintSchedule) modSched_fb.close(); - + return false; } -Pass *createModuloSchedulingPass(const TargetMachine &tgt) { +Pass *createModuloSchedulingPass(const TargetMachine & tgt) +{ return new ModuloSchedulingPass(tgt); } - Index: llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.h diff -u llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.h:1.2 llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.h:1.3 --- llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.h:1.2 Sun Apr 6 18:56:19 2003 +++ llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.h Wed Apr 9 16:51:34 2003 @@ -1,7 +1,7 @@ -//// - head file for the classes ModuloScheduling and ModuloScheduling ----*- C++ -*-===// +// ModuloScheduling.h -------------------------------------------*- C++ -*-===// // -// This header defines the the classes ModuloScheduling and ModuloSchedulingSet 's structure -// +// This header defines the the classes ModuloScheduling and +// ModuloSchedulingSet's structure // //===----------------------------------------------------------------------===// @@ -13,151 +13,148 @@ #include #include -using std::vector; +class ModuloScheduling: NonCopyable { +private: -class ModuloScheduling:NonCopyable { - private: typedef std::vector NodeVec; - - /// the graph to feed in - ModuloSchedGraph& graph; - const TargetMachine& target; - - //the BasicBlock to be scheduled - BasicBlock* bb; + typedef std::vector > Resources; + + // The graph to feed in + ModuloSchedGraph &graph; + const TargetMachine ⌖ + + // The BasicBlock to be scheduled + BasicBlock *bb; - ///Iteration Intervel - ///FIXME: II may be a better name for its meaning + // Iteration Interval + // FIXME: II may be a better name for its meaning unsigned II; - //the vector containing the nodes which have been scheduled + // The vector containing the nodes which have been scheduled NodeVec nodeScheduled; - - ///the remaining unscheduled nodes - const NodeVec& oNodes; - - ///the machine resource table - std::vector< std::vector > > resourceTable ; - + + // The remaining unscheduled nodes + const NodeVec &oNodes; + + // The machine resource table + std::vector > > resourceTable; + ///the schedule( with many schedule stage) std::vector > schedule; - + ///the kernel(core) schedule(length = II) std::vector > coreSchedule; - typedef BasicBlock::InstListType InstListType; - typedef std::vector > vvNodeType; - - + typedef BasicBlock::InstListType InstListType; + typedef std::vector > vvNodeType; public: - - ///constructor - ModuloScheduling(ModuloSchedGraph& _graph): - graph(_graph), - target(graph.getTarget()), - oNodes(graph.getONodes()) - { - II = graph.getMII(); - bb=(BasicBlock*)graph.getBasicBlocks()[0]; - instrScheduling(); - }; + ModuloScheduling(ModuloSchedGraph & _graph): + graph(_graph), target(graph.getTarget()), oNodes(graph.getONodes()) + { + II = graph.getMII(); + bb = (BasicBlock *) graph.getBasicBlocks()[0]; + instrScheduling(); + }; - ///destructor - ~ModuloScheduling(){}; + ~ModuloScheduling() {}; ///the method to compute schedule and instert epilogue and prologue void instrScheduling(); ///debug functions: ///dump the schedule and core schedule - void dumpScheduling(); - + void + dumpScheduling(); + ///dump the input vector of nodes //sch: the input vector of nodes - void dumpSchedule( std::vector > sch); + void dumpSchedule(std::vector> sch); ///dump the resource usage table void dumpResourceUsageTable(); - - //*******************internel functions******************************* + //*******************internal functions******************************* private: //clear memory from the last round and initialize if necessary - void clearInitMem(const TargetSchedInfo& ); + void clearInitMem(const TargetSchedInfo&); //compute schedule and coreSchedule with the current II bool computeSchedule(); - BasicBlock* getSuccBB(BasicBlock*); - BasicBlock* getPredBB(BasicBlock*); - void constructPrologue(BasicBlock* prologue); - void constructKernel(BasicBlock* prologue,BasicBlock* kernel,BasicBlock* epilogue); - void constructEpilogue(BasicBlock* epilogue,BasicBlock* succ_bb); - - ///update the resource table at the startCycle - //vec: the resouce usage - //startCycle: the start cycle the resouce usage is - void updateResourceTable(std::vector > vec,int startCycle); - - ///un-do the update in the resource table in the startCycle - //vec: the resouce usage - //startCycle: the start cycle the resouce usage is - void undoUpdateResourceTable(std::vector > vec,int startCycle); - - ///return whether the resourcetable has negative element - ///this function is called after updateResouceTable() to determine whether a node can - /// be scheduled at certain cycle + BasicBlock *getSuccBB(BasicBlock *); + BasicBlock *getPredBB(BasicBlock *); + void constructPrologue(BasicBlock *prologue); + void constructKernel(BasicBlock *prologue, + BasicBlock *kernel, + BasicBlock *epilogue); + void constructEpilogue(BasicBlock *epilogue, BasicBlock *succ_bb); + + // update the resource table at the startCycle + // vec: the resouce usage + // startCycle: the start cycle the resouce usage is + void updateResourceTable(std::vector> vec, + int startCycle); + + // un-do the update in the resource table in the startCycle + // vec: the resouce usage + // startCycle: the start cycle the resouce usage is + void undoUpdateResourceTable(std::vector> vec, + int startCycle); + + // return whether the resourcetable has negative element + // this function is called after updateResouceTable() to determine whether a + // node can be scheduled at certain cycle bool resourceTableNegative(); - - ///try to Schedule the node starting from start to end cycle(inclusive) - //if it can be scheduled, put it in the schedule and update nodeScheduled - //node: the node to be scheduled - //start: start cycle - //end : end cycle - //nodeScheduled: a vector storing nodes which has been scheduled - bool ScheduleNode(ModuloSchedGraphNode* node,unsigned start, unsigned end, NodeVec& nodeScheduled); + // try to Schedule the node starting from start to end cycle(inclusive) + // if it can be scheduled, put it in the schedule and update nodeScheduled + // node: the node to be scheduled + // start: start cycle + // end : end cycle + // nodeScheduled: a vector storing nodes which has been scheduled + bool ScheduleNode(ModuloSchedGraphNode * node, unsigned start, + unsigned end, NodeVec &nodeScheduled); //each instruction has a memory of the latest clone instruction //the clone instruction can be get using getClone() - //this function clears the memory, i.e. getClone() after calling this function returns null + //this function clears the memory, i.e. getClone() after calling this function + //returns null void clearCloneMemory(); - //this fuction make a clone of this input Instruction and update the clone memory + //this fuction make a clone of this input Instruction and update the clone + //memory //inst: the instrution to be cloned - Instruction* cloneInstSetMemory(Instruction* inst); + Instruction *cloneInstSetMemory(Instruction *inst); //this function update each instrutions which uses ist as its operand //after update, each instruction will use ist's clone as its operand - void updateUseWithClone(Instruction* ist); + void updateUseWithClone(Instruction * ist); }; -class ModuloSchedulingSet:NonCopyable{ - private: - +class ModuloSchedulingSet: +NonCopyable { +private: + //the graphSet to feed in - ModuloSchedGraphSet& graphSet; - public: + ModuloSchedGraphSet & graphSet; + +public: //constructor //Scheduling graph one by one - ModuloSchedulingSet(ModuloSchedGraphSet _graphSet):graphSet(_graphSet){ - for(unsigned i=0;i Changes in directory llvm/lib/Reoptimizer/BinInterface: bitmath.h updated: 1.5 -> 1.6 sparc9.h updated: 1.9 -> 1.10 --- Log message: Added more instruction-construction macros (must fix integer overflow warning), and field-extraction macros. --- Diffs of the changes: Index: llvm/lib/Reoptimizer/BinInterface/bitmath.h diff -u llvm/lib/Reoptimizer/BinInterface/bitmath.h:1.5 llvm/lib/Reoptimizer/BinInterface/bitmath.h:1.6 --- llvm/lib/Reoptimizer/BinInterface/bitmath.h:1.5 Sun Dec 15 05:07:01 2002 +++ llvm/lib/Reoptimizer/BinInterface/bitmath.h Thu Apr 10 00:33:56 2003 @@ -132,7 +132,9 @@ return ((0xFFFFAA50 >> w) & 3)+n; // this is a LUT } - +static unsigned LOW10(unsigned value) { return value & 0x000003ff; } +static unsigned HIGH22(unsigned value) { return value >> 10; } +static unsigned HIGHWORD(uint64_t value) { return (unsigned) (value >> 32); } +static unsigned LOWWORD(uint64_t value) { return (unsigned) value; } #endif - Index: llvm/lib/Reoptimizer/BinInterface/sparc9.h diff -u llvm/lib/Reoptimizer/BinInterface/sparc9.h:1.9 llvm/lib/Reoptimizer/BinInterface/sparc9.h:1.10 --- llvm/lib/Reoptimizer/BinInterface/sparc9.h:1.9 Tue Apr 1 16:13:35 2003 +++ llvm/lib/Reoptimizer/BinInterface/sparc9.h Thu Apr 10 00:33:56 2003 @@ -395,5 +395,35 @@ MK_FLD(INSTR_I, 1) | \ MK_FLD(INSTR_OP3, OP3_ADD)) +// Many of these macros can generate 'integer overflow in expression' warnings in some +// cases (e.g., passing a numeric literal for an immediate field), and the root cause has +// not yet been determined. FIXME. +// Construct immediate-valued logical operation +#define MK_LOGIC_IMM(op3, dreg, sreg, imm) \ + (MK_FLD(INSTR_OP, OP_2) | \ + MK_FLD(INSTR_RD, dreg) | \ + MK_FLD(INSTR_RS1, sreg) | \ + MK_FLD(INSTR_SIMM13, imm) | \ + MK_FLD(INSTR_I, 1) | \ + MK_FLD(INSTR_OP3, op3)) + +// Construct sethi instruction + +#define MK_SETHI(dreg, imm) \ + (MK_FLD(INSTR_OP, OP_BRANCH) | \ + MK_FLD(INSTR_RD, dreg) | \ + MK_FLD(INSTR_OP2, OP2_SETHI) | \ + MK_FLD(INSTR_IMM22, imm)) + +// Construct S{LL,RL,RA}X shift instruction. + +#define MK_SHIFTX(op3, dreg, sreg, shcnt) \ + (MK_FLD(INSTR_OP, OP_2) | \ + MK_FLD(INSTR_RD, dreg) | \ + MK_FLD(INSTR_OP3, op3) | \ + MK_FLD(INSTR_RS1, sreg) | \ + MK_FLD(INSTR_I, 1) | \ + MK_FLD(INSTR_X, 1) | \ + MK_FLD(INSTR_SHCNT64, shcnt)) From jstanley at cs.uiuc.edu Thu Apr 10 00:34:00 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Thu Apr 10 00:34:00 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/Inst/InstManip.cpp InstManip.h Phase2.cpp design.txt Message-ID: <200304100535.AAA24484@cypher.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/Inst: InstManip.cpp updated: 1.1 -> 1.2 InstManip.h updated: 1.1 -> 1.2 Phase2.cpp updated: 1.4 -> 1.5 design.txt updated: 1.6 -> 1.7 --- Log message: --- Diffs of the changes: Index: llvm/lib/Reoptimizer/Inst/InstManip.cpp diff -u llvm/lib/Reoptimizer/Inst/InstManip.cpp:1.1 llvm/lib/Reoptimizer/Inst/InstManip.cpp:1.2 --- llvm/lib/Reoptimizer/Inst/InstManip.cpp:1.1 Tue Apr 8 23:32:03 2003 +++ llvm/lib/Reoptimizer/Inst/InstManip.cpp Thu Apr 10 00:35:02 2003 @@ -38,18 +38,21 @@ return RD_FLD(inst, INSTR_OP3) == OP3_SAVE ? addr + 4 : addr; } -void InstManip::generateLoad64(uint64_t value, std::vector& snippet) const +void InstManip::generateLoad64(uint64_t value, + std::vector& snippet, + TargetRegister reg) const { // Using %o0 and %o1, load the 64-bit value 'value' into %o0. The sequence of // instructions to do this is placed in the provided instruction vector 'snippet'. unsigned initSize = snippet.size(); - snippet.push_back(0x11000000 | high22(highWord(value))); // sethi (upper 22b of upper wrd), %o0 - snippet.push_back(0x90122000 | low10(highWord(value))); // or %o0, (lower 10b of upper wrd), %o0 + + snippet.push_back(0x11000000 | HIGH22(HIGHWORD(value))); // sethi (upper 22b of upper wrd), %o0 + snippet.push_back(0x90122000 | LOW10(HIGHWORD(value))); // or %o0, (lower 10b of upper wrd), %o0 snippet.push_back(0x912a3020); // sllx %o0, 32, %o0 - snippet.push_back(0x13000000 | high22(lowWord(value))); // sethi (upper 22b of lwr wrd), %o1 + snippet.push_back(0x13000000 | HIGH22(LOWWORD(value))); // sethi (upper 22b of lwr wrd), %o1 snippet.push_back(0x90120009); // or %o0, %o1, %o0 - snippet.push_back(0x90022000 | low10(lowWord(value))); // add %o0, (lwr 10b of lwr wrd), %o0 + snippet.push_back(0x90022000 | LOW10(LOWWORD(value))); // add %o0, (lwr 10b of lwr wrd), %o0 assert(snippet.size() - initSize == getGenLoad64Size() && "Unexpected number of instructions in code sequence for 64-bit value -> %o0"); Index: llvm/lib/Reoptimizer/Inst/InstManip.h diff -u llvm/lib/Reoptimizer/Inst/InstManip.h:1.1 llvm/lib/Reoptimizer/Inst/InstManip.h:1.2 --- llvm/lib/Reoptimizer/Inst/InstManip.h:1.1 Tue Apr 8 23:32:03 2003 +++ llvm/lib/Reoptimizer/Inst/InstManip.h Thu Apr 10 00:35:03 2003 @@ -21,6 +21,8 @@ class InstManip { public: + enum TargetRegister { REG_0, REG_1 }; + void printRange(unsigned* start, unsigned* end) const; inline void printRange(uint64_t start, uint64_t end) const; @@ -29,7 +31,9 @@ uint64_t skipFunctionHdr(uint64_t addr, VirtualMem* vm) const; - void generateLoad64(uint64_t value, std::vector& snippet) const; + void generateLoad64(uint64_t value, + std::vector& snippet, + TargetRegister reg = REG_0) const; inline unsigned getBranchAlways(uint64_t dest, uint64_t pc, bool annulHigh = true) const; inline unsigned getCall(uint64_t dest, uint64_t pc) const; @@ -38,18 +42,12 @@ unsigned getNOP() const { return 0x01000000; } unsigned getGenLoad64Size() const { return 6; } - private: //////////////// // Instruction constants and field-extraction "macros", etc. // Branch-always (annul bit high) instruction base (i.e. address not filled in yet) static const unsigned BRANCH_ALWAYS_BASE = 0x30480000; - - static unsigned low10(unsigned value) { return value & 0x000003ff; } - static unsigned high22(unsigned value) { return value >> 10; } - static unsigned highWord(uint64_t value) { return (unsigned) (value >> 32); } - static unsigned lowWord(uint64_t value) { return (unsigned) value; } }; void InstManip::printRange(uint64_t start, uint64_t end) const Index: llvm/lib/Reoptimizer/Inst/Phase2.cpp diff -u llvm/lib/Reoptimizer/Inst/Phase2.cpp:1.4 llvm/lib/Reoptimizer/Inst/Phase2.cpp:1.5 --- llvm/lib/Reoptimizer/Inst/Phase2.cpp:1.4 Tue Apr 8 23:32:03 2003 +++ llvm/lib/Reoptimizer/Inst/Phase2.cpp Thu Apr 10 00:35:03 2003 @@ -122,9 +122,7 @@ MemoryManager* mm = m_traceCache.getMemMgr(); uint64_t slotBase = mm->getMemory(getSlotSize()); unsigned origInstr = vm->readInstrFrmVm(repInstAddr); - - if(m_instManip.isBranch(origInstr)) - assert(0 && "Unhandled case: branch instruction first in function body"); + 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 vm->writeInstToVM(repInstAddr, m_instManip.getBranchAlways(slotBase, repInstAddr)); Index: llvm/lib/Reoptimizer/Inst/design.txt diff -u llvm/lib/Reoptimizer/Inst/design.txt:1.6 llvm/lib/Reoptimizer/Inst/design.txt:1.7 --- llvm/lib/Reoptimizer/Inst/design.txt:1.6 Fri Apr 4 17:08:56 2003 +++ llvm/lib/Reoptimizer/Inst/design.txt Thu Apr 10 00:35:03 2003 @@ -653,7 +653,7 @@ }}} -{{{ MEETING MINUTES 03 Apr 3003 +{{{ MEETING MINUTES 03 Apr 2003 New definition of different phases: @@ -726,6 +726,28 @@ }}} +{{{ MEETING MINUTES 09 Apr 2003 + +- Talked about ICS reviewer comments; for thesis work, or for later papers, we must keep +in mind the following: + + - Related work in the RT field, esp. language support for metrics. How are we + different? We need to read the current literature on this. + + - Address in the writing the difference between our approach and standard measurement + tools, specifically SpeedShop and other hardware-counter-related tools. I thought we + did this, but apparently we weren't very clear. + +- Must concentrate on results and finished implementation in the short-term. + +- To that end, we discussed using the dummy function memory and how to re-use it. Because +it's a fixed-size thing, we ought to only place indirect jumps to heap-allocated memory +there, and then, in the heap-allocated memory write the actual code to do the +instrumentation, etc, etc. + +- Rewrite instruction building mechanisms are general BinInterface macros. Blech. + +}}} {{{ IMPLEMENTATION SKETCH {{{ Current implementation sketch: From brukman at cs.uiuc.edu Thu Apr 10 14:20:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Thu Apr 10 14:20:01 2003 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/ModuloScheduling/ModuloSchedGraph.cpp ModuloSchedGraph.h ModuloScheduling.cpp ModuloScheduling.h Message-ID: <200304101919.OAA28872@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/ModuloScheduling: ModuloSchedGraph.cpp updated: 1.3 -> 1.4 ModuloSchedGraph.h updated: 1.3 -> 1.4 ModuloScheduling.cpp updated: 1.3 -> 1.4 ModuloScheduling.h updated: 1.3 -> 1.4 --- Log message: Fixed compilation errors, command-line argument declarations, cleaned up code to look nicer and removed useless stuff. Also renamed a few variables, moved them into namespaces, converted outputting to a file into a print to std::cerr with a DEBUG() guard, as all passes should do anyway. No functional changes have been made. However, this code now compiles. --- Diffs of the changes: Index: llvm/lib/CodeGen/ModuloScheduling/ModuloSchedGraph.cpp diff -u llvm/lib/CodeGen/ModuloScheduling/ModuloSchedGraph.cpp:1.3 llvm/lib/CodeGen/ModuloScheduling/ModuloSchedGraph.cpp:1.4 --- llvm/lib/CodeGen/ModuloScheduling/ModuloSchedGraph.cpp:1.3 Wed Apr 9 16:51:34 2003 +++ llvm/lib/CodeGen/ModuloScheduling/ModuloSchedGraph.cpp Thu Apr 10 14:19:23 2003 @@ -12,35 +12,41 @@ #include "llvm/Target/TargetSchedInfo.h" #include "Support/StringExtras.h" #include "Support/STLExtras.h" +#include "Support/hash_map" +#include "Support/Statistic.h" +#include "ModuloScheduling.h" #include "ModuloSchedGraph.h" #include +#include +#include + +// FIXME: Should be using #include #include //#include #define UNIDELAY 1 -extern std::ostream modSched_os; -extern ModuloSchedDebugLevel_t ModuloSchedDebugLevel; + //*********************** Internal Data Structures *************************/ // The following two types need to be classes, not typedefs, so we can use // opaque declarations in SchedGraph.h // -struct RefVec:public std::vector < std::pair < ModuloSchedGraphNode *, int >> { +struct RefVec:public std::vector > { typedef std::vector >::iterator iterator; typedef std::vector >::const_iterator const_iterator; }; -struct RegToRefVecMap:public std::hash_map < int, RefVec > { - typedef std::hash_map::iterator iterator; - typedef std::hash_map::const_iterator const_iterator; +struct RegToRefVecMap:public hash_map { + typedef hash_map::iterator iterator; + typedef hash_map::const_iterator const_iterator; }; -struct ValueToDefVecMap:public std::hash_map < const Instruction *, RefVec > { - typedef std::hash_map::iterator iterator; - typedef std::hash_map { + typedef hash_map::iterator iterator; + typedef hash_map::const_iterator const_iterator; }; @@ -603,21 +609,21 @@ void ModuloSchedGraph::dumpCircuits() { - modSched_os << "dumping circuits for graph: " << "\n"; + DEBUG(std::cerr << "dumping circuits for graph:\n"); int j = -1; while (circuits[++j][0] != 0) { int k = -1; while (circuits[j][++k] != 0) - modSched_os << circuits[j][k] << "\t"; - modSched_os << "\n"; + DEBUG(std::cerr << circuits[j][k] << "\t"); + DEBUG(std::cerr << "\n"); } } void ModuloSchedGraph::dumpSet(std::vector < ModuloSchedGraphNode * >set) { for (unsigned i = 0; i < set.size(); i++) - modSched_os << set[i]->getNodeId() << "\t"; - modSched_os << "\n"; + DEBUG(std::cerr << set[i]->getNodeId() << "\t"); + DEBUG(std::cerr << "\n"); } std::vector @@ -674,7 +680,7 @@ const BasicBlock *bb = bbVec[0]; unsigned numNodes = bb->size(); - //first order all the sets + // first order all the sets int j = -1; int totalDelay = -1; int preDelay = -1; @@ -691,7 +697,7 @@ totalDelay += edge->getMinDelay(); } if (preDelay != -1 && totalDelay > preDelay) { - //swap circuits[j][] and cuicuits[j-1][] + // swap circuits[j][] and cuicuits[j-1][] unsigned temp[MAXNODE]; for (int k = 0; k < MAXNODE; k++) { temp[k] = circuits[j - 1][k]; @@ -703,11 +709,11 @@ } } - //build the first set + // build the first set int backEdgeSrc; int backEdgeSink; - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os << "building the first set" << "\n"; + if (ModuloScheduling::printScheduleProcess()) + DEBUG(std::cerr << "building the first set" << "\n"); int setSeq = -1; int k = -1; setSeq++; @@ -717,17 +723,17 @@ backEdgeSrc = circuits[setSeq][k - 1]; backEdgeSink = circuits[setSeq][0]; } - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) { - modSched_os << "the first set is:"; + if (ModuloScheduling::printScheduleProcess()) { + DEBUG(std::cerr << "the first set is:"); dumpSet(set); } - //implement the ordering algorithm + // implement the ordering algorithm enum OrderSeq { bottom_up, top_down }; OrderSeq order; std::vector R; while (!set.empty()) { - std::vector < ModuloSchedGraphNode * >pset = predSet(oNodes); - std::vector < ModuloSchedGraphNode * >sset = succSet(oNodes); + std::vector pset = predSet(oNodes); + std::vector sset = succSet(oNodes); if (!pset.empty() && !vectorConj(pset, set).empty()) { R = vectorConj(pset, set); @@ -751,8 +757,8 @@ while (!R.empty()) { if (order == top_down) { - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os << "in top_down round" << "\n"; + if (ModuloScheduling::printScheduleProcess()) + DEBUG(std::cerr << "in top_down round\n"); while (!R.empty()) { int maxHeight = -1; NodeVec::iterator chosenI; @@ -795,8 +801,8 @@ order = bottom_up; R = vectorConj(predSet(oNodes), set); } else { - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os << "in bottom up round" << "\n"; + if (ModuloScheduling::printScheduleProcess()) + DEBUG(std::cerr << "in bottom up round\n"); while (!R.empty()) { int maxDepth = -1; NodeVec::iterator chosenI; @@ -822,17 +828,17 @@ R = vectorConj(succSet(oNodes), set); } } - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) { - modSched_os << "order finished" << "\n"; - modSched_os << "dumping the ordered nodes: " << "\n"; + if (ModuloScheduling::printScheduleProcess()) { + DEBUG(std::cerr << "order finished\n"); + DEBUG(std::cerr << "dumping the ordered nodes:\n"); dumpSet(oNodes); dumpCircuits(); } //create a new set //FIXME: the nodes between onodes and this circuit should also be include in //this set - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os << "building the next set" << "\n"; + if (ModuloScheduling::printScheduleProcess()) + DEBUG(std::cerr << "building the next set\n"); set.clear(); int k = -1; setSeq++; @@ -845,9 +851,8 @@ if (set.empty()) { //no circuits any more //collect all other nodes - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os << "no circuits any more, collect the rest nodes" << - "\n"; + if (ModuloScheduling::printScheduleProcess()) + DEBUG(std::cerr << "no circuits any more, collect the rest nodes\n"); for (unsigned i = 2; i < numNodes + 2; i++) { bool inset = false; for (unsigned j = 0; j < oNodes.size(); j++) @@ -859,8 +864,8 @@ set.push_back(getNode(i)); } } - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) { - modSched_os << "next set is: " << "\n"; + if (ModuloScheduling::printScheduleProcess()) { + DEBUG(std::cerr << "next set is:\n"); dumpSet(set); } } //while(!set.empty()) @@ -869,9 +874,6 @@ - - - void ModuloSchedGraph::buildGraph(const TargetMachine & target) { const BasicBlock *bb = bbVec[0]; @@ -888,7 +890,7 @@ // We use this to add memory dependence edges without a second full walk. // // vector memVec; - std::vector < ModuloSchedGraphNode * >memNodeVec; + std::vector memNodeVec; // Use this data structure to note any uses or definitions of // machine registers so we can add edges for those later without @@ -900,8 +902,6 @@ // RegToRefVecMap regToRefVecMap; - - // Make a dummy root node. We'll add edges to the real roots later. graphRoot = new ModuloSchedGraphNode(0, NULL, NULL, -1, target); graphLeaf = new ModuloSchedGraphNode(1, NULL, NULL, -1, target); @@ -919,11 +919,11 @@ //dump only the blocks which are from loops - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + if (ModuloScheduling::printScheduleProcess()) this->dump(bb); if (!isLoop(bb)) { - modSched_os << " dumping non-loop BB:\n"; + DEBUG(std::cerr << " dumping non-loop BB:\n"); dump(bb); } if (isLoop(bb)) { @@ -937,21 +937,21 @@ //this->dump(); int ResII = this->computeResII(bb); - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os << "ResII is " << ResII << "\n";; + if (ModuloScheduling::printScheduleProcess()) + DEBUG(std::cerr << "ResII is " << ResII << "\n"); int RecII = this->computeRecII(bb); - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os << "RecII is " << RecII << "\n"; + if (ModuloScheduling::printScheduleProcess()) + DEBUG(std::cerr << "RecII is " << RecII << "\n"); this->MII = std::max(ResII, RecII); this->computeNodeProperty(bb); - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + if (ModuloScheduling::printScheduleProcess()) this->dumpNodeProperty(); this->orderNodes(); - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + if (ModuloScheduling::printScheduleProcess()) this->dump(); //this->instrScheduling(); @@ -974,7 +974,6 @@ //os<<"begining computerRecII()"<<"\n"; - //FIXME: only deal with circuits starting at the first node: the phi node //nodeId=2; @@ -984,7 +983,6 @@ unsigned path[MAXNODE]; unsigned stack[MAXNODE][MAXNODE]; - for (int j = 0; j < MAXNODE; j++) { path[j] = 0; for (int k = 0; k < MAXNODE; k++) @@ -1004,19 +1002,19 @@ while (currentNode != NULL) { unsigned currentNodeId = currentNode->getNodeId(); - // modSched_os<<"current node is "<beginOutEdges(), E = currentNode->endOutEdges(); I != E; I++) { - //modSched_os <<" searching in outgoint edges of node + //DEBUG(std::cerr <<" searching in outgoint edges of node //"<getSink()->getNodeId(); bool inpath = false, instack = false; int k; - //modSched_os<<"nodeId is "<getNodeId()<<"\n"; + //DEBUG(std::cerr<<"find the next Node "<getNodeId()<<"\n"); int j = 0; while (stack[i][j] != 0) @@ -1051,7 +1049,7 @@ path[i] = nextNode->getNodeId(); currentNode = nextNode; } else { - //modSched_os<<"no expansion any more"<<"\n"; + //DEBUG(std::cerr<<"no expansion any more"<<"\n"); //confirmCircuit(); for (ModuloSchedGraphNode::const_iterator I = currentNode->beginOutEdges(), E = currentNode->endOutEdges(); @@ -1077,16 +1075,16 @@ } if (i == 0) { - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os << "circuits found are: " << "\n"; + if (ModuloScheduling::printScheduleProcess()) + DEBUG(std::cerr << "circuits found are:\n"); int j = -1; while (circuits[++j][0] != 0) { int k = -1; while (circuits[j][++k] != 0) - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os << circuits[j][k] << "\t"; - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os << "\n"; + if (ModuloScheduling::printScheduleProcess()) + DEBUG(std::cerr << circuits[j][k] << "\t"); + if (ModuloScheduling::printScheduleProcess()) + DEBUG(std::cerr << "\n"); //for this circuit, compute the sum of all edge delay int sumDelay = 0; @@ -1115,9 +1113,9 @@ // assume we have distance 1, in this case the sumDelay is RecII // this is correct for SSA form only // - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os << "The total Delay in the circuit is " << sumDelay - << "\n"; + if (ModuloScheduling::printScheduleProcess()) + DEBUG(std::cerr << "The total Delay in the circuit is " << sumDelay + << "\n"); RecII = RecII > sumDelay ? RecII : sumDelay; @@ -1133,7 +1131,7 @@ void ModuloSchedGraph::addResourceUsage(std::vector > &ruVec, int rid) { - //modSched_os<<"\nadding a resouce , current resouceUsage vector size is + //DEBUG(std::cerr<<"\nadding a resouce , current resouceUsage vector size is //"< > &ru) { TargetSchedInfo & msi = (TargetSchedInfo &) target.getSchedInfo(); - std::vector> resourceNumVector = msi.resourceNumVector; - modSched_os << "resourceID\t" << "resourceNum" << "\n"; + std::vector > resourceNumVector = msi.resourceNumVector; + DEBUG(std::cerr << "resourceID\t" << "resourceNum\n"); for (unsigned i = 0; i < resourceNumVector.size(); i++) - modSched_os << resourceNumVector[i]. - first << "\t" << resourceNumVector[i].second << "\n"; + DEBUG(std::cerr << resourceNumVector[i]. + first << "\t" << resourceNumVector[i].second << "\n"); - modSched_os << " maxNumIssueTotal(issue slot in one cycle) = " << msi. - maxNumIssueTotal << "\n"; - modSched_os << "resourceID\t resourceUsage\t ResourceNum" << "\n"; + DEBUG(std::cerr << " maxNumIssueTotal(issue slot in one cycle) = " << msi. + maxNumIssueTotal << "\n"); + DEBUG(std::cerr << "resourceID\t resourceUsage\t ResourceNum\n"); for (unsigned i = 0; i < ru.size(); i++) { - modSched_os << ru[i].first << "\t" << ru[i].second; + DEBUG(std::cerr << ru[i].first << "\t" << ru[i].second); const unsigned resNum = msi.getCPUResourceNum(ru[i].first); - modSched_os << "\t" << resNum << "\n"; + DEBUG(std::cerr << "\t" << resNum << "\n"); } } @@ -1175,7 +1173,7 @@ const TargetSchedInfo & msi = target.getSchedInfo(); int ResII; - std::vector> resourceUsage; + std::vector > resourceUsage; //pair //FIXME: number of functional units the target machine can provide should be @@ -1183,15 +1181,15 @@ for (BasicBlock::const_iterator I = bb->begin(), E = bb->end(); I != E; I++) { - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) { - modSched_os << "machine instruction for llvm instruction( node " << - getGraphNodeForInst(I)->getNodeId() << ")" << "\n"; - modSched_os << "\t" << *I; + if (ModuloScheduling::printScheduleProcess()) { + DEBUG(std::cerr << "machine instruction for llvm instruction( node " << + getGraphNodeForInst(I)->getNodeId() << ")\n"); + DEBUG(std::cerr << "\t" << *I); } MachineCodeForInstruction & tempMvec = MachineCodeForInstruction::get(I); - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os << "size =" << tempMvec.size() << "\n"; + if (ModuloScheduling::printScheduleProcess()) + DEBUG(std::cerr << "size =" << tempMvec.size() << "\n"); for (unsigned i = 0; i < tempMvec.size(); i++) { MachineInstr *minstr = tempMvec[i]; @@ -1201,27 +1199,27 @@ msi.getClassRUsage(mii.getSchedClass(minstr->getOpCode())); unsigned totCycles = classRUsage.totCycles; - std::vector> resources =rUsage.resourcesByCycle; + std::vector > resources=rUsage.resourcesByCycle; assert(totCycles == resources.size()); - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os << "resources Usage for this Instr(totCycles=" << - totCycles << ",mindLatency=" << mii.minLatency(minstr-> - getOpCode()) << - "): " << *minstr << "\n"; + if (ModuloScheduling::printScheduleProcess()) + DEBUG(std::cerr << "resources Usage for this Instr(totCycles=" + << totCycles << ",mindLatency=" + << mii.minLatency(minstr->getOpCode()) << "): " << *minstr + << "\n"); for (unsigned j = 0; j < resources.size(); j++) { - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os << "cycle " << j << ": "; + if (ModuloScheduling::printScheduleProcess()) + DEBUG(std::cerr << "cycle " << j << ": "); for (unsigned k = 0; k < resources[j].size(); k++) { - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os << "\t" << resources[j][k]; + if (ModuloScheduling::printScheduleProcess()) + DEBUG(std::cerr << "\t" << resources[j][k]); addResourceUsage(resourceUsage, resources[j][k]); } - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os << "\n"; + if (ModuloScheduling::printScheduleProcess()) + DEBUG(std::cerr << "\n"); } } } - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + if (ModuloScheduling::printScheduleProcess()) this->dumpResourceUsage(resourceUsage); //compute ResII @@ -1240,8 +1238,8 @@ return ResII; } -ModuloSchedGraphSet::ModuloSchedGraphSet(const Function * function, - const TargetMachine & target) +ModuloSchedGraphSet::ModuloSchedGraphSet(const Function *function, + const TargetMachine &target) : method(function) { buildGraphsForMethod(method, target); @@ -1257,20 +1255,20 @@ void ModuloSchedGraphSet::dump() const { - modSched_os << " ====== ModuloSched graphs for function `" << - method->getName() << "' =========\n\n"; + DEBUG(std::cerr << " ====== ModuloSched graphs for function `" << + method->getName() << "' =========\n\n"); for (const_iterator I = begin(); I != end(); ++I) (*I)->dump(); - modSched_os << "\n=========End graphs for funtion` " << method->getName() - << "' ==========\n\n"; + DEBUG(std::cerr << "\n=========End graphs for function `" << method->getName() + << "' ==========\n\n"); } void ModuloSchedGraph::dump(const BasicBlock * bb) { - modSched_os << "dumping basic block:"; - modSched_os << (bb->hasName()? bb->getName() : "block") - << " (" << bb << ")" << "\n"; + DEBUG(std::cerr << "dumping basic block:"); + DEBUG(std::cerr << (bb->hasName()? bb->getName() : "block") + << " (" << bb << ")" << "\n"); } @@ -1283,27 +1281,27 @@ void ModuloSchedGraph::dump() const { - modSched_os << " ModuloSchedGraph for basic Blocks:"; + DEBUG(std::cerr << " ModuloSchedGraph for basic Blocks:"); for (unsigned i = 0, N = bbVec.size(); i < N; i++) { - modSched_os << (bbVec[i]->hasName()? bbVec[i]->getName() : "block") - << " (" << bbVec[i] << ")" << ((i == N - 1) ? "" : ", "); + DEBUG(std::cerr << (bbVec[i]->hasName()? bbVec[i]->getName() : "block") + << " (" << bbVec[i] << ")" << ((i == N - 1) ? "" : ", ")); } - modSched_os << "\n\n Actual Root nodes : "; + DEBUG(std::cerr << "\n\n Actual Root nodes : "); for (unsigned i = 0, N = graphRoot->outEdges.size(); i < N; i++) - modSched_os << graphRoot->outEdges[i]->getSink()->getNodeId() - << ((i == N - 1) ? "" : ", "); + DEBUG(std::cerr << graphRoot->outEdges[i]->getSink()->getNodeId() + << ((i == N - 1) ? "" : ", ")); - modSched_os << "\n Graph Nodes:\n"; + DEBUG(std::cerr << "\n Graph Nodes:\n"); //for (const_iterator I=begin(); I != end(); ++I) - //modSched_os << "\n" << *I->second; + //DEBUG(std::cerr << "\n" << *I->second; unsigned numNodes = bbVec[0]->size(); for (unsigned i = 2; i < numNodes + 2; i++) { ModuloSchedGraphNode *node = getNode(i); - modSched_os << "\n" << *node; + DEBUG(std::cerr << "\n" << *node); } - modSched_os << "\n"; + DEBUG(std::cerr << "\n"); } void ModuloSchedGraph::dumpNodeProperty() const @@ -1312,13 +1310,12 @@ unsigned numNodes = bb->size(); for (unsigned i = 2; i < numNodes + 2; i++) { ModuloSchedGraphNode *node = getNode(i); - modSched_os << "NodeId " << node->getNodeId() << "\t"; - modSched_os << "ASAP " << node->getASAP() << "\t"; - modSched_os << "ALAP " << node->getALAP() << "\t"; - modSched_os << "mov " << node->getMov() << "\t"; - modSched_os << "depth " << node->getDepth() << "\t"; - modSched_os << "height " << node->getHeight() << "\t"; - modSched_os << "\n"; + DEBUG(std::cerr << "NodeId " << node->getNodeId() << "\t"); + DEBUG(std::cerr << "ASAP " << node->getASAP() << "\t"); + DEBUG(std::cerr << "ALAP " << node->getALAP() << "\t"); + DEBUG(std::cerr << "mov " << node->getMov() << "\t"); + DEBUG(std::cerr << "depth " << node->getDepth() << "\t"); + DEBUG(std::cerr << "height " << node->getHeight() << "\t\n"); } } Index: llvm/lib/CodeGen/ModuloScheduling/ModuloSchedGraph.h diff -u llvm/lib/CodeGen/ModuloScheduling/ModuloSchedGraph.h:1.3 llvm/lib/CodeGen/ModuloScheduling/ModuloSchedGraph.h:1.4 --- llvm/lib/CodeGen/ModuloScheduling/ModuloSchedGraph.h:1.3 Wed Apr 9 16:51:34 2003 +++ llvm/lib/CodeGen/ModuloScheduling/ModuloSchedGraph.h Thu Apr 10 14:19:23 2003 @@ -13,17 +13,10 @@ #include "llvm/Target/TargetInstrInfo.h" #include "Support/HashExtras.h" #include "Support/GraphTraits.h" +#include "Support/hash_map" #include "../InstrSched/SchedGraphCommon.h" #include -//for debug information selecton -enum ModuloSchedDebugLevel_t { - ModuloSched_NoDebugInfo, - ModuloSched_Disable, - ModuloSched_PrintSchedule, - ModuloSched_PrintScheduleProcess, -}; - //===----------------------------------------------------------------------===// // ModuloSchedGraphNode - Implement a data structure based on the // SchedGraphNodeCommon this class stores informtion needed later to order the @@ -160,20 +153,20 @@ typedef std::vector NodeVec; //the function to compute properties - void computeNodeASAP(const BasicBlock * bb); - void computeNodeALAP(const BasicBlock * bb); - void computeNodeMov(const BasicBlock * bb); - void computeNodeDepth(const BasicBlock * bb); - void computeNodeHeight(const BasicBlock * bb); + void computeNodeASAP(const BasicBlock *bb); + void computeNodeALAP(const BasicBlock *bb); + void computeNodeMov(const BasicBlock *bb); + void computeNodeDepth(const BasicBlock *bb); + void computeNodeHeight(const BasicBlock *bb); //the function to compute node property - void computeNodeProperty(const BasicBlock * bb); + void computeNodeProperty(const BasicBlock *bb); //the function to sort nodes void orderNodes(); //add the resource usage -void addResourceUsage(std::vector>&, int); +void addResourceUsage(std::vector > &, int); //debug functions: //dump circuits @@ -181,7 +174,7 @@ //dump the input set of nodes void dumpSet(std::vector set); //dump the input resource usage table - void dumpResourceUsage(std::vector> &); + void dumpResourceUsage(std::vector > &); public: //help functions @@ -195,16 +188,16 @@ NodeVec predSet(NodeVec set); //get the predessor set of the node - NodeVec predSet(ModuloSchedGraphNode * node, unsigned, unsigned); - NodeVec predSet(ModuloSchedGraphNode * node); + NodeVec predSet(ModuloSchedGraphNode *node, unsigned, unsigned); + NodeVec predSet(ModuloSchedGraphNode *node); //get the successor set of the set NodeVec succSet(NodeVec set, unsigned, unsigned); NodeVec succSet(NodeVec set); //get the succssor set of the node - NodeVec succSet(ModuloSchedGraphNode * node, unsigned, unsigned); - NodeVec succSet(ModuloSchedGraphNode * node); + NodeVec succSet(ModuloSchedGraphNode *node, unsigned, unsigned); + NodeVec succSet(ModuloSchedGraphNode *node); //return the uniton of the two vectors NodeVec vectorUnion(NodeVec set1, NodeVec set2); @@ -248,17 +241,22 @@ //return this basibBlock contains a loop bool isLoop(); - //return the node for the input instruction ModuloSchedGraphNode *getGraphNodeForInst(const Instruction * inst) const { const_iterator onePair = this->find(inst); return (onePair != this->end()) ? (*onePair).second : NULL; } - //Debugging support//dump the graph void dump() const; - //dump the basicBlock + + // Debugging support + //dump the graph + void dump() const; + + // dump the basicBlock void dump(const BasicBlock * bb); + //dump the basicBlock into 'os' stream void dump(const BasicBlock * bb, std::ostream & os); + //dump the node property void dumpNodeProperty() const; @@ -267,7 +265,8 @@ public: ModuloSchedGraph(const BasicBlock *bb, const TargetMachine &_target) - :SchedGraphCommon(bb), target(_target) { + :SchedGraphCommon(bb), target(_target) + { buildGraph(target); } @@ -276,8 +275,8 @@ delete I->second; } - //unorder iterators - //return values are pair + // Unorder iterators + // return values are pair using map_base::begin; using map_base::end; @@ -348,8 +347,8 @@ using baseVector::begin; using baseVector::end; -// Debugging support -void dump() const; + // Debugging support + void dump() const; private: void addGraph(ModuloSchedGraph *graph) { @@ -360,6 +359,6 @@ // Graph builder void buildGraphsForMethod(const Function *F, const TargetMachine &target); -} +}; #endif Index: llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.cpp diff -u llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.cpp:1.3 llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.cpp:1.4 --- llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.cpp:1.3 Wed Apr 9 16:51:34 2003 +++ llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.cpp Thu Apr 10 14:19:23 2003 @@ -19,6 +19,7 @@ #include "llvm/Target/TargetSchedInfo.h" #include "llvm/Target/TargetMachine.h" #include "Support/CommandLine.h" +#include "Support/Statistic.h" #include "ModuloSchedGraph.h" #include "ModuloScheduling.h" #include @@ -34,29 +35,26 @@ // see ModuloSchedulingPass::runOnFunction() //************************************************************ -ModuloSchedDebugLevel_t ModuloSchedDebugLevel; -static cl::opt -SDL_opt("modsched", cl::Hidden, cl::location(ModuloSchedDebugLevel), - cl::desc("enable modulo scheduling debugging information"), - cl::values(clEnumValN - (ModuloSched_NoDebugInfo, "n", "disable debug output"), - clEnumValN(ModuloSched_Disable, "off", - "disable modulo scheduling"), - clEnumValN(ModuloSched_PrintSchedule, "psched", - "print original and new schedule"), - clEnumValN(ModuloSched_PrintScheduleProcess, "pschedproc", - "print how the new schdule is produced"), 0)); - -std::filebuf modSched_fb; -std::ostream modSched_os(&modSched_fb); +namespace { + cl::opt + SDL_opt("modsched", cl::Hidden, cl::location(ModuloScheduling::DebugLevel), + cl::desc("enable modulo scheduling debugging information"), + cl::values(clEnumValN(ModuloScheduling::DebugLevel_NoDebugInfo, + "none", "disable debug output"), + clEnumValN(ModuloScheduling::DebugLevel_PrintSchedule, + "psched", "print original and new schedule"), + clEnumValN(ModuloScheduling::DebugLevel_PrintScheduleProcess, + "pschedproc", + "print how the new schdule is produced"), + 0)); +} // Computes the schedule and inserts epilogue and prologue // void ModuloScheduling::instrScheduling() { - - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os << "*************** computing modulo schedule **************\n"; + if (ModuloScheduling::printScheduleProcess()) + DEBUG(std::cerr << "************ computing modulo schedule ***********\n"); const TargetSchedInfo & msi = target.getSchedInfo(); @@ -74,13 +72,13 @@ if (!success) { II++; - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os << "increase II to " << II << "\n"; + if (ModuloScheduling::printScheduleProcess()) + DEBUG(std::cerr << "increase II to " << II << "\n"); } } //print the final schedule if necessary - if (ModuloSchedDebugLevel >= ModuloSched_PrintSchedule) + if (ModuloScheduling::printSchedule()) dumpScheduling(); //the schedule has been computed @@ -90,8 +88,8 @@ BasicBlock *succ_bb = getSuccBB(bb); //print the original BasicBlock if necessary - if (ModuloSchedDebugLevel >= ModuloSched_PrintSchedule) { - modSched_os << "dumping the orginal block\n"; + if (ModuloScheduling::printSchedule()) { + DEBUG(std::cerr << "dumping the orginal block\n"); graph.dump(bb); } //construction of prologue, kernel and epilogue @@ -109,12 +107,12 @@ constructEpilogue(epilogue, succ_bb); //print the BasicBlocks if necessary - if (ModuloSchedDebugLevel >= ModuloSched_PrintSchedule) { - modSched_os << "dumping the prologue block:\n"; + if (ModuloScheduling::printSchedule()) { + DEBUG(std::cerr << "dumping the prologue block:\n"); graph.dump(prologue); - modSched_os << "dumping the kernel block\n"; + DEBUG(std::cerr << "dumping the kernel block\n"); graph.dump(kernel); - modSched_os << "dumping the epilogue block\n"; + DEBUG(std::cerr << "dumping the epilogue block\n"); graph.dump(epilogue); } } @@ -125,11 +123,10 @@ { unsigned numIssueSlots = msi.maxNumIssueTotal; // clear nodeScheduled from the last round - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) { - modSched_os << "***** new round with II= " << II << - " *******************\n"; - modSched_os << - " ************clear the vector nodeScheduled*************\n"; + if (ModuloScheduling::printScheduleProcess()) { + DEBUG(std::cerr << "***** new round with II= " << II << " ***********\n"); + DEBUG(std::cerr << + " ************clear the vector nodeScheduled*************\n"); } nodeScheduled.clear(); @@ -158,13 +155,13 @@ bool ModuloScheduling::computeSchedule() { - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os << "start to compute schedule\n"; + if (ModuloScheduling::printScheduleProcess()) + DEBUG(std::cerr << "start to compute schedule\n"); // Loop over the ordered nodes for (NodeVec::const_iterator I = oNodes.begin(); I != oNodes.end(); ++I) { // Try to schedule for node I - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) + if (ModuloScheduling::printScheduleProcess()) dumpScheduling(); ModuloSchedGraphNode *node = *I; @@ -255,8 +252,8 @@ endTime = node->getEarlyStart() + II - 1; } //try to schedule this node based on the startTime and endTime - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os << "scheduling the node " << (*I)->getNodeId() << "\n"; + if (ModuloScheduling::printScheduleProcess()) + DEBUG(std::cerr << "scheduling the node " << (*I)->getNodeId() << "\n"); bool success = this->ScheduleNode(node, startTime, endTime, nodeScheduled); @@ -337,10 +334,9 @@ // void ModuloScheduling::constructPrologue(BasicBlock *prologue) { - InstListType & prologue_ist = prologue->getInstList(); vvNodeType & tempSchedule_prologue = - *(new vector < std::vector < ModuloSchedGraphNode * >>(schedule)); + *(new std::vector >(schedule)); //compute the schedule for prologue unsigned round = 0; @@ -395,7 +391,6 @@ BasicBlock *kernel, BasicBlock *epilogue) { - //*************fill instructions in the kernel**************** InstListType & kernel_ist = kernel->getInstList(); BranchInst *brchInst; @@ -472,8 +467,8 @@ { //compute the schedule for epilogue - vvNodeType & tempSchedule_epilogue = - *(new vector < std::vector < ModuloSchedGraphNode * >>(schedule)); + vvNodeType &tempSchedule_epilogue = + *(new std::vector >(schedule)); unsigned scheduleSize = schedule.size(); int round = 0; while (round < ceil(1.0 * scheduleSize / II) - 1) { @@ -626,17 +621,17 @@ const TargetSchedInfo & msi = target.getSchedInfo(); unsigned int numIssueSlots = msi.maxNumIssueTotal; - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os << "startTime= " << start << " endTime= " << end << "\n"; + if (ModuloScheduling::printScheduleProcess()) + DEBUG(std::cerr << "startTime= " << start << " endTime= " << end << "\n"); bool isScheduled = false; for (unsigned i = start; i <= end; i++) { - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os << " now try cycle " << i << ":" << "\n"; + if (ModuloScheduling::printScheduleProcess()) + DEBUG(std::cerr << " now try cycle " << i << ":" << "\n"); for (unsigned j = 0; j < numIssueSlots; j++) { unsigned int core_i = i % II; unsigned int core_j = j; - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os << "\t Trying slot " << j << "..........."; + if (ModuloScheduling::printScheduleProcess()) + DEBUG(std::cerr << "\t Trying slot " << j << "..........."); //check the resouce table, make sure there is no resource conflicts const Instruction *instr = node->getInst(); MachineCodeForInstruction & tempMvec = @@ -675,10 +670,9 @@ } } if (!resourceConflict && !coreSchedule[core_i][core_j]) { - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) { - modSched_os << " OK!" << "\n"; - modSched_os << "Node " << node-> - getNodeId() << " is scheduleed." << "\n"; + if (ModuloScheduling::printScheduleProcess()) { + DEBUG(std::cerr << " OK!" << "\n"); + DEBUG(std::cerr << "Node " << node->getNodeId() << " scheduled.\n"); } //schedule[i][j]=node; while (schedule.size() <= i) { @@ -688,7 +682,7 @@ newCycle->push_back(NULL); schedule.push_back(*newCycle); } - vector < ModuloSchedGraphNode * >::iterator startIterator; + std::vector::iterator startIterator; startIterator = schedule[i].begin(); schedule[i].insert(startIterator + j, node); startIterator = schedule[i].begin(); @@ -697,8 +691,8 @@ //update coreSchedule //coreSchedule[core_i][core_j]=node; while (coreSchedule.size() <= core_i) { - std::vector < ModuloSchedGraphNode * >*newCycle = - new std::vector < ModuloSchedGraphNode * >(); + std::vector *newCycle = + new std::vector(); for (unsigned k = 0; k < numIssueSlots; k++) newCycle->push_back(NULL); coreSchedule.push_back(*newCycle); @@ -715,11 +709,11 @@ break; } else if (coreSchedule[core_i][core_j]) { - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os << " Slot not available " << "\n"; + if (ModuloScheduling::printScheduleProcess()) + DEBUG(std::cerr << " Slot not available\n"); } else { - if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) - modSched_os << " Resource conflicts" << "\n"; + if (ModuloScheduling::printScheduleProcess()) + DEBUG(std::cerr << " Resource conflicts\n"); } } if (isScheduled) @@ -804,12 +798,12 @@ void ModuloScheduling::dumpResourceUsageTable() { - modSched_os << "dumping resource usage table" << "\n"; + DEBUG(std::cerr << "dumping resource usage table\n"); for (unsigned i = 0; i < resourceTable.size(); i++) { for (unsigned j = 0; j < resourceTable[i].size(); j++) - modSched_os << resourceTable[i][j]. - first << ":" << resourceTable[i][j].second << " "; - modSched_os << "\n"; + DEBUG(std::cerr << resourceTable[i][j].first + << ":" << resourceTable[i][j].second << " "); + DEBUG(std::cerr << "\n"); } } @@ -825,18 +819,17 @@ const TargetSchedInfo & msi = target.getSchedInfo(); unsigned numIssueSlots = msi.maxNumIssueTotal; for (unsigned i = 0; i < numIssueSlots; i++) - modSched_os << "\t#"; - modSched_os << "\n"; + DEBUG(std::cerr << "\t#"); + DEBUG(std::cerr << "\n"); for (unsigned i = 0; i < thisSchedule.size(); i++) { - modSched_os << "cycle" << i << ": "; + DEBUG(std::cerr << "cycle" << i << ": "); for (unsigned j = 0; j < thisSchedule[i].size(); j++) if (thisSchedule[i][j] != NULL) - modSched_os << thisSchedule[i][j]->getNodeId() << "\t"; + DEBUG(std::cerr << thisSchedule[i][j]->getNodeId() << "\t"); else - modSched_os << "\t"; - modSched_os << "\n"; + DEBUG(std::cerr << "\t"); + DEBUG(std::cerr << "\n"); } - } @@ -849,34 +842,34 @@ void ModuloScheduling::dumpScheduling() { - modSched_os << "dump schedule:" << "\n"; + DEBUG(std::cerr << "dump schedule:" << "\n"); const TargetSchedInfo & msi = target.getSchedInfo(); unsigned numIssueSlots = msi.maxNumIssueTotal; for (unsigned i = 0; i < numIssueSlots; i++) - modSched_os << "\t#"; - modSched_os << "\n"; + DEBUG(std::cerr << "\t#"); + DEBUG(std::cerr << "\n"); for (unsigned i = 0; i < schedule.size(); i++) { - modSched_os << "cycle" << i << ": "; + DEBUG(std::cerr << "cycle" << i << ": "); for (unsigned j = 0; j < schedule[i].size(); j++) if (schedule[i][j] != NULL) - modSched_os << schedule[i][j]->getNodeId() << "\t"; + DEBUG(std::cerr << schedule[i][j]->getNodeId() << "\t"); else - modSched_os << "\t"; - modSched_os << "\n"; + DEBUG(std::cerr << "\t"); + DEBUG(std::cerr << "\n"); } - modSched_os << "dump coreSchedule:" << "\n"; + DEBUG(std::cerr << "dump coreSchedule:" << "\n"); for (unsigned i = 0; i < numIssueSlots; i++) - modSched_os << "\t#"; - modSched_os << "\n"; + DEBUG(std::cerr << "\t#"); + DEBUG(std::cerr << "\n"); for (unsigned i = 0; i < coreSchedule.size(); i++) { - modSched_os << "cycle" << i << ": "; + DEBUG(std::cerr << "cycle" << i << ": "); for (unsigned j = 0; j < coreSchedule[i].size(); j++) if (coreSchedule[i][j] != NULL) - modSched_os << coreSchedule[i][j]->getNodeId() << "\t"; + DEBUG(std::cerr << coreSchedule[i][j]->getNodeId() << "\t"); else - modSched_os << "\t"; - modSched_os << "\n"; + DEBUG(std::cerr << "\t"); + DEBUG(std::cerr << "\n"); } } @@ -893,12 +886,15 @@ namespace { class ModuloSchedulingPass:public FunctionPass { - const TargetMachine & target; + const TargetMachine ⌖ + public: - ModuloSchedulingPass(const TargetMachine &T):target(T) { - } const char *getPassName() const { + ModuloSchedulingPass(const TargetMachine &T):target(T) {} + + const char *getPassName() const { return "Modulo Scheduling"; } + // getAnalysisUsage - We use LiveVarInfo... virtual void getAnalysisUsage(AnalysisUsage &AU) const { //AU.addRequired(FunctionLiveVarInfo::ID); @@ -909,23 +905,8 @@ bool ModuloSchedulingPass::runOnFunction(Function &F) { - - //if necessary , open the output for debug purpose - if (ModuloSchedDebugLevel == ModuloSched_Disable) - return false; - - if (ModuloSchedDebugLevel >= ModuloSched_PrintSchedule) { - modSched_fb.open("moduloSchedDebugInfo.output", std::ios::out); - modSched_os << - "******************Modula Scheduling debug information****************" - << "\n "; - } - ModuloSchedGraphSet *graphSet = new ModuloSchedGraphSet(&F, target); ModuloSchedulingSet ModuloSchedulingSet(*graphSet); - - if (ModuloSchedDebugLevel >= ModuloSched_PrintSchedule) - modSched_fb.close(); return false; } Index: llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.h diff -u llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.h:1.3 llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.h:1.4 --- llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.h:1.3 Wed Apr 9 16:51:34 2003 +++ llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.h Thu Apr 10 14:19:23 2003 @@ -60,19 +60,32 @@ ~ModuloScheduling() {}; - ///the method to compute schedule and instert epilogue and prologue + // for debug information selecton + enum DebugLevel_t { + DebugLevel_NoDebugInfo, + DebugLevel_PrintSchedule, + DebugLevel_PrintScheduleProcess, + }; + + static DebugLevel_t DebugLevel; + + static bool printSchedule() { return DebugLevel >= DebugLevel_PrintSchedule; } + static bool printScheduleProcess() { + return DebugLevel >= DebugLevel_PrintScheduleProcess; + } + + // The method to compute schedule and instert epilogue and prologue void instrScheduling(); - ///debug functions: - ///dump the schedule and core schedule - void - dumpScheduling(); - - ///dump the input vector of nodes - //sch: the input vector of nodes - void dumpSchedule(std::vector> sch); + // Debug functions: + // Dump the schedule and core schedule + void dumpScheduling(); + + // Dump the input vector of nodes + // sch: the input vector of nodes + void dumpSchedule(std::vector > sch); - ///dump the resource usage table + // Dump the resource usage table void dumpResourceUsageTable(); //*******************internal functions******************************* @@ -94,13 +107,13 @@ // update the resource table at the startCycle // vec: the resouce usage // startCycle: the start cycle the resouce usage is - void updateResourceTable(std::vector> vec, + void updateResourceTable(std::vector > vec, int startCycle); // un-do the update in the resource table in the startCycle // vec: the resouce usage // startCycle: the start cycle the resouce usage is - void undoUpdateResourceTable(std::vector> vec, + void undoUpdateResourceTable(std::vector > vec, int startCycle); // return whether the resourcetable has negative element From lattner at cs.uiuc.edu Thu Apr 10 14:22:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Apr 10 14:22:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/Mem2Reg/2003-04-10-DFNotFound.ll Message-ID: <200304101921.OAA28975@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/Mem2Reg: 2003-04-10-DFNotFound.ll added (r1.1) --- Log message: New testcase --- Diffs of the changes: From lattner at cs.uiuc.edu Thu Apr 10 14:42:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Apr 10 14:42:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp Message-ID: <200304101941.OAA29682@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: PromoteMemoryToRegister.cpp updated: 1.36 -> 1.37 --- Log message: * Fix bug: Mem2Reg/2003-04-10-DFNotFound.ll * Make Mem2Reg assign version numbers now for renamed variables instead of .mem2reg suffixes. This produces what people think of as SSA. --- Diffs of the changes: Index: llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp diff -u llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp:1.36 llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp:1.37 --- llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp:1.36 Mon Mar 3 11:25:18 2003 +++ llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp Thu Apr 10 14:41:13 2003 @@ -24,6 +24,7 @@ #include "llvm/Function.h" #include "llvm/Constant.h" #include "llvm/Type.h" +#include "Support/StringExtras.h" /// isAllocaPromotable - Return true if this alloca is legal for promotion. /// This is true if there are only loads and stores to the alloca... @@ -50,6 +51,7 @@ namespace { struct PromoteMem2Reg { const std::vector &Allocas; // the alloca instructions.. + std::vector VersionNumbers; // Current version counters DominanceFrontier &DF; const TargetData &TD; @@ -84,6 +86,7 @@ if (Allocas.empty()) return; Function &F = *DF.getRoot()->getParent(); + VersionNumbers.resize(Allocas.size()); for (unsigned i = 0, e = Allocas.size(); i != e; ++i) { assert(isAllocaPromotable(Allocas[i], TD) && @@ -118,19 +121,23 @@ for (unsigned j = 0; j != WriteSets[i].size(); j++) { // Look up the DF for this write, add it to PhiNodes DominanceFrontier::const_iterator it = DF.find(WriteSets[i][j]); - DominanceFrontier::DomSetType S = it->second; - for (DominanceFrontier::DomSetType::iterator P = S.begin(), PE = S.end(); - P != PE; ++P) - QueuePhiNode(*P, i); + if (it != DF.end()) { + const DominanceFrontier::DomSetType &S = it->second; + for (DominanceFrontier::DomSetType::iterator P = S.begin(),PE = S.end(); + P != PE; ++P) + QueuePhiNode(*P, i); + } } // Perform iterative step for (unsigned k = 0; k != PhiNodes[i].size(); k++) { DominanceFrontier::const_iterator it = DF.find(PhiNodes[i][k]); - DominanceFrontier::DomSetType S = it->second; - for (DominanceFrontier::DomSetType::iterator P = S.begin(), PE = S.end(); - P != PE; ++P) - QueuePhiNode(*P, i); + if (it != DF.end()) { + const DominanceFrontier::DomSetType &S = it->second; + for (DominanceFrontier::DomSetType::iterator P = S.begin(),PE = S.end(); + P != PE; ++P) + QueuePhiNode(*P, i); + } } } @@ -154,6 +161,15 @@ Instruction *I = KillList.back(); KillList.pop_back(); + // If there are any uses of these instructions left, they must be in + // sections of dead code that were not processed on the dominance frontier. + // Just delete the users now. + // + while (!I->use_empty()) { + Instruction *U = cast(I->use_back()); + U->getParent()->getInstList().erase(U); + } + I->getParent()->getInstList().erase(I); } } @@ -173,7 +189,8 @@ // Create a PhiNode using the dereferenced type... and add the phi-node to the // BasicBlock PHINode *PN = new PHINode(Allocas[AllocaNo]->getAllocatedType(), - Allocas[AllocaNo]->getName()+".mem2reg", + Allocas[AllocaNo]->getName() + "." + + utostr(VersionNumbers[AllocaNo]++), BB->begin()); BBPNs[AllocaNo] = PN; PhiNodes[AllocaNo].push_back(BB); From jstanley at cs.uiuc.edu Thu Apr 10 15:32:01 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Thu Apr 10 15:32:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/BinInterface/bitmath.h sparc9.h Message-ID: <200304102033.PAA28357@cypher.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/BinInterface: bitmath.h updated: 1.6 -> 1.7 sparc9.h updated: 1.10 -> 1.11 --- Log message: --- Diffs of the changes: Index: llvm/lib/Reoptimizer/BinInterface/bitmath.h diff -u llvm/lib/Reoptimizer/BinInterface/bitmath.h:1.6 llvm/lib/Reoptimizer/BinInterface/bitmath.h:1.7 --- llvm/lib/Reoptimizer/BinInterface/bitmath.h:1.6 Thu Apr 10 00:33:56 2003 +++ llvm/lib/Reoptimizer/BinInterface/bitmath.h Thu Apr 10 15:32:49 2003 @@ -32,7 +32,7 @@ //********************************* #define FLD_UPPER(FLD_DEF) (1 ? FLD_DEF) #define FLD_LOWER(FLD_DEF) (0 ? FLD_DEF) -#define MASKBELOW(V) ((1 << V) - 1) +#define MASKBELOW(V) ((((uint64_t) 1) << V) - 1) // 64-bit '1' constant here to avoid overflow warnings #define MASKEQBELOW(V) ((1 << V) | MASKBELOW(V)) //masks off everything ABOVE #define RD_FLD(x, FLD) ((x & MASKEQBELOW(FLD_UPPER(FLD))) >> FLD_LOWER(FLD)) #define MK_FLD(FLD, val) ((val << FLD_LOWER(FLD)) & MASKEQBELOW(FLD_UPPER(FLD))) Index: llvm/lib/Reoptimizer/BinInterface/sparc9.h diff -u llvm/lib/Reoptimizer/BinInterface/sparc9.h:1.10 llvm/lib/Reoptimizer/BinInterface/sparc9.h:1.11 --- llvm/lib/Reoptimizer/BinInterface/sparc9.h:1.10 Thu Apr 10 00:33:56 2003 +++ llvm/lib/Reoptimizer/BinInterface/sparc9.h Thu Apr 10 15:32:49 2003 @@ -395,18 +395,24 @@ MK_FLD(INSTR_I, 1) | \ MK_FLD(INSTR_OP3, OP3_ADD)) -// Many of these macros can generate 'integer overflow in expression' warnings in some -// cases (e.g., passing a numeric literal for an immediate field), and the root cause has -// not yet been determined. FIXME. - // Construct immediate-valued logical operation -#define MK_LOGIC_IMM(op3, dreg, sreg, imm) \ - (MK_FLD(INSTR_OP, OP_2) | \ - MK_FLD(INSTR_RD, dreg) | \ - MK_FLD(INSTR_RS1, sreg) | \ - MK_FLD(INSTR_SIMM13, imm) | \ - MK_FLD(INSTR_I, 1) | \ +#define MK_LOGIC_IMM(op3, dreg, sreg, imm) \ + (MK_FLD(INSTR_OP, OP_2) | \ + MK_FLD(INSTR_RD, dreg) | \ + MK_FLD(INSTR_RS1, sreg) | \ + MK_FLD(INSTR_SIMM13, imm) | \ + MK_FLD(INSTR_I, 1) | \ + MK_FLD(INSTR_OP3, op3)) + +// Construct reg-to-reg logical operation + +#define MK_LOGIC(op3, dreg, sreg1, sreg2) \ + (MK_FLD(INSTR_OP, OP_2) | \ + MK_FLD(INSTR_RD, dreg) | \ + MK_FLD(INSTR_RS1, sreg1) | \ + MK_FLD(INSTR_RS2, sreg2) | \ + MK_FLD(INSTR_I, 0) | \ MK_FLD(INSTR_OP3, op3)) // Construct sethi instruction From jstanley at cs.uiuc.edu Thu Apr 10 15:32:04 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Thu Apr 10 15:32:04 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/Inst/InstManip.cpp InstManip.h Message-ID: <200304102033.PAA28370@cypher.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/Inst: InstManip.cpp updated: 1.2 -> 1.3 InstManip.h updated: 1.2 -> 1.3 --- Log message: Now uses BinInterface macros for instruction-word generation. --- Diffs of the changes: Index: llvm/lib/Reoptimizer/Inst/InstManip.cpp diff -u llvm/lib/Reoptimizer/Inst/InstManip.cpp:1.2 llvm/lib/Reoptimizer/Inst/InstManip.cpp:1.3 --- llvm/lib/Reoptimizer/Inst/InstManip.cpp:1.2 Thu Apr 10 00:35:02 2003 +++ llvm/lib/Reoptimizer/Inst/InstManip.cpp Thu Apr 10 15:33:31 2003 @@ -42,18 +42,43 @@ std::vector& snippet, TargetRegister reg) const { - // Using %o0 and %o1, load the 64-bit value 'value' into %o0. The sequence of - // instructions to do this is placed in the provided instruction vector 'snippet'. + // 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. + // The sequence of instructions is placed into the provided instruction vector. unsigned initSize = snippet.size(); + unsigned destReg, tmpReg; + switch(reg) { + case REG_0: + destReg = R_O0; + tmpReg = R_O1; + break; + case REG_1: + destReg = R_O1; + tmpReg = R_O2; + break; + default: + assert(0 && "Invalid destination register"); + } - snippet.push_back(0x11000000 | HIGH22(HIGHWORD(value))); // sethi (upper 22b of upper wrd), %o0 - snippet.push_back(0x90122000 | LOW10(HIGHWORD(value))); // or %o0, (lower 10b of upper wrd), %o0 - snippet.push_back(0x912a3020); // sllx %o0, 32, %o0 - snippet.push_back(0x13000000 | HIGH22(LOWWORD(value))); // sethi (upper 22b of lwr wrd), %o1 - snippet.push_back(0x90120009); // or %o0, %o1, %o0 - snippet.push_back(0x90022000 | LOW10(LOWWORD(value))); // add %o0, (lwr 10b of lwr wrd), %o0 + // sethi (upper 22b of upper wrd), %o0 + snippet.push_back(MK_SETHI(destReg, HIGH22(HIGHWORD(value)))); + + // or %o0, (lower 10b of upper wrd), %o0 + snippet.push_back(MK_LOGIC_IMM(OP3_OR, destReg, destReg, LOW10(HIGHWORD(value)))); + + // sllx %o0, 32, %o0 + snippet.push_back(MK_SHIFTX(OP3_SLL, destReg, destReg, 32)); + + // sethi (upper 22b of lwr wrd), %o1 + snippet.push_back(MK_SETHI(tmpReg, HIGH22(LOWWORD(value)))); + + // or %o0, %o1, %o0 + snippet.push_back(MK_LOGIC(OP3_OR, destReg, destReg, tmpReg)); + + // 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() && - "Unexpected number of instructions in code sequence for 64-bit value -> %o0"); + "Unexpected number of instructions in code sequence for 64-bit value -> %destReg"); } Index: llvm/lib/Reoptimizer/Inst/InstManip.h diff -u llvm/lib/Reoptimizer/Inst/InstManip.h:1.2 llvm/lib/Reoptimizer/Inst/InstManip.h:1.3 --- llvm/lib/Reoptimizer/Inst/InstManip.h:1.2 Thu Apr 10 00:35:03 2003 +++ llvm/lib/Reoptimizer/Inst/InstManip.h Thu Apr 10 15:33:32 2003 @@ -43,9 +43,6 @@ unsigned getGenLoad64Size() const { return 6; } private: - //////////////// - // Instruction constants and field-extraction "macros", etc. - // Branch-always (annul bit high) instruction base (i.e. address not filled in yet) static const unsigned BRANCH_ALWAYS_BASE = 0x30480000; }; From brukman at cs.uiuc.edu Thu Apr 10 16:26:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Thu Apr 10 16:26:01 2003 Subject: [llvm-commits] CVS: CVSROOT/commit-diffs.pl Message-ID: <200304102125.QAA11419@neo.cs.uiuc.edu> Changes in directory CVSROOT: commit-diffs.pl updated: 1.31 -> 1.32 --- Log message: * Display contents of new-ly added files (ie. diff with /dev/null :) * Converted tabs to spaces. --- Diffs of the changes: Index: CVSROOT/commit-diffs.pl diff -u CVSROOT/commit-diffs.pl:1.31 CVSROOT/commit-diffs.pl:1.32 --- CVSROOT/commit-diffs.pl:1.31 Tue Oct 1 18:06:18 2002 +++ CVSROOT/commit-diffs.pl Thu Apr 10 16:25:08 2003 @@ -14,13 +14,10 @@ # The mail sent includes change summary, log message and a unidiff # about the changes. -# The original author of this script is Jouni Heikniemi -# Feel free to do whatever you wish with this. -# The home page of this script is -# . - -# -# This script was hacked by Misha & Chris to work under unix +# Original author: Jouni Heikniemi +# This script was improved by Misha & Chris: +# * Hacked to work under Unix +# * ...? # ###################################################################### @@ -30,19 +27,19 @@ # those to a hash and returns a ref to it. sub createChangeItem($) { #($) - my @arr = split(',', shift); - my %change; - $change{'filename'} = $arr[0]; - $change{'oldrev'} = $arr[1]; - $change{'newrev'} = $arr[2]; - if ($arr[1] eq 'NONE') { - $change{'type'} = 'add'; - } elsif ($arr[2] eq 'NONE') { - $change{'type'} = 'rm'; - } else { - $change{'type'} = 'c'; - } - return \%change; + my @arr = split(',', shift); + my %change; + $change{'filename'} = $arr[0]; + $change{'oldrev'} = $arr[1]; + $change{'newrev'} = $arr[2]; + if ($arr[1] eq 'NONE') { + $change{'type'} = 'add'; + } elsif ($arr[2] eq 'NONE') { + $change{'type'} = 'rm'; + } else { + $change{'type'} = 'c'; + } + return \%change; } ## Main code: @@ -91,15 +88,15 @@ my $islogmessage = 0; foreach $s (@loginfodata) { - if ($islogmessage) { - @logmessage = (@logmessage, $s); - next; - } - - if ($s =~ /^Log Message:/) { - $islogmessage = 1; - next; - } + if ($islogmessage) { + @logmessage = (@logmessage, $s); + next; + } + + if ($s =~ /^Log Message:/) { + $islogmessage = 1; + next; + } } # Format the output @@ -109,15 +106,16 @@ my $subject = "$changedir/"; foreach $m (@changeItems) { - $subject .= "$m->{'filename'} "; - if ($m->{'type'} eq 'add') { - $msg .= "$m->{'filename'} added (r$m->{'newrev'})\n"; - } elsif ($m->{'type'} eq 'rm') { - $msg .= "$m->{'filename'} (r$m->{'oldrev'}) removed\n"; - } else { - $msg .= "$m->{'filename'} updated: $m->{'oldrev'} -> $m->{'newrev'}\n"; - $diffs .= `cvs -Qf rdiff -u -r $m->{'oldrev'} -r $m->{'newrev'} $changedir/$m->{'filename'} 2> /dev/null` . "\n\n"; - } + $subject .= "$m->{'filename'} "; + if ($m->{'type'} eq 'add') { + $msg .= "$m->{'filename'} added (r$m->{'newrev'})\n"; + $diffs .= `cat $changedir/$m->{'filename'}; 2> /dev/null` . "\n\n"; + } elsif ($m->{'type'} eq 'rm') { + $msg .= "$m->{'filename'} (r$m->{'oldrev'}) removed\n"; + } else { + $msg .= "$m->{'filename'} updated: $m->{'oldrev'} -> $m->{'newrev'}\n"; + $diffs .= `cvs -Qf rdiff -u -r $m->{'oldrev'} -r $m->{'newrev'} $changedir/$m->{'filename'} 2> /dev/null` . "\n\n"; + } } $msg .= "\n---\nLog message:\n\n" . join('', at logmessage); $msg .= "\n---\nDiffs of the changes:\n\n" . $diffs; From brukman at cs.uiuc.edu Thu Apr 10 16:44:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Thu Apr 10 16:44:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/ModuloSched/ Message-ID: <200304102143.QAA01696@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/ModuloSched: --- Log message: Directory /home/vadve/vadve/Research/DynOpt/CVSRepository/llvm/test/Regression/Transforms/ModuloSched added to the repository --- Diffs of the changes: From brukman at cs.uiuc.edu Thu Apr 10 16:45:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Thu Apr 10 16:45:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/ModuloSched/for-array.c Message-ID: <200304102144.QAA01711@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/ModuloSched: for-array.c added (r1.1) --- Log message: Not only is this the first test case for ModuloScheduing, it's also the first test case for the CVS commit-diffs.pl script which should show the entire contents of this file below: --- Diffs of the changes: From brukman at cs.uiuc.edu Thu Apr 10 16:48:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Thu Apr 10 16:48:01 2003 Subject: [llvm-commits] CVS: CVSROOT/commit-diffs.pl Message-ID: <200304102147.QAA01730@apoc.cs.uiuc.edu> Changes in directory CVSROOT: commit-diffs.pl updated: 1.32 -> 1.33 --- Log message: Removed extraneous semicolon in the command to show contents of newly added files. --- Diffs of the changes: Index: CVSROOT/commit-diffs.pl diff -u CVSROOT/commit-diffs.pl:1.32 CVSROOT/commit-diffs.pl:1.33 --- CVSROOT/commit-diffs.pl:1.32 Thu Apr 10 16:25:08 2003 +++ CVSROOT/commit-diffs.pl Thu Apr 10 16:47:03 2003 @@ -109,7 +109,7 @@ $subject .= "$m->{'filename'} "; if ($m->{'type'} eq 'add') { $msg .= "$m->{'filename'} added (r$m->{'newrev'})\n"; - $diffs .= `cat $changedir/$m->{'filename'}; 2> /dev/null` . "\n\n"; + $diffs .= `cat $changedir/$m->{'filename'} 2> /dev/null` . "\n\n"; } elsif ($m->{'type'} eq 'rm') { $msg .= "$m->{'filename'} (r$m->{'oldrev'}) removed\n"; } else { From brukman at cs.uiuc.edu Thu Apr 10 16:50:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Thu Apr 10 16:50:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/ModuloSched/array-simple.c Message-ID: <200304102149.QAA01767@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/ModuloSched: array-simple.c added (r1.1) --- Log message: Adding a simple test case in the hope that commit-diffs.pl will pick this up. --- Diffs of the changes: From brukman at cs.uiuc.edu Thu Apr 10 16:56:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Thu Apr 10 16:56:01 2003 Subject: [llvm-commits] CVS: CVSROOT/commit-diffs.pl Message-ID: <200304102155.QAA02274@apoc.cs.uiuc.edu> Changes in directory CVSROOT: commit-diffs.pl updated: 1.33 -> 1.34 --- Log message: Hopefully this will now correctly show the contents of new files (take #3). --- Diffs of the changes: Index: CVSROOT/commit-diffs.pl diff -u CVSROOT/commit-diffs.pl:1.33 CVSROOT/commit-diffs.pl:1.34 --- CVSROOT/commit-diffs.pl:1.33 Thu Apr 10 16:47:03 2003 +++ CVSROOT/commit-diffs.pl Thu Apr 10 16:55:41 2003 @@ -109,7 +109,7 @@ $subject .= "$m->{'filename'} "; if ($m->{'type'} eq 'add') { $msg .= "$m->{'filename'} added (r$m->{'newrev'})\n"; - $diffs .= `cat $changedir/$m->{'filename'} 2> /dev/null` . "\n\n"; + $diffs .= `cvs -Qf rdiff -r0 -r1.1 $changedir/$m->{'filename'} 2> /dev/null` . "\n\n"; } elsif ($m->{'type'} eq 'rm') { $msg .= "$m->{'filename'} (r$m->{'oldrev'}) removed\n"; } else { From brukman at cs.uiuc.edu Thu Apr 10 17:02:00 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Thu Apr 10 17:02:00 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/ModuloSched/arith-simple.c Message-ID: <200304102201.RAA02644@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/ModuloSched: arith-simple.c added (r1.1) --- Log message: Simple arithmetic loop-based test case for modulo scheduling. --- Diffs of the changes: Index: llvm/test/Regression/Transforms/ModuloSched/arith-simple.c diff -c /dev/null llvm/test/Regression/Transforms/ModuloSched/arith-simple.c:1.1 *** /dev/null Thu Apr 10 17:01:25 2003 --- llvm/test/Regression/Transforms/ModuloSched/arith-simple.c Thu Apr 10 17:01:15 2003 *************** *** 0 **** --- 1,18 ---- + #include + + int main (int argc, char** argv) { + int a, b, c, d, i; + + a = b = c = d = 1; + + for (i=0; i < 15; i++) { + a = b + c; + c = d - b; + d = a + b; + b = c + i; + } + + printf("a = %d, b = %d, c = %d, d = %d\n", a, b, c, d); + + return 0; + } From jstanley at cs.uiuc.edu Thu Apr 10 17:33:00 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Thu Apr 10 17:33:00 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/Inst/Phase2.cpp design.txt Message-ID: <200304102234.RAA28623@cypher.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/Inst: Phase2.cpp updated: 1.5 -> 1.6 design.txt updated: 1.7 -> 1.8 --- Log message: --- Diffs of the changes: Index: llvm/lib/Reoptimizer/Inst/Phase2.cpp diff -u llvm/lib/Reoptimizer/Inst/Phase2.cpp:1.5 llvm/lib/Reoptimizer/Inst/Phase2.cpp:1.6 --- llvm/lib/Reoptimizer/Inst/Phase2.cpp:1.5 Thu Apr 10 00:35:03 2003 +++ llvm/lib/Reoptimizer/Inst/Phase2.cpp Thu Apr 10 17:34:16 2003 @@ -6,27 +6,20 @@ // // On program startup ("phase 2" function called from main()): // -// 0. Read the neccessary ELF data associated with the executable image. -// 1. Build a starting-addres-to-function-extent map for use by later phases. +// 1. Read the neccessary ELF data associated with the executable image. // -// 2. For each function F (only in text segment preferably), setup phase 3 branches. +// 2. For each function F (only in text segment preferably), write code to call phase 3. // -// Approach A: -// // 2a. Replace the first instruction in F with a branch to a new slot in the // dummy function. // -// 2b. At the new slot write first the (replaced) first instruction in F, -// followed by code to call the phase 3 function with the address of F as an -// argument. -// -// Approach B: -// -// 2a. Save the first number instructions in an F -> [instructions] record of -// some kind. Phase 3 will restore them later +// 2b. Obtain a heap region to write the phase 3 call into. // -// 2b. Over the top of the original instructions (now saved), write a call to -// phase 3, passing the address of F as an argument. +// 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. +// +// 2d. Write code to call phase 3 into the heap region, etc. +// #include #include Index: llvm/lib/Reoptimizer/Inst/design.txt diff -u llvm/lib/Reoptimizer/Inst/design.txt:1.7 llvm/lib/Reoptimizer/Inst/design.txt:1.8 --- llvm/lib/Reoptimizer/Inst/design.txt:1.7 Thu Apr 10 00:35:03 2003 +++ llvm/lib/Reoptimizer/Inst/design.txt Thu Apr 10 17:34:16 2003 @@ -745,9 +745,8 @@ there, and then, in the heap-allocated memory write the actual code to do the instrumentation, etc, etc. -- Rewrite instruction building mechanisms are general BinInterface macros. Blech. - }}} + {{{ IMPLEMENTATION SKETCH {{{ Current implementation sketch: From jstanley at cs.uiuc.edu Thu Apr 10 17:35:00 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Thu Apr 10 17:35:00 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/Inst/Phase2.cpp Message-ID: <200304102236.RAA28645@cypher.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/Inst: Phase2.cpp (r1.6) removed --- Log message: Renamed Phase2.cpp -> Phases.cpp --- Diffs of the changes: From jstanley at cs.uiuc.edu Thu Apr 10 17:45:01 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Thu Apr 10 17:45:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/TraceCache/MemoryManager.h Message-ID: <200304102246.RAA28776@cypher.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/TraceCache: MemoryManager.h (r1.2) removed --- Log message: Moved lib/Reoptimizer/TraceCache/MemoryManager.h -> include/llvm/Reoptimizer/MemoryManager.h --- Diffs of the changes: From jstanley at cs.uiuc.edu Thu Apr 10 17:48:01 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Thu Apr 10 17:48:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/TraceCache/MemoryManager.cpp TraceCache.cpp Message-ID: <200304102249.RAA28928@cypher.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/TraceCache: MemoryManager.cpp updated: 1.4 -> 1.5 TraceCache.cpp updated: 1.10 -> 1.11 --- Log message: Changed inclusion of MemoryManager.h to reflect move to include directory. --- Diffs of the changes: Index: llvm/lib/Reoptimizer/TraceCache/MemoryManager.cpp diff -u llvm/lib/Reoptimizer/TraceCache/MemoryManager.cpp:1.4 llvm/lib/Reoptimizer/TraceCache/MemoryManager.cpp:1.5 --- llvm/lib/Reoptimizer/TraceCache/MemoryManager.cpp:1.4 Wed Feb 19 13:19:11 2003 +++ llvm/lib/Reoptimizer/TraceCache/MemoryManager.cpp Thu Apr 10 17:49:24 2003 @@ -23,7 +23,7 @@ // //===----------------------------------------------------------------------===// -#include "MemoryManager.h" +#include "llvm/Reoptimizer/MemoryManager.h" #include #include Index: llvm/lib/Reoptimizer/TraceCache/TraceCache.cpp diff -u llvm/lib/Reoptimizer/TraceCache/TraceCache.cpp:1.10 llvm/lib/Reoptimizer/TraceCache/TraceCache.cpp:1.11 --- llvm/lib/Reoptimizer/TraceCache/TraceCache.cpp:1.10 Fri Apr 4 14:28:01 2003 +++ llvm/lib/Reoptimizer/TraceCache/TraceCache.cpp Thu Apr 10 17:49:24 2003 @@ -17,7 +17,7 @@ // //===----------------------------------------------------------------------===// -#include "MemoryManager.h" +#include "llvm/Reoptimizer/MemoryManager.h" #include "llvm/Reoptimizer/TraceCache.h" #include "llvm/Reoptimizer/VirtualMem.h" #include "llvm/Reoptimizer/InstrUtils.h" @@ -370,8 +370,6 @@ #undef GET_TRACE_TIME -//Do the following: -//1. Insert a jump at location instrAddr with target as new trace bool TraceCache::addTrace(uint64_t instAddr, int sz, int traceUniqId, uint64_t &addr){ From jstanley at cs.uiuc.edu Thu Apr 10 18:03:01 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Thu Apr 10 18:03:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/BinInterface/bitmath.h sparc9.h sparcdis.h Message-ID: <200304102304.SAA29046@cypher.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/BinInterface: bitmath.h (r1.7) removed sparc9.h (r1.11) removed sparcdis.h (r1.5) removed --- Log message: Moved: lib/Reoptimizer/BinInterface/bitmath.h --> include/llvm/Reoptimizer/BinInterface/bitmath.h lib/Reoptimizer/BinInterface/sparc9.h --> include/llvm/Reoptimizer/BinInterface/sparc9.h lib/Reoptimizer/BinInterface/sparcdis.h --> include/llvm/Reoptimizer/BinInterface/sparcdis.h --- Diffs of the changes: From jstanley at cs.uiuc.edu Thu Apr 10 18:12:01 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Thu Apr 10 18:12:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/BinInterface/analyze.cpp construct.cpp emit.cpp regmask.h salloc.cpp select.cpp sparc9.cpp sparcbin.cpp sparcdis.cpp test.cpp Message-ID: <200304102312.SAA29648@cypher.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/BinInterface: analyze.cpp updated: 1.7 -> 1.8 construct.cpp updated: 1.2 -> 1.3 emit.cpp updated: 1.2 -> 1.3 regmask.h updated: 1.2 -> 1.3 salloc.cpp updated: 1.3 -> 1.4 select.cpp updated: 1.2 -> 1.3 sparc9.cpp updated: 1.3 -> 1.4 sparcbin.cpp updated: 1.3 -> 1.4 sparcdis.cpp updated: 1.7 -> 1.8 test.cpp updated: 1.2 -> 1.3 --- Log message: Changed source to reflect movement of {bitmath,sparc9,sparcdis}.h to include directory. --- Diffs of the changes: Index: llvm/lib/Reoptimizer/BinInterface/analyze.cpp diff -u llvm/lib/Reoptimizer/BinInterface/analyze.cpp:1.7 llvm/lib/Reoptimizer/BinInterface/analyze.cpp:1.8 --- llvm/lib/Reoptimizer/BinInterface/analyze.cpp:1.7 Sun Dec 15 05:06:55 2002 +++ llvm/lib/Reoptimizer/BinInterface/analyze.cpp Thu Apr 10 18:12:35 2003 @@ -17,9 +17,9 @@ #include #include -#include "sparc9.h" // SPARC 9 opcode and field definitions -#include "bitmath.h" // Binary arithmatic library -#include "analyze.h" // Defintion of analysis interface +#include "llvm/Reoptimizer/BinInterface/sparc9.h" // SPARC 9 opcode and field definitions +#include "llvm/Reoptimizer/BinInterface/bitmath.h" // Binary arithmetic library +#include "analyze.h" // Defintion of analysis interface #include //***************************************************************************** Index: llvm/lib/Reoptimizer/BinInterface/construct.cpp diff -u llvm/lib/Reoptimizer/BinInterface/construct.cpp:1.2 llvm/lib/Reoptimizer/BinInterface/construct.cpp:1.3 --- llvm/lib/Reoptimizer/BinInterface/construct.cpp:1.2 Sun Dec 15 05:07:11 2002 +++ llvm/lib/Reoptimizer/BinInterface/construct.cpp Thu Apr 10 18:12:35 2003 @@ -16,10 +16,11 @@ #include "analyze.h" // SPARC analysis library #include "sparcbin.h" // Prototype for this class #include "sparcpriv.h" // Private definitions -#include "sparcdis.h" // prototype for sparc disassembler -#include "bitmath.h" // header of optimized binary math routines -#include "sparc9.h" // SPARC 9 opcode definitions #include "regmask.h" // the register mask allocator + +#include "llvm/Reoptimizer/BinInterface/sparcdis.h" // prototype for sparc disassembler +#include "llvm/Reoptimizer/BinInterface/bitmath.h" // header of optimized binary math routines +#include "llvm/Reoptimizer/BinInterface/sparc9.h" // SPARC 9 opcode definitions #include using std::pair; // use STL pair class Index: llvm/lib/Reoptimizer/BinInterface/emit.cpp diff -u llvm/lib/Reoptimizer/BinInterface/emit.cpp:1.2 llvm/lib/Reoptimizer/BinInterface/emit.cpp:1.3 --- llvm/lib/Reoptimizer/BinInterface/emit.cpp:1.2 Sun Dec 15 05:07:16 2002 +++ llvm/lib/Reoptimizer/BinInterface/emit.cpp Thu Apr 10 18:12:35 2003 @@ -16,10 +16,11 @@ #include "analyze.h" // SPARC analysis library #include "sparcbin.h" // Prototype for this class #include "sparcpriv.h" // Private definitions -#include "sparcdis.h" // prototype for sparc disassembler -#include "bitmath.h" // header of optimized binary math routines -#include "sparc9.h" // SPARC 9 opcode definitions #include "regmask.h" // Register mask allocator + +#include "llvm/Reoptimizer/BinInterface/sparcdis.h" // prototype for sparc disassembler +#include "llvm/Reoptimizer/BinInterface/bitmath.h" // header of optimized binary math routines +#include "llvm/Reoptimizer/BinInterface/sparc9.h" // SPARC 9 opcode definitions #include // Use STL pair class using std::pair; Index: llvm/lib/Reoptimizer/BinInterface/regmask.h diff -u llvm/lib/Reoptimizer/BinInterface/regmask.h:1.2 llvm/lib/Reoptimizer/BinInterface/regmask.h:1.3 --- llvm/lib/Reoptimizer/BinInterface/regmask.h:1.2 Sun Dec 15 05:07:22 2002 +++ llvm/lib/Reoptimizer/BinInterface/regmask.h Thu Apr 10 18:12:35 2003 @@ -11,7 +11,7 @@ #ifndef __REGMASK_H__ #define __REGMASK_H__ -#include "bitmath.h" +#include "llvm/Reoptimizer/BinInterface/bitmath.h" #define VREG_ISMEM(x) (x >= 32) #define VREG_ISREG(x) (x < 32) Index: llvm/lib/Reoptimizer/BinInterface/salloc.cpp diff -u llvm/lib/Reoptimizer/BinInterface/salloc.cpp:1.3 llvm/lib/Reoptimizer/BinInterface/salloc.cpp:1.4 --- llvm/lib/Reoptimizer/BinInterface/salloc.cpp:1.3 Sun Dec 15 05:07:24 2002 +++ llvm/lib/Reoptimizer/BinInterface/salloc.cpp Thu Apr 10 18:12:35 2003 @@ -8,7 +8,7 @@ #include #include "salloc.h" -#include "bitmath.h" +#include "llvm/Reoptimizer/BinInterface/bitmath.h" #include #include #include Index: llvm/lib/Reoptimizer/BinInterface/select.cpp diff -u llvm/lib/Reoptimizer/BinInterface/select.cpp:1.2 llvm/lib/Reoptimizer/BinInterface/select.cpp:1.3 --- llvm/lib/Reoptimizer/BinInterface/select.cpp:1.2 Sun Dec 15 05:07:29 2002 +++ llvm/lib/Reoptimizer/BinInterface/select.cpp Thu Apr 10 18:12:35 2003 @@ -18,10 +18,11 @@ #include "analyze.h" // SPARC analysis library #include "sparcbin.h" // Prototype for this class #include "sparcpriv.h" // Private definitions -#include "sparcdis.h" // prototype for sparc disassembler -#include "bitmath.h" // header of optimized binary math routines -#include "sparc9.h" // SPARC 9 opcode definitions #include "regmask.h" // Register mask allocator + +#include "llvm/Reoptimizer/BinInterface/sparcdis.h" // prototype for sparc disassembler +#include "llvm/Reoptimizer/BinInterface/bitmath.h" // header of optimized binary math routines +#include "llvm/Reoptimizer/BinInterface/sparc9.h" // SPARC 9 opcode definitions #include // Use STL pair class using std::pair; Index: llvm/lib/Reoptimizer/BinInterface/sparc9.cpp diff -u llvm/lib/Reoptimizer/BinInterface/sparc9.cpp:1.3 llvm/lib/Reoptimizer/BinInterface/sparc9.cpp:1.4 --- llvm/lib/Reoptimizer/BinInterface/sparc9.cpp:1.3 Tue Apr 1 16:13:35 2003 +++ llvm/lib/Reoptimizer/BinInterface/sparc9.cpp Thu Apr 10 18:12:35 2003 @@ -7,7 +7,7 @@ // 2002 Cameron Buschardt //***************************************************************************** -#include "sparc9.h" +#include "llvm/Reoptimizer/BinInterface/sparc9.h" char * cc_names[] = { "fcc0", "fcc1", "fcc2", "fcc3", Index: llvm/lib/Reoptimizer/BinInterface/sparcbin.cpp diff -u llvm/lib/Reoptimizer/BinInterface/sparcbin.cpp:1.3 llvm/lib/Reoptimizer/BinInterface/sparcbin.cpp:1.4 --- llvm/lib/Reoptimizer/BinInterface/sparcbin.cpp:1.3 Sun Dec 15 05:07:37 2002 +++ llvm/lib/Reoptimizer/BinInterface/sparcbin.cpp Thu Apr 10 18:12:35 2003 @@ -24,9 +24,10 @@ #include "analyze.h" // SPARC analysis library #include "sparcbin.h" // Prototype for this class #include "sparcpriv.h" // Private definitions -#include "sparcdis.h" // prototype for sparc disassembler -#include "bitmath.h" // header of optimized binary math routines -#include "sparc9.h" // SPARC 9 opcode definitions + +#include "llvm/Reoptimizer/BinInterface/sparcdis.h" // prototype for sparc disassembler +#include "llvm/Reoptimizer/BinInterface/bitmath.h" // header of optimized binary math routines +#include "llvm/Reoptimizer/BinInterface/sparc9.h" // SPARC 9 opcode definitions #include // Bring in STL pair class using std::pair; Index: llvm/lib/Reoptimizer/BinInterface/sparcdis.cpp diff -u llvm/lib/Reoptimizer/BinInterface/sparcdis.cpp:1.7 llvm/lib/Reoptimizer/BinInterface/sparcdis.cpp:1.8 --- llvm/lib/Reoptimizer/BinInterface/sparcdis.cpp:1.7 Tue Apr 1 16:13:35 2003 +++ llvm/lib/Reoptimizer/BinInterface/sparcdis.cpp Thu Apr 10 18:12:35 2003 @@ -22,8 +22,8 @@ #include #include -#include "sparc9.h" // SPARC 9 definitions -#include "bitmath.h" +#include "llvm/Reoptimizer/BinInterface/sparc9.h" // SPARC 9 definitions +#include "llvm/Reoptimizer/BinInterface/bitmath.h" #include void sparc_printop_rs1(unsigned instr, int labelrs1) Index: llvm/lib/Reoptimizer/BinInterface/test.cpp diff -u llvm/lib/Reoptimizer/BinInterface/test.cpp:1.2 llvm/lib/Reoptimizer/BinInterface/test.cpp:1.3 --- llvm/lib/Reoptimizer/BinInterface/test.cpp:1.2 Sun Dec 15 05:07:48 2002 +++ llvm/lib/Reoptimizer/BinInterface/test.cpp Thu Apr 10 18:12:35 2003 @@ -8,13 +8,12 @@ #include #include -#include "sparc9.h" #include "analyze.h" -#include "sparcdis.h" +#include "llvm/Reoptimizer/BinInterface/sparcdis.h" #include -#include "sparc9.h" -#include "bitmath.h" +#include "llvm/Reoptimizer/BinInterface/sparc9.h" +#include "llvm/Reoptimizer/BinInterface/bitmath.h" #include "sparcbin.h" #include "sparcpriv.h" // Private definitions From jstanley at cs.uiuc.edu Thu Apr 10 18:23:01 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Thu Apr 10 18:23:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/Inst/ElfReader.cpp InstManip.cpp InstManip.h Phases.cpp Message-ID: <200304102324.SAA29776@cypher.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/Inst: ElfReader.cpp updated: 1.3 -> 1.4 InstManip.cpp updated: 1.3 -> 1.4 InstManip.h updated: 1.3 -> 1.4 Phases.cpp updated: 1.6 -> 1.7 --- Log message: Changed source to reflect movement of {bitmath,sparc9,sparcdis}.h [BinInterface dependences] to include directory. --- Diffs of the changes: Index: llvm/lib/Reoptimizer/Inst/ElfReader.cpp diff -u llvm/lib/Reoptimizer/Inst/ElfReader.cpp:1.3 llvm/lib/Reoptimizer/Inst/ElfReader.cpp:1.4 --- llvm/lib/Reoptimizer/Inst/ElfReader.cpp:1.3 Tue Apr 8 22:35:57 2003 +++ llvm/lib/Reoptimizer/Inst/ElfReader.cpp Thu Apr 10 18:23:58 2003 @@ -6,8 +6,8 @@ // // TODO: // -// Replace the primitive read-and-raw-FD mechanism with C++-stream-based code. -// The version of libg++ we're using doesn't seem to have a mechanism for +// Replace the primitive raw-FD read()-based mechanism with C++-stream-based +// code. The version of libg++ we're using doesn't seem to have a mechanism for // obtaining the file descriptor associated with an open ifstream. (rdbuf() will // yield the file buffer object, but there's no way to get the associated file // and therefore the FD from that. :( Index: llvm/lib/Reoptimizer/Inst/InstManip.cpp diff -u llvm/lib/Reoptimizer/Inst/InstManip.cpp:1.3 llvm/lib/Reoptimizer/Inst/InstManip.cpp:1.4 --- llvm/lib/Reoptimizer/Inst/InstManip.cpp:1.3 Thu Apr 10 15:33:31 2003 +++ llvm/lib/Reoptimizer/Inst/InstManip.cpp Thu Apr 10 18:23:58 2003 @@ -7,8 +7,8 @@ #include #include #include "llvm/Reoptimizer/VirtualMem.h" -#include "../BinInterface/sparc9.h" // TODO: Move to proper include directory -#include "../BinInterface/bitmath.h" // TODO: Move to proper include directory +#include "llvm/Reoptimizer/BinInterface/sparc9.h" +#include "llvm/Reoptimizer/BinInterface/bitmath.h" #include "InstManip.h" void InstManip::printRange(unsigned* start, unsigned* end) const Index: llvm/lib/Reoptimizer/Inst/InstManip.h diff -u llvm/lib/Reoptimizer/Inst/InstManip.h:1.3 llvm/lib/Reoptimizer/Inst/InstManip.h:1.4 --- llvm/lib/Reoptimizer/Inst/InstManip.h:1.3 Thu Apr 10 15:33:32 2003 +++ llvm/lib/Reoptimizer/Inst/InstManip.h Thu Apr 10 18:23:58 2003 @@ -14,7 +14,7 @@ #define _INCLUDED_INSTMANIP_H #include -#include "../BinInterface/sparcdis.h" // TODO: Move to proper include directory +#include "llvm/Reoptimizer/BinInterface/sparcdis.h" #include "llvm/Reoptimizer/InstrUtils.h" class VirtualMem; Index: llvm/lib/Reoptimizer/Inst/Phases.cpp diff -u llvm/lib/Reoptimizer/Inst/Phases.cpp:1.6 llvm/lib/Reoptimizer/Inst/Phases.cpp:1.7 --- llvm/lib/Reoptimizer/Inst/Phases.cpp:1.6 Thu Apr 10 17:34:16 2003 +++ llvm/lib/Reoptimizer/Inst/Phases.cpp Thu Apr 10 18:23:58 2003 @@ -1,9 +1,11 @@ //////////////// // programmer: Joel Stanley // date: Fri Apr 4 16:59:48 CST 2003 -// fileid: Phase2.cpp -// purpose: Implements phase 2 of the peformance-oriented language extensions. +// fileid: Phases.cpp +// purpose: Implements various runtime phases of the peformance-oriented language +// extensions. // +// PHASE 2: // On program startup ("phase 2" function called from main()): // // 1. Read the neccessary ELF data associated with the executable image. @@ -20,6 +22,10 @@ // // 2d. Write code to call phase 3 into the heap region, etc. // +// PHASE 3: +// +// PHASE 4: +// #include #include @@ -28,7 +34,7 @@ #include "llvm/Reoptimizer/TraceCache.h" #include "llvm/Reoptimizer/VirtualMem.h" -#include "../TraceCache/MemoryManager.h" // TODO: Move to proper include directory +#include "llvm/Reoptimizer/MemoryManager.h" #include "ElfReader.h" #include "InstManip.h" From jstanley at cs.uiuc.edu Thu Apr 10 18:40:01 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Thu Apr 10 18:40:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/Inst/Phases.cpp Message-ID: <200304102341.SAA29868@cypher.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/Inst: Phases.cpp updated: 1.7 -> 1.8 --- Log message: Checkpoint before generating phase3 calls in heap regions. --- Diffs of the changes: Index: llvm/lib/Reoptimizer/Inst/Phases.cpp diff -u llvm/lib/Reoptimizer/Inst/Phases.cpp:1.7 llvm/lib/Reoptimizer/Inst/Phases.cpp:1.8 --- llvm/lib/Reoptimizer/Inst/Phases.cpp:1.7 Thu Apr 10 18:23:58 2003 +++ llvm/lib/Reoptimizer/Inst/Phases.cpp Thu Apr 10 18:40:49 2003 @@ -43,6 +43,8 @@ using std::cerr; using std::endl; +void phase3(uint64_t value); + // 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. @@ -90,13 +92,6 @@ cerr << "============================== End Phase 2 ==============================\n"; } -void phase3(uint64_t value) -{ - printf("phase3 called!\n"); - printf("value passed in is: %lx\n", value); - fflush(stdout); -} - void Phase2::transformFunction(std::pair& range) { //////////////// @@ -162,4 +157,11 @@ // ===> [size of code for loading 64-bit value] + 5 return m_instManip.getGenLoad64Size() + 5; +} + +void phase3(uint64_t value) +{ + printf("phase3 called!\n"); + printf("value passed in is: %lx\n", value); + fflush(stdout); } From jstanley at cs.uiuc.edu Fri Apr 11 00:21:01 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Fri Apr 11 00:21:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/Inst/InstManip.cpp InstManip.h Phases.cpp Message-ID: <200304110522.AAA00409@cypher.cs.uiuc.edu> 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& snippet, - TargetRegister reg) const +void InstManip::generateLoad(uint64_t value, + std::vector& 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& 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& 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 #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& snippet, - TargetRegister reg = REG_0) const; - + void generateLoad(uint64_t value, + std::vector& snippet, + TargetRegister reg = REG_0) const; + + void generateCall(uint64_t dest, + uint64_t slotBase, + std::vector& snippet); + + void generateBranchAlways(uint64_t dest, + uint64_t slotBase, + std::vector& 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 #include #include +#include #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 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& 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 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& range) + +static void copySnippetToSlot(vector& snippet, + uint64_t slotBase, + VirtualMem* vm, + InstManip* im) +{ + uint64_t currAddr = slotBase; + for(vector::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 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::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 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"; } From jstanley at cs.uiuc.edu Fri Apr 11 18:56:01 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Fri Apr 11 18:56:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/Inst/InstManip.cpp InstManip.h Phases.cpp Message-ID: <200304112357.SAA05525@cypher.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/Inst: InstManip.cpp updated: 1.5 -> 1.6 InstManip.h updated: 1.5 -> 1.6 Phases.cpp updated: 1.9 -> 1.10 --- Log message: Started load-candidate selection code, and phase3 is making its initial transformation. --- Diffs of the changes: Index: llvm/lib/Reoptimizer/Inst/InstManip.cpp diff -u llvm/lib/Reoptimizer/Inst/InstManip.cpp:1.5 llvm/lib/Reoptimizer/Inst/InstManip.cpp:1.6 --- llvm/lib/Reoptimizer/Inst/InstManip.cpp:1.5 Fri Apr 11 00:22:20 2003 +++ llvm/lib/Reoptimizer/Inst/InstManip.cpp Fri Apr 11 18:57:07 2003 @@ -13,30 +13,34 @@ const unsigned InstManip::NOP_INST = 0x01000000; +using std::cout; +using std::cerr; +using std::endl; + void InstManip::printRange(unsigned* start, unsigned* end) const { // Dumps contents (and corresponding disassembly) of memory range given by range // to stdout. TODO: Parameterize by an ostream instance; cannot do this yet // because BinInterface is hard-coded to use printf and must be changed. - std::cout << "Sparc dissassembly of range [" - << start << ", " << end << "]:" << std::endl; + cout << "Sparc dissassembly of range [" + << start << ", " << end << "]:" << endl; for(; start <= end; ++start) { - std::cout << start << " | " + cout << start << " | " << std::hex << std::setw(8) << std::setfill('0') << *start << " | "; sparc_print(*start); - std::cout << std::endl; + cout << endl; } } -uint64_t InstManip::skipFunctionHdr(uint64_t addr, VirtualMem* vm) const +uint64_t InstManip::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 = vm->readInstrFrmVm(addr); + 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"); @@ -124,3 +128,137 @@ "Unexpected number of instruction in code sequence for branch-always"); } +void InstManip::findCandidates(uint64_t start, + uint64_t end, + std::vector& candidates) +{ + for(uint64_t currAddr = start; currAddr <= end; currAddr += getInstWidth()) { + unsigned inst = m_pVM->readInstrFrmVm(currAddr); + + cout << "findCandidates processing instruction:\t"; + printInst(m_pVM->readInstrFrmVm(currAddr)); + cout << endl; + + InstCandidate cand; + if(isCandidateLoad(currAddr, end, cand)) + cerr << "It's a candidate load!" << endl; + } +} + +static inline bool isLoadHalfWord(unsigned inst) +{ + // Returns true if inst is an lduh instruction + return RD_FLD(inst, INSTR_OP) == OP_3 && + RD_FLD(inst, INSTR_OP3) == OP3_LDUH; +} + +static inline bool isSTH(unsigned inst) +{ + return RD_FLD(inst, INSTR_OP) == OP_3 && + RD_FLD(inst, INSTR_OP3) == OP3_STH; +} + +static inline bool isSTB(unsigned inst) +{ + return RD_FLD(inst, INSTR_OP) == OP_3 && + RD_FLD(inst, INSTR_OP3) == OP3_STB; +} + +static inline unsigned getLoadDest(unsigned inst) +{ + // Assumes that inst is a load instruction, and returns the register ID of its + // destination operand. + + return RD_FLD(inst, INSTR_RD); +} + +static inline unsigned getStoreSrc(unsigned inst) +{ + // Assumes that inst is a stb/sth instruction, and returns the register ID of its + // source operand (by source, we don't mean rs1 or rs2, but rather rd, which specifies + // the register which contains the value being stored) + + return RD_FLD(inst, INSTR_RD); +} + +bool InstManip::isCandidateLoad(uint64_t addr, + uint64_t end, + InstCandidate& cand) +{ + // {{{ Description of heuristic + // A candidate load is the first instruction in a sequence (with an arbitrary number + // of instructions in between elements of this sequence) that is a "signature" for the + // particular load of a volatile variable which needs to be replaced with a call to an + // instrumentation function. + // + // Detecting this candidacy condition is accomplished via the application of a + // relatively simple heurstic. The signature sequence always begins with a "load + // half-word" and ends with a "store byte". However, we cannot guarantee that the + // sequence looks like: + // + // lduh [mem1], %r[d] | + // ... | "Schema 1" + // stb %r[d], [mem2] | + // + // although this is a perfectly valid pattern to look for. However, unoptimized code + // will frequently transfer this data using the stack, as in this instruction sequence: + // + // lduh [mem1] %r[d] | + // ... | + // sth %r[d], [stack loc] | + // ... | "Schema 2" + // lduh [stack loc], %r[d'] | + // ... | + // stb %r[d'], [mem2] | + // + // The current heurstic catches both of these patterns (designated "direct" and "stack + // transfer" respectively), and will be extended as insufficiencies in the heuristic + // are revealed. + // }}} + + // Address of potential candidate load is given by 'addr', maximum search address is + // given by 'end' + + unsigned inst = m_pVM->readInstrFrmVm(addr); + + if(isLoadHalfWord(inst)) { + // Search forward until a sth/stb from inst's target register is encountered + uint64_t storeAddr = findNextStore(addr, end, getLoadDest(inst)); + if(!storeAddr) + return false; // No store? Can't be a candidate load. + + // If STB, ... If STH, ... + + unsigned storeInst = m_pVM->readInstrFrmVm(storeAddr); + if(isSTH(storeInst)) { + cerr << "Discovered sth: " << endl; + } + else { + // STB instruction + cerr << "Discovered stb: " << endl; + } + + printInst(storeInst); + + return true; + } + + return false; +} + +uint64_t InstManip::findNextStore(uint64_t addr, + uint64_t end, + unsigned srcReg) +{ + // Sweep the range of addresses starting at addr (up to end) looking for stb or sth + // instructions that are storing _from_ 'fromReg'. Return the first such instance, or + // 0 if such an instance cannot be found. + + for(uint64_t currAddr = addr; currAddr <= end; currAddr += getInstWidth()) { + unsigned inst = m_pVM->readInstrFrmVm(currAddr); + if(isSTH(inst) || isSTB(inst) && getStoreSrc(inst) == srcReg) + return currAddr; + } + + return 0; +} Index: llvm/lib/Reoptimizer/Inst/InstManip.h diff -u llvm/lib/Reoptimizer/Inst/InstManip.h:1.5 llvm/lib/Reoptimizer/Inst/InstManip.h:1.6 --- llvm/lib/Reoptimizer/Inst/InstManip.h:1.5 Fri Apr 11 00:22:20 2003 +++ llvm/lib/Reoptimizer/Inst/InstManip.h Fri Apr 11 18:57:07 2003 @@ -3,25 +3,68 @@ // date: Tue Apr 8 22:42:14 CDT 2003 // fileid: InstManip.h // purpose: InstManip is a wrapper class around any BinInterface macros/mechanisms, as -// well as the TraceCache "instruction utilities", all which are SparcV9-specific. -// This class exists both for conceptual clarity and to facilitate the hiding of -// Sparc-specific code from the Phase2/3 actions (and thus making it easier to use the -// transformations on other platforms in the future; we should be able to change which -// instruction manipulator object is instantiated, after making the appropriate -// superclass, etc). +// well as the TraceCache "instruction utilities", all which are (currently) +// SparcV9-specific. This class exists both for conceptual clarity and to facilitate +// the hiding of Sparc-specific code from the Phase2/3 actions (and thus making it +// easier to use the transformations on other platforms in the future; we should be +// able to change which instruction manipulator object is instantiated, after making +// the appropriate superclass, etc). #ifndef _INCLUDED_INSTMANIP_H #define _INCLUDED_INSTMANIP_H #include +#include #include "llvm/Reoptimizer/BinInterface/sparcdis.h" #include "llvm/Reoptimizer/InstrUtils.h" // getCallInstr, getUndepJumpInstr, etc. class VirtualMem; +// InstCandidate is a class that represents a location in the code that is determined to +// be a candidate for instrumentation. Because the transformation action required for a +// particular candidate requires auxiliary information (such as other instructions found +// within the region of the primary candidate instruction), these are encapsulated in the +// InstCandidate as well. + +class InstCandidate +{ + public: + enum CandType { DIRECT, STACK_XFER }; + + InstCandidate() {} + InstCandidate(CandType type): m_type(type) {} + + void setType(CandType type) { m_type = type; } + bool isDirect() const { return m_type == DIRECT; } + bool isStackXfer() const { return m_type == STACK_XFER; } + + const std::vector >& getInsts() const + { + return m_insts; + } + + void push_back(uint64_t addr, unsigned inst) + { + m_insts.push_back(std::make_pair(addr, inst)); + } + + protected: + CandType m_type; + + // Each element of this vector holds a (address, inst) pair. + std::vector > m_insts; +}; + class InstManip { public: + InstManip(VirtualMem* vm): m_pVM(vm) + { + assert(vm && "InstManip requires valid VirtualMem instance"); + } + + typedef std::pair Inst; // (location, inst word) pair + enum TargetRegister { REG_0, REG_1 }; void printRange(unsigned* start, unsigned* end) const; @@ -30,7 +73,7 @@ inline void printInst(unsigned inst) const; inline void printInst(unsigned* instAddr) const; - uint64_t skipFunctionHdr(uint64_t addr, VirtualMem* vm) const; + uint64_t skipFunctionHdr(uint64_t addr) const; void generateLoad(uint64_t value, std::vector& snippet, @@ -45,6 +88,10 @@ std::vector& snippet, bool annul = true); + void findCandidates(uint64_t start, + uint64_t end, + std::vector& candidates); + 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; @@ -59,9 +106,21 @@ unsigned getInstWidth() const { return 4; } private: + InstManip() {} + + bool isCandidateLoad(uint64_t addr, + uint64_t end, + InstCandidate& cand); + + uint64_t findNextStore(uint64_t addr, + uint64_t end, + unsigned srcReg); + // 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; + + VirtualMem* m_pVM; }; 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.9 llvm/lib/Reoptimizer/Inst/Phases.cpp:1.10 --- llvm/lib/Reoptimizer/Inst/Phases.cpp:1.9 Fri Apr 11 00:22:20 2003 +++ llvm/lib/Reoptimizer/Inst/Phases.cpp Fri Apr 11 18:57:07 2003 @@ -24,20 +24,18 @@ // // PHASE 3: // +// - Deallocate the parameter structure whenever it is convenient to do so. +// // 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. +// 2. Analyze the function and determine the load-volatile candidates. // -// 4. For each load-volatile candidate, +// 3. For each load-volatile candidate, // -// 4a. +// 3a. // -// 5. Deallocate the parameter structure and mark the phase 2 slot for deletion by a -// later invocation of phase 3. +// 4. Deallocate the slot that originated this invocation. // // PHASE 4: // @@ -117,13 +115,36 @@ void transformFunction(AddressRange& range); private: - Phase2() {} + Phase2(): m_instManip(0) {} inline unsigned getSlotSize() const; TraceCache* m_pTraceCache; InstManip m_instManip; }; +// Phase3 is the class that is responsible for making the "phase 3" transformation; the +// global function phase3() is responsible for constructing a one Phase3 instance per +// invocation and for deallocating the originating slot. + +class Phase3 +{ + public: + Phase3(Phase3Info* p3info); + void transform(); + + private: + Phase3(): m_instManip(0) {} + + uint64_t m_startAddr; + uint64_t m_endAddr; + TraceCache* m_pTraceCache; + InstManip m_instManip; + uint64_t m_slotDescriptor; +}; + + +//////////////// Phase 2 implementation //////////////// + extern "C" void phase2() { Phase2 ph(new TraceCache()); @@ -131,7 +152,8 @@ } Phase2::Phase2(TraceCache* tc): - m_pTraceCache(tc) + m_pTraceCache(tc), + m_instManip(tc->getVM()) { } @@ -193,12 +215,12 @@ // 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 repInstAddr = m_instManip.skipFunctionHdr(range.first); uint64_t slotBase = m_pTraceCache->getMemMgr()->getMemory(getSlotSize()); assert(slotBase && "Unable to obtain memory from MemoryManger instance"); // Replace instruction at repInstAddr with a branch to start of slot. + VirtualMem* vm = m_pTraceCache->getVM(); unsigned origInst = vm->readInstrFrmVm(repInstAddr); assert(!m_instManip.isBranch(origInst) && "Unhandled case: branch instruction first in function body"); @@ -236,28 +258,53 @@ m_instManip.getGenBranchAlwaysSize(); } +//////////////// Phase3 implementation //////////////// + void phase3(Phase3Info* p3info) { + Phase3 p3(p3info); + p3info = 0; + + p3.transform(); + + // Deallocate the originating slot (i.e. the slot that invoked us). + // + // NB: Yes, we are, in fact, deallocating a memory segment (i.e., the slot obtained by + // the TraceCache's MemoryManager instance) before returning to it. This is not a + // problem for single-threaded codes, because no threads may claim that memory and + // write to it. However, it does indeed pose a problem for multi-threaded codes. A + // modification to the general mechanism itself is required to achieve thread-safety. + + // (TODO) +} + +Phase3::Phase3(Phase3Info* p3info): + m_instManip(p3info->getTraceCache()->getVM()) +{ assert(p3info && "phase3 requires valid Phase3Info ptr"); + + m_startAddr = p3info->getStartAddr(); + m_endAddr = p3info->getEndAddr(); + m_pTraceCache = p3info->getTraceCache(); + m_slotDescriptor = p3info->getSlot(); cerr << "================ Begin Phase 3 [" << std::hex - << p3info->getStartAddr() << ", " << p3info->getEndAddr() + << m_startAddr << ", " << m_endAddr << "] ================\n"; // Restore the replaced instruction to its original location (thus effectively // removing the branch to the slot created by phase 2 as well) + m_pTraceCache->getVM()->writeInstToVM(p3info->getReplaceAddr(), p3info->getOrigInst()); - 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 - + // Deallocate the parameter structure delete p3info; +} + +void Phase3::transform() +{ + // Gather up the instruction candidates within the function we to transform. + vector candidates; + m_instManip.findCandidates(m_startAddr, m_endAddr, candidates); cerr << "============================== End Phase 3 ==============================\n"; } From lattner at cs.uiuc.edu Sat Apr 12 22:51:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sat Apr 12 22:51:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Instrumentation/TraceValues.cpp Message-ID: <200304130350.WAA08911@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Instrumentation: TraceValues.cpp updated: 1.53 -> 1.54 --- Log message: Make help message more clear --- Diffs of the changes: Index: llvm/lib/Transforms/Instrumentation/TraceValues.cpp diff -u llvm/lib/Transforms/Instrumentation/TraceValues.cpp:1.53 llvm/lib/Transforms/Instrumentation/TraceValues.cpp:1.54 --- llvm/lib/Transforms/Instrumentation/TraceValues.cpp:1.53 Tue Jan 14 16:39:29 2003 +++ llvm/lib/Transforms/Instrumentation/TraceValues.cpp Sat Apr 12 22:50:14 2003 @@ -23,10 +23,12 @@ static cl::opt DisablePtrHashing("tracedisablehashdisable", cl::Hidden, - cl::desc("Disable pointer hashing")); + cl::desc("Disable pointer hashing in the -trace or -tracem " + "passes")); static cl::list -TraceFuncNames("tracefunc", cl::desc("trace only specific functions"), +TraceFuncNames("tracefunc", cl::desc("Only trace specific functions in the " + "-trace or -tracem passes"), cl::value_desc("function"), cl::Hidden); static void TraceValuesAtBBExit(BasicBlock *BB,