+bool exprNode_loopMustExec (exprNode forPred)
+{
+ /*
+ ** Returns true if it is obvious that the loop always executes at least once
+ **
+ ** For now, we only identify the most obvious cases. Should be true anytime
+ ** we can prove init => !test.
+ */
+
+ if (exprNode_isDefined (forPred))
+ {
+ exprNode init, test, inc;
+ exprData edata;
+
+ llassert (forPred->kind == XPR_FORPRED);
+
+ edata = forPred->edata;
+ init = exprData_getTripleInit (edata);
+ test = exprData_getTripleTest (edata);
+ inc = exprData_getTripleInc (edata);
+
+ if (exprNode_isAssign (init))
+ {
+ exprNode loopVar = exprData_getOpA (init->edata);
+ exprNode loopInit = exprData_getOpB (init->edata);
+
+ if (exprNode_isDefined (test) && test->kind == XPR_OP)
+ {
+ exprNode testVar = exprData_getOpA (test->edata);
+ exprNode testVal = exprData_getOpB (test->edata);
+ lltok comp = exprData_getOpTok (test->edata);
+ int opid = lltok_getTok (comp);
+
+ DPRINTF (("Same storage: %s / %s", exprNode_unparse (loopVar),
+ exprNode_unparse (testVar)));
+
+ if (exprNode_sameStorage (loopVar, testVar))
+ {
+ multiVal valinit = exprNode_getValue (loopInit);
+ multiVal valtest = exprNode_getValue (testVal);
+
+ DPRINTF (("Values: %s / %s", multiVal_unparse (valinit),
+ multiVal_unparse (valtest)));
+
+ if (multiVal_isInt (valinit) && multiVal_isInt (valtest))
+ {
+ long v1 = multiVal_forceInt (valinit);
+ long v2 = multiVal_forceInt (valtest);
+
+ DPRINTF (("Here: %ld %ld", v1, v2));
+
+ if ((opid == EQ_OP && v1 < v2)
+ || (opid == NE_OP && v1 != v2)
+ || (opid == TLT && v1 <= v2)
+ || (opid == TGT && v1 >= v2)
+ || (opid == LE_OP && v1 < v2)
+ || (opid == GE_OP && v1 > v2))
+ {
+ DPRINTF (("mustexec if inc"));
+ return TRUE;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ DPRINTF (("loop must exec: FALSE"));
+ return FALSE;
+}
+