diff options
Diffstat (limited to 'compiler_and_linker/FrontEnd/Optimizer/IroJump.c')
-rw-r--r-- | compiler_and_linker/FrontEnd/Optimizer/IroJump.c | 267 |
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; +} |