diff options
Diffstat (limited to 'compiler_and_linker/FrontEnd/Optimizer/IrOptimizer.c')
-rw-r--r-- | compiler_and_linker/FrontEnd/Optimizer/IrOptimizer.c | 400 |
1 files changed, 400 insertions, 0 deletions
diff --git a/compiler_and_linker/FrontEnd/Optimizer/IrOptimizer.c b/compiler_and_linker/FrontEnd/Optimizer/IrOptimizer.c new file mode 100644 index 0000000..59bb368 --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IrOptimizer.c @@ -0,0 +1,400 @@ +#include "IrOptimizer.h" +#include "compiler/CError.h" +#include "compiler/CParser.h" +#include "compiler/InlineAsmPPC.h" +#include "IroCSE.h" +#include "IroDump.h" +#include "IroEval.h" +#include "IroFlowgraph.h" +#include "IroLinearForm.h" +#include "IroSubable.h" +#include "IroTransform.h" +#include "IROUseDef.h" +#include "IroUtil.h" +#include "IroVars.h" +#include "compiler/objects.h" +#include "IroPropagate.h" +#include "IroPointerAnalysis.h" +#include "IroJump.h" +#include "IroRangePropagation.h" +#include "IroEmptyLoop.h" +#include "IroUnrollLoop.h" +#include "IroLoop.h" +#include "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; + int pass; + int passCount; + + CError_ASSERT(234, stIsSetup); + +#ifdef CW_ENABLE_IRO_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); + + changed = IRO_RemoveRedundantJumps(); + IRO_DumpAfterPhase("IRO_RemoveRedundantJumps", 0); + + changed |= IRO_RemoveLabels(); + IRO_DumpAfterPhase("IRO_RemoveLabels", 0); + + changed |= IRO_DoJumpChaining(); + IRO_DumpAfterPhase("IRO_DoJumpChaining", 0); + + if (copts.propagation) { + IRO_RenumberInts(); + IRO_DumpAfterPhase("Before IRO_CopyAndConstantPropagation", 0); + changed |= IRO_CopyAndConstantPropagation(); + IRO_DumpAfterPhase("After IRO_CopyAndConstantPropagation", 0); + IRO_ConstantFolding(); + } + + if (copts.deadstore || copts.propagation) + changed |= IRO_UseDef(copts.deadstore, copts.propagation); + IRO_DumpAfterPhase("IRO_UseDef", 0); + + changed |= IRO_EvaluateConditionals(); + IRO_DumpAfterPhase("IRO_EvaluateConditionals", 0); + } while (changed); + } + + 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; +} |