diff options
author | Ash Wolf <ninji@wuffs.org> | 2023-01-26 11:30:47 +0000 |
---|---|---|
committer | Ash Wolf <ninji@wuffs.org> | 2023-01-26 11:30:47 +0000 |
commit | 094b96ca1df4a035b5f93c351f773306c0241f3f (patch) | |
tree | 95ce05e3ebe816c7ee7996206bb37ea17d8ca33c /compiler_and_linker/unsorted/COptimizer.c | |
parent | fc0c4c0df7b583b55a08317cf1ef6a71d27c0440 (diff) | |
download | MWCC-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.c | 1831 |
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; -} |