// Optimiser.cpp: implementation of the COptimiser class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "archimedes.h" #include "Optimiser.h" #include "ArmletDisassembler.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// COptimiser::COptimiser() { TRACE("construct COptimiser \n"); BOOL armletSuccess = armletReportFile.Open( _T("D:\\Work\\Project\\armletDiss.txt"), CFile::modeCreate | CFile::modeWrite | CFile::shareDenyWrite | CFile::typeText ); generator = new CGenerator(); } COptimiser::~COptimiser() { delete generator; } // // takes a linked list of armlets forming a chunk and optimises them // passing them on to the generator when finished // void COptimiser::optimise(CLinkedList *chunkList) { // ??? perform constant folding // ??? perform any other work that needs doing before // adding/removing armlets becomes expensive (i.e. before linked list destroyed) // create array of armlets for fast access // get number of armlets in the linked list totalArmlets = chunkList->numberOfElements(); chunk = new Armlet*[ totalArmlets ]; // remove pointers from list and put them in array int index = 0; while( !chunkList->empty() ) { chunk[index] = (Armlet*)chunkList->removeHead(); index++; // ??? debugging TRACE("armlet index=%d added \n", index); } // perform basic block analysis identifyLeaders(); // remove redundant flag calculations TRACE("REDUNDANT FLAG REMOVAL IS DISABLED\n"); // ??? //removeRedundantFlagCalculations(); // ??? disassemble debugging CArmletDisassembler diss; TRACE("list post redundant flag removal\n"); for(int i=0; igenerate(chunk, totalArmlets); // ??? delete chunk of armlets // delete []chunk; } // // Mark all the armlets which are leaders of a basic block as such // void COptimiser::identifyLeaders() { // force first armlet in block to be a leader (as it must be) chunk[0]->leader = TRUE; // examine all the armlets for(int armlet=0; armletopcode; if( (opcode >= irGOTOEQ) && (opcode <=irGOTO) ) { // get destination of goto uint32 destination = chunk[armlet]->value; // set the destination of the goto to be a leader chunk[destination]->leader = TRUE; // set armlet following this goto (if there is one) to be a leader if(armlet+1 < totalArmlets) chunk[armlet+1]->leader = TRUE; } else { // if opcode is a leave if(opcode==irLEAVE) { // set armlet following this leave (if there is one) to be a leader if(armlet+1 < totalArmlets) chunk[armlet+1]->leader = TRUE; } } } } // // Remove any outflags settings that are never utilised by inflags // because they are overwritten by a later outflags. This will also // leave settings ok for the end of the basic block. // void COptimiser::removeRedundantFlagCalculations() { BOOL flagChanged[4]; // details whether the flag has changed needlessly uint32 flagSetBy[4]; // details which armlet output the flag // go through all armlets for(int armlet = 0; armletleader ) { // clear information for(int flag=0; flag<4; flag++) { flagChanged[flag] = FALSE; flagSetBy[flag] = -1; } } // check inflags for(int inflag=0; inflag<4; inflag++) { // if this armlet requires this flag to be set correctly if( chunk[armlet]->inflags & (1<outflags & (1<outflags &= ~(1<setCodeCache(aCodeCache); }