summaryrefslogtreecommitdiff
path: root/compiler_and_linker/FrontEnd/Optimizer/IrOptimizer.c
diff options
context:
space:
mode:
authorAsh Wolf <ninji@wuffs.org>2023-01-26 11:30:47 +0000
committerAsh Wolf <ninji@wuffs.org>2023-01-26 11:30:47 +0000
commit094b96ca1df4a035b5f93c351f773306c0241f3f (patch)
tree95ce05e3ebe816c7ee7996206bb37ea17d8ca33c /compiler_and_linker/FrontEnd/Optimizer/IrOptimizer.c
parentfc0c4c0df7b583b55a08317cf1ef6a71d27c0440 (diff)
downloadMWCC-094b96ca1df4a035b5f93c351f773306c0241f3f.tar.gz
MWCC-094b96ca1df4a035b5f93c351f773306c0241f3f.zip
move lots of source files around to match their actual placement in the original treemain
Diffstat (limited to 'compiler_and_linker/FrontEnd/Optimizer/IrOptimizer.c')
-rw-r--r--compiler_and_linker/FrontEnd/Optimizer/IrOptimizer.c400
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;
+}