#include "compiler/IroEval.h" #include "compiler/CInt64.h" #include "compiler/CMachine.h" #include "compiler/CParser.h" #include "compiler/IroFlowgraph.h" #include "compiler/IroLinearForm.h" #include "compiler/IroMalloc.h" #include "compiler/IroPointerAnalysis.h" #include "compiler/IroUtil.h" #include "compiler/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; }