summaryrefslogtreecommitdiff
path: root/compiler_and_linker/FrontEnd/Optimizer/IroEval.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/FrontEnd/Optimizer/IroEval.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/FrontEnd/Optimizer/IroEval.c')
-rw-r--r--compiler_and_linker/FrontEnd/Optimizer/IroEval.c914
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;
+}