MWCC/compiler_and_linker/unsorted/IrOptimizer.c

402 lines
12 KiB
C

#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.opt_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._B4 ? 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.opt_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.opt_dead_assignments || copts.opt_propagation)
IRO_UseDef(copts.opt_dead_assignments, copts.opt_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.opt_unroll_loops && !copts.optimize_for_size && pass == 0) {
IRO_DumpAfterPhase("Before IRO_LoopUnroller", 0);
IRO_LoopUnroller();
IRO_DumpAfterPhase("After IRO_LoopUnroller", 0);
IRO_RenumberInts();
}
VectorPhaseCalledFromUnroll = 0;
if (pass == 0 && (copts.opt_loop_invariants || copts.opt_strength_reduction)) {
IRO_DumpAfterPhase("Before IRO_FindLoops", 0);
IRO_FindLoops();
LoopOptimizerRun = 1;
IRO_SetLoopDepth();
}
IRO_DumpAfterPhase("After IRO_FindLoops", 0);
if (copts.opt_propagation) {
IRO_CopyAndConstantPropagation();
IRO_ConstantFolding();
IRO_EvaluateConditionals();
}
IRO_DumpAfterPhase("Second pass:IRO_CopyAndConstantPropagation, IRO_ConstantFolding, IRO_EvaluateConditionals", 0);
if (copts.opt_common_subs)
IRO_FindExpressions(NULL, 0);
if (copts.opt_common_subs) {
IRO_ComputeAvail();
IRO_CommonSubs();
}
IRO_DumpAfterPhase("IRO_CommonSubs", 0);
IRO_UpdateFlagsOnInts();
IRO_UpdateVars();
IRO_DoTransformations();
IRO_ConstantFolding();
do {
IRO_UpdateFlagsOnInts();
if (copts.opt_dead_code)
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.opt_propagation) {
IRO_RenumberInts();
IRO_DumpAfterPhase("Before IRO_CopyAndConstantPropagation", 0);
changed2 |= IRO_CopyAndConstantPropagation();
IRO_DumpAfterPhase("After IRO_CopyAndConstantPropagation", 0);
IRO_ConstantFolding();
}
if (copts.opt_dead_assignments || copts.opt_propagation)
changed2 |= IRO_UseDef(copts.opt_dead_assignments, copts.opt_propagation);
IRO_DumpAfterPhase("IRO_UseDef", 0);
changed2 |= IRO_EvaluateConditionals();
IRO_DumpAfterPhase("IRO_EvaluateConditionals", 0);
} while (changed2);
}
if (copts.opt_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.opt_dead_code = flag;
flag = copts.optimizationlevel >= 2;
copts.opt_propagation = flag;
copts.opt_common_subs = flag;
flag = copts.optimizationlevel >= 3;
copts.opt_vectorize_loops = flag;
copts.opt_unroll_loops = flag;
copts.opt_dead_assignments = flag;
copts.opt_lifetimes = flag;
copts.opt_strength_reduction = flag;
copts.opt_loop_invariants = flag;
flag = copts.optimizationlevel >= 4;
copts._B4 = flag;
}