2022-12-14 00:16:59 +00:00
|
|
|
#include "compiler/IroEmptyLoop.h"
|
|
|
|
#include "compiler/IroDump.h"
|
|
|
|
#include "compiler/IroFlowgraph.h"
|
|
|
|
#include "compiler/IroLinearForm.h"
|
|
|
|
#include "compiler/IroLoop.h"
|
|
|
|
#include "compiler/IroUtil.h"
|
|
|
|
#include "compiler/IroVars.h"
|
|
|
|
#include "compiler/CInt64.h"
|
|
|
|
|
|
|
|
// forward decls
|
|
|
|
static Boolean EmptyLoop(IRONode *fnode);
|
|
|
|
static int CanRemoveRedundantLoop(IROLoop *loop);
|
|
|
|
static int CanRemoveRedundantLoop1(IROLoop *loop);
|
|
|
|
static int RedundantLoopCheck(IROLoop *loop);
|
|
|
|
static int CheckStepOverFlow1_EmptyLoop(IROLoop *loop, CInt64 *val1, CInt64 *val2);
|
|
|
|
static int CheckStepOverFlow2_EmptyLoop(IROLoop *loop, CInt64 *val1, CInt64 *val2);
|
|
|
|
|
|
|
|
void IRO_FindEmptyLoops(void) {
|
|
|
|
IRONode *fnode;
|
|
|
|
IRONode *pred;
|
|
|
|
UInt16 i;
|
|
|
|
UInt16 x;
|
|
|
|
|
|
|
|
for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
|
|
|
|
x = 0;
|
|
|
|
for (i = 0; i < fnode->numpred; i++) {
|
|
|
|
pred = IRO_NodeTable[fnode->pred[i]];
|
|
|
|
if (Bv_IsBitSet(fnode->index, pred->dom)) {
|
|
|
|
if (!x) {
|
|
|
|
Bv_AllocVector(&InLoop, IRO_NumNodes + 1);
|
|
|
|
Bv_Clear(InLoop);
|
|
|
|
Bv_SetBit(fnode->index, InLoop);
|
|
|
|
}
|
|
|
|
x = 1;
|
|
|
|
Bv_SetBit(pred->index, InLoop);
|
|
|
|
if (pred != fnode)
|
|
|
|
AddPreds(pred);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (x) {
|
|
|
|
IRO_Dump("IRO_FindEmptyLoops:Found loop with header %d\n", fnode->index);
|
|
|
|
IRO_DumpBits("Loop includes: ", InLoop);
|
|
|
|
EmptyLoop(fnode);
|
|
|
|
IRO_UpdateFlagsOnInts();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
IRO_CheckForUserBreak();
|
|
|
|
}
|
|
|
|
|
|
|
|
static Boolean EmptyLoop(IRONode *fnode) {
|
|
|
|
VarRecord *var;
|
|
|
|
IRONode *bestpred;
|
|
|
|
IRONode *pred;
|
|
|
|
UInt16 i;
|
|
|
|
int flag2;
|
|
|
|
IRONode *r24;
|
|
|
|
Boolean flag;
|
|
|
|
int counter;
|
|
|
|
int j;
|
|
|
|
IRONode *succ;
|
|
|
|
IRONode *bestsucc;
|
|
|
|
int counter2;
|
|
|
|
UInt32 counter3;
|
|
|
|
IROLoop *loop;
|
|
|
|
IRONode *r21;
|
|
|
|
IRONode *r20;
|
|
|
|
IROLinear *constnd;
|
|
|
|
Type *type20;
|
|
|
|
ENode *enode;
|
|
|
|
IROLinear *save;
|
|
|
|
|
|
|
|
flag = 0;
|
|
|
|
counter = 0;
|
|
|
|
LoopNode = fnode;
|
|
|
|
FindMustReach();
|
|
|
|
|
|
|
|
for (var = IRO_FirstVar; var; var = var->next)
|
|
|
|
var->xA = 1;
|
|
|
|
|
|
|
|
ComputeLoopKills();
|
|
|
|
ComputeLoopInvariance();
|
|
|
|
ComputeLoopInduction();
|
|
|
|
|
|
|
|
LoopNode = fnode;
|
|
|
|
ConditionalHeaderAtBottom = 0;
|
|
|
|
|
|
|
|
bestpred = NULL;
|
|
|
|
flag2 = 0;
|
|
|
|
for (i = 0; i < LoopNode->numpred; i++) {
|
|
|
|
pred = IRO_NodeTable[LoopNode->pred[i]];
|
|
|
|
if (!Bv_IsBitSet(pred->index, InLoop)) {
|
|
|
|
flag2 = 1;
|
|
|
|
if (pred->nextnode == fnode) {
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_ASSERT(173, !bestpred || pred == bestpred);
|
2022-12-14 00:16:59 +00:00
|
|
|
bestpred = pred;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!flag2) {
|
|
|
|
IRO_Dump("No predecessor outside the loop\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bestsucc = NULL;
|
|
|
|
for (i = 0; i < LoopNode->numsucc; i++) {
|
|
|
|
succ = IRO_NodeTable[LoopNode->succ[i]];
|
|
|
|
if (Bv_IsBitSet(succ->index, InLoop)) {
|
|
|
|
bestsucc = succ;
|
|
|
|
counter++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (LoopNode == bestsucc && counter == 1)
|
|
|
|
flag = 1;
|
|
|
|
|
|
|
|
if (LoopNode->last->type != IROLinearIf || LoopNode->last->type != IROLinearIfNot || flag) {
|
|
|
|
counter2 = 0;
|
|
|
|
for (j = 0; j < LoopNode->numpred; j++) {
|
|
|
|
if (Bv_IsBitSet(IRO_NodeTable[LoopNode->pred[j]]->index, InLoop)) {
|
|
|
|
r21 = IRO_NodeTable[LoopNode->pred[j]];
|
|
|
|
counter2++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
r24 = NULL;
|
|
|
|
counter3 = 0;
|
|
|
|
for (j = 0; j < LoopNode->numpred; j++) {
|
|
|
|
if (!Bv_IsBitSet(IRO_NodeTable[LoopNode->pred[j]]->index, InLoop)) {
|
|
|
|
r24 = IRO_NodeTable[LoopNode->pred[j]];
|
|
|
|
counter3++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (counter2 == 1 && counter3 == 1) {
|
|
|
|
if (r21->last->type == IROLinearIf) {
|
|
|
|
if ((Bv_IsBitSet(LoopNode->nextnode->index, InLoop) && !Bv_IsBitSet(r21->nextnode->index, InLoop)) || flag) {
|
|
|
|
IRO_Dump("Standard while loop layout\n");
|
|
|
|
loop = ExtractLoopInfo(r21);
|
|
|
|
if (flag)
|
|
|
|
loop->flags |= LoopFlags_20000;
|
|
|
|
FindAssignmenttoInductionVar(loop, r24);
|
|
|
|
r20 = r24;
|
|
|
|
while (r20 && !loop->nd14 && r20->numpred == 1 && IRO_NodeTable[r20->pred[0]]->numsucc == 1) {
|
|
|
|
FindAssignmenttoInductionVar(loop, IRO_NodeTable[r20->pred[0]]);
|
|
|
|
r20 = IRO_NodeTable[r20->pred[0]];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (CanRemoveRedundantLoop(loop)) {
|
2023-01-14 13:20:48 +00:00
|
|
|
IRO_Dump("EmptyLoop: # of iterations =%" PRId32 ", FinalStoreVal=%" PRId32 "\n", CInt64_GetULong(&loop->x28), CInt64_GetULong(&loop->x30));
|
2022-12-14 00:16:59 +00:00
|
|
|
IRO_NopOut(r21->last->u.label.x4);
|
|
|
|
r21->last->type = IROLinearNop;
|
|
|
|
type20 = loop->induction->nd->rtype;
|
|
|
|
constnd = IRO_NewLinear(IROLinearOperand);
|
|
|
|
constnd->index = ++IRO_NumLinear;
|
|
|
|
enode = IRO_NewENode(EINTCONST);
|
|
|
|
enode->rtype = type20;
|
|
|
|
enode->data.intval = loop->x30;
|
|
|
|
constnd->u.node = enode;
|
|
|
|
constnd->rtype = type20;
|
|
|
|
|
|
|
|
if (loop->induction->nd->type == IROLinearOp1Arg) {
|
|
|
|
save = loop->induction->nd->u.monadic;
|
|
|
|
loop->induction->nd->type = IROLinearOp2Arg;
|
|
|
|
loop->induction->nd->nodetype = EASS;
|
|
|
|
loop->induction->nd->u.diadic.left = save;
|
|
|
|
loop->induction->nd->u.diadic.right = constnd;
|
|
|
|
IRO_Paste(constnd, constnd, loop->induction->nd);
|
|
|
|
} else if (loop->induction->nd->type == IROLinearOp2Arg) {
|
|
|
|
loop->induction->nd->nodetype = EASS;
|
|
|
|
IRO_NopOut(loop->induction->nd->u.diadic.right);
|
|
|
|
loop->induction->nd->u.diadic.right = constnd;
|
|
|
|
IRO_Paste(constnd, constnd, loop->induction->nd);
|
|
|
|
}
|
|
|
|
} else if (CanRemoveRedundantLoop1(loop)) {
|
|
|
|
IRO_Dump("EmptyLoop: self recursive dowhile(--n ) loop\n");
|
|
|
|
|
|
|
|
r21->last->type = IROLinearNop;
|
|
|
|
type20 = loop->induction->nd->rtype;
|
|
|
|
constnd = IRO_NewLinear(IROLinearOperand);
|
|
|
|
constnd->index = ++IRO_NumLinear;
|
|
|
|
enode = IRO_NewENode(EINTCONST);
|
|
|
|
enode->rtype = type20;
|
|
|
|
enode->data.intval = cint64_zero;
|
|
|
|
constnd->u.node = enode;
|
|
|
|
constnd->rtype = type20;
|
|
|
|
|
|
|
|
save = loop->induction->nd->u.monadic;
|
|
|
|
loop->induction->nd->type = IROLinearOp2Arg;
|
|
|
|
loop->induction->nd->nodetype = EASS;
|
|
|
|
loop->induction->nd->u.diadic.left = save;
|
|
|
|
loop->induction->nd->u.diadic.right = constnd;
|
|
|
|
IRO_Paste(constnd, constnd, loop->induction->nd);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
IRO_Dump("NonStandard while loop layout\n");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
IRO_Dump("NonStandard while loop layout\n");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
IRO_Dump("Cannot handle Do While Loop with multiple tails\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int CanRemoveRedundantLoop(IROLoop *loop) {
|
|
|
|
IROLinear *inner;
|
|
|
|
|
|
|
|
if (loop->flags & LoopFlags_10000) {
|
|
|
|
IRO_Dump("CanRemoveRedundantLoop:No because detection of dowhile(n--) loop not supported\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (loop->flags & LP_LOOP_HAS_ASM) {
|
|
|
|
IRO_Dump("CanRemoveRedundantLoop:No due to LP_LOOP_HAS_ASM \n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (loop->flags & LP_IFEXPR_NON_CANONICAL) {
|
|
|
|
IRO_Dump("CanRemoveRedundantLoop:No due to LP_IFEXPR_NON_CANONICAL \n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (loop->flags & LP_LOOP_HAS_CALLS) {
|
|
|
|
IRO_Dump("CanRemoveRedundantLoop:No due to LP_LOOP_HAS_CALLS \n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (loop->flags & LP_LOOP_HAS_CNTRLFLOW) {
|
|
|
|
IRO_Dump("CanRemoveRedundantLoop:No due to LP_LOOP_HAS_CNTRLFLOW \n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (loop->flags & LP_INDUCTION_NOT_FOUND) {
|
|
|
|
IRO_Dump("CanRemoveRedundantLoop:No due to LP_INDUCTION_NOT_FOUND \n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (loop->flags & LP_HAS_MULTIPLE_INDUCTIONS) {
|
|
|
|
IRO_Dump("CanRemoveRedundantLoop:No due to LP_HAS_MULTIPLE_INDUCTIONS \n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (loop->flags & LP_LOOP_HDR_HAS_SIDEEFFECTS) {
|
|
|
|
IRO_Dump("CanRemoveRedundantLoop:No due to LP_LOOP_HDR_HAS_SIDEEFFECTS \n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(loop->flags & LoopFlags_200)) {
|
|
|
|
IRO_Dump("CanRemoveRedundantLoop:No because header does not follow induction update \n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(loop->flags & LoopFlags_10000)) {
|
|
|
|
inner = loop->nd18->u.diadic.right;
|
|
|
|
if (!IRO_IsIntConstant(inner) && !(inner->flags & IROLF_LoopInvariant)) {
|
|
|
|
IRO_Dump("CanRemoveRedundantLoop:No because Loop Upper Bound is Variant in the loop\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!loop->nd14) {
|
|
|
|
IRO_Dump("CanRemoveRedundantLoop:No because there is no initialization of loop index in PreHeader\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!IRO_IsVariable(loop->nd14->u.diadic.left)) {
|
|
|
|
IRO_Dump("CanRemoveRedundantLoop:No because initial value of induction stored thru pointer\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!IRO_IsUnsignedType(loop->nd14->rtype)) {
|
|
|
|
if (IRO_IsIntConstant(loop->nd14->u.diadic.right)) {
|
|
|
|
if (!CInt64_GreaterEqual(loop->nd14->u.diadic.right->u.node->data.intval, cint64_zero)) {
|
|
|
|
IRO_Dump("CanRemoveRedundantLoop:No because initial value of induction is signed but < 0\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
IRO_Dump("CanRemoveRedundantLoop:No because initial value of induction is signed and not constant\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(loop->flags & LP_LOOP_STEP_ISPOS) && !(loop->flags & LP_LOOP_STEP_ISNEG)) {
|
|
|
|
IRO_Dump("CanRemoveRedundantLoop:No because LP_LOOP_STEP_ISPOS/LP_LOOP_STEP_ISNEG is not set\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((loop->flags & LP_LOOP_STEP_ISPOS) && CheckStepOverFlow1_EmptyLoop(loop, &loop->x28, &loop->x30)) {
|
|
|
|
IRO_Dump("CanRemoveRedundantLoop:No because Final Value of indution will overflow\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((loop->flags & LP_LOOP_STEP_ISNEG) && CheckStepOverFlow2_EmptyLoop(loop, &loop->x28, &loop->x30)) {
|
|
|
|
IRO_Dump("CanRemoveRedundantLoop:No because Final Value of indution will overflow\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return RedundantLoopCheck(loop) != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int CanRemoveRedundantLoop1(IROLoop *loop) {
|
|
|
|
if ((loop->flags & LoopFlags_10000) && (loop->flags & LoopFlags_20000)) {
|
|
|
|
if (loop->flags & LP_LOOP_HAS_ASM) {
|
|
|
|
IRO_Dump("CanRemoveRedundantLoop1:No due to LP_LOOP_HAS_ASM \n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (loop->flags & LP_IFEXPR_NON_CANONICAL) {
|
|
|
|
IRO_Dump("CanRemoveRedundantLoop1:No due to LP_IFEXPR_NON_CANONICAL \n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (loop->flags & LP_LOOP_HAS_CALLS) {
|
|
|
|
IRO_Dump("CanRemoveRedundantLoop1:No due to LP_LOOP_HAS_CALLS \n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (loop->flags & LP_LOOP_HAS_CNTRLFLOW) {
|
|
|
|
IRO_Dump("CanRemoveRedundantLoop1:No due to LP_LOOP_HAS_CNTRLFLOW \n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (loop->flags & LP_INDUCTION_NOT_FOUND) {
|
|
|
|
IRO_Dump("CanRemoveRedundantLoop1:No due to LP_INDUCTION_NOT_FOUND \n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (loop->flags & LP_HAS_MULTIPLE_INDUCTIONS) {
|
|
|
|
IRO_Dump("CanRemoveRedundantLoop1:No due to LP_HAS_MULTIPLE_INDUCTIONS \n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (loop->flags & LP_LOOP_HDR_HAS_SIDEEFFECTS) {
|
|
|
|
IRO_Dump("CanRemoveRedundantLoop1:No due to LP_LOOP_HDR_HAS_SIDEEFFECTS \n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(loop->flags & LoopFlags_200)) {
|
|
|
|
IRO_Dump("CanRemoveRedundantLoop1:No because header does not follow induction update \n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (loop->induction->nd->type == IROLinearOp1Arg && loop->induction->nd->nodetype == EPREDEC) {
|
|
|
|
if (IRO_IsUnsignedType(loop->induction->nd->rtype))
|
|
|
|
return 1;
|
|
|
|
IRO_Dump("CanRemoveRedundantLoop1:No because induction not of the right type \n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
IRO_Dump("CanRemoveRedundantLoop1:No because induction operator not a predec \n");
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int RedundantLoopCheck(IROLoop *loop) {
|
|
|
|
IRONode *fnode;
|
|
|
|
IROLinear *nd;
|
|
|
|
|
|
|
|
for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
|
|
|
|
if (Bv_IsBitSet(fnode->index, InLoop) && fnode != loop->fnode && (nd = fnode->first)) {
|
|
|
|
while (1) {
|
|
|
|
if ((nd->index < loop->index20 || nd->index > loop->index24) && nd->type != IROLinearNop && nd->type != IROLinearLabel) {
|
|
|
|
if (IS_LINEAR_DIADIC(nd, EASS)) {
|
|
|
|
if (!(nd->flags & IROLF_Reffed)) {
|
|
|
|
if (IS_LINEAR_MONADIC(nd->u.diadic.left, EINDIRECT)) {
|
|
|
|
if (nd->u.diadic.left->rtype && CParser_IsVolatile(nd->u.diadic.left->rtype, nd->u.diadic.left->nodeflags & ENODE_FLAG_QUALS)) {
|
|
|
|
IRO_Dump(" EASS at %d fail as store to volatile memory \n", nd->index);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((nd->u.diadic.left->u.monadic->flags & IROLF_LoopInvariant) && (nd->u.diadic.right->flags & IROLF_LoopInvariant)) {
|
|
|
|
IRO_Dump(" EASS at %d pass\n", nd->index);
|
|
|
|
} else {
|
|
|
|
IRO_Dump(" EASS at %d fail, either LHS address or RHS is variant \n", nd->index);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
IRO_Dump("Found EASS nodes whose lhs root is not a EINDIRECT node\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
IRO_Dump("Found EASS node that is referenced i.e embedded assignment\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!(nd->flags & IROLF_Reffed)) {
|
|
|
|
IRO_Dump("Found non EASS top level node in the loop\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nd == fnode->last)
|
|
|
|
break;
|
|
|
|
nd = nd->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int CheckStepOverFlow1_EmptyLoop(IROLoop *loop, CInt64 *val1, CInt64 *val2) {
|
|
|
|
Boolean isUnsigned;
|
|
|
|
IROLinear *nd2;
|
|
|
|
IROLinear *nd1;
|
|
|
|
CInt64 nd2value;
|
|
|
|
CInt64 nd1value;
|
|
|
|
CInt64 addConst;
|
|
|
|
CInt64 work;
|
|
|
|
CInt64 neg1;
|
|
|
|
|
|
|
|
nd2 = loop->nd14->u.diadic.right;
|
|
|
|
nd1 = loop->nd18->u.diadic.right;
|
|
|
|
isUnsigned = IRO_IsUnsignedType(loop->nd18->u.diadic.right->rtype);
|
|
|
|
|
|
|
|
if (IRO_IsIntConstant(nd2) && IRO_IsIntConstant(nd1)) {
|
|
|
|
nd2value = nd2->u.node->data.intval;
|
|
|
|
nd1value = nd1->u.node->data.intval;
|
|
|
|
if (isUnsigned) {
|
|
|
|
if (CInt64_LessEqualU(nd1value, nd2value))
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
if (CInt64_LessEqual(nd1value, nd2value))
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
CInt64_SetLong(&addConst, loop->induction->addConst);
|
|
|
|
CInt64_SetLong(&neg1, -1);
|
|
|
|
*val1 = CInt64_Sub(nd1value, nd2value);
|
|
|
|
*val1 = CInt64_Add(*val1, addConst);
|
|
|
|
if (IS_LINEAR_DIADIC(loop->nd18, ELESS))
|
|
|
|
*val1 = CInt64_Add(*val1, neg1);
|
|
|
|
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_ASSERT(855, !CInt64_IsZero(&addConst));
|
2022-12-14 00:16:59 +00:00
|
|
|
|
|
|
|
if (isUnsigned)
|
|
|
|
*val1 = CInt64_DivU(*val1, addConst);
|
|
|
|
else
|
|
|
|
*val1 = CInt64_Div(*val1, addConst);
|
|
|
|
|
|
|
|
if (CInt64_Equal(*val1, cint64_zero))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
if (isUnsigned) {
|
2022-12-29 12:32:55 +00:00
|
|
|
if (CInt64_LessEqualU(*val1, cint64_zero))
|
|
|
|
CError_FATAL(877);
|
2022-12-14 00:16:59 +00:00
|
|
|
} else {
|
2022-12-29 12:32:55 +00:00
|
|
|
if (CInt64_LessEqual(*val1, cint64_zero))
|
|
|
|
CError_FATAL(886);
|
2022-12-14 00:16:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (isUnsigned) {
|
|
|
|
*val2 = CInt64_MulU(*val1, addConst);
|
|
|
|
*val2 = CInt64_Add(*val2, nd2value);
|
|
|
|
} else {
|
|
|
|
*val2 = CInt64_Mul(*val1, addConst);
|
|
|
|
*val2 = CInt64_Add(*val2, nd2value);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
CInt64_SetLong(&addConst, loop->induction->addConst);
|
|
|
|
work = CInt64_Add(nd1value, addConst);
|
|
|
|
|
|
|
|
if (isUnsigned) {
|
|
|
|
if (CInt64_LessU(work, nd1value))
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
if (CInt64_Less(work, nd1value))
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int CheckStepOverFlow2_EmptyLoop(IROLoop *loop, CInt64 *val1, CInt64 *val2) {
|
|
|
|
Boolean isUnsigned;
|
|
|
|
IROLinear *nd2;
|
|
|
|
IROLinear *nd1;
|
|
|
|
CInt64 nd2value;
|
|
|
|
CInt64 nd1value;
|
|
|
|
CInt64 addConst;
|
|
|
|
CInt64 work;
|
|
|
|
CInt64 neg1;
|
|
|
|
|
|
|
|
nd1 = loop->nd14->u.diadic.right;
|
|
|
|
nd2 = loop->nd18->u.diadic.right;
|
|
|
|
isUnsigned = IRO_IsUnsignedType(loop->nd18->u.diadic.right->rtype);
|
|
|
|
|
|
|
|
if (IRO_IsIntConstant(nd2) && IRO_IsIntConstant(nd1)) {
|
|
|
|
nd2value = nd2->u.node->data.intval;
|
|
|
|
nd1value = nd1->u.node->data.intval;
|
|
|
|
if (isUnsigned) {
|
|
|
|
if (CInt64_LessEqualU(nd1value, nd2value))
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
if (CInt64_LessEqual(nd1value, nd2value))
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
CInt64_SetLong(&addConst, loop->induction->addConst);
|
|
|
|
CInt64_SetLong(&neg1, -1);
|
|
|
|
*val1 = CInt64_Sub(nd1value, nd2value);
|
|
|
|
*val1 = CInt64_Add(*val1, addConst);
|
|
|
|
if (IS_LINEAR_DIADIC(loop->nd18, EGREATER))
|
|
|
|
*val1 = CInt64_Add(*val1, neg1);
|
|
|
|
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_ASSERT(995, !CInt64_IsZero(&addConst));
|
2022-12-14 00:16:59 +00:00
|
|
|
|
|
|
|
if (isUnsigned)
|
|
|
|
*val1 = CInt64_DivU(*val1, addConst);
|
|
|
|
else
|
|
|
|
*val1 = CInt64_Div(*val1, addConst);
|
|
|
|
|
|
|
|
if (CInt64_Equal(*val1, cint64_zero))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
if (isUnsigned) {
|
|
|
|
if (CInt64_LessEqualU(*val1, cint64_zero))
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
if (CInt64_LessEqual(*val1, cint64_zero))
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isUnsigned) {
|
|
|
|
*val2 = CInt64_MulU(*val1, addConst);
|
|
|
|
*val2 = CInt64_Sub(nd1value, *val2);
|
|
|
|
} else {
|
|
|
|
*val2 = CInt64_Mul(*val1, addConst);
|
|
|
|
*val2 = CInt64_Sub(nd1value, *val2);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
CInt64_SetLong(&addConst, loop->induction->addConst);
|
|
|
|
work = CInt64_Sub(nd2value, addConst);
|
|
|
|
|
|
|
|
if (isUnsigned) {
|
|
|
|
if (CInt64_GreaterU(work, nd2value))
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
if (CInt64_Greater(work, nd1value))
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|