diff options
Diffstat (limited to 'compiler_and_linker/FrontEnd/Optimizer/IroEval.c')
-rw-r--r-- | compiler_and_linker/FrontEnd/Optimizer/IroEval.c | 914 |
1 files changed, 914 insertions, 0 deletions
diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroEval.c b/compiler_and_linker/FrontEnd/Optimizer/IroEval.c new file mode 100644 index 0000000..aba64e1 --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroEval.c @@ -0,0 +1,914 @@ +#include "IroEval.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "IroFlowgraph.h" +#include "IroLinearForm.h" +#include "IroMalloc.h" +#include "IroPointerAnalysis.h" +#include "IroUtil.h" +#include "IroVars.h" +#include "compiler/enode.h" +#include "compiler/objects.h" +#include "compiler/types.h" + +static Boolean IsAssociativeENodeType[MAXEXPR]; + +void IRO_InitializeIsAssociativeENodeTypeArray(void) { + int i; + + for (i = 0; i < MAXEXPR; i++) + IsAssociativeENodeType[i] = 0; + + IsAssociativeENodeType[EPOSTINC] = 0; + IsAssociativeENodeType[EPOSTDEC] = 0; + IsAssociativeENodeType[EPREINC] = 0; + IsAssociativeENodeType[EPREDEC] = 0; + IsAssociativeENodeType[EINDIRECT] = 0; + IsAssociativeENodeType[EMONMIN] = 0; + IsAssociativeENodeType[EBINNOT] = 0; + IsAssociativeENodeType[ELOGNOT] = 0; + IsAssociativeENodeType[EFORCELOAD] = 0; + IsAssociativeENodeType[EMUL] = 1; + IsAssociativeENodeType[EMULV] = 1; + IsAssociativeENodeType[EDIV] = 0; + IsAssociativeENodeType[EMODULO] = 0; + IsAssociativeENodeType[EADDV] = 1; + IsAssociativeENodeType[ESUBV] = 0; + IsAssociativeENodeType[EADD] = 1; + IsAssociativeENodeType[ESUB] = 0; + IsAssociativeENodeType[ESHL] = 0; + IsAssociativeENodeType[ESHR] = 0; + IsAssociativeENodeType[ELESS] = 0; + IsAssociativeENodeType[EGREATER] = 0; + IsAssociativeENodeType[ELESSEQU] = 0; + IsAssociativeENodeType[EGREATEREQU] = 0; + IsAssociativeENodeType[EEQU] = 0; + IsAssociativeENodeType[ENOTEQU] = 0; + IsAssociativeENodeType[EAND] = 1; + IsAssociativeENodeType[EXOR] = 1; + IsAssociativeENodeType[EOR] = 1; + IsAssociativeENodeType[ELAND] = 0; + IsAssociativeENodeType[ELOR] = 0; + IsAssociativeENodeType[EASS] = 0; + IsAssociativeENodeType[EMULASS] = 0; + IsAssociativeENodeType[EDIVASS] = 0; + IsAssociativeENodeType[EMODASS] = 0; + IsAssociativeENodeType[EADDASS] = 0; + IsAssociativeENodeType[ESUBASS] = 0; + IsAssociativeENodeType[ESHLASS] = 0; + IsAssociativeENodeType[ESHRASS] = 0; + IsAssociativeENodeType[EANDASS] = 0; + IsAssociativeENodeType[EXORASS] = 0; + IsAssociativeENodeType[EORASS] = 0; + IsAssociativeENodeType[ECOMMA] = 0; + IsAssociativeENodeType[EPMODULO] = 0; + IsAssociativeENodeType[EROTL] = 0; + IsAssociativeENodeType[EROTR] = 0; + IsAssociativeENodeType[EBCLR] = 0; + IsAssociativeENodeType[EBTST] = 0; + IsAssociativeENodeType[EBSET] = 0; + IsAssociativeENodeType[ETYPCON] = 0; + IsAssociativeENodeType[EBITFIELD] = 0; + IsAssociativeENodeType[EINTCONST] = 0; + IsAssociativeENodeType[EFLOATCONST] = 0; + IsAssociativeENodeType[ESTRINGCONST] = 0; + IsAssociativeENodeType[ECOND] = 0; + IsAssociativeENodeType[EFUNCCALL] = 0; + IsAssociativeENodeType[EFUNCCALLP] = 0; + IsAssociativeENodeType[EOBJREF] = 0; + IsAssociativeENodeType[EMFPOINTER] = 0; + IsAssociativeENodeType[ENULLCHECK] = 0; + IsAssociativeENodeType[EPRECOMP] = 0; + IsAssociativeENodeType[ETEMP] = 0; + IsAssociativeENodeType[EARGOBJ] = 0; + IsAssociativeENodeType[ELOCOBJ] = 0; + IsAssociativeENodeType[ELABEL] = 0; + IsAssociativeENodeType[ESETCONST] = 0; + IsAssociativeENodeType[ENEWEXCEPTION] = 0; + IsAssociativeENodeType[ENEWEXCEPTIONARRAY] = 0; + IsAssociativeENodeType[EOBJLIST] = 0; + IsAssociativeENodeType[EMEMBER] = 0; + IsAssociativeENodeType[ETEMPLDEP] = 0; + IsAssociativeENodeType[EINSTRUCTION] = 0; + IsAssociativeENodeType[EDEFINE] = 0; + IsAssociativeENodeType[EREUSE] = 0; + IsAssociativeENodeType[EASSBLK] = 0; + IsAssociativeENodeType[EVECTOR128CONST] = 0; + IsAssociativeENodeType[ECONDASS] = 0; +} + +void IRO_TruncateValueToType(CInt64 *val, Type *type) { + if (IRO_IsUnsignedType(type)) { + switch (type->size) { + case 1: + CInt64_ConvertUInt8(val); + break; + case 2: + CInt64_ConvertUInt16(val); + break; + case 4: + CInt64_ConvertUInt32(val); + break; + } + } else { + switch (type->size) { + case 1: + CInt64_ConvertInt8(val); + break; + case 2: + CInt64_ConvertInt16(val); + break; + case 4: + CInt64_ConvertInt32(val); + break; + } + } +} + +void IRO_TruncateBitfieldValueToType(CInt64 *val, Type *type, Type *type2) { + UInt32 limit; + UInt32 i; + UInt32 j; + CInt64 work; + + work = cint64_zero; + limit = TYPE_BITFIELD(type2)->bitlength; + for (i = 0; i < limit; i++) + work = CInt64_Or(work, CInt64_Shl(cint64_one, IRO_MakeULong(i))); + *val = CInt64_And(*val, work); + + if (!IRO_IsUnsignedType(type)) { + work = cint64_zero; + for (j = 0; j <= (i - 1); j++) { + if (j == (i - 1)) + work = CInt64_Or(work, CInt64_Shl(cint64_one, IRO_MakeULong(j))); + } + if (CInt64_NotEqual(CInt64_And(work, *val), cint64_zero)) { + for (j = i - 1; j < 64; j++) + *val = CInt64_Or(*val, CInt64_Shl(cint64_one, IRO_MakeULong(j))); + } + } + + IRO_TruncateValueToType(val, type); +} + +void IRO_ConstantFolding(void) { + IROLinear *nd; + ENode *expr; + int isCompare; + int flag; + CInt64 val; + + for (nd = IRO_FirstLinear; nd; nd = nd->next) { + switch (nd->type) { + case IROLinearOp1Arg: + if (IRO_IsIntConstant(nd->u.monadic)) { + expr = NULL; + flag = 0; + val = nd->u.monadic->u.node->data.intval; + if (nd->nodetype == ETYPCON && IS_TYPE_FLOAT(nd->rtype)) { + expr = IRO_NewENode(EFLOATCONST); + if (!IRO_IsUnsignedType(nd->u.monadic->rtype)) + expr->data.floatval.value = CInt64_ConvertToLongDouble(&val); + else + expr->data.floatval.value = CInt64_ConvertUToLongDouble(&val); + expr->rtype = nd->rtype; + } else { + switch (nd->nodetype) { + case ETYPCON: + flag = 1; + break; + case ELOGNOT: + val = CInt64_Not(val); + flag = 1; + break; + case EBINNOT: + val = CInt64_Inv(val); + flag = 1; + break; + case EMONMIN: + val = CInt64_Neg(val); + flag = 1; + break; + } + + if (flag) { + IRO_TruncateValueToType(&val, nd->rtype); + expr = IRO_NewENode(EINTCONST); + expr->rtype = nd->rtype; + expr->data.intval = val; + } + } + + if (expr) { + nd->u.monadic->type = IROLinearNop; + nd->type = IROLinearOperand; + nd->u.node = expr; + } + } + break; + + case IROLinearOp2Arg: + if (IRO_IsIntConstant(nd->u.diadic.left) && !IRO_IsIntConstant(nd->u.diadic.right) && IsAssociativeENodeType[nd->nodetype]) { + IROLinear *tmp = nd->u.diadic.right; + nd->u.diadic.right = nd->u.diadic.left; + nd->u.diadic.left = tmp; + } + + if (IRO_IsIntConstant(nd->u.diadic.right) && nd->nodetype == ESUB) { + nd->nodetype = EADD; + if (IRO_IsIntConstant(nd->u.diadic.right)) { + CInt64 v; + v = CInt64_Neg(nd->u.diadic.right->u.node->data.intval); + nd->u.diadic.right->u.node->data.intval = v; + } else { + Float f; + f = CMach_CalcFloatMonadic( + nd->u.diadic.right->rtype, + '-', + nd->u.diadic.right->u.node->data.floatval); + nd->u.diadic.right->u.node->data.floatval = f; + } + } + + if ( + IRO_IsIntConstant(nd->u.diadic.right) && + IsAssociativeENodeType[nd->nodetype] && + nd->u.diadic.left->type == IROLinearOp2Arg && + nd->u.diadic.left->nodetype == nd->nodetype && + nd->u.diadic.left->rtype == nd->rtype && + IRO_IsIntConstant(nd->u.diadic.left->u.diadic.right) && + nd->u.diadic.left->u.diadic.right->rtype == nd->u.diadic.right->rtype + ) + { + IROLinear *tmp = nd->u.diadic.left; + nd->u.diadic.left = tmp->u.diadic.left; + tmp->u.diadic.left = tmp->u.diadic.right; + tmp->u.diadic.right = nd->u.diadic.right; + tmp->rtype = tmp->u.diadic.left->rtype; + nd->u.diadic.right = tmp; + nd = tmp; + } + + if (IRO_IsIntConstant(nd->u.diadic.left) && IRO_IsIntConstant(nd->u.diadic.right)) { + CInt64 val1 = nd->u.diadic.left->u.node->data.intval; + CInt64 val2 = nd->u.diadic.right->u.node->data.intval; + flag = 0; + switch (nd->nodetype) { + case EADD: + val = CInt64_Add(val1, val2); + flag = 1; + break; + case ESUB: + val = CInt64_Sub(val1, val2); + flag = 1; + break; + case EMUL: + if (IRO_IsUnsignedType(nd->rtype)) + val = CInt64_MulU(val1, val2); + else + val = CInt64_Mul(val1, val2); + flag = 1; + break; + case EDIV: + if (!CInt64_IsZero(&val2)) { + if (IRO_IsUnsignedType(nd->rtype)) + val = CInt64_DivU(val1, val2); + else + val = CInt64_Div(val1, val2); + flag = 1; + } + break; + case EMODULO: + if (!CInt64_IsZero(&val2)) { + if (IRO_IsUnsignedType(nd->rtype)) + val = CInt64_ModU(val1, val2); + else + val = CInt64_Mod(val1, val2); + flag = 1; + } + break; + case ESHL: + val = CInt64_Shl(val1, val2); + flag = 1; + break; + case ESHR: + if (IRO_IsUnsignedType(nd->rtype)) + val = CInt64_ShrU(val1, val2); + else + val = CInt64_Shr(val1, val2); + flag = 1; + break; + case EAND: + val = CInt64_And(val1, val2); + flag = 1; + break; + case EOR: + val = CInt64_Or(val1, val2); + flag = 1; + break; + case EXOR: + val = CInt64_Xor(val1, val2); + flag = 1; + break; + case ELESS: + if (IRO_IsUnsignedType(nd->u.diadic.left->rtype)) + CInt64_SetULong(&val, CInt64_LessU(val1, val2)); + else + CInt64_SetULong(&val, CInt64_Less(val1, val2)); + flag = 1; + break; + case EGREATER: + if (IRO_IsUnsignedType(nd->u.diadic.left->rtype)) + CInt64_SetULong(&val, CInt64_GreaterU(val1, val2)); + else + CInt64_SetULong(&val, CInt64_Greater(val1, val2)); + flag = 1; + break; + case ELESSEQU: + if (IRO_IsUnsignedType(nd->u.diadic.left->rtype)) + CInt64_SetULong(&val, CInt64_LessEqualU(val1, val2)); + else + CInt64_SetULong(&val, CInt64_LessEqual(val1, val2)); + flag = 1; + break; + case EGREATEREQU: + if (IRO_IsUnsignedType(nd->u.diadic.left->rtype)) + CInt64_SetULong(&val, CInt64_GreaterEqualU(val1, val2)); + else + CInt64_SetULong(&val, CInt64_GreaterEqual(val1, val2)); + flag = 1; + break; + case EEQU: + CInt64_SetULong(&val, CInt64_Equal(val1, val2)); + flag = 1; + break; + case ENOTEQU: + CInt64_SetULong(&val, CInt64_NotEqual(val1, val2)); + flag = 1; + break; + } + + if (flag) { + IRO_TruncateValueToType(&val, nd->rtype); + expr = IRO_NewENode(EINTCONST); + expr->rtype = nd->rtype; + expr->data.intval = val; + nd->u.diadic.left->type = IROLinearNop; + nd->u.diadic.right->type = IROLinearNop; + nd->type = IROLinearOperand; + nd->u.node = expr; + } + } + + if (IRO_IsFloatConstant(nd->u.diadic.left) && IRO_IsFloatConstant(nd->u.diadic.right)) { + Float fval1 = nd->u.diadic.left->u.node->data.floatval; + Float fval2 = nd->u.diadic.right->u.node->data.floatval; + Float fval; + flag = 0; + isCompare = 0; + switch (nd->nodetype) { + case EADD: + fval = CMach_CalcFloatDiadic(nd->rtype, fval1, '+', fval2); + flag = 1; + break; + case ESUB: + fval = CMach_CalcFloatDiadic(nd->rtype, fval1, '-', fval2); + flag = 1; + break; + case EMUL: + fval = CMach_CalcFloatDiadic(nd->rtype, fval1, '*', fval2); + flag = 1; + break; + case EDIV: + fval = CMach_CalcFloatDiadic(nd->rtype, fval1, '/', fval2); + flag = 1; + break; + case ELESS: + CInt64_SetULong(&val, CMach_CalcFloatDiadicBool(nd->rtype, fval1, '<', fval2)); + flag = 1; + isCompare = 1; + break; + case EGREATER: + CInt64_SetULong(&val, CMach_CalcFloatDiadicBool(nd->rtype, fval1, '>', fval2)); + flag = 1; + isCompare = 1; + break; + case ELESSEQU: + CInt64_SetULong(&val, CMach_CalcFloatDiadicBool(nd->rtype, fval1, TK_LESS_EQUAL, fval2)); + flag = 1; + isCompare = 1; + break; + case EGREATEREQU: + CInt64_SetULong(&val, CMach_CalcFloatDiadicBool(nd->rtype, fval1, TK_GREATER_EQUAL, fval2)); + flag = 1; + isCompare = 1; + break; + case EEQU: + CInt64_SetULong(&val, CMach_CalcFloatDiadicBool(nd->rtype, fval1, TK_LOGICAL_EQ, fval2)); + flag = 1; + isCompare = 1; + break; + case ENOTEQU: + CInt64_SetULong(&val, CMach_CalcFloatDiadicBool(nd->rtype, fval1, TK_LOGICAL_NE, fval2)); + flag = 1; + isCompare = 1; + break; + } + + if (flag) { + if (isCompare) { + IRO_TruncateValueToType(&val, nd->rtype); + expr = IRO_NewENode(EINTCONST); + expr->rtype = nd->rtype; + expr->data.intval = val; + nd->u.diadic.left->type = IROLinearNop; + nd->u.diadic.right->type = IROLinearNop; + nd->type = IROLinearOperand; + nd->u.node = expr; + } else { + expr = IRO_NewENode(EFLOATCONST); + expr->rtype = nd->rtype; + expr->data.floatval = fval; + nd->u.diadic.left->type = IROLinearNop; + nd->u.diadic.right->type = IROLinearNop; + nd->type = IROLinearOperand; + nd->u.node = expr; + } + } + } + + break; + } + } + + IRO_CheckForUserBreak(); +} + +Boolean IRO_EvaluateConditionals(void) { + IRONode *fnode; + IROLinear *nd; + Boolean changed = 0; + SwitchInfo *switchInfo; + SwitchCase *swcase; + char found; + CInt64 val; + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + nd = fnode->last; + switch (nd->type) { + case IROLinearIf: + case IROLinearIfNot: + if (IRO_IsIntConstant(nd->u.label.x4)) { + Boolean isZero = CInt64_IsZero(&nd->u.label.x4->u.node->data.intval); + IRO_NopOut(nd->u.label.x4); + if ((isZero == 0) == (nd->type == IROLinearIf)) + nd->type = IROLinearGoto; + else + nd->type = IROLinearNop; + changed = 1; + } + break; + + case IROLinearSwitch: + if (IRO_IsIntConstant(nd->u.swtch.x4)) { + val = nd->u.swtch.x4->u.node->data.intval; + switchInfo = nd->u.swtch.info; + swcase = switchInfo->cases; + + IRO_NopOut(nd->u.swtch.x4); + nd->type = IROLinearGoto; + + found = 0; + while (swcase) { + if (CInt64_GreaterEqual(val, swcase->min) && CInt64_LessEqual(val, swcase->max)) { + found = 1; + nd->u.label.label = swcase->label; + break; + } + swcase = swcase->next; + } + + if (!found) + nd->u.label.label = switchInfo->defaultlabel; + changed = 1; + } + break; + } + } + + if (changed) { + IRO_ComputeSuccPred(); + IRO_ComputeDom(); + } + IRO_CheckForUserBreak(); + + return changed; +} + +static int EEquConst(IROLinear *nd) { + return nd && (nd->nodetype == EEQU) && IRO_IsIntConstant(nd->u.diadic.right); +} + +static Object *VEquConst(IROLinear *nd) { + if (EEquConst(nd)) + return IRO_IsVariable(nd->u.diadic.left); + else + return NULL; +} + +static int IsConsecutive(CInt64 a, CInt64 b) { + CInt64 diff; + + if (!CInt64_Equal(a, cint64_min) && !CInt64_Equal(b, cint64_min)) { + diff = CInt64_Sub(b, a); + return CInt64_Equal(diff, cint64_one) || CInt64_Equal(diff, cint64_negone); + } + + return 0; +} + +static IROLinear *findLabel(CLabel *label) { + IROLinear *nd; + + for (nd = IRO_FirstLinear; nd; nd = nd->next) { + if (nd->type == IROLinearLabel && nd->u.label.label == label) + break; + } + + return nd; +} + +static IROLinear *leftLeaveOf(IROLinear *nd) { + switch (nd->type) { + case IROLinearOp1Arg: + return leftLeaveOf(nd->u.monadic); + case IROLinearOp2Arg: + return leftLeaveOf(nd->u.diadic.left); + case IROLinearOperand: + return nd; + default: + return NULL; + } +} + +static int checkNode(IRONode *fnode) { + IROLinear *nd; + + if (fnode->numpred <= 1) { + nd = fnode->first; + while (nd != fnode->last && (nd->type == IROLinearNop || nd->type == IROLinearLabel)) + nd = nd->next; + + if (nd == leftLeaveOf(fnode->last->u.label.x4)) + return 1; + } + + return 0; +} + +static int checkLabel(CLabel *label, IRONode *fnode) { + switch (fnode->last->type) { + case IROLinearIf: + if (label == fnode->last->u.label.label) + return 1; + break; + } + + return 0; +} + +static Object *checkExpr(Object *a, IROLinear *nd) { + Object *b = VEquConst(nd); + + if ((!a || a == b) && !IRO_HasSideEffect(nd)) + return b; + + return NULL; +} + +static int checkStruct(IRONode *fnode1, IRONode *fnode2) { + CLabel *label; + Object *var; + + if (fnode1 == fnode2) + return (int) checkExpr(NULL, fnode1->last->u.label.x4); + + label = fnode1->last->u.label.label; + var = IRO_IsVariable(fnode1->last->u.label.x4->u.monadic); + return checkNode(fnode2) && checkLabel(label, fnode2) && checkExpr(var, fnode2->last->u.label.x4); +} + +typedef struct ReduceInfo { + int x0; + int x4; + Object *x8; + IRONode *fnode; + struct ReduceInfo *next; + CInt64 val; +} ReduceInfo; + +static int MarkPattern1(ReduceInfo *info1, ReduceInfo *info2, CInt64 *val) { + ReduceInfo *scan; + + if (!info2) + return 0; + + if (info2->x0) + return MarkPattern1(info1, info2->next, val); + + for (scan = info1; scan; scan = scan->next) { + if (scan->x0 == 2) { + if (CInt64_Equal(info2->val, scan->val)) { + IRO_NopOut(scan->fnode->last); + IRO_NopOut(scan->fnode->last->u.label.x4); // right union? + scan->x0 = -1; + return MarkPattern1(info1, info2->next, val); + } + + if (IsConsecutive(info2->val, scan->val)) { + info2->x0 = 2; + if (CInt64_Greater(*val, scan->val)) + *val = scan->val; + if (CInt64_Greater(*val, info2->val)) + *val = info2->val; + MarkPattern1(scan->next, info2, val); + MarkPattern1(info1, info1->next, val); + return 1; + } + } + } + + return MarkPattern1(info1, info2->next, val); +} + +static int DoReducible1(ReduceInfo *info, CInt64 val) { + ReduceInfo *last; + ReduceInfo *scan; + IROLinear *right; + IROLinear *left; + IROLinear *typconRight; + IROLinear *typconLeft; + IROLinear *cond; + int count; + + count = 0; + for (scan = info; scan; scan = scan->next) { + if (scan->x0 == 2) { + last = scan; + count++; + } + } + + if (!count) + return 0; + + for (scan = info; scan != last; scan = scan->next) { + if (scan->x0 == 2) { + scan->x0 = -1; + IRO_NopOut(scan->fnode->last); + IRO_NopOut(scan->fnode->last->u.label.x4); + } + } + + last->x0 = -1; + + cond = last->fnode->last; + cond->u.label.x4->nodetype = ELESSEQU; + CInt64_SetULong(&cond->u.label.x4->u.diadic.right->u.node->data.intval, count - 1); + + typconLeft = IRO_NewLinear(IROLinearOp1Arg); + typconLeft->nodetype = ETYPCON; + typconLeft->rtype = IRO_UnsignedType(cond->u.label.x4->u.diadic.left->rtype); + typconLeft->index = ++IRO_NumLinear; + + typconRight = IRO_NewLinear(IROLinearOp1Arg); + *typconRight = *typconLeft; + typconRight->index = ++IRO_NumLinear; + + left = IRO_NewLinear(IROLinearOp2Arg); + left->nodetype = EADD; + left->rtype = cond->u.label.x4->u.diadic.left->rtype; + left->index = ++IRO_NumLinear; + + right = IRO_NewLinear(IROLinearOperand); + right->nodetype = EINTCONST; + right->rtype = cond->u.label.x4->u.diadic.left->rtype; + right->index = ++IRO_NumLinear; + right->u.node = IRO_NewENode(EINTCONST); + right->u.node->data.intval = CInt64_Neg(val); + right->u.node->rtype = right->rtype; + + typconLeft->next = cond->u.label.x4->u.diadic.left->next; + cond->u.label.x4->u.diadic.left->next = right; + right->next = left; + left->next = typconLeft; + + typconRight->next = cond->u.label.x4->u.diadic.right->next; + cond->u.label.x4->u.diadic.right->next = typconRight; + + typconLeft->u.monadic = left; + left->u.diadic.left = cond->u.label.x4->u.diadic.left; + left->u.diadic.right = right; + cond->u.label.x4->u.diadic.left = typconLeft; + typconRight->u.monadic = cond->u.label.x4->u.diadic.right; + cond->u.label.x4->u.diadic.right = typconRight; + + return count; +}; + +static int ReducePattern1(IRONode *startnode, IRONode *endnode) { + ReduceInfo *infos; + ReduceInfo *info; + int changed = 0; + int count; + IRONode *fnode; + int i; + int j; + CInt64 val; + + if (startnode == endnode) + return 0; + + count = 0; + for (fnode = startnode; fnode != endnode; fnode = fnode->nextnode) + count++; + + infos = oalloc(sizeof(ReduceInfo) * ++count); + + fnode = startnode; + for (i = 0; i < count; i++) { + infos[i].x0 = 0; + infos[i].x4 = 0; + infos[i].fnode = fnode; + infos[i].next = NULL; + infos[i].x8 = VEquConst(fnode->last->u.label.x4); + if (infos[i].x8) { + infos[i].val = fnode->last->u.label.x4->u.diadic.right->u.node->data.intval; + infos[i].x4 = 1; + } + fnode = fnode->nextnode; + } + + for (j = 0; j < count; j++) { + if (infos[j].x4 == 1 && infos[j].x8) { + infos[j].x4 = -1; + info = &infos[j]; + for (i = j + 1; i < count; i++) { + if (infos[j].x8 == infos[i].x8) { + info->next = &infos[i]; + info = &infos[i]; + infos[i].x4 = 0; + } + } + } + } + + for (j = 0; j < count; j++) { + if (infos[j].x4 == -1) { + for (info = &infos[j]; info; info = info->next) { + if (info->x0 == 0) { + info->x0 = 2; + val = info->val; + if (MarkPattern1(&infos[j], info->next, &val)) { + changed = 1; + DoReducible1(&infos[j], val); + } else { + info->x0 = -1; + } + } + } + } + } + + return changed; +} + +static int ReduceConsecutiveIf(IRONode *startnode, IRONode *endnode) { + IRONode *node31; + IRONode *node30; + int changed = 0; + + while (startnode != endnode) { + if (checkStruct(startnode, startnode)) + break; + startnode = startnode->nextnode; + } + + node31 = startnode; + if (startnode != endnode) { + node30 = startnode; + node31 = startnode->nextnode; + while (node31 != endnode) { + if (checkStruct(startnode, node31)) { + node30 = node31; + node31 = node31->nextnode; + } else { + node31 = node30; + break; + } + } + + if (node31 == endnode && !checkStruct(startnode, node31)) + node31 = node30; + + if (startnode != node31 && ReducePattern1(startnode, node31)) + changed = 1; + + if (node31 != endnode) + node31 = node31->nextnode; + } + + if (node31 != endnode && ReduceConsecutiveIf(node31, endnode)) + changed = 1; + + return changed; +} + +int IRO_SimplifyConditionals(void) { + IRONode *fnode; + IRONode *start; + IRONode *end; + int changed = 0; + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + if (fnode->last->type == IROLinearIf) { + start = end = fnode; + while (fnode->nextnode && fnode->nextnode->last->type == IROLinearIf) { + end = fnode = fnode->nextnode; + } + if (start != end && ReduceConsecutiveIf(start, end)) + changed = 1; + } + } + + if (changed) { + IRO_ComputeSuccPred(); + IRO_ComputeDom(); + } + IRO_CheckForUserBreak(); + return changed; +} + +Boolean IRO_EvaluateDefinitePointers(Object *func) { + IROLinear *nd; + Boolean result; // r29 + Boolean changed; // r28 + Boolean changed2; // r26 + IROLinear *nd2; // r25 + IROListNode *scan; // r25 + IROListNode *list; + + if (!copts.opt_pointer_analysis) + return 0; + + result = 0; + + do { + changed = 0; + + for (nd = IRO_FirstLinear; nd; nd = nd->next) { + if ( + nd->type == IROLinearOp1Arg && + nd->nodetype == EINDIRECT && + !(nd->flags & IROLF_Assigned) && + nd->pointsToFunction && + !IRO_HasSideEffect(nd) && + PointerAnalysis_IsLinearNodePointerExprDefinite(func, nd) + ) + { + list = NULL; + PointerAnalysis_LookupLinearNodePointerExpr(func, nd, &list); + if (list) { + if (list->list.head && list->list.tail && !list->nextList) { + changed2 = IRO_LocateFather_Cut_And_Paste(nd, list->list.tail) != NULL; + if (changed2) { + IRO_PasteAfter(list->list.head, list->list.tail, nd); + for (nd2 = list->list.head; nd2 != list->list.tail->next; nd2 = nd2->next) { + if (nd2->type == IROLinearOperand && nd2->u.node->type == EOBJREF) { + if (nd2->u.node->data.objref->datatype == DDATA || nd2->u.node->data.objref->datatype == DLOCAL) + IRO_FindVar(nd2->u.node->data.objref, 1, 1); + else + nd2->u.node->data.objref->varptr = NULL; + } + } + } + changed |= changed2; + } + + while (list) { + scan = list->nextList; + IRO_free(list); + list = scan; + } + } + } + } + + result |= changed; + IRO_CheckForUserBreak(); + } while (changed); + + return result; +} |