#include "compiler/IrOptimizer.h" #include "compiler/CError.h" #include "compiler/CParser.h" #include "compiler/InlineAsmPPC.h" #include "compiler/IroCSE.h" #include "compiler/IroDump.h" #include "compiler/IroEval.h" #include "compiler/IroFlowgraph.h" #include "compiler/IroLinearForm.h" #include "compiler/IroSubable.h" #include "compiler/IroTransform.h" #include "compiler/IROUseDef.h" #include "compiler/IroUtil.h" #include "compiler/IroVars.h" #include "compiler/objects.h" #include "compiler/IroPropagate.h" #include "compiler/IroPointerAnalysis.h" #include "compiler/IroJump.h" #include "compiler/IroRangePropagation.h" #include "compiler/IroEmptyLoop.h" #include "compiler/IroUnrollLoop.h" #include "compiler/IroLoop.h" #include "compiler/IroExprRegeneration.h" Boolean DoScalarize; Boolean DoLinearize; Boolean EarlyReturn; Boolean IRO_CPFirstTime; Boolean VectorPhaseCalledFromUnroll; Boolean IRO_Log; static Boolean stIsSetup; static void CountRefToObject(Object *object, int depth) { static unsigned short LoopUsage[] = {1, 4, 16, 64}; if (depth > 3) depth = 3; object->u.var.info->usage += LoopUsage[depth]; object->u.var.info->used = 1; } static void CountARef(IROLinear *node, int depth) { Object *object; object = node->u.node->data.objref; CError_ASSERT(78, object->datatype != DALIAS); if (object->datatype == DLOCAL && object->u.var.info) { CountRefToObject(object, depth); if ((node->flags & IROLF_Used) && (node->flags & IROLF_Assigned)) CountRefToObject(object, depth); if (!(node->flags & IROLF_Immind) && !object->u.var.info->noregister) object->u.var.info->noregister = 2; } } static void CountDoubleInd(IROLinear *node, int depth) { if (IRO_IsVariable(node)) { CountARef(node->u.monadic, depth); } else if (node->type == IROLinearOp2Arg) { if (node->nodetype == EADD) { CountDoubleInd(node->u.diadic.left, depth); CountDoubleInd(node->u.diadic.right, depth); } else if (IRO_IsAddressMultiply(node)) { if (IRO_IsVariable(node->u.diadic.left)) CountARef(node->u.diadic.left->u.monadic, depth); } } } static void CountUsage(void) { IRONode *fnode = IRO_FirstNode; IROLinear *node; if (IRO_FirstNode) { for (; fnode; fnode = fnode->nextnode) { for (node = fnode->first; node; node = node->next) { if (IS_LINEAR_ENODE(node, EOBJREF)) CountARef(node, fnode->loopdepth); else if (IS_LINEAR_MONADIC(node, EINDIRECT)) CountDoubleInd(node->u.monadic, fnode->loopdepth); if (node->type == IROLinearAsm) { IAEffects effects; int i; CodeGen_GetAsmEffects(node->u.asm_stmt, &effects); for (i = 0; i < effects.numoperands; i++) { Object *object = effects.operands[i].object; if (object->datatype == DLOCAL && object->u.var.info) { CountRefToObject(object, fnode->loopdepth); if (effects.operands[i].type == IAOpnd_3 && !object->u.var.info->noregister) object->u.var.info->noregister = 2; } } } if (node == fnode->last) break; } } } else { for (node = IRO_FirstLinear; node; node = node->next) { if (IS_LINEAR_ENODE(node, EOBJREF)) CountARef(node, 0); else if (IS_LINEAR_MONADIC(node, EINDIRECT)) CountDoubleInd(node->u.monadic, 0); } } IRO_CheckForUserBreak(); } Statement *IRO_Optimizer(Object *func, Statement *statements) { Boolean changed; Boolean changed2; int pass; int passCount; CError_ASSERT(234, stIsSetup); #ifdef CW_PATCH_DEBUG if (copts.debuglisting) IRO_Log = 1; #endif DisableDueToAsm = 0; FunctionName = func; DoScalarize = 1; DoLinearize = 1; EarlyReturn = 0; IRO_Depends = NULL; LoopOptimizerRun = 0; IRO_IsLeafFunction = 1; IRO_FunctionHasReturn = 0; IRO_SetupForUserBreakChecking(); IRO_Dump("Starting function %s\n", func ? func->name->name : "Init-code"); IRO_Dump("--------------------------------------------------------------------------------\n"); if (DoLinearize) IRO_PreLinearize(statements); if (copts.optimizationlevel > 0) IRO_TransformTree(statements); VectorPhaseCalledFromUnroll = 0; IRO_Linearize(statements); CurStat = NULL; IRO_FirstExpr = NULL; IRO_LastExpr = NULL; IRO_FirstAssign = NULL; IRO_LastAssign = NULL; IRO_FirstVarUse = NULL; IRO_LastVarUse = NULL; IRO_FirstNode = NULL; IRO_LastNode = NULL; if (copts.optimizationlevel > 0) IRO_DoTransformations(); IRO_BuildFlowgraph(IRO_FirstLinear); IRO_DumpAfterPhase("IRO_BuildflowGraph", 0); IRO_FindAllVars(); IRO_CheckInit(); if (!DisableDueToAsm && copts.optimizationlevel > 0 && copts.opt_pointer_analysis && func) { IRO_AnalyzePointers(func); if (copts.propagation && IRO_EvaluateDefinitePointers(func)) { IRO_UpdateFlagsOnInts(); IRO_UpdateVars(); IRO_DumpAfterPhase("IRO_EvaluateDefinitePointers", 0); } } if (copts.optimizationlevel > 0) { changed = IRO_EvaluateConditionals(); if (!DisableDueToAsm) { changed |= IRO_RemoveUnreachable(); IRO_DumpAfterPhase("IRO_RemoveUnreachable", 0); } changed |= IRO_RemoveRedundantJumps(); IRO_DumpAfterPhase("IRO_RemoveRedundantJumps", 0); if (!DisableDueToAsm) { changed |= IRO_RemoveLabels(); IRO_DumpAfterPhase("IRO_RemoveLabels()", 0); } if (changed) { IRO_BuildFlowgraph(IRO_FirstLinear); IRO_DumpAfterPhase("IRO_BuildflowGraph--1", 0); } } if (!DisableDueToAsm && copts.optimizationlevel > 0) { passCount = copts.multiplepasses ? 2 : 1; IRO_CPFirstTime = 1; for (pass = 0; pass < passCount; pass++) { IRO_Dump("*****************\n"); IRO_Dump("Dumps for pass=%d\n", pass); IRO_Dump("*****************\n"); if (DoScalarize) IRO_ScalarizeClassDataMembers(); IRO_DumpAfterPhase("IRO_ScalarizeClassDataMembers", 0); if (copts.propagation) { IRO_CopyAndConstantPropagation(); IRO_CPFirstTime = 0; IRO_ExpressionPropagation(); IRO_DumpAfterPhase("Copy and constant propagation", 0); IRO_RangePropagateInFNode(); IRO_DumpAfterPhase("IRO_RangePropagateInFNode", 0); IRO_UpdateFlagsOnInts(); } IRO_DumpAfterPhase("IRO_ExpressionPropagation", 0); if (copts.deadstore || copts.propagation) IRO_UseDef(copts.deadstore, copts.propagation); IRO_DumpAfterPhase("after IRO_UseDef", 0); IRO_UpdateVars(); IRO_ConstantFolding(); IRO_DumpAfterPhase("IRO_ConstantFolding", 0); IRO_EvaluateConditionals(); IRO_RemoveUnreachable(); IRO_SimplifyConditionals(); if (pass == 1 && copts.optimizationlevel > 2) { IRO_RenumberInts(); IRO_DumpAfterPhase("Before IRO_FindEmptyLoops", 0); IRO_FindEmptyLoops(); IRO_DumpAfterPhase("After IRO_FindEmptyLoops", 0); IRO_RenumberInts(); } if (copts.unrolling && !copts.optimizesize && pass == 0) { IRO_DumpAfterPhase("Before IRO_LoopUnroller", 0); IRO_LoopUnroller(); IRO_DumpAfterPhase("After IRO_LoopUnroller", 0); IRO_RenumberInts(); } VectorPhaseCalledFromUnroll = 0; if (pass == 0 && (copts.loopinvariants || copts.strengthreduction)) { IRO_DumpAfterPhase("Before IRO_FindLoops", 0); IRO_FindLoops(); LoopOptimizerRun = 1; IRO_SetLoopDepth(); } IRO_DumpAfterPhase("After IRO_FindLoops", 0); if (copts.propagation) { IRO_CopyAndConstantPropagation(); IRO_ConstantFolding(); IRO_EvaluateConditionals(); } IRO_DumpAfterPhase("Second pass:IRO_CopyAndConstantPropagation, IRO_ConstantFolding, IRO_EvaluateConditionals", 0); if (copts.commonsubs) IRO_FindExpressions(NULL, 0); if (copts.commonsubs) { IRO_ComputeAvail(); IRO_CommonSubs(); } IRO_DumpAfterPhase("IRO_CommonSubs", 0); IRO_UpdateFlagsOnInts(); IRO_UpdateVars(); IRO_DoTransformations(); IRO_ConstantFolding(); do { IRO_UpdateFlagsOnInts(); if (copts.deadcode) IRO_RemoveUnreachable(); IRO_DumpAfterPhase("IRO_RemoveUnreachable", 0); changed2 = IRO_RemoveRedundantJumps(); IRO_DumpAfterPhase("IRO_RemoveRedundantJumps", 0); changed2 |= IRO_RemoveLabels(); IRO_DumpAfterPhase("IRO_RemoveLabels", 0); changed2 |= IRO_DoJumpChaining(); IRO_DumpAfterPhase("IRO_DoJumpChaining", 0); if (copts.propagation) { IRO_RenumberInts(); IRO_DumpAfterPhase("Before IRO_CopyAndConstantPropagation", 0); changed2 |= IRO_CopyAndConstantPropagation(); IRO_DumpAfterPhase("After IRO_CopyAndConstantPropagation", 0); IRO_ConstantFolding(); } if (copts.deadstore || copts.propagation) changed2 |= IRO_UseDef(copts.deadstore, copts.propagation); IRO_DumpAfterPhase("IRO_UseDef", 0); changed2 |= IRO_EvaluateConditionals(); IRO_DumpAfterPhase("IRO_EvaluateConditionals", 0); } while (changed2); } if (copts.lifetimes) { IRO_UseDef(0, 0); IRO_SplitLifetimes(); } IRO_DoTransformations(); IRO_DumpAfterPhase("Before RebuildCondExpressions", 0); } IRO_RenumberInts(); IRO_DumpAfterPhase("before IRO_RewriteBitFieldTemps", 0); IRO_RewriteBitFieldTemps(); IRO_DumpAfterPhase("After IRO_RewriteBitFieldTemps", 0); CountUsage(); if (!DisableDueToAsm) { IRO_RegenerateExpressions(); IRO_DumpAfterPhase("IRO_RegenerateExpressions", 0); } IRO_DumpAfterPhase("After IRO_Optimizer", 0); statements = IRO_Delinearize(IRO_FirstNode, NULL); IRO_ZapVarPtrs(); freeoheap(); return statements; } void IRO_Setup(void) { static Boolean ENodeArraysHaveBeenInitialized; if (!stIsSetup) { IRO_Log = 0; IRO_SetupDump(); if (!ENodeArraysHaveBeenInitialized) { IRO_InitializeNodeNamesArray(); IRO_InitializeIsAssociativeENodeTypeArray(); IRO_InitializeIsSubableOpArray(); IRO_InitializeAssignmentOpArray(); IRO_InitializeComplementaryOpArray(); IRO_InitializeComplementaryOpLogicalArray(); IRO_InitializeNonAssignmentOpArray(); IRO_InitializeAssignmentFoldingFunctionArray(); IRO_InitializeIRO_IsModifyOpArray(); IRO_InitializeIRO_IsAssignOpArray(); ENodeArraysHaveBeenInitialized = 1; } stIsSetup = 1; } } void IRO_Cleanup(void) { if (stIsSetup) { IRO_CleanupDump(); stIsSetup = 0; } } void CodeGen_UpdateOptimizerOptions(void) { Boolean flag; flag = copts.optimizationlevel >= 1; copts.deadcode = flag; flag = copts.optimizationlevel >= 2; copts.propagation = flag; copts.commonsubs = flag; flag = copts.optimizationlevel >= 3; copts.vectorizeloops = flag; copts.unrolling = flag; copts.deadstore = flag; copts.lifetimes = flag; copts.strengthreduction = flag; copts.loopinvariants = flag; flag = copts.optimizationlevel >= 4; copts.multiplepasses = flag; }