summaryrefslogtreecommitdiff
path: root/compiler_and_linker/FrontEnd/Optimizer/IroJump.c
diff options
context:
space:
mode:
Diffstat (limited to 'compiler_and_linker/FrontEnd/Optimizer/IroJump.c')
-rw-r--r--compiler_and_linker/FrontEnd/Optimizer/IroJump.c267
1 files changed, 267 insertions, 0 deletions
diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroJump.c b/compiler_and_linker/FrontEnd/Optimizer/IroJump.c
new file mode 100644
index 0000000..9af248e
--- /dev/null
+++ b/compiler_and_linker/FrontEnd/Optimizer/IroJump.c
@@ -0,0 +1,267 @@
+#include "IroJump.h"
+#include "IroDump.h"
+#include "IroFlowgraph.h"
+#include "IroLinearForm.h"
+#include "IroUtil.h"
+#include "compiler/CFunc.h"
+#include "compiler/Exceptions.h"
+
+static Boolean CheckChain(CLabel **labelptr) {
+ IRONode *node;
+
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ if (node->first && node->first->type == IROLinearLabel && node->first->u.label.label == *labelptr) {
+ IROLinear *linear;
+ CLabel *lab;
+ for (linear = node->first->next, lab = NULL; linear && (linear->type == IROLinearLabel || linear->type == IROLinearNop); linear = linear->next) {
+ if (linear->type == IROLinearLabel)
+ lab = linear->u.label.label;
+ }
+
+ if (linear->type == IROLinearGoto && *labelptr != linear->u.label.label) {
+ *labelptr = linear->u.label.label;
+ IRO_Dump("Chaining goto at %d\n", linear->index);
+ return 1;
+ }
+
+ if (lab && *labelptr != lab)
+ *labelptr = lab;
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+Boolean IRO_DoJumpChaining(void) {
+ IRONode *node;
+ IROLinear *linear;
+ Boolean flag;
+ SwitchInfo *info;
+ SwitchCase *curcase;
+ Boolean result;
+
+ result = 0;
+ do {
+ flag = 0;
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ if (node->first) {
+ linear = node->last;
+ switch (linear->type) {
+ case IROLinearGoto:
+ if (CheckChain(&linear->u.label.label))
+ flag = 1;
+ break;
+ case IROLinearIf:
+ case IROLinearIfNot:
+ if (CheckChain(&linear->u.label.label))
+ flag = 1;
+ break;
+ case IROLinearSwitch:
+ info = linear->u.swtch.info;
+ for (curcase = info->cases; curcase; curcase = curcase->next) {
+ if (CheckChain(&curcase->label))
+ flag = 1;
+ }
+ if (CheckChain(&info->defaultlabel))
+ flag = 1;
+ break;
+ }
+ }
+ }
+ result |= flag;
+ IRO_CheckForUserBreak();
+ } while (flag);
+
+ return result;
+}
+
+void IRO_MakeReachable(IRONode *node) {
+ UInt16 i;
+ Boolean flag;
+
+ node->x36 = 1;
+ do {
+ flag = 0;
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ if (node->x36 && !node->x37) {
+ for (i = 0; i < node->numsucc; i++) {
+ if (!IRO_NodeTable[node->succ[i]]->x36) {
+ flag = 1;
+ IRO_NodeTable[node->succ[i]]->x36 = 1;
+ }
+ }
+ node->x37 = 1;
+ }
+ }
+ } while (flag);
+}
+
+Boolean IRO_RemoveUnreachable(void) {
+ IRONode *node2;
+ IRONode *node1;
+ IROLinear *scan;
+ IROLinear *linear;
+ Boolean result;
+ ExceptionAction **actptr;
+ ExceptionAction *act;
+
+ result = 0;
+ IRO_ComputeSuccPred();
+ IRO_MakeReachable(IRO_FirstNode);
+ node1 = IRO_FirstNode;
+ for (node2 = IRO_FirstNode->nextnode; node2; node2 = node2->nextnode) {
+ if (node2->first && !node2->x36) {
+ IRO_Dump("Removing unreachable code at: %d\n", node2->index);
+ node1->nextnode = node2->nextnode;
+ node1->last->next = node2->last->next;
+ result = 1;
+ for (linear = node2->first; linear && linear->type == IROLinearLabel && linear != node2->last->next; linear = linear->next) {
+ for (scan = IRO_FirstLinear; scan; scan = scan->next) {
+ if (scan->stmt)
+ scan->stmt->marked = 0;
+ }
+
+ for (scan = IRO_FirstLinear; scan; scan = scan->next) {
+ if (scan->stmt && !scan->stmt->marked) {
+ scan->stmt->marked = 1;
+ for (actptr = &scan->stmt->dobjstack; (act = *actptr); actptr = &act->prev) {
+ if (
+ (act->type == EAT_CATCHBLOCK && act->data.catch_block.catch_label == linear->u.label.label) ||
+ (act->type == EAT_SPECIFICATION && act->data.specification.unexp_label == linear->u.label.label)) {
+ *actptr = act->prev;
+ }
+ }
+ }
+ }
+ }
+ if (node2 == IRO_LastNode)
+ IRO_LastNode = node1;
+ } else {
+ node1 = node2;
+ }
+ }
+
+ if (result) {
+ IRO_ComputeSuccPred();
+ IRO_ComputeDom();
+ }
+
+ IRO_CheckForUserBreak();
+ return result;
+}
+
+Boolean IRO_RemoveRedundantJumps(void) {
+ IRONode *node;
+ IROLinear *linear;
+ IROLinear *scan;
+ IROLinear *scan2;
+ SwitchInfo *info;
+ SwitchCase *curcase;
+ Boolean result;
+
+ result = 0;
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ if (node->first) {
+ linear = node->last;
+ switch (linear->type) {
+ case IROLinearGoto:
+ scan = linear->next;
+ while (scan && ((scan->type == IROLinearNop) || (scan->type == IROLinearLabel && scan->u.label.label != linear->u.label.label)))
+ scan = scan->next;
+ while (1) {
+ if (!scan) break;
+ if (scan->type != IROLinearLabel) break;
+ if (scan->u.label.label == linear->u.label.label) {
+ IRO_Dump("Removing goto next at %d\n", linear->index);
+ linear->type = IROLinearNop;
+ result = 1;
+ break;
+ }
+ scan = scan->next;
+ }
+ break;
+
+ case IROLinearIf:
+ case IROLinearIfNot:
+ scan = linear->next;
+ while (scan && scan->type == IROLinearNop)
+ scan = scan->next;
+ if (scan && scan->type == IROLinearGoto) {
+ scan2 = scan->next;
+ while (scan2 && ((scan2->type == IROLinearNop) || (scan2->type == IROLinearLabel && scan2->u.label.label != linear->u.label.label)))
+ scan2 = scan2->next;
+
+ if (scan2 && scan2->type == IROLinearLabel && scan2->u.label.label == linear->u.label.label) {
+ if (linear->type == IROLinearIf)
+ linear->type = IROLinearIfNot;
+ else
+ linear->type = IROLinearIf;
+
+ linear->u.label.label = scan->u.label.label;
+ scan->type = IROLinearNop;
+ IRO_Dump("Removing branch around goto at %d\n", linear->index);
+ result = 1;
+ }
+ }
+
+ scan2 = linear->next;
+ while (scan2 && ((scan2->type == IROLinearNop) || (scan2->type == IROLinearLabel && scan2->u.label.label != linear->u.label.label)))
+ scan2 = scan2->next;
+ while (1) {
+ if (!scan2) break;
+ if (scan2->type != IROLinearLabel) break;
+ if (scan2->u.label.label == linear->u.label.label) {
+ IRO_Dump("Removing If/IfNot_Goto next at %d\n", linear->index);
+ linear->type = IROLinearNop;
+ IRO_CheckSideEffect(linear->u.label.x4);
+ result = 1;
+ break;
+ }
+ scan2 = scan2->next;
+ }
+ break;
+
+ case IROLinearSwitch:
+ info = linear->u.swtch.info;
+ curcase = info->cases;
+ while (curcase && curcase->label == info->defaultlabel)
+ curcase = curcase->next;
+ if (!curcase) {
+ IRO_Dump("Removing Switch next at %d\n", linear->index);
+ IRO_CheckSideEffect(linear->u.swtch.x4);
+ linear->type = IROLinearGoto;
+ linear->u.label.label = info->defaultlabel;
+ result = 1;
+ }
+ break;
+ }
+ }
+ }
+
+ if (result) {
+ IRO_ComputeSuccPred();
+ IRO_ComputeDom();
+ }
+
+ IRO_CheckForUserBreak();
+ return result;
+}
+
+Boolean IRO_RemoveLabels(void) {
+ Boolean result;
+ IRONode *node;
+
+ result = 0;
+ IRO_ComputeSuccPred();
+ for (node = IRO_FirstNode; node; node = node->nextnode) {
+ if (node->first && node->first->type == IROLinearLabel && !node->x39) {
+ node->first->type = IROLinearNop;
+ node->first->flags &= ~IROLF_1;
+ result = 1;
+ }
+ }
+
+ IRO_CheckForUserBreak();
+ return result;
+}