summaryrefslogtreecommitdiff
path: root/compiler_and_linker/unsorted/COptimizer.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/unsorted/COptimizer.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/unsorted/COptimizer.c')
-rw-r--r--compiler_and_linker/unsorted/COptimizer.c1831
1 files changed, 0 insertions, 1831 deletions
diff --git a/compiler_and_linker/unsorted/COptimizer.c b/compiler_and_linker/unsorted/COptimizer.c
deleted file mode 100644
index 9833a2b..0000000
--- a/compiler_and_linker/unsorted/COptimizer.c
+++ /dev/null
@@ -1,1831 +0,0 @@
-#include "compiler/COptimizer.h"
-#include "compiler/CompilerTools.h"
-#include "compiler/CClass.h"
-#include "compiler/CDecl.h"
-#include "compiler/CError.h"
-#include "compiler/CExpr.h"
-#include "compiler/CFunc.h"
-#include "compiler/CInt64.h"
-#include "compiler/CMachine.h"
-#include "compiler/CParser.h"
-#include "compiler/InlineAsm.h"
-#include "compiler/enode.h"
-#include "compiler/objects.h"
-#include "compiler/CodeGen.h"
-#include "compiler/Switch.h"
-#include "compiler/Exceptions.h"
-#include "compiler/IrOptimizer.h"
-#include "cos.h"
-
-COptBlock *basicblocks;
-Boolean copt_isleaffunction;
-static Boolean stmtchanged;
-static COptBlock *currentblock;
-static ENode *mexpr;
-static short setbytes;
-static COptCSE *csenodes[MAXEXPR];
-static COptCSEList *cselist;
-static short extravars;
-static Boolean cse_found;
-static Boolean cse_invals;
-static Boolean static_for_inlines;
-static short replaces;
-static ENode *objrefnode;
-static int objrefnodes;
-
-static short bitmasks[] = {
- 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80,
- 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000
-};
-
-// forward decls
-static COptCSE *cse_expression(ENode *expr);
-
-static COptCSE *cse_new(ENode *expr) {
- COptCSE *cse = oalloc(sizeof(COptCSE));
- cse->expr = expr;
- cse->replaced = NULL;
- cse->block = currentblock;
- cse->mexpr = mexpr;
- cse->left = NULL;
- cse->right = NULL;
- cse->x1C = 1;
- return cse;
-}
-
-static COptCSE *cse_append(COptCSE *cse, ENode *expr) {
- COptCSEList *list = oalloc(sizeof(COptCSEList));
- list->next = cselist;
- cselist = list;
- list->cse = cse;
- list->expr = expr;
- return cse;
-}
-
-static void cse_cleanup(void) {
- COptCSEList *scanlist;
- COptCSEList *prevlist;
- COptCSE *scan;
- COptCSE *prev;
- short op;
-
- scanlist = cselist;
- while (scanlist && !scanlist->cse)
- scanlist = scanlist->next;
- cselist = scanlist;
-
- if (scanlist) {
- do {
- prevlist = scanlist;
- do {
- scanlist = scanlist->next;
- } while (scanlist && !scanlist->cse);
- prevlist->next = scanlist;
- } while (scanlist);
- }
-
- for (op = 0; op < MAXEXPR; op++) {
- scan = csenodes[op];
- while (scan && scan->x1C < 0)
- scan = scan->next;
- csenodes[op] = scan;
-
- if (scan) {
- do {
- prev = scan;
- do {
- scan = scan->next;
- } while (scan && scan->x1C < 0);
- prev->next = scan;
- } while (scan);
- }
- }
-}
-
-static void cse_inval(COptCSE *cse) {
- COptCSEList *scanlist;
- COptCSE *scan;
- short op;
-
- if (cse) {
- for (scanlist = cselist; scanlist; scanlist = scanlist->next) {
- if (scanlist->cse == cse) {
- scanlist->cse = NULL;
- scanlist->expr = NULL;
- }
- }
-
- cse->x1C = -1;
- cse->left = NULL;
- cse->right = NULL;
-
- for (op = 0; op < MAXEXPR; op++) {
- for (scan = csenodes[op]; scan; scan = scan->next) {
- if (scan->left == cse || scan->right == cse)
- cse_inval(scan);
- }
- }
- }
-}
-
-static void cse_update_usages(COptCSE *cse, short amount) {
- cse->x1C /= amount;
- if (cse->left)
- cse_update_usages(cse->left, amount);
- if (cse->right)
- cse_update_usages(cse->right, amount);
-}
-
-static void cse_replace(ENode *expr, COptCSE *cse) {
- COptCSEList *list;
-
- for (list = cselist; list; list = list->next) {
- if (list->cse == cse) {
- *list->expr = *expr;
- replaces++;
- list->cse = NULL;
- list->expr = NULL;
- }
- }
-}
-
-static short cse_objectcost(Object *obj) {
- if (obj->datatype == DLOCAL && !obj->u.var.info->noregister)
- return 0;
- return 1;
-}
-
-static void cse_treereplacemexpr(COptCSE *cse, ENode *from, ENode *to) {
- if (cse->mexpr == from)
- cse->mexpr = to;
- if (cse->left)
- cse_treereplacemexpr(cse->left, from, to);
- if (cse->right)
- cse_treereplacemexpr(cse->right, from, to);
-}
-
-static Boolean cse_issubcse(COptCSE *a, COptCSE *b) {
- if (a == b)
- return 1;
- if (b->left && cse_issubcse(a, b->left))
- return 1;
- if (b->right && cse_issubcse(a, b->right))
- return 1;
-
- return 0;
-}
-
-static short cse_cost(COptCSE *cse) {
- short cost;
-
- if (cse) {
- while (ENODE_IS(cse->expr, ETYPCON) && cse->expr->rtype->type == cse->expr->data.monadic->rtype->type && cse->expr->rtype->size == cse->expr->data.monadic->rtype->size)
- cse = cse->left;
-
- if (ENODE_IS_INDIRECT_TO(cse->expr, EOBJREF))
- return cse_objectcost(cse->expr->data.monadic->data.objref);
-
- cost = 1;
- if (!copts.optimizesize) {
- if (ENODE_IS3(cse->expr, EMUL, EDIV, EMODULO))
- cost = 2;
- }
- return cse_cost(cse->left) + cse_cost(cse->right) + cost;
- }
-
- return 0;
-}
-
-static void cse_remove(void) {
- short op; // r27
- COptCSE *cse; // r25
- COptCSE *best_cse; // r28
- int best_cost; // r30
- Object *obj; // r31
- Boolean did_replacement; // r24
- VarInfo *vi; // r27
- ObjectList *objlist;
- ENode *expr1;
- ENode *expr2;
- ENode *expr3;
- ENode *expr4;
- ENode *mexprsave;
- COptCSEList *list;
- short cost;
-
- while (1) {
- op = 0;
- best_cse = NULL;
- best_cost = 0;
- did_replacement = 0;
-
- for (; op < MAXEXPR; op++) {
- switch (op) {
- case EINTCONST:
- case EFLOATCONST:
- case EOBJREF:
- case EVECTOR128CONST:
- break;
- default:
- for (cse = csenodes[op]; cse; cse = cse->next) {
- if (cse->x1C > 1 && (cost = cse_cost(cse)) > 4) {
- if (cse->replaced) {
- replaces = 0;
- cse_replace(cse->replaced, cse);
- CError_ASSERT(348, replaces >= 1);
- cse_found = 1;
- did_replacement = 1;
- cse_update_usages(cse, cse->x1C);
- } else {
- if ((cse->x1C * cost) > best_cost) {
- best_cse = cse;
- best_cost = cse->x1C * cost;
- }
- }
- }
- }
- break;
- }
- }
-
- if (did_replacement)
- continue;
- if (!best_cse || extravars >= 256)
- return;
-
- obj = lalloc(sizeof(Object));
- memclrw(obj, sizeof(Object));
- obj->name = CParser_GetUniqueName();
- obj->type = cse->expr->rtype;
- obj->datatype = DLOCAL;
- vi = CodeGen_GetNewVarInfo();
- obj->u.var.info = vi;
-
- objlist = lalloc(sizeof(ObjectList));
- objlist->object = obj;
- objlist->next = locals;
- locals = objlist;
-
- vi->used = 1;
- vi->usage = cse->x1C + 1;
-
- expr1 = lalloc(sizeof(ENode));
- expr1->type = EOBJREF;
- expr1->cost = 0;
- expr1->flags = 0;
- expr1->data.objref = obj;
- expr1->rtype = CDecl_NewPointerType(obj->type);
-
- expr2 = lalloc(sizeof(ENode));
- expr2->type = EINDIRECT;
- expr2->cost = 1;
- expr2->flags = 0;
- expr2->data.monadic = expr1;
- expr2->rtype = obj->type;
-
- expr3 = lalloc(sizeof(ENode));
- expr3->type = EASS;
- expr3->cost = -1;
- expr3->flags = 0;
- expr3->rtype = obj->type;
- expr3->data.diadic.left = expr2;
- expr3->data.diadic.right = lalloc(sizeof(ENode));
-
- *expr3->data.diadic.right = *cse->expr;
- cse->expr = expr3->data.diadic.right;
-
- replaces = 0;
- cse_replace(expr2, cse);
- cse->replaced = expr2;
-
- if (replaces < 2)
- CError_FATAL(390);
- else
- cse_found = 1;
-
- expr4 = lalloc(sizeof(ENode));
- *expr4 = *cse->mexpr;
-
- cse->mexpr->type = ECOMMA;
- cse->mexpr->data.diadic.left = expr3;
- cse->mexpr->data.diadic.right = expr4;
-
- cse_update_usages(cse, cse->x1C);
- extravars++;
-
- mexprsave = cse->mexpr;
- if (mexpr == mexprsave)
- mexpr = expr4;
-
- for (list = cselist; list; list = list->next) {
- if (list->cse && !cse_issubcse(list->cse, cse)) {
- if (list->cse->mexpr == mexprsave)
- list->cse->mexpr = expr4;
- if (list->cse->expr == mexprsave)
- list->cse->expr = expr4;
- if (list->expr == mexprsave)
- list->expr = expr4;
- }
- }
- }
-}
-
-static COptCSE *cse_intconst(ENode *expr) {
- COptCSE *cse = csenodes[EINTCONST];
-
- for (; cse; cse = cse->next) {
- if (expr->rtype == cse->expr->rtype)
- if (CInt64_Equal(cse->expr->data.intval, expr->data.intval))
- return cse;
- }
-
- cse = cse_new(expr);
- cse->next = csenodes[EINTCONST];
- csenodes[EINTCONST] = cse;
- return cse;
-}
-
-static COptCSE *cse_floatconst(ENode *expr) {
- COptCSE *cse = csenodes[EFLOATCONST];
- Float val = expr->data.floatval;
-
- for (; cse; cse = cse->next) {
- if (CMach_CalcFloatDiadicBool(cse->expr->rtype, cse->expr->data.floatval, TK_LOGICAL_EQ, val))
- if (expr->rtype == cse->expr->rtype)
- return cse;
- }
-
- cse = cse_new(expr);
- cse->next = csenodes[EFLOATCONST];
- csenodes[EFLOATCONST] = cse;
- return cse;
-}
-
-static COptCSE *cse_vectorconst(ENode *expr) {
- COptCSE *cse = csenodes[EVECTOR128CONST];
- MWVector128 val = expr->data.vector128val;
-
- for (; cse; cse = cse->next) {
- if (CMach_CalcVectorDiadicBool(cse->expr->rtype, &cse->expr->data.vector128val, TK_LOGICAL_EQ, &val))
- if (expr->rtype == cse->expr->rtype)
- return cse;
- }
-
- cse = cse_new(expr);
- cse->next = csenodes[EVECTOR128CONST];
- csenodes[EVECTOR128CONST] = cse;
- return cse;
-}
-
-static COptCSE *cse_objref(ENode *expr) {
- COptCSE *cse = csenodes[EOBJREF];
- Object *obj = expr->data.objref;
-
- for (; cse; cse = cse->next) {
- if (cse->expr->data.objref == obj)
- return cse;
- }
-
- cse = cse_new(expr);
- cse->next = csenodes[EOBJREF];
- csenodes[EOBJREF] = cse;
- return cse;
-}
-
-static COptCSE *cse_add_monadic_node(ENode *outer, COptCSE *innercse) {
- COptCSE *cse;
-
- if (!innercse)
- return NULL;
-
- for (cse = csenodes[outer->type]; cse; cse = cse->next) {
- if (cse->left == innercse && cse->expr->rtype == outer->rtype) {
- CError_ASSERT(524, cse->expr != outer);
- cse->x1C++;
- return cse;
- }
- }
-
- cse = cse_new(outer);
- cse->next = csenodes[outer->type];
- csenodes[outer->type] = cse;
- cse->left = innercse;
- return cse;
-}
-
-static COptCSE *cse_add_typecon_node(ENode *outer, COptCSE *innercse) {
- COptCSE *cse;
-
- if (!innercse)
- return NULL;
-
- for (cse = csenodes[outer->type]; cse; cse = cse->next) {
- if (cse->left == innercse && cse->expr->rtype == outer->rtype) {
- CError_ASSERT(552, cse->expr != outer);
- cse->x1C++;
- return cse;
- }
- }
-
- cse = cse_new(outer);
- cse->next = csenodes[outer->type];
- csenodes[outer->type] = cse;
- cse->left = innercse;
- return cse;
-}
-
-static COptCSE *cse_add_diadic_node(ENode *outer, COptCSE *leftcse, COptCSE *rightcse) {
- COptCSE *cse;
-
- if (!leftcse || !rightcse)
- return NULL;
-
- for (cse = csenodes[outer->type]; cse; cse = cse->next) {
- if (cse->left == leftcse && cse->right == rightcse) {
- CError_ASSERT(581, cse->expr != outer);
- cse->x1C++;
- return cse;
- }
- }
-
- cse = cse_new(outer);
- cse->next = csenodes[outer->type];
- csenodes[outer->type] = cse;
- cse->left = leftcse;
- cse->right = rightcse;
- return cse;
-}
-
-static COptCSE *cse_add_commdiadic_node(ENode *outer, COptCSE *leftcse, COptCSE *rightcse) {
- COptCSE *cse;
-
- if (!leftcse || !rightcse)
- return NULL;
-
- for (cse = csenodes[outer->type]; cse; cse = cse->next) {
- if ((cse->left == leftcse && cse->right == rightcse) || (cse->left == rightcse && cse->right == leftcse)) {
- CError_ASSERT(612, cse->expr != outer);
- cse->x1C++;
- return cse;
- }
- }
-
- cse = cse_new(outer);
- cse->next = csenodes[outer->type];
- csenodes[outer->type] = cse;
- cse->left = leftcse;
- cse->right = rightcse;
- return cse;
-}
-
-static void sfind_objref(ENode *expr) {
- while (1) {
- switch (expr->type) {
- case ETYPCON:
- expr = expr->data.monadic;
- break;
- case EOBJREF:
- objrefnode = expr;
- objrefnodes++;
- return;
- case EADD:
- case ESUB:
- sfind_objref(expr->data.diadic.left);
- expr = expr->data.diadic.right;
- break;
- default:
- return;
- }
- }
-}
-
-static ENode *find_objref_node(ENode *expr) {
- objrefnode = NULL;
- objrefnodes = 0;
- sfind_objref(expr);
- if (objrefnodes == 1)
- return objrefnode;
- else
- return NULL;
-}
-
-static void cse_mem_modify(void) {
- COptCSE *cse;
-
- for (cse = csenodes[EINDIRECT]; cse; cse = cse->next) {
- if (ENODE_IS(cse->expr->data.monadic, EOBJREF)) {
- Object *obj = cse->expr->data.monadic->data.objref;
- CError_ASSERT(672, obj->datatype != DALIAS);
- if (obj->datatype == DLOCAL && !obj->u.var.info->noregister)
- continue;
- }
-
- cse_inval(cse);
- }
-}
-
-static void cse_modify_expression(ENode *expr) {
- if (!expr) {
- short op;
-
- cse_remove();
- for (op = 0; op < MAXEXPR; op++)
- csenodes[op] = NULL;
-
- cselist = NULL;
- freeoheap();
- } else {
- ENode *objnode;
- Object *obj;
- COptCSE *cse;
-
- cse_invals = 1;
- if (ENODE_IS(expr, EINDIRECT) && (objnode = find_objref_node(expr->data.monadic))) {
- do {
- obj = objnode->data.objref;
- cse_remove();
- for (cse = csenodes[EINDIRECT]; cse; cse = cse->next) {
- if ((objnode = find_objref_node(cse->expr->data.monadic)) && obj == objnode->data.objref)
- cse_inval(cse);
- }
-
- objnode = find_objref_node(expr->data.monadic);
- if (!objnode) {
- cse_mem_modify();
- break;
- }
- } while (obj != objnode->data.objref);
- } else {
- cse_remove();
- cse_mem_modify();
- }
- }
-}
-
-static void cse_pascalcall(ENode *expr) {
- ENodeList *list;
-
- for (list = expr->data.funccall.args; list; list = list->next)
- cse_expression(list->node);
-
- if (ENODE_IS(expr, EFUNCCALLP))
- cse_expression(expr->data.funccall.funcref);
-
- cse_remove();
- cse_mem_modify();
-}
-
-static Boolean cse_pusharg(ENodeList *exprs, FuncArg *args) {
- Boolean result;
-
- if (!exprs)
- return 1;
-
- if (args && args != &elipsis && args != &oldstyle)
- args = args->next;
- if (exprs->next)
- result = cse_pusharg(exprs->next, args);
-
- cse_expression(exprs->node);
- return result;
-}
-
-static void cse_ccall(ENode *expr) {
- if (cse_pusharg(expr->data.funccall.args, expr->data.funccall.functype->args)) {
- if (ENODE_IS(expr, EFUNCCALL))
- cse_expression(expr->data.funccall.funcref);
-
- cse_remove();
- cse_mem_modify();
- } else {
- cse_modify_expression(NULL);
- }
-}
-
-static COptCSE *cse_expression(ENode *expr) {
- ENode *save;
- COptCSE *tmp;
- ENodeType nt = expr->type;
-
- switch (nt) {
- case EFUNCCALL:
- cse_ccall(expr);
- return NULL;
- case EFUNCCALLP:
- cse_pascalcall(expr);
- return NULL;
- case EPOSTINC:
- case EPOSTDEC:
- case EPREINC:
- case EPREDEC:
- save = mexpr;
- mexpr = expr;
- CError_ASSERT(816, ENODE_IS(expr->data.monadic, EINDIRECT));
-
- cse_expression(expr->data.monadic->data.monadic);
- cse_modify_expression(expr->data.monadic);
- mexpr = save;
- return NULL;
-
- case EINDIRECT:
- case EMONMIN:
- case EBINNOT:
- case ELOGNOT:
- case EFORCELOAD:
- return cse_append(cse_add_monadic_node(expr, cse_expression(expr->data.monadic)), expr);
-
- case ETYPCON:
- return cse_append(cse_add_typecon_node(expr, cse_expression(expr->data.monadic)), expr);
-
- case EMUL:
- case EMULV:
- case EADDV:
- case EADD:
- case EEQU:
- case ENOTEQU:
- case EAND:
- case EXOR:
- case EOR:
- tmp = cse_expression(expr->data.diadic.left);
- if (expr->type == nt)
- return cse_append(cse_add_commdiadic_node(expr, tmp, cse_expression(expr->data.diadic.right)), expr);
- else
- return NULL;
-
- case EDIV:
- case EMODULO:
- case ESUBV:
- case ESUB:
- case ESHL:
- case ESHR:
- case ELESS:
- case EGREATER:
- case ELESSEQU:
- case EGREATEREQU:
- case EPMODULO:
- case EROTL:
- case EROTR:
- case EBTST:
- tmp = cse_expression(expr->data.diadic.left);
- if (expr->type == nt)
- return cse_append(cse_add_diadic_node(expr, tmp, cse_expression(expr->data.diadic.right)), expr);
- else
- return NULL;
-
- case EASS:
- case EMULASS:
- case EDIVASS:
- case EMODASS:
- case EADDASS:
- case ESUBASS:
- case ESHLASS:
- case ESHRASS:
- case EANDASS:
- case EXORASS:
- case EORASS:
- CError_ASSERT(887, ENODE_IS(expr->data.diadic.left, EINDIRECT));
- save = mexpr;
- mexpr = expr;
- cse_expression(expr->data.diadic.right);
- if (expr->type == nt) {
- cse_expression(expr->data.diadic.left->data.monadic);
- cse_modify_expression(expr->data.diadic.left);
- mexpr = save;
- return NULL;
- } else {
- cse_modify_expression(NULL);
- return NULL;
- }
-
- case ECOMMA:
- cse_expression(expr->data.diadic.left);
- save = mexpr;
- mexpr = expr->data.diadic.right;
- tmp = cse_expression(expr->data.diadic.right);
- mexpr = save;
- return tmp;
-
- case EINTCONST:
- return cse_intconst(expr);
- case EFLOATCONST:
- return cse_floatconst(expr);
- case EVECTOR128CONST:
- return cse_vectorconst(expr);
- case EOBJREF:
- return cse_objref(expr);
-
- case EBITFIELD:
- cse_modify_expression(NULL);
- return NULL;
-
- case ECOND:
- cse_expression(expr->data.cond.cond);
- cse_modify_expression(NULL);
- return NULL;
-
- case ENULLCHECK:
- cse_expression(expr->data.nullcheck.nullcheckexpr);
- cse_modify_expression(NULL);
- return NULL;
-
- case ELAND:
- case ELOR:
- cse_expression(expr->data.diadic.left);
- cse_modify_expression(NULL);
- return NULL;
-
- case ESTRINGCONST:
- case ELABEL:
- return NULL;
-
- case EPRECOMP:
- CError_FATAL(948);
-
- default:
- CError_FATAL(951);
- return NULL;
- }
-}
-
-static void cse_block(COptBlock *block) {
- Statement *stmt;
- COptBlock *check;
- COptBlockList *scan;
- COptBlock *best;
- short i;
- SInt32 counter;
- UInt32 starttime;
-
- starttime = COS_GetTicks();
- counter = 0;
-
- while (1) {
- cse_invals = 0;
- currentblock = block;
- block->x1E = 1;
-
- for (stmt = block->stmt, i = block->x1C; i > 0; stmt = stmt->next, i--) {
- switch (stmt->type) {
- case ST_EXPRESSION:
- case ST_SWITCH:
- case ST_IFGOTO:
- case ST_IFNGOTO:
- mexpr = stmt->expr;
- cse_expression(mexpr);
- break;
- case ST_RETURN:
- mexpr = stmt->expr;
- if (mexpr)
- cse_expression(mexpr);
- break;
- }
- }
-
- i = 0;
- for (scan = block->blocks2; scan; scan = scan->next) {
- check = scan->block;
- if (!check->x1E && check->blocks && !check->blocks->next && check->blocks->block == block) {
- best = check;
- i++;
- }
- }
-
- if (i != 1)
- break;
-
- block = best;
- if (COS_GetTicks() > (starttime + 60)) {
- if (counter++ & 1) {
- if (CWDisplayLines(cparamblkptr->context, lines))
- CError_UserBreak();
- } else {
- if (CWDisplayLines(cparamblkptr->context, lines + 1))
- CError_UserBreak();
- }
- starttime = COS_GetTicks();
- }
-
- if (cse_invals)
- cse_cleanup();
- }
-
- cse_remove();
-}
-
-static void CSE(void) {
- COptBlock *block;
-
- for (block = basicblocks->next; block; block = block->next)
- block->x1E = 0;
-
- for (block = basicblocks->next; block; block = block->next) {
- if (!block->x1E) {
- short op;
-
- for (op = 0; op < MAXEXPR; op++)
- csenodes[op] = NULL;
-
- cselist = NULL;
- cse_found = 0;
- cse_block(block);
- freeoheap();
- }
- }
-}
-
-static short TestSetBit(short *set, short bit) {
- return set[bit >> 4] & bitmasks[bit & 15];
-}
-
-static void SetSetBit(short *set, short bit) {
- set[bit >> 4] |= bitmasks[bit & 15];
-}
-
-UInt32 RegAllocMask(short var) {
- COptBlock *block;
- UInt32 mask = 0;
-
- for (block = basicblocks; block; block = block->next) {
- if (TestSetBit(block->set1, var) || TestSetBit(block->set2, var))
- mask |= block->allocmask;
- }
-
- return mask;
-}
-
-void MarkRegAllocMask(short var, short bit, Boolean flag) {
- COptBlock *block;
- UInt32 mask = 1 << bit;
-
- if (flag) {
- for (block = basicblocks; block; block = block->next) {
- if (TestSetBit(block->set1, var) || TestSetBit(block->set2, var))
- block->allocmask |= mask;
- }
- } else {
- for (block = basicblocks; block; block = block->next) {
- block->allocmask |= mask;
- }
- }
-}
-
-static COptBlock *newblock(void) {
- COptBlock *block;
- short i;
- short max;
-
- block = lalloc(sizeof(COptBlock) + (setbytes * 2));
- block->x1E = 0;
- block->next = NULL;
- block->blocks = NULL;
- block->blocks2 = NULL;
- block->allocmask = 0;
- block->set1 = (short *) (((long) block) + sizeof(COptBlock));
- block->set2 = (short *) (((long) block) + setbytes + sizeof(COptBlock));
-
- for (i = 0, max = setbytes / 2; i < max; i++) {
- block->set1[i] = 0;
- block->set2[i] = 0;
- }
-
- return block;
-}
-
-static void MarkFollow(COptBlock *block) {
- COptBlockList *list;
-
-restart:
- block->x1E = 1;
- if ((list = block->blocks2)) {
- while (1) {
- if (!list->block->x1E) {
- if (!list->next) {
- block = list->block;
- goto restart;
- }
- MarkFollow(list->block);
- list = list->next;
- } else {
- list = list->next;
- if (!list)
- break;
- }
- }
- }
-}
-
-static Boolean CheckInit(short var) {
- Boolean result;
- COptBlock *block;
-
- result = 1;
- for (block = basicblocks; block; block = block->next) {
- if (!block->x1E && TestSetBit(block->set2, var))
- MarkFollow(block);
- }
-
- for (block = basicblocks; block; block = block->next) {
- if (!block->x1E) {
- if (TestSetBit(block->set1, var))
- result = 0;
- } else {
- block->x1E = 0;
- }
- }
-
- return result;
-}
-
-static void CheckVarInit(void) {
- COptBlock *block;
- VarInfo *vi;
- ObjectList *list;
-
- for (block = basicblocks; block; block = block->next)
- block->x1E = 0;
-
- for (list = locals; list; list = list->next) {
- if (list->object->datatype == DLOCAL && !IsTempName(list->object->name) && !is_volatile_object(list->object)) {
- vi = list->object->u.var.info;
- if (vi->used && !CheckInit(vi->varnumber)) {
- if (!IS_TYPE_CLASS(list->object->type) || !CClass_IsEmpty(TYPE_CLASS(list->object->type))) {
- CError_SetErrorToken(&vi->deftoken);
- CError_Warning(CErrorStr185, list->object->name->name);
- }
- }
- }
- }
-}
-
-static void AddVar(Object *obj, Boolean whichSet) {
- VarInfo *vi;
-
- if (obj->datatype == DLOCAL) {
- vi = obj->u.var.info;
- if (!whichSet) {
- SetSetBit(currentblock->set1, vi->varnumber);
- } else {
- if (!TestSetBit(currentblock->set1, vi->varnumber))
- SetSetBit(currentblock->set2, vi->varnumber);
- }
- }
-}
-
-static void CheckExpr(ENode *expr) {
- ENodeList *list;
-
- while (1) {
- switch (expr->type) {
- case EINDIRECT:
- if (ENODE_IS(expr->data.monadic, EOBJREF)) {
- AddVar(expr->data.monadic->data.objref, 0);
- return;
- }
- expr = expr->data.monadic;
- break;
- case EOBJREF:
- AddVar(expr->data.objref, 1);
- return;
- case EFUNCCALL:
- case EFUNCCALLP:
- CheckExpr(expr->data.funccall.funcref);
- for (list = expr->data.funccall.args; list; list = list->next)
- CheckExpr(list->node);
- return;
- case ECOND:
- CheckExpr(expr->data.cond.cond);
- CheckExpr(expr->data.cond.expr1);
- CheckExpr(expr->data.cond.expr2);
- return;
- case EASS:
- if (ENODE_IS_INDIRECT_TO(expr->data.diadic.left, EOBJREF)) {
- CheckExpr(expr->data.diadic.right);
- AddVar(expr->data.diadic.left->data.monadic->data.objref, 1);
- return;
- }
- case EMUL:
- case EMULV:
- case EDIV:
- case EMODULO:
- case EADDV:
- case ESUBV:
- case EADD:
- case ESUB:
- case ESHL:
- case ESHR:
- case ELESS:
- case EGREATER:
- case ELESSEQU:
- case EGREATEREQU:
- case EEQU:
- case ENOTEQU:
- case EAND:
- case EXOR:
- case EOR:
- case ELAND:
- case ELOR:
- case EMULASS:
- case EDIVASS:
- case EMODASS:
- case EADDASS:
- case ESUBASS:
- case ESHLASS:
- case ESHRASS:
- case EANDASS:
- case EXORASS:
- case EORASS:
- case ECOMMA:
- case EPMODULO:
- case EROTL:
- case EROTR:
- case EBCLR:
- case EBTST:
- case EBSET:
- CheckExpr(expr->data.diadic.left);
- expr = expr->data.diadic.right;
- break;
- case EPOSTINC:
- case EPOSTDEC:
- case EPREINC:
- case EPREDEC:
- case EMONMIN:
- case EBINNOT:
- case ELOGNOT:
- case EFORCELOAD:
- case ETYPCON:
- case EBITFIELD:
- expr = expr->data.monadic;
- break;
- case ENULLCHECK:
- CheckExpr(expr->data.nullcheck.nullcheckexpr);
- expr = expr->data.nullcheck.condexpr;
- break;
- case EINTCONST:
- case EFLOATCONST:
- case ESTRINGCONST:
- case EPRECOMP:
- case ELABEL:
- case EVECTOR128CONST:
- return;
- default:
- CError_FATAL(1332);
- }
- }
-}
-
-static short CheckPath(COptBlock *block, short var) {
- COptBlockList *list;
-
- if (block->x1E)
- return TestSetBit(block->set1, var);
-
- block->x1E = 1;
- if (TestSetBit(block->set1, var))
- return -1;
- if (TestSetBit(block->set2, var))
- return 0;
-
- for (list = block->blocks2; list; list = list->next) {
- if (CheckPath(list->block, var)) {
- SetSetBit(block->set1, var);
- return -1;
- }
- }
-
- return 0;
-}
-
-static void MarkPre(COptBlock *block, short var) {
- COptBlockList *list;
-
-restart:
- block->x1E = 1;
- for (list = block->blocks; list; list = list->next) {
- if (!list->block->x1E) {
- if (!TestSetBit(list->block->set2, var)) {
- SetSetBit(list->block->set1, var);
- if (!list->next) {
- block = list->block;
- goto restart;
- }
- MarkPre(list->block, var);
- } else {
- list->block->x1E = 1;
- }
- }
- }
-}
-
-static void CheckVarUsage(void) {
- short local;
- COptBlock *block;
- short counter;
-
- for (currentblock = basicblocks; currentblock; currentblock = currentblock->next) {
- Statement *stmt = currentblock->stmt;
- if (currentblock->x1C > 0 && stmt->type == ST_LABEL && (stmt->flags & StmtFlag_1)) {
- short i;
- for (i = 0; i < localcount; i++)
- SetSetBit(currentblock->set2, i);
- }
-
- for (counter = currentblock->x1C; counter > 0; counter--) {
- if (stmt->type >= ST_EXPRESSION && stmt->type <= ST_GOTOEXPR && stmt->expr)
- CheckExpr(stmt->expr);
- stmt = stmt->next;
- }
- }
-
- for (local = 0; local < localcount; local++) {
- for (block = basicblocks; block; block = block->next) {
- if (!block->x1E && TestSetBit(block->set1, local))
- MarkPre(block, local);
- }
- for (block = basicblocks; block; block = block->next) {
- block->x1E = 0;
- }
- }
-}
-
-static void SplitCommaExpressions(void) {
- COptBlock *block;
- Statement *stmt;
- ENode *expr;
- Statement *stmtcopy;
- short counter;
- Boolean flag;
-
- block = basicblocks->next;
- while (block) {
- stmt = block->stmt;
- counter = block->x1C;
- flag = 1;
- while (counter > 0) {
- if (stmt->type >= ST_EXPRESSION && stmt->type <= ST_GOTOEXPR) {
- if ((expr = stmt->expr) && ENODE_IS(expr, ECOMMA)) {
- stmtcopy = lalloc(sizeof(Statement));
- *stmtcopy = *stmt;
- stmt->next = stmtcopy;
- stmt->type = ST_EXPRESSION;
- stmt->expr = expr->data.diadic.left;
- stmtcopy->expr = expr->data.diadic.right;
- block->x1C++;
- flag = 0;
- break;
- }
- }
-
- stmt = stmt->next;
- counter--;
- }
-
- if (flag)
- block = block->next;
- }
-}
-
-static void BasicBlockAnalyze(Statement *stmt) {
- COptBlock *block;
- ObjectList *objlist;
- COptBlockList *scan;
- COptBlockList *list;
- CLabel *label;
- COptBlock *iblock;
- COptBlock *oblock;
- SwitchCase *swcase;
-
- setbytes = 2 * ((localcount - 1) / 16) + 2;
- if (copts.globaloptimizer) {
- setbytes += 32;
- extravars = 0;
- }
-
- block = newblock();
- basicblocks = block;
- block->stmt = NULL;
- block->x1C = 0;
-
- if (stmt) {
- list = lalloc(sizeof(COptBlockList));
- list->next = NULL;
- block->blocks2 = list;
- list->block = (COptBlock *) stmt;
- }
-
- for (objlist = arguments; objlist; objlist = objlist->next) {
- SetSetBit(block->set2, objlist->object->u.var.info->varnumber);
- }
-
- while (stmt) {
- int counter;
-
- block->next = newblock();
- block = block->next;
- block->stmt = stmt;
- counter = 1;
-
- innerLoop:
- switch (stmt->type) {
- case ST_ASM:
- label = InlineAsm_GetReferencedLabel(stmt);
- if (!label)
- goto jumpahead;
- list = lalloc(sizeof(COptBlockList));
- list->next = block->blocks2;
- block->blocks2 = list;
- list->block = (COptBlock *) label->stmt;
- if (stmt->next) {
- list = lalloc(sizeof(COptBlockList));
- list->next = block->blocks2;
- block->blocks2 = list;
- list->block = (COptBlock *) stmt->next;
- }
- stmt = stmt->next;
- block->x1C = counter;
- continue;
- case ST_NOP:
- case ST_LABEL:
- case ST_ENTRY:
- if (stmt->next && stmt->next->type != ST_LABEL) {
- stmt = stmt->next;
- counter++;
- goto innerLoop;
- }
- break;
- case ST_EXPRESSION:
- case ST_BEGINCATCH:
- case ST_ENDCATCH:
- case ST_ENDCATCHDTOR:
- jumpahead:
- if (stmt->next && stmt->next->type == ST_GOTO) {
- stmt = stmt->next;
- counter++;
- goto innerLoop;
- }
- break;
- }
-
- switch (stmt->type) {
- case ST_SWITCH:
- label = ((SwitchInfo *) stmt->label)->defaultlabel;
- if (label != cleanreturnlabel) {
- list = lalloc(sizeof(COptBlockList));
- list->next = block->blocks2;
- block->blocks2 = list;
- list->block = (COptBlock *) label->stmt;
- }
- for (swcase = ((SwitchInfo *) stmt->label)->cases; swcase; swcase = swcase->next) {
- label = swcase->label;
- if (label != cleanreturnlabel) {
- list = lalloc(sizeof(COptBlockList));
- list->next = block->blocks2;
- block->blocks2 = list;
- list->block = (COptBlock *) label->stmt;
- }
- }
- break;
- case ST_RETURN:
- case ST_EXIT:
- case ST_GOTOEXPR:
- break;
- case ST_GOTO:
- case ST_IFGOTO:
- case ST_IFNGOTO:
- case ST_OVF:
- label = stmt->label;
- if (label != cleanreturnlabel) {
- list = lalloc(sizeof(COptBlockList));
- list->next = block->blocks2;
- block->blocks2 = list;
- list->block = (COptBlock *) label->stmt;
- }
- if (stmt->type == ST_GOTO)
- break;
- default:
- if (stmt->next) {
- list = lalloc(sizeof(COptBlockList));
- list->next = block->blocks2;
- block->blocks2 = list;
- list->block = (COptBlock *) stmt->next;
- }
- break;
- }
-
- stmt = stmt->next;
- block->x1C = counter;
- }
-
- for (oblock = basicblocks; oblock; oblock = oblock->next) {
- for (scan = oblock->blocks2; scan; scan = scan->next) {
- stmt = (Statement *) scan->block;
- for (iblock = basicblocks->next; iblock; iblock = iblock->next) {
- if (iblock->stmt == stmt) {
- scan->block = iblock;
- list = lalloc(sizeof(COptBlockList));
- list->next = iblock->blocks;
- iblock->blocks = list;
- list->block = oblock;
- break;
- }
- }
-
- CError_ASSERT(1602, iblock);
- }
- }
-
- SplitCommaExpressions();
- CheckVarUsage();
-}
-
-static CLabel *finallabel(CLabel *label, Statement *stmt) {
- Statement *scan;
-
- for (scan = label->stmt; scan; scan = scan->next) {
- if (scan->type > ST_LABEL) {
- if (scan == stmt)
- return label;
- if (scan->type == ST_GOTO) {
- if (scan->label != label)
- stmtchanged = 1;
- return scan->label;
- }
- return label;
- }
- }
-
- return label;
-}
-
-static void optimizegoto(Statement *stmt) {
- Statement *scan;
-
- for (scan = stmt->next; scan; scan = scan->next) {
- if (stmt->label->stmt == scan) {
- stmt->type = ST_NOP;
- stmtchanged = 1;
- return;
- }
- if (scan->type > ST_LABEL)
- break;
- }
-
- stmt->label = finallabel(stmt->label, stmt);
-}
-
-static void removeif(Statement *stmt, Boolean flag) {
- if (((stmt->type == ST_IFGOTO) && flag) || ((stmt->type == ST_IFNGOTO) && !flag)) {
- Statement *copy = lalloc(sizeof(Statement));
- *copy = *stmt;
- copy->type = ST_GOTO;
- stmt->next = copy;
- }
- stmt->type = ST_EXPRESSION;
- stmtchanged = 1;
-}
-
-static void optimizeif(Statement *stmt) {
- Statement *scan;
- Statement *scan2;
- Boolean flag;
-
- if (iszero(stmt->expr)) {
- removeif(stmt, 0);
- return;
- }
- if (isnotzero(stmt->expr)) {
- removeif(stmt, 1);
- return;
- }
-
- for (scan = stmt->next, flag = 0; scan; scan = scan->next) {
- if (scan->type > ST_LABEL) {
- if (scan->type == ST_GOTO) {
- if (scan->label == stmt->label) {
- stmt->type = ST_EXPRESSION;
- stmtchanged = 1;
- return;
- }
-
- if (!flag) {
- for (scan2 = scan->next; scan2; scan2 = scan2->next) {
- if (scan2->type > ST_LABEL)
- break;
- if (stmt->label->stmt == scan2) {
- stmt->label = scan->label;
- scan->type = ST_NOP;
- if (stmt->type == ST_IFGOTO)
- stmt->type = ST_IFNGOTO;
- else
- stmt->type = ST_IFGOTO;
- stmtchanged = 1;
- stmt->label = finallabel(stmt->label, stmt);
- return;
- }
- }
- }
- } else if (scan->type == ST_RETURN && !scan->expr && !static_for_inlines && !flag) {
- for (scan2 = scan->next; scan2; scan2 = scan2->next) {
- if (scan2->type > ST_LABEL)
- break;
- if (stmt->label->stmt == scan2) {
- stmt->label = cleanreturnlabel;
- needs_cleanup = 1;
- scan->type = ST_NOP;
- if (stmt->type == ST_IFGOTO)
- stmt->type = ST_IFNGOTO;
- else
- stmt->type = ST_IFGOTO;
- stmtchanged = 1;
- return;
- }
- }
- }
- break;
- }
-
- if (scan->type == ST_LABEL)
- flag = 1;
-
- if (stmt->label->stmt == scan) {
- stmt->type = ST_EXPRESSION;
- stmtchanged = 1;
- return;
- }
- }
-
- stmt->label = finallabel(stmt->label, stmt);
-}
-
-static void optimizeswitch(Statement *stmt) {
- SwitchInfo *info;
- SwitchCase *swcase;
-
- info = (SwitchInfo *) stmt->label;
- CError_ASSERT(1746, info && info->cases && info->defaultlabel);
-
- info->defaultlabel = finallabel(info->defaultlabel, stmt);
- for (swcase = info->cases; swcase; swcase = swcase->next)
- swcase->label = finallabel(swcase->label, stmt);
-
- if (ENODE_IS(stmt->expr, EINTCONST)) {
- for (swcase = info->cases; swcase; swcase = swcase->next) {
- if (CInt64_GreaterEqual(swcase->min, stmt->expr->data.intval) && CInt64_LessEqual(swcase->max, stmt->expr->data.intval))
- break;
- }
-
- stmt->type = ST_GOTO;
- stmt->label = swcase ? swcase->label : info->defaultlabel;
- }
-}
-
-static void removeunusedlabels(Statement *stmt) {
- Statement *scan;
- CLabel *label;
- SwitchCase *swcase;
- ExceptionAction *action;
-
- for (scan = stmt; scan; scan = scan->next)
- scan->marked = 0;
-
- for (scan = stmt; scan; scan = scan->next) {
- switch (scan->type) {
- case ST_GOTO:
- case ST_IFGOTO:
- case ST_IFNGOTO:
- case ST_OVF:
- if (scan->label->stmt)
- scan->label->stmt->marked = 1;
- break;
- case ST_SWITCH:
- ((SwitchInfo *) scan->label)->defaultlabel->stmt->marked = 1;
- for (swcase = ((SwitchInfo *) scan->label)->cases; swcase; swcase = swcase->next)
- swcase->label->stmt->marked = 1;
- break;
- case ST_ASM:
- if ((label = InlineAsm_GetReferencedLabel(scan)))
- label->stmt->marked = 1;
- if ((label = InlineAsm_GetReferencedLabel2(scan)))
- label->stmt->marked = 1;
- break;
- case ST_BEGINLOOP:
- ((LoopInfo *) scan->expr)->stmt->marked = 1;
- break;
- case ST_ENDLOOP:
- if (scan->next->type == ST_GOTO && scan->next->next->type == ST_LABEL)
- scan->next->next->marked = 1;
- break;
- default:
- for (action = scan->dobjstack; action; action = action->prev) {
- if (action->type == EAT_CATCHBLOCK) {
- action->data.catch_block.catch_label->stmt->marked = 1;
- action->data.catch_block.catch_label->stmt->flags = action->data.catch_block.catch_label->stmt->flags | StmtFlag_1;
- } else if (action->type == EAT_SPECIFICATION) {
- action->data.specification.unexp_label->stmt->marked = 1;
- action->data.specification.unexp_label->stmt->flags = action->data.specification.unexp_label->stmt->flags | StmtFlag_1;
- }
- }
- }
- }
-
- for (scan = stmt; scan; scan = scan->next) {
- if (scan->type == ST_LABEL && !scan->marked && !(scan->flags & StmtFlag_1)) {
- scan->type = ST_NOP;
- stmtchanged = 1;
- }
- }
-}
-
-static void optimizebranches(Statement *stmt) {
- removeunusedlabels(stmt);
- while (stmt) {
- switch (stmt->type) {
- case ST_GOTO:
- optimizegoto(stmt);
- break;
- case ST_IFGOTO:
- case ST_IFNGOTO:
- optimizeif(stmt);
- break;
- case ST_SWITCH:
- optimizeswitch(stmt);
- break;
- }
- stmt = stmt->next;
- }
-}
-
-void SetVarUsage(Object *obj, Boolean noregister) {
- VarInfo *vi;
- CError_ASSERT(1875, obj->datatype != DALIAS);
-
- if (obj->datatype == DLOCAL || obj->datatype == DNONLAZYPTR) {
- vi = obj->u.var.info;
- vi->used = 1;
- if (!copts.globaloptimizer) {
- if (copts.optimizesize)
- vi->usage++;
- else
- vi->usage += curstmtvalue;
- }
-
- if (noregister)
- vi->noregister = 1;
- }
-}
-
-static void checkexpression(ENode *expr) {
- ENodeList *list;
-
- while (1) {
- switch (expr->type) {
- case EOBJREF:
- SetVarUsage(expr->data.objref, 1);
- return;
- case EINDIRECT:
- if (ENODE_IS(expr->data.monadic, EOBJREF)) {
- SetVarUsage(expr->data.monadic->data.objref, 0);
- return;
- }
- expr = expr->data.monadic;
- break;
- case EFUNCCALL:
- case EFUNCCALLP:
- copt_isleaffunction = 0;
- checkexpression(expr->data.funccall.funcref);
- for (list = expr->data.funccall.args; list; list = list->next)
- checkexpression(list->node);
- return;
- case ECOND:
- case ECONDASS:
- checkexpression(expr->data.cond.cond);
- checkexpression(expr->data.cond.expr1);
- checkexpression(expr->data.cond.expr2);
- return;
- case EMUL:
- case EMULV:
- case EDIV:
- case EMODULO:
- case EADDV:
- case ESUBV:
- case EADD:
- case ESUB:
- case ESHL:
- case ESHR:
- case ELESS:
- case EGREATER:
- case ELESSEQU:
- case EGREATEREQU:
- case EEQU:
- case ENOTEQU:
- case EAND:
- case EXOR:
- case EOR:
- case ELAND:
- case ELOR:
- case EASS:
- case EMULASS:
- case EDIVASS:
- case EMODASS:
- case EADDASS:
- case ESUBASS:
- case ESHLASS:
- case ESHRASS:
- case EANDASS:
- case EXORASS:
- case EORASS:
- case ECOMMA:
- case EPMODULO:
- case EROTL:
- case EROTR:
- case EBCLR:
- case EBTST:
- case EBSET:
- checkexpression(expr->data.diadic.left);
- expr = expr->data.diadic.right;
- break;
- case EPOSTINC:
- case EPOSTDEC:
- case EPREINC:
- case EPREDEC:
- case EMONMIN:
- case EBINNOT:
- case ELOGNOT:
- case EFORCELOAD:
- case ETYPCON:
- case EBITFIELD:
- expr = expr->data.monadic;
- break;
- case ENULLCHECK:
- checkexpression(expr->data.nullcheck.nullcheckexpr);
- expr = expr->data.nullcheck.condexpr;
- break;
- case EINTCONST:
- case EFLOATCONST:
- case EPRECOMP:
- case ELABEL:
- case EVECTOR128CONST:
- return;
- case ESTRINGCONST:
- return;
- default:
- CError_FATAL(1998);
- }
- }
-}
-
-static void checklocalusage(Statement *stmt) {
- Statement *scan;
-
- for (scan = stmt; scan; scan = scan->next) {
- if (scan->type >= ST_EXPRESSION && scan->type <= ST_GOTOEXPR && scan->expr) {
- curstmtvalue = scan->value;
- checkexpression(scan->expr);
- } else if (scan->type == ST_ASM) {
- curstmtvalue = scan->value;
- InlineAsm_CheckLocalUsage(scan);
- }
- }
-}
-
-static void colorcode(Statement *stmt) {
- CLabel *label;
- SwitchCase *swcase;
-
- while (stmt && !stmt->marked) {
- stmt->marked = 1;
- switch (stmt->type) {
- case ST_GOTOEXPR:
- return;
- case ST_IFGOTO:
- case ST_IFNGOTO:
- case ST_OVF:
- colorcode(stmt->label->stmt);
- break;
- case ST_GOTO:
- case ST_EXIT:
- stmt = stmt->label->stmt;
- continue;
- case ST_RETURN:
- return;
- case ST_SWITCH:
- for (swcase = ((SwitchInfo *) stmt->label)->cases; swcase; swcase = swcase->next)
- colorcode(swcase->label->stmt);
- stmt = ((SwitchInfo *) stmt->label)->defaultlabel->stmt;
- continue;
- case ST_ASM:
- if ((label = InlineAsm_GetReferencedLabel(stmt)))
- colorcode(label->stmt);
- if ((label = InlineAsm_GetReferencedLabel2(stmt)))
- colorcode(label->stmt);
- break;
- case ST_ENDLOOP:
- if (stmt->next && stmt->next->type == ST_GOTO) {
- stmt = stmt->next;
- stmt->marked = 1;
- }
- break;
- case ST_NOP:
- case ST_LABEL:
- case ST_EXPRESSION:
- case ST_ENTRY:
- case ST_BEGINCATCH:
- case ST_ENDCATCH:
- case ST_ENDCATCHDTOR:
- case ST_BEGINLOOP:
- break;
- default:
- CError_FATAL(2096);
- }
- stmt = stmt->next;
- }
-}
-
-static void removeunusedcode(Statement *stmt) {
- Statement *scan;
-
- for (scan = stmt; scan; scan = scan->next)
- scan->marked = 0;
-
- colorcode(stmt);
- for (scan = stmt; scan; scan = scan->next) {
- if (!scan->marked && (scan->flags & StmtFlag_1))
- colorcode(scan);
- }
-
- for (scan = stmt; scan; scan = scan->next) {
- if (!scan->marked && scan->type != ST_NOP) {
- scan->type = ST_NOP;
- stmtchanged = 1;
- }
- }
-}
-
-static void COpt_ReturnCheck(Object *obj, Statement *stmt) {
- if ((copts.pedantic || copts.cplusplus) && obj && TYPE_FUNC(obj->type)->functype != &stvoid) {
- while (stmt) {
- if (!stmt->next && stmt->type != ST_GOTO && stmt->type != ST_RETURN) {
- CError_Warning(CErrorStr184);
- break;
- }
-
- if (stmt->type == ST_RETURN && !stmt->expr && !(stmt->flags & StmtFlag_8)) {
- CError_Warning(CErrorStr184);
- break;
- }
-
- stmt = stmt->next;
- }
- }
-}
-
-static void COpt_Optimize(Object *obj, Statement *stmt) {
- Statement **ptr;
-
- do {
- stmtchanged = 0;
- optimizebranches(stmt->next);
- removeunusedcode(stmt->next);
- } while (stmtchanged);
-
- ptr = &stmt->next;
- while (*ptr) {
- if ((*ptr)->type == ST_NOP)
- *ptr = (*ptr)->next;
- else
- ptr = &(*ptr)->next;
- }
-}
-
-static void COpt_ELABELCallBack(ENode *expr) {
- CError_ASSERT(2195, expr->data.label->stmt && expr->data.label->stmt->type == ST_LABEL);
- expr->data.label->stmt->flags = expr->data.label->stmt->flags | StmtFlag_1;
-}
-
-void COpt_SimpleOptimizer(Object *obj, Statement *stmt) {
- Statement *scan;
-
- for (scan = stmt; scan; scan = scan->next) {
- if ((scan->type >= ST_EXPRESSION && scan->type <= ST_GOTOEXPR) && scan->expr)
- CExpr_SearchExprTree(scan->expr, COpt_ELABELCallBack, 1, ELABEL);
- }
-
- static_for_inlines = 1;
- cleanreturnlabel = NULL;
- COpt_Optimize(obj, stmt);
- COpt_ReturnCheck(obj, stmt);
-}
-
-Statement *COpt_Optimizer(Object *obj, Statement *stmt) {
- copt_isleaffunction = 1;
- if (copts.globaloptimizer)
- stmt = IRO_Optimizer(obj, stmt);
-
- static_for_inlines = 0;
- COpt_Optimize(obj, stmt);
-
- if (obj && !(obj->qual & Q_INLINE))
- COpt_ReturnCheck(obj, stmt);
-
- checklocalusage(stmt->next);
- return stmt;
-}