mirror of https://git.wuffs.org/MWCC
1532 lines
50 KiB
C
1532 lines
50 KiB
C
#include "compiler/IroExprRegeneration.h"
|
|
#include "compiler/IroCSE.h"
|
|
#include "compiler/IroDump.h"
|
|
#include "compiler/IroFlowgraph.h"
|
|
#include "compiler/IroLinearForm.h"
|
|
#include "compiler/IroSubable.h"
|
|
#include "compiler/IroTransform.h"
|
|
#include "compiler/IROUseDef.h"
|
|
#include "compiler/IroUtil.h"
|
|
#include "compiler/IroVars.h"
|
|
#include "compiler/CDecl.h"
|
|
#include "compiler/CExpr.h"
|
|
#include "compiler/CFunc.h"
|
|
#include "compiler/CInt64.h"
|
|
#include "compiler/CMachine.h"
|
|
#include "compiler/CParser.h"
|
|
#include "compiler/objects.h"
|
|
|
|
// forward decls
|
|
static void GetExprUses(IROLinear *linear, Boolean isEntry);
|
|
static void RebuildPossibleCondExpression(IRONode *fnode);
|
|
static void AddNodeAndSuccessorsRecursively(IRONodes *nodes, IRONode *fnode1, IRONode *fnode2);
|
|
|
|
static Boolean FindFlowgraphNodeThatStartsWithLabel(CLabel *label, IRONode **result1, IRONode **result2) {
|
|
IRONode *prev;
|
|
IRONode *iter;
|
|
|
|
prev = IRO_FirstNode;
|
|
if (prev != NULL)
|
|
iter = prev->nextnode;
|
|
|
|
while (iter) {
|
|
if (iter->first->type == IROLinearLabel && iter->first->u.label.label == label) {
|
|
*result1 = iter;
|
|
*result2 = prev;
|
|
return 1;
|
|
}
|
|
|
|
prev = iter;
|
|
iter = iter->nextnode;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static IROLinear *FindLastDiadicTopLevelAssignmentInFlowgraphNode(IRONode *fnode) {
|
|
IROLinear *scan;
|
|
IROLinear *result;
|
|
|
|
result = NULL;
|
|
|
|
for (scan = fnode->first; scan != fnode->last->next; scan = scan->next) {
|
|
if (scan->type == IROLinearOp2Arg && scan->nodetype == EASS && !(scan->flags & IROLF_Reffed))
|
|
result = scan;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static Boolean RewriteUse(IROUse *use, ENode *enode, IROLinear *nd, Boolean flag) {
|
|
IROLinear *father;
|
|
IROLinear *father2;
|
|
|
|
if (
|
|
use &&
|
|
use->x1C &&
|
|
use->linear &&
|
|
use->linear->type == IROLinearOperand &&
|
|
use->linear->u.node->type == EOBJREF &&
|
|
use->linear->u.node->data.objref == enode->data.objref &&
|
|
(father = IRO_LocateFather(use->linear)) &&
|
|
father->type == IROLinearOp1Arg &&
|
|
father->nodetype == EINDIRECT &&
|
|
father->rtype == nd->rtype &&
|
|
(father2 = IRO_LocateFather(father)) &&
|
|
((father2->type != IROLinearOp1Arg && father2->type != IROLinearOp2Arg) || !IRO_IsModifyOp[father2->nodetype])
|
|
) {
|
|
if (flag)
|
|
IRO_LocateFather_Cut_And_Paste(father, nd);
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifdef __MWERKS__
|
|
#pragma options align=mac68k
|
|
#endif
|
|
static struct {
|
|
jmp_buf buf;
|
|
UInt16 index;
|
|
Boolean flag;
|
|
} scuai;
|
|
#ifdef __MWERKS__
|
|
#pragma options align=reset
|
|
#endif
|
|
|
|
static void StatementContainsUseAction(IROLinear *linear, Boolean isFirst) {
|
|
if (isFirst && linear->index == scuai.index) {
|
|
scuai.flag = 1;
|
|
longjmp(scuai.buf, 1);
|
|
}
|
|
}
|
|
|
|
static Boolean StatementContainsUse(IROLinear *a, IROLinear *b) {
|
|
memset(&scuai, 0, sizeof(scuai));
|
|
scuai.index = b->index;
|
|
scuai.flag = 0;
|
|
|
|
if (!setjmp(scuai.buf))
|
|
IRO_WalkInts(a, a, StatementContainsUseAction);
|
|
|
|
return scuai.flag;
|
|
}
|
|
|
|
#ifdef __MWERKS__
|
|
#pragma options align=mac68k
|
|
#endif
|
|
static struct {
|
|
jmp_buf buf;
|
|
Boolean flag;
|
|
} scseai;
|
|
#ifdef __MWERKS__
|
|
#pragma options align=reset
|
|
#endif
|
|
|
|
static void StatementContainsSideEffectAction(IROLinear *linear, Boolean isFirst) {
|
|
if (isFirst) {
|
|
switch (linear->type) {
|
|
case IROLinearOperand:
|
|
case IROLinearOp1Arg:
|
|
case IROLinearOp2Arg:
|
|
case IROLinearOp3Arg:
|
|
case IROLinearFunccall:
|
|
case IROLinearAsm:
|
|
if (IRO_HasSideEffect(linear)) {
|
|
scseai.flag = 1;
|
|
longjmp(scseai.buf, 1);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static Boolean StatementContainsSideEffect(IROLinear *linear) {
|
|
memset(&scseai, 0, sizeof(scseai));
|
|
scseai.flag = 0;
|
|
|
|
if (!setjmp(scseai.buf))
|
|
IRO_WalkInts(linear, linear, StatementContainsSideEffectAction);
|
|
|
|
return scseai.flag;
|
|
}
|
|
|
|
static Boolean HasSideEffectsBeforeUse(IRONode *fnode1, IRONode *fnode2, IRONode *fnode3, IROLinear *nd, Boolean flag) {
|
|
IRONode *fnode;
|
|
IROLinear *scannd;
|
|
UInt16 i;
|
|
|
|
if (fnode1 != fnode3) {
|
|
if (flag) {
|
|
for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode)
|
|
fnode->x3C = 0;
|
|
} else if (fnode1->x3C) {
|
|
return 0;
|
|
}
|
|
fnode1->x3C = 1;
|
|
}
|
|
|
|
for (scannd = fnode1->first; scannd && scannd != fnode1->last->next; scannd = scannd->next) {
|
|
if (!(scannd->flags & IROLF_Reffed)) {
|
|
if (StatementContainsUse(scannd, nd))
|
|
return 0;
|
|
if (StatementContainsSideEffect(scannd))
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
if (fnode1 != fnode3) {
|
|
for (i = 0; i < fnode1->numsucc; i++) {
|
|
if (HasSideEffectsBeforeUse(IRO_NodeTable[fnode1->succ[i]], fnode2, fnode3, nd, 0))
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static Boolean UsesAKilledVarBeforeUse(IRONode *fnode1, IRONode *fnode2, IRONode *fnode3, IROLinear *nd, BitVector *bv, Boolean flag) {
|
|
IRONode *fnode;
|
|
UInt16 i;
|
|
IROLinear *scannd;
|
|
|
|
if (fnode1 != fnode3) {
|
|
if (flag) {
|
|
for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode)
|
|
fnode->x3C = 0;
|
|
} else if (fnode1->x3C) {
|
|
return 0;
|
|
}
|
|
fnode1->x3C = 1;
|
|
}
|
|
|
|
for (scannd = fnode1->first; scannd && scannd != fnode1->last->next; scannd = scannd->next) {
|
|
if (!(scannd->flags & IROLF_Reffed)) {
|
|
if (StatementContainsUse(scannd, nd))
|
|
return 0;
|
|
Bv_Clear(IRO_VarKills);
|
|
IRO_WalkInts(scannd, scannd, GetExprUses);
|
|
if (Bv_BitsInCommon(bv, IRO_VarKills))
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
if (fnode1 != fnode3) {
|
|
for (i = 0; i < fnode1->numsucc; i++) {
|
|
if (UsesAKilledVarBeforeUse(IRO_NodeTable[fnode1->succ[i]], fnode2, fnode3, nd, bv, 0))
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void GetExprUses(IROLinear *linear, Boolean isEntry) {
|
|
Object *obj;
|
|
VarRecord *var;
|
|
|
|
if (isEntry) {
|
|
if (linear->type == IROLinearOperand && linear->u.node->type == EOBJREF) {
|
|
obj = linear->u.node->data.objref;
|
|
if ((linear->flags & IROLF_Ind) && (!(linear->flags & IROLF_Assigned) || (linear->flags & IROLF_Used))) {
|
|
if ((var = IRO_FindVar(obj, 0, 1)))
|
|
Bv_SetBit(var->index, IRO_VarKills);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void GetExprKills(IROLinear *linear, Boolean isEntry) {
|
|
if (isEntry)
|
|
IRO_GetKills(linear);
|
|
}
|
|
|
|
static void CheckUnorderedRegionForSideEffectsAndUses(IROLinear *nd, BitVector *bv1, BitVector *bv2, Boolean *result) {
|
|
if (IRO_HasSideEffect(nd)) {
|
|
*result = 1;
|
|
} else {
|
|
Bv_Clear(bv2);
|
|
Bv_Clear(IRO_VarKills);
|
|
IRO_WalkTree(nd, GetExprUses);
|
|
Bv_Or(IRO_VarKills, bv2);
|
|
|
|
if (Bv_BitsInCommon(bv1, bv2))
|
|
*result = 1;
|
|
}
|
|
}
|
|
|
|
static void CheckUnorderedRegionsForSideEffectsAndUses(IROLinear *nd1, IROLinear *nd2, BitVector *bv1, BitVector *bv2, Boolean *result) {
|
|
int i;
|
|
|
|
switch (nd1->type) {
|
|
case IROLinearOp2Arg:
|
|
if (nd1->nodetype != ELAND && nd1->nodetype != ELOR && nd1->nodetype != ECOMMA) {
|
|
if (nd1->u.diadic.left != nd2)
|
|
CheckUnorderedRegionForSideEffectsAndUses(nd1->u.diadic.left, bv1, bv2, result);
|
|
if (nd1->u.diadic.right != nd2)
|
|
CheckUnorderedRegionForSideEffectsAndUses(nd1->u.diadic.right, bv1, bv2, result);
|
|
}
|
|
break;
|
|
case IROLinearFunccall:
|
|
if (nd1->u.funccall.linear8 != nd2)
|
|
CheckUnorderedRegionForSideEffectsAndUses(nd1->u.funccall.linear8, bv1, bv2, result);
|
|
for (i = 0; !*result && i < nd1->u.funccall.argCount; i++) {
|
|
if (nd1->u.funccall.args[i] != nd2)
|
|
CheckUnorderedRegionForSideEffectsAndUses(nd1->u.funccall.args[i], bv1, bv2, result);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
static Boolean CheckThenOrElseBranch(IRONode *fnode1, IRONode *fnode2, IROLinear *nd, Boolean flag) {
|
|
IRONode *fnode;
|
|
IROLinear *scannd;
|
|
IRONodes nodes;
|
|
Boolean result;
|
|
|
|
IROFlowgraph_sub_4C2140(&nodes);
|
|
|
|
for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode)
|
|
fnode->x3C = 0;
|
|
AddNodeAndSuccessorsRecursively(&nodes, fnode1, fnode2);
|
|
|
|
while (IROFlowgraph_sub_4C2040(&nodes)) {
|
|
fnode = IRO_NodeTable[IROFlowgraph_sub_4C2100(&nodes)];
|
|
if (fnode) {
|
|
if (!Bv_IsBitSet(fnode1->index, fnode->dom)) {
|
|
result = 0;
|
|
goto done;
|
|
}
|
|
|
|
for (scannd = fnode->first; scannd && scannd != fnode->last->next; scannd = scannd->next) {
|
|
if (!nd || scannd != nd) {
|
|
if (!flag || (scannd->type != IROLinearReturn)) {
|
|
if (fnode->numpred == 2 && scannd->type == IROLinearLabel)
|
|
RebuildPossibleCondExpression(fnode);
|
|
|
|
if (scannd->type != IROLinearNop &&
|
|
scannd->type != IROLinearLabel &&
|
|
scannd->type != IROLinearGoto &&
|
|
!(scannd->flags & IROLF_Reffed)) {
|
|
result = 0;
|
|
goto done;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
result = 1;
|
|
done:
|
|
IROFlowgraph_sub_4C20E0(&nodes);
|
|
return result;
|
|
}
|
|
|
|
static void RebuildPossibleCondExpression(IRONode *fnode) {
|
|
IRONode *pred1;
|
|
IRONode *pred2;
|
|
IRONode *r30;
|
|
IROLinear *leftAss;
|
|
IROLinear *rightAss;
|
|
IROLinear *r27;
|
|
IROLinear *r13;
|
|
IROLinear *var_58;
|
|
IRONode *left;
|
|
IRONode *right;
|
|
IRONode *r24;
|
|
ENode *r23;
|
|
IRODef *r22;
|
|
IRODef *r21;
|
|
IRODef *def;
|
|
IROUse *use;
|
|
UInt32 r20;
|
|
UInt32 r19;
|
|
Boolean r18;
|
|
Boolean r17;
|
|
UInt32 i;
|
|
Boolean compareType;
|
|
Type *var_60;
|
|
IROLinear copy1;
|
|
IROLinear copy2;
|
|
IROLinear copy3;
|
|
|
|
if (
|
|
!fnode ||
|
|
fnode->numpred != 2 ||
|
|
!fnode->first ||
|
|
fnode->first->type != IROLinearLabel
|
|
)
|
|
return;
|
|
|
|
pred1 = IRO_NodeTable[fnode->pred[0]];
|
|
pred2 = IRO_NodeTable[fnode->pred[1]];
|
|
if (
|
|
!pred1 || !pred2 ||
|
|
pred1->numsucc != 1 || pred2->numsucc != 1
|
|
)
|
|
return;
|
|
|
|
r24 = NULL;
|
|
for (i = 0; i < IRO_NumNodes; i++) {
|
|
if (
|
|
Bv_IsBitSet(i, fnode->dom) &&
|
|
(r24 = IRO_NodeTable[i]) &&
|
|
r24->last &&
|
|
(r24->last->type == IROLinearIf || r24->last->type == IROLinearIfNot) &&
|
|
r24->last->u.label.label &&
|
|
r24->numsucc == 2
|
|
) {
|
|
if (Bv_IsBitSet(r24->succ[0], pred1->dom) &&
|
|
!Bv_IsBitSet(r24->succ[0], pred2->dom) &&
|
|
Bv_IsBitSet(r24->succ[1], pred2->dom) &&
|
|
!Bv_IsBitSet(r24->succ[1], pred1->dom))
|
|
break;
|
|
|
|
if (Bv_IsBitSet(r24->succ[0], pred2->dom) &&
|
|
!Bv_IsBitSet(r24->succ[0], pred1->dom) &&
|
|
Bv_IsBitSet(r24->succ[1], pred1->dom) &&
|
|
!Bv_IsBitSet(r24->succ[1], pred2->dom))
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i >= IRO_NumNodes)
|
|
return;
|
|
|
|
/*if (
|
|
(r30 = IRO_NodeTable[r24->succ[0]]) &&
|
|
r30->numpred == 1 &&
|
|
r30->first &&
|
|
r30->first->type == IROLinearLabel &&
|
|
r30->first->u.label.label == r24->last->u.label.label
|
|
) {
|
|
goto ok;
|
|
} else if (
|
|
(r30 = IRO_NodeTable[r24->succ[1]]) &&
|
|
r30->numpred == 1 &&
|
|
r30->first &&
|
|
r30->first->type == IROLinearLabel &&
|
|
r30->first->u.label.label == r24->last->u.label.label
|
|
) {
|
|
goto ok;
|
|
} else {
|
|
return;
|
|
}*/
|
|
/*if (
|
|
(!(r30 = IRO_NodeTable[r24->succ[0]]) ||
|
|
r30->numpred != 1 ||
|
|
!r30->first ||
|
|
r30->first->type != IROLinearLabel ||
|
|
r30->first->u.label.label != r24->last->u.label.label)
|
|
&&
|
|
(!(r30 = IRO_NodeTable[r24->succ[1]]) ||
|
|
r30->numpred != 1 ||
|
|
!r30->first ||
|
|
r30->first->type != IROLinearLabel ||
|
|
r30->first->u.label.label != r24->last->u.label.label)
|
|
)
|
|
return;*/
|
|
r30 = IRO_NodeTable[r24->succ[0]];
|
|
if (
|
|
r30 &&
|
|
r30->numpred == 1 &&
|
|
r30->first &&
|
|
r30->first->type == IROLinearLabel &&
|
|
r30->first->u.label.label == r24->last->u.label.label
|
|
) {
|
|
(void)0;
|
|
} else {
|
|
r30 = IRO_NodeTable[r24->succ[1]];
|
|
if (
|
|
r30 &&
|
|
r30->numpred == 1 &&
|
|
r30->first &&
|
|
r30->first->type == IROLinearLabel &&
|
|
r30->first->u.label.label == r24->last->u.label.label
|
|
) {
|
|
} else {
|
|
return;
|
|
}
|
|
}
|
|
|
|
ok:
|
|
if (Bv_IsBitSet(r30->index, pred1->dom)) {
|
|
left = pred2;
|
|
right = pred1;
|
|
} else {
|
|
left = pred1;
|
|
right = pred2;
|
|
}
|
|
|
|
leftAss = FindLastDiadicTopLevelAssignmentInFlowgraphNode(left);
|
|
if (
|
|
!leftAss ||
|
|
leftAss->type != IROLinearOp2Arg ||
|
|
!leftAss->u.diadic.left ||
|
|
leftAss->u.diadic.left->type != IROLinearOp1Arg ||
|
|
leftAss->u.diadic.left->nodetype != EINDIRECT ||
|
|
!leftAss->u.diadic.left->u.monadic ||
|
|
leftAss->u.diadic.left->u.monadic->type != IROLinearOperand ||
|
|
!(r23 = leftAss->u.diadic.left->u.monadic->u.node) ||
|
|
!r23->rtype ||
|
|
!IS_TYPE_POINTER_ONLY(r23->rtype) ||
|
|
!r23->data.objref ||
|
|
is_volatile_object(r23->data.objref) ||
|
|
r23->data.objref->datatype != DLOCAL
|
|
)
|
|
r23 = NULL;
|
|
|
|
if (r23) {
|
|
rightAss = FindLastDiadicTopLevelAssignmentInFlowgraphNode(right);
|
|
if (
|
|
!rightAss ||
|
|
rightAss->type != IROLinearOp2Arg ||
|
|
!rightAss->u.diadic.left ||
|
|
rightAss->u.diadic.left->type != IROLinearOp1Arg ||
|
|
rightAss->u.diadic.left->nodetype != EINDIRECT ||
|
|
!rightAss->u.diadic.left->u.monadic ||
|
|
rightAss->u.diadic.left->u.monadic->type != IROLinearOperand ||
|
|
!rightAss->u.diadic.left->u.monadic->u.node ||
|
|
!rightAss->u.diadic.left->u.monadic->u.node->rtype ||
|
|
!IS_TYPE_POINTER_ONLY(rightAss->u.diadic.left->u.monadic->u.node->rtype) ||
|
|
rightAss->u.diadic.left->u.monadic->u.node->type != EOBJREF ||
|
|
rightAss->u.diadic.left->u.monadic->u.node->data.objref != r23->data.objref ||
|
|
rightAss->rtype != leftAss->rtype
|
|
)
|
|
r23 = NULL;
|
|
}
|
|
|
|
if (r23) {
|
|
if (!CheckThenOrElseBranch(r24->nextnode, left, leftAss, 0) || !CheckThenOrElseBranch(r30, right, rightAss, 0))
|
|
return;
|
|
|
|
r19 = 0;
|
|
r20 = 0;
|
|
r18 = 0;
|
|
r17 = 0;
|
|
if (!r23->data.objref->varptr || !r23->data.objref->varptr->uses || !r23->data.objref->varptr->defs) {
|
|
r23 = NULL;
|
|
} else {
|
|
r21 = NULL;
|
|
r22 = NULL;
|
|
for (def = r23->data.objref->varptr->defs; def && (!r22 || !r21); def = def->varnext) {
|
|
if (def->x18 && def->linear == leftAss)
|
|
r22 = def;
|
|
else if (def->x18 && def->linear == rightAss)
|
|
r21 = def;
|
|
}
|
|
|
|
if (!r22 || !r21) {
|
|
r23 = NULL;
|
|
} else {
|
|
for (use = r23->data.objref->varptr->uses; r23 && use; use = use->varnext) {
|
|
if (use->x1C) {
|
|
r20++;
|
|
if (Bv_IsBitSet(r22->index, use->x18) && Bv_IsBitSet(r21->index, use->x18)) {
|
|
for (i = 0; r23 && i < use->x18->size; i++) {
|
|
if (i != r22->index && i != r21->index && Bv_IsBitSet(i, use->x18))
|
|
r23 = NULL;
|
|
}
|
|
|
|
if (r23 && !Bv_IsBitSet(fnode->index, use->node->dom))
|
|
r23 = NULL;
|
|
|
|
if (r23) {
|
|
if (RewriteUse(use, r23, rightAss, 0))
|
|
r19++;
|
|
else
|
|
r23 = NULL;
|
|
}
|
|
|
|
if (r23 && !r17)
|
|
r17 = HasSideEffectsBeforeUse(fnode, fnode, use->node, use->linear, 1);
|
|
|
|
if (r23 && !r18 && (IRO_HasSideEffect(r24->last->u.label.x4) || IRO_HasSideEffect(leftAss->u.label.x4) ||
|
|
IRO_HasSideEffect(rightAss->u.label.x4)))
|
|
r18 = 1;
|
|
} else if (Bv_IsBitSet(r22->index, use->x18) || Bv_IsBitSet(r21->index, use->x18)) {
|
|
r23 = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!r23)
|
|
return;
|
|
|
|
compareType = r24->last->type == IROLinearIf;
|
|
r27 = r24->last->u.label.x4;
|
|
r13 = leftAss->u.label.x4;
|
|
var_58 = rightAss->u.label.x4;
|
|
var_60 = rightAss->rtype;
|
|
memcpy(©1, r13, sizeof(IROLinear));
|
|
memcpy(©2, rightAss, sizeof(IROLinear));
|
|
|
|
r24->last->type = IROLinearNop;
|
|
r24->last->expr = NULL;
|
|
r30->first->type = IROLinearNop;
|
|
r30->first->expr = NULL;
|
|
fnode->first->type = IROLinearNop;
|
|
fnode->first->expr = NULL;
|
|
if (left->last->type == IROLinearGoto) {
|
|
left->last->type = IROLinearNop;
|
|
left->last->expr = NULL;
|
|
}
|
|
if (right->last->type == IROLinearGoto) {
|
|
right->last->type = IROLinearNop;
|
|
right->last->expr = NULL;
|
|
}
|
|
|
|
if (r23) {
|
|
IRO_NopOut(leftAss->u.diadic.left);
|
|
leftAss->type = IROLinearNop;
|
|
leftAss->expr = NULL;
|
|
}
|
|
|
|
memcpy(rightAss, ©1, sizeof(IROLinear));
|
|
rightAss->type = IROLinearOp3Arg;
|
|
rightAss->nodetype = ECOND;
|
|
rightAss->index = copy2.index;
|
|
rightAss->u.args3.a = r27;
|
|
rightAss->rtype = var_60;
|
|
rightAss->next = copy2.next;
|
|
if (compareType) {
|
|
rightAss->u.args3.b = var_58;
|
|
rightAss->u.args3.c = r13;
|
|
} else {
|
|
rightAss->u.args3.b = r13;
|
|
rightAss->u.args3.c = var_58;
|
|
}
|
|
rightAss->flags |= IROLF_Reffed;
|
|
|
|
if (r19 == 1 && !r17 && !r18 && !r23->data.objref->varptr->xB) {
|
|
for (use = r23->data.objref->varptr->uses; use; use = use->varnext) {
|
|
if (use->x1C && Bv_IsBitSet(r22->index, use->x18) && Bv_IsBitSet(r21->index, use->x18)) {
|
|
RewriteUse(use, r23, rightAss, 1);
|
|
if ((r18 = (use->linear->flags & IROLF_4000) && IRO_HasSideEffect(r27))) {
|
|
IROLinear *tmp;
|
|
Object *obj;
|
|
|
|
tmp = IRO_NewLinear(IROLinearOperand);
|
|
memcpy(tmp, copy2.u.diadic.left->u.monadic, sizeof(IROLinear));
|
|
tmp->index = IRO_NumLinear++;
|
|
tmp->rtype = r27->rtype;
|
|
if (r20 == 1) {
|
|
tmp->u.node->data.objref->type = r27->rtype;
|
|
tmp->u.node->rtype = CDecl_NewPointerType(r27->rtype);
|
|
} else {
|
|
obj = create_temp_object(tmp->rtype);
|
|
IRO_FindVar(obj, 1, 1);
|
|
tmp->u.node = create_objectrefnode(obj);
|
|
}
|
|
IRO_PasteAfter(tmp, tmp, r27);
|
|
|
|
tmp = IRO_NewLinear(IROLinearOp1Arg);
|
|
memcpy(tmp, copy2.u.diadic.left, sizeof(IROLinear));
|
|
tmp->index = IRO_NumLinear++;
|
|
tmp->u.monadic = r27->next;
|
|
tmp->rtype = r27->rtype;
|
|
IRO_PasteAfter(tmp, tmp, r27->next);
|
|
|
|
tmp = IRO_NewLinear(IROLinearOp2Arg);
|
|
memcpy(tmp, ©2, sizeof(IROLinear));
|
|
tmp->index = IRO_NumLinear++;
|
|
tmp->u.diadic.right = r27;
|
|
tmp->u.diadic.left = r27->next->next;
|
|
tmp->rtype = r27->rtype;
|
|
IRO_PasteAfter(tmp, tmp, r27->next->next);
|
|
|
|
if (r20 != 1) {
|
|
tmp = copy2.u.diadic.left->u.monadic;
|
|
tmp->u.node = create_objectrefnode(obj);
|
|
}
|
|
|
|
rightAss->u.args3.a = copy2.u.diadic.left;
|
|
rightAss->u.args3.a->rtype = r27->rtype;
|
|
|
|
if (r20 == 1) {
|
|
r21->linear = r27->next->next;
|
|
if (Bv_IsBitSet(r21->index, right->x1A)) {
|
|
Bv_ClearBit(r21->index, right->x1A);
|
|
Bv_SetBit(r21->index, r24->x1A);
|
|
}
|
|
if (Bv_IsBitSet(r21->index, right->x1E)) {
|
|
Bv_ClearBit(r21->index, right->x1E);
|
|
Bv_SetBit(r21->index, r24->x1E);
|
|
}
|
|
if (Bv_IsBitSet(r21->index, right->x22)) {
|
|
Bv_ClearBit(r21->index, right->x22);
|
|
Bv_SetBit(r21->index, r24->x22);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!r18) {
|
|
if (r20 == 1 && r23->data.objref->u.var.info) {
|
|
r23->data.objref->u.var.info->usage = 0;
|
|
r23->data.objref->u.var.info->used = 0;
|
|
}
|
|
r22->x18 = 0;
|
|
IRO_NopOut(copy2.u.diadic.left);
|
|
r21->x18 = 0;
|
|
}
|
|
} else {
|
|
memcpy(©3, fnode->first, sizeof(IROLinear));
|
|
memcpy(fnode->first, ©2, sizeof(IROLinear));
|
|
|
|
fnode->first->index = copy3.index;
|
|
fnode->first->u.diadic.right = rightAss;
|
|
fnode->first->next = copy3.next;
|
|
r22->x18 = 0;
|
|
r21->linear = fnode->first;
|
|
if (Bv_IsBitSet(r21->index, right->x1A)) {
|
|
Bv_ClearBit(r21->index, right->x1A);
|
|
Bv_SetBit(r21->index, fnode->x1A);
|
|
}
|
|
if (Bv_IsBitSet(r21->index, right->x1E)) {
|
|
Bv_ClearBit(r21->index, right->x1E);
|
|
Bv_SetBit(r21->index, fnode->x1E);
|
|
}
|
|
if (Bv_IsBitSet(r21->index, right->x22)) {
|
|
Bv_ClearBit(r21->index, right->x22);
|
|
Bv_SetBit(r21->index, fnode->x22);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void RebuildPossibleReturnCondExpression(IRONode *fnode) {
|
|
IRONode *succ1;
|
|
IRONode *succ2;
|
|
IROLinear *node1;
|
|
IROLinear *node2;
|
|
IROLinear *node3;
|
|
IRONode *r27;
|
|
Boolean isIf;
|
|
Type *type;
|
|
IROList list;
|
|
|
|
if (
|
|
!fnode ||
|
|
fnode->numsucc != 2 ||
|
|
!fnode->last ||
|
|
(fnode->last->type != IROLinearIf && fnode->last->type != IROLinearIfNot)
|
|
)
|
|
return;
|
|
|
|
succ1 = IRO_NodeTable[fnode->succ[0]];
|
|
succ2 = IRO_NodeTable[fnode->succ[1]];
|
|
if (
|
|
!succ1 || !succ2 ||
|
|
succ1->numsucc != 0 || succ1->numpred != 1 ||
|
|
succ2->numsucc != 0 || succ2->numpred != 1
|
|
)
|
|
return;
|
|
|
|
if (succ1->first && succ1->first->type == IROLinearLabel && succ1->first->u.label.label == fnode->last->u.label.label) {
|
|
r27 = succ1;
|
|
} else if (succ2->first && succ2->first->type == IROLinearLabel && succ2->first->u.label.label == fnode->last->u.label.label) {
|
|
r27 = succ2;
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
if (r27->numpred != 1)
|
|
return;
|
|
|
|
if (!CheckThenOrElseBranch(fnode->nextnode, fnode->nextnode, NULL, 1) || !CheckThenOrElseBranch(r27, r27, NULL, 1))
|
|
return;
|
|
|
|
if (
|
|
!fnode->nextnode->last ||
|
|
fnode->nextnode->last->type != IROLinearReturn ||
|
|
!fnode->nextnode->last->u.monadic ||
|
|
!r27->last ||
|
|
r27->last->type != IROLinearReturn ||
|
|
!r27->last->u.monadic ||
|
|
!IRO_TypesEqual(fnode->nextnode->last->u.monadic->rtype, r27->last->u.monadic->rtype)
|
|
)
|
|
return;
|
|
|
|
isIf = fnode->last->type == IROLinearIf;
|
|
node1 = fnode->last->u.diadic.right;
|
|
node2 = fnode->nextnode->last->u.diadic.left;
|
|
node3 = r27->last->u.diadic.left;
|
|
type = node2->rtype;
|
|
|
|
fnode->last->type = IROLinearNop;
|
|
fnode->last->expr = NULL;
|
|
r27->last->type = IROLinearNop;
|
|
r27->last->expr = NULL;
|
|
r27->first->type = IROLinearNop;
|
|
r27->first->expr = NULL;
|
|
|
|
if (IRO_IsIntConstant(node2) && IRO_IsIntConstant(node3) &&
|
|
((IRO_IsConstantOne(node2) && IRO_IsConstantZero(node3)) ||
|
|
(IRO_IsConstantZero(node2) && IRO_IsConstantOne(node3)))) {
|
|
if (!(node1->type == IROLinearOp1Arg && node1->nodetype == ELOGNOT && node1->rtype == type)) {
|
|
IROLinear *tmp1;
|
|
IROLinear *tmp2;
|
|
|
|
tmp1 = IRO_NewLinear(IROLinearOp1Arg);
|
|
memcpy(tmp1, node2, sizeof(IROLinear));
|
|
tmp1->type = IROLinearOp1Arg;
|
|
tmp1->nodetype = ELOGNOT;
|
|
tmp1->index = IRO_NumLinear++;
|
|
tmp1->u.monadic = node1;
|
|
|
|
tmp1->next = tmp2 = IRO_NewLinear(IROLinearOp1Arg);
|
|
memcpy(tmp2, node2, sizeof(IROLinear));
|
|
tmp2->type = IROLinearOp1Arg;
|
|
tmp2->nodetype = ELOGNOT;
|
|
tmp2->index = IRO_NumLinear++;
|
|
tmp2->u.monadic = tmp1;
|
|
|
|
IRO_PasteAfter(tmp1, tmp2, node1);
|
|
node1 = tmp2;
|
|
}
|
|
|
|
if ((IRO_IsConstantZero(node2) && !isIf) || (IRO_IsConstantOne(node2) && isIf)) {
|
|
if (node1->type == IROLinearOp1Arg && node1->nodetype == ELOGNOT && node1->rtype == node1->u.monadic->rtype) {
|
|
IROLinear *tmp = node1;
|
|
node1 = node1->u.monadic;
|
|
tmp->type = IROLinearNop;
|
|
tmp->expr = NULL;
|
|
} else {
|
|
IROLinear *tmp = IRO_NewLinear(IROLinearOp1Arg);
|
|
memcpy(tmp, node2, sizeof(IROLinear));
|
|
tmp->type = IROLinearOp1Arg;
|
|
tmp->nodetype = ELOGNOT;
|
|
tmp->index = IRO_NumLinear++;
|
|
tmp->u.monadic = node1;
|
|
IRO_PasteAfter(tmp, tmp, node1);
|
|
node1 = tmp;
|
|
}
|
|
}
|
|
|
|
node2->type = IROLinearNop;
|
|
node2->expr = NULL;
|
|
node3->type = IROLinearNop;
|
|
node3->expr = NULL;
|
|
fnode->nextnode->last->u.monadic = node1;
|
|
} else {
|
|
IROLinear *tmp1;
|
|
IROLinear *tmp2;
|
|
|
|
IRO_InitList(&list);
|
|
tmp1 = IRO_DuplicateExpr(node3, &list);
|
|
IRO_NopOut(node3);
|
|
IRO_Paste(list.head, list.tail, fnode->nextnode->last);
|
|
|
|
tmp2 = IRO_NewLinear(IROLinearOp3Arg);
|
|
memcpy(tmp2, node2, sizeof(IROLinear));
|
|
tmp2->type = IROLinearOp3Arg;
|
|
tmp2->nodetype = ECOND;
|
|
tmp2->index = IRO_NumLinear++;
|
|
tmp2->u.args3.a = node1;
|
|
tmp2->rtype = type;
|
|
IRO_Paste(tmp2, tmp2, fnode->nextnode->last);
|
|
|
|
if (isIf) {
|
|
tmp2->u.args3.b = tmp1;
|
|
tmp2->u.args3.c = node2;
|
|
} else {
|
|
tmp2->u.args3.b = node2;
|
|
tmp2->u.args3.c = tmp1;
|
|
}
|
|
|
|
fnode->nextnode->last->u.monadic = tmp2;
|
|
}
|
|
}
|
|
|
|
static void RebuildCondExpressions(void) {
|
|
IRONode *fnode;
|
|
|
|
for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
|
|
if (fnode->numpred == 2) {
|
|
if (fnode->first && fnode->first->type == IROLinearLabel)
|
|
RebuildPossibleCondExpression(fnode);
|
|
} else if (fnode->numsucc == 2) {
|
|
if (fnode->last && (fnode->last->type == IROLinearIf || fnode->last->type == IROLinearIfNot))
|
|
RebuildPossibleReturnCondExpression(fnode);
|
|
}
|
|
}
|
|
|
|
IRO_CheckForUserBreak();
|
|
}
|
|
|
|
static Boolean IsLogicalExpressionAssign(IROLinear *nd) {
|
|
IROLinear *right;
|
|
IROLinear *left;
|
|
|
|
return (
|
|
nd->type == IROLinearOp2Arg &&
|
|
nd->nodetype == EASS &&
|
|
(left = nd->u.diadic.left) &&
|
|
(right = nd->u.diadic.right) &&
|
|
right->type == IROLinearOperand &&
|
|
right->u.node &&
|
|
right->u.node->type == EINTCONST &&
|
|
(CInt64_Equal(right->u.node->data.intval, cint64_one) || CInt64_Equal(right->u.node->data.intval, cint64_zero)) &&
|
|
left->type == IROLinearOp1Arg &&
|
|
left->nodetype == EINDIRECT &&
|
|
left->u.monadic &&
|
|
IS_TYPE_POINTER_ONLY(left->u.monadic->rtype) &&
|
|
left->u.monadic->type == IROLinearOperand &&
|
|
left->u.monadic->u.node &&
|
|
left->u.monadic->u.node->type == EOBJREF &&
|
|
left->u.monadic->u.node->data.objref &&
|
|
left->u.monadic->u.node->data.objref->datatype == DLOCAL);
|
|
}
|
|
|
|
static Boolean IsPossibleLogicalExpressionStart(IRONode *fnode, IROLinear *nd) {
|
|
return
|
|
fnode->numsucc == 2 &&
|
|
fnode->last &&
|
|
(fnode->last->type == IROLinearIf || fnode->last->type == IROLinearIfNot) &&
|
|
IsLogicalExpressionAssign(nd);
|
|
}
|
|
|
|
static Boolean CheckForTopLevelExpressions(IRONode *fnode1, IRONode *fnode2, IRONode *fnode3, IROLinear *nd1, IROLinear *nd2, Boolean flag) {
|
|
IRONode *fnode;
|
|
IROLinear *nd;
|
|
UInt16 i;
|
|
|
|
if (fnode1 != fnode3) {
|
|
if (!Bv_IsBitSet(fnode2->index, fnode1->dom))
|
|
return 0;
|
|
|
|
if (flag) {
|
|
for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode)
|
|
fnode->x3C = 0;
|
|
} else if (fnode1->x3C) {
|
|
return 1;
|
|
}
|
|
fnode1->x3C = 1;
|
|
|
|
for (i = 0; i < fnode1->numsucc; i++) {
|
|
fnode = IRO_NodeTable[fnode1->succ[i]];
|
|
if (!CheckForTopLevelExpressions(fnode, fnode2, fnode3, fnode->first, nd2, 0))
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
for (nd = nd1; nd && nd != fnode1->last->next; nd = nd->next) {
|
|
if (nd == nd2)
|
|
return 1;
|
|
|
|
if (nd->type != IROLinearNop && nd->type != IROLinearLabel && !(nd->flags & IROLF_Reffed))
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static void AddNodeAndSuccessorsRecursively(IRONodes *nodes, IRONode *fnode1, IRONode *fnode2) {
|
|
UInt16 i;
|
|
|
|
if (fnode1 && !fnode1->x3C) {
|
|
fnode1->x3C = 1;
|
|
IROFlowgraph_sub_4C3880(nodes, fnode1->index);
|
|
if (fnode1 != fnode2) {
|
|
for (i = 0; i < fnode1->numsucc; i++)
|
|
AddNodeAndSuccessorsRecursively(nodes, IRO_NodeTable[fnode1->succ[i]], fnode2);
|
|
}
|
|
}
|
|
}
|
|
|
|
static Boolean RebuildPossibleLogicalExpression(IRONode *fnode, IROLinear *nd) {
|
|
IROUse *use;
|
|
IROLinear *nd2;
|
|
IROLinear *left;
|
|
IROLinear *right;
|
|
IRONode *r25;
|
|
IRONode *r24;
|
|
ENode *objnode;
|
|
IRODef *def1;
|
|
IRODef *def2;
|
|
UInt32 useCount;
|
|
UInt32 rewrittenUseCount;
|
|
Boolean sideEffectFlag;
|
|
IROLinearType compareType;
|
|
CLabel *somelab;
|
|
IRONode *var_68;
|
|
IRONode *var_6C;
|
|
CInt64 compareVal;
|
|
Boolean killedFlag;
|
|
BitVector *bv1;
|
|
BitVector *bv2;
|
|
|
|
IROLinear *father;
|
|
IROLinear *iter;
|
|
IRODef *def;
|
|
UInt32 i;
|
|
IROLinear *newlin;
|
|
|
|
objnode = nd->u.diadic.left->u.monadic->u.node;
|
|
if (!objnode->data.objref->varptr)
|
|
return 0;
|
|
|
|
if (CInt64_Equal(nd->u.diadic.right->u.node->data.intval, cint64_zero)) {
|
|
compareType = IROLinearIfNot;
|
|
compareVal = cint64_one;
|
|
} else {
|
|
compareType = IROLinearIf;
|
|
compareVal = cint64_zero;
|
|
}
|
|
|
|
var_68 = NULL;
|
|
def1 = NULL;
|
|
for (def = objnode->data.objref->varptr->defs; def && !def1; def = def->varnext) {
|
|
if (def->x18 && def->linear == nd)
|
|
def1 = def;
|
|
}
|
|
|
|
if (def1) {
|
|
for (use = objnode->data.objref->varptr->uses; use; use = use->varnext) {
|
|
if (use->x1C == 2 && Bv_IsBitSet(def1->index, use->x18)) {
|
|
if (!var_68) {
|
|
var_68 = use->node;
|
|
} else if (Bv_IsBitSet(use->node->index, var_68->dom)) {
|
|
var_68 = use->node;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (var_68) {
|
|
for (use = objnode->data.objref->varptr->uses; use; use = use->varnext) {
|
|
if (use->node != var_68 && use->x1C == 2 && Bv_IsBitSet(def1->index, use->x18) && !Bv_IsBitSet(var_68->index, use->node->dom)) {
|
|
var_68 = NULL;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (
|
|
!var_68 ||
|
|
!var_68->first ||
|
|
var_68->first->type != IROLinearLabel ||
|
|
!(somelab = var_68->first->u.label.label) ||
|
|
var_68->numpred != 3
|
|
)
|
|
return 0;
|
|
|
|
r25 = IRO_NodeTable[var_68->pred[0]];
|
|
if (Bv_IsBitSet(IRO_NodeTable[var_68->pred[1]]->index, r25->dom)) {
|
|
r25 = IRO_NodeTable[var_68->pred[1]];
|
|
} else if (!Bv_IsBitSet(r25->index, IRO_NodeTable[var_68->pred[1]]->dom)) {
|
|
return 0;
|
|
}
|
|
|
|
if (Bv_IsBitSet(IRO_NodeTable[var_68->pred[2]]->index, r25->dom)) {
|
|
r25 = IRO_NodeTable[var_68->pred[2]];
|
|
} else if (!Bv_IsBitSet(r25->index, IRO_NodeTable[var_68->pred[2]]->dom)) {
|
|
return 0;
|
|
}
|
|
|
|
if (
|
|
!r25 ||
|
|
!(left = r25->last) ||
|
|
left->type != compareType ||
|
|
left->u.label.label != somelab
|
|
)
|
|
return 0;
|
|
|
|
if (
|
|
!FindFlowgraphNodeThatStartsWithLabel(left->u.label.label, &var_68, &var_6C) ||
|
|
!var_6C ||
|
|
var_6C->numpred != 1 ||
|
|
!(r24 = IRO_NodeTable[var_6C->pred[0]]) ||
|
|
!(right = r24->last) ||
|
|
right->type != compareType ||
|
|
right->u.label.label != left->u.label.label ||
|
|
!(nd2 = FindLastDiadicTopLevelAssignmentInFlowgraphNode(var_6C)) ||
|
|
!IsLogicalExpressionAssign(nd2) ||
|
|
nd2->u.diadic.left->u.monadic->u.node->data.objref != objnode->data.objref ||
|
|
!CInt64_Equal(compareVal, nd2->u.diadic.right->u.node->data.intval) ||
|
|
nd2->rtype != nd->rtype
|
|
)
|
|
return 0;
|
|
|
|
if (
|
|
!CheckForTopLevelExpressions(fnode, fnode, r25, nd->next, left, 1) ||
|
|
!CheckForTopLevelExpressions(r25->nextnode, r25->nextnode, r24, r25->nextnode->first, right, 1) ||
|
|
!CheckForTopLevelExpressions(r24->nextnode, r24->nextnode, var_6C, right->next, nd2, 1) ||
|
|
!CheckForTopLevelExpressions(var_6C, var_6C, var_6C, nd2->next, var_68->first, 1)
|
|
)
|
|
return 0;
|
|
|
|
rewrittenUseCount = 0;
|
|
useCount = 0;
|
|
killedFlag = 0;
|
|
sideEffectFlag = 0;
|
|
if (!objnode->data.objref->varptr || !(objnode->data.objref->varptr->uses) || !(objnode->data.objref->varptr->defs)) {
|
|
objnode = NULL;
|
|
} else {
|
|
def1 = def2 = NULL;
|
|
for (def = objnode->data.objref->varptr->defs; def && (!def1 || !def2); def = def->varnext) {
|
|
if (def->x18 && def->linear == nd)
|
|
def1 = def;
|
|
else if (def->x18 && def->linear == nd2)
|
|
def2 = def;
|
|
}
|
|
|
|
if (!def1 || !def2) {
|
|
objnode = NULL;
|
|
} else {
|
|
for (use = objnode->data.objref->varptr->uses; objnode && use; use = use->varnext) {
|
|
if (use->x1C) {
|
|
useCount++;
|
|
if (Bv_IsBitSet(def1->index, use->x18) && Bv_IsBitSet(def2->index, use->x18)) {
|
|
for (i = 0; objnode && i < use->x18->size; i++) {
|
|
if (i != def1->index && i != def2->index && Bv_IsBitSet(i, use->x18))
|
|
objnode = NULL;
|
|
}
|
|
|
|
if (objnode && !Bv_IsBitSet(var_68->index, use->node->dom))
|
|
objnode = NULL;
|
|
|
|
if (objnode) {
|
|
if (RewriteUse(use, objnode, nd2, 0))
|
|
rewrittenUseCount++;
|
|
else
|
|
objnode = NULL;
|
|
}
|
|
|
|
if (objnode) {
|
|
if (!sideEffectFlag)
|
|
sideEffectFlag = HasSideEffectsBeforeUse(var_68, var_68, use->node, use->linear, 1);
|
|
|
|
if (!killedFlag && (IRO_HasSideEffect(left->u.label.x4) || IRO_HasSideEffect(right->u.label.x4))) {
|
|
iter = use->linear;
|
|
if ((father = IRO_LocateFather(use->linear))) {
|
|
Bv_AllocVector(&bv1, IRO_NumVars + 1);
|
|
Bv_AllocVector(&bv2, IRO_NumVars + 1);
|
|
Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1);
|
|
IRO_WalkTree(left->u.label.x4, GetExprKills);
|
|
IRO_WalkTree(right->u.label.x4, GetExprKills);
|
|
Bv_Or(IRO_VarKills, bv1);
|
|
while (father && !killedFlag) {
|
|
CheckUnorderedRegionsForSideEffectsAndUses(father, iter, bv1, bv2, &killedFlag);
|
|
iter = father;
|
|
father = IRO_LocateFather(father);
|
|
}
|
|
}
|
|
|
|
if (!killedFlag)
|
|
killedFlag = UsesAKilledVarBeforeUse(var_68, var_68, use->node, use->linear, bv1, 1);
|
|
}
|
|
}
|
|
} else if (Bv_IsBitSet(def1->index, use->x18) || Bv_IsBitSet(def2->index, use->x18))
|
|
objnode = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!objnode)
|
|
return 0;
|
|
|
|
left->type = right->type = IROLinearNop;
|
|
left->expr = right->expr = NULL;
|
|
|
|
IRO_NopOut(nd);
|
|
|
|
newlin = IRO_NewLinear(IROLinearOp2Arg);
|
|
memcpy(newlin, nd2, sizeof(IROLinear));
|
|
newlin->nodetype = (compareType == IROLinearIf) ? ELOR : ELAND;
|
|
newlin->index = IRO_NumLinear++;
|
|
newlin->u.diadic.left = left->u.label.x4;
|
|
newlin->u.diadic.right = right->u.label.x4;
|
|
newlin->flags |= IROLF_Reffed;
|
|
IRO_Paste(newlin, newlin, nd2);
|
|
|
|
if (rewrittenUseCount == 1 && !sideEffectFlag && !killedFlag && !objnode->data.objref->varptr->xB) {
|
|
for (use = objnode->data.objref->varptr->uses; use; use = use->varnext) {
|
|
if (use->x1C && Bv_IsBitSet(def1->index, use->x18) && Bv_IsBitSet(def2->index, use->x18))
|
|
RewriteUse(use, objnode, newlin, 1);
|
|
}
|
|
|
|
if (useCount == 1 && objnode->data.objref->u.var.info) {
|
|
objnode->data.objref->u.var.info->usage = 0;
|
|
objnode->data.objref->u.var.info->used = 0;
|
|
}
|
|
IRO_NopOut(nd2);
|
|
def1->x18 = 0;
|
|
def2->x18 = 0;
|
|
} else {
|
|
IRO_NopOut(nd2->u.label.x4);
|
|
nd2->u.label.x4 = newlin;
|
|
def1->x18 = 0;
|
|
}
|
|
|
|
if (r24->numpred == 1 && IRO_NodeTable[r24->pred[0]] == r25 && IRO_MergeFlowGraphNodes(r25, r24))
|
|
r24 = r25;
|
|
if (var_6C->numpred == 1 && IRO_NodeTable[var_6C->pred[0]] == r24 && IRO_MergeFlowGraphNodes(r24, var_6C))
|
|
var_6C = r24;
|
|
if (var_68->numpred == 1 && r24 == r25 && var_6C == r24)
|
|
IRO_MergeFlowGraphNodes(var_6C, var_68);
|
|
return 1;
|
|
}
|
|
|
|
static void RebuildLogicalExpressions(void) {
|
|
IRONode *fnode;
|
|
IROLinear *nd;
|
|
Boolean flag;
|
|
|
|
flag = 1;
|
|
while (flag) {
|
|
flag = 0;
|
|
for (fnode = IRO_FirstNode; fnode && fnode->last; fnode = fnode->nextnode) {
|
|
for (nd = fnode->first; nd && nd != fnode->last->next; nd = nd->next) {
|
|
if (IsPossibleLogicalExpressionStart(fnode, nd) && RebuildPossibleLogicalExpression(fnode, nd))
|
|
flag = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
IRO_CheckForUserBreak();
|
|
}
|
|
|
|
static Boolean IsPossibleCondAssStart(IRONode *fnode) {
|
|
return (fnode->numsucc == 2) && fnode->last && (fnode->last->type == IROLinearIf || fnode->last->type == IROLinearIfNot);
|
|
}
|
|
|
|
static Type *logicalType(void) {
|
|
if (copts.cplusplus && copts.booltruefalse)
|
|
return TYPE(&stbool);
|
|
else
|
|
return TYPE(&stsignedint);
|
|
}
|
|
|
|
static Boolean GeneratePossibleCondAss(IRONode *fnode) {
|
|
IROLinear *r31;
|
|
IRONode *node2;
|
|
IRONode *r29;
|
|
Boolean r28;
|
|
IRONode *node1;
|
|
IROLinear *r24;
|
|
Boolean r23;
|
|
IROLinear *r19;
|
|
Boolean r18;
|
|
IROLinear *r20;
|
|
Boolean r19flag;
|
|
IROLinear *r18nd;
|
|
IROLinear *ass;
|
|
IROLinear *cond;
|
|
IROLinear *r16;
|
|
IROLinear *r15;
|
|
BitVector *saveVarKills;
|
|
IROList list;
|
|
Object *obj;
|
|
IROLinear *r14;
|
|
|
|
if (!fnode || fnode->numsucc != 2 || !fnode->last || (fnode->last->type != IROLinearIf && fnode->last->type != IROLinearIfNot))
|
|
return 0;
|
|
|
|
if (IRO_NodeTable[fnode->succ[0]] &&
|
|
IRO_NodeTable[fnode->succ[0]]->first &&
|
|
IRO_NodeTable[fnode->succ[0]]->first->type == IROLinearLabel &&
|
|
IRO_NodeTable[fnode->succ[0]]->first->u.label.label == fnode->last->u.label.label) {
|
|
node1 = IRO_NodeTable[fnode->succ[0]];
|
|
node2 = IRO_NodeTable[fnode->succ[1]];
|
|
} else {
|
|
node1 = IRO_NodeTable[fnode->succ[1]];
|
|
if (node1 && node1->first && node1->first->type == IROLinearLabel && node1->first->u.label.label == fnode->last->u.label.label) {
|
|
node2 = IRO_NodeTable[fnode->succ[0]];
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if (!node2 || node2->numpred != 1 || node2->numsucc != 1 || node2->last->next != node1->first)
|
|
return 0;
|
|
|
|
if (IRO_NodeTable[node2->succ[0]] == node1 && Bv_IsBitSet(fnode->index, node1->dom)) {
|
|
r28 = 0;
|
|
} else if (
|
|
node1->numpred == 1 && node1->numsucc == 1 &&
|
|
node2->succ[0] == node1->succ[0] &&
|
|
(r29 = IRO_NodeTable[node2->succ[0]]) &&
|
|
Bv_IsBitSet(fnode->index, r29->dom) &&
|
|
node1->last->next == r29->first
|
|
) {
|
|
r28 = 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
|
|
r24 = NULL;
|
|
if (node2->last) {
|
|
for (r19 = node2->first; r19 && r19 != node2->last->next; r19 = r19->next) {
|
|
if (IRO_IsAssignment(r19) && !(r19->flags & IROLF_Reffed) && !r24) {
|
|
r24 = r19;
|
|
} else if (r19->type != IROLinearNop && r19->type != IROLinearLabel && r19->type != IROLinearGoto && !(r19->flags & IROLF_Reffed)) {
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (
|
|
!r24 ||
|
|
(r24->nodetype != EASS && !IRO_TransformSelfAssignmentToAssignment(r24)) ||
|
|
!r24->u.diadic.left ||
|
|
r24->u.diadic.left->type != IROLinearOp1Arg ||
|
|
r24->u.diadic.left->nodetype != EINDIRECT ||
|
|
!r24->u.diadic.left->u.monadic ||
|
|
r24->u.diadic.left->u.monadic->type != IROLinearOperand ||
|
|
!r24->u.diadic.left->u.monadic->u.node ||
|
|
!r24->u.diadic.left->u.monadic->u.node->rtype ||
|
|
!IS_TYPE_POINTER_ONLY(r24->u.diadic.left->u.monadic->u.node->rtype) ||
|
|
!r24->u.diadic.left->u.monadic->u.node->data.monadic
|
|
)
|
|
return 0;
|
|
|
|
if (r28) {
|
|
r31 = NULL;
|
|
if (node1->last) {
|
|
for (r19 = node1->first; r19 && r19 != node1->last->next; r19 = r19->next) {
|
|
if (IRO_IsAssignment(r19) && !(r19->flags & IROLF_Reffed) && !r31) {
|
|
r31 = r19;
|
|
} else if (r19->type != IROLinearNop && r19->type != IROLinearLabel && r19->type != IROLinearGoto && !(r19->flags & IROLF_Reffed)) {
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (
|
|
!r31 ||
|
|
(r31->nodetype != EASS && !IRO_TransformSelfAssignmentToAssignment(r31)) ||
|
|
!r31->u.diadic.left ||
|
|
r31->u.diadic.left->type != IROLinearOp1Arg ||
|
|
r31->u.diadic.left->nodetype != EINDIRECT ||
|
|
!r31->u.diadic.left->u.monadic ||
|
|
r31->u.diadic.left->u.monadic->type != IROLinearOperand ||
|
|
!r31->u.diadic.left->u.monadic->u.node ||
|
|
!r31->u.diadic.left->u.monadic->u.node->rtype ||
|
|
!IS_TYPE_POINTER_ONLY(r31->u.diadic.left->u.monadic->u.node->rtype) ||
|
|
!r31->u.diadic.left->u.monadic->u.node->data.monadic
|
|
)
|
|
return 0;
|
|
|
|
r18 = IRO_ExprsSame(r24->u.diadic.left, r31->u.diadic.left);
|
|
}
|
|
|
|
r23 = fnode->last->type == IROLinearIf;
|
|
r20 = fnode->last->u.diadic.right;
|
|
r19flag = 0;
|
|
if (r28 && copts.commonsubs && IRO_IsSubableExpression(r20))
|
|
r19flag = 1;
|
|
|
|
if (r19flag) {
|
|
IRO_FindDepends(r20);
|
|
r19flag = !IRO_NotSubable;
|
|
}
|
|
|
|
if (r28) {
|
|
if (r18) {
|
|
r19flag = 0;
|
|
} else if (IRO_HasSideEffect(r20)) {
|
|
r19flag = 1;
|
|
} else {
|
|
Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1);
|
|
IRO_WalkTree(r20, GetExprUses);
|
|
saveVarKills = IRO_VarKills;
|
|
Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1);
|
|
IRO_WalkTree(r20, GetExprKills);
|
|
if (Bv_BitsInCommon(IRO_VarKills, saveVarKills))
|
|
r19flag = 1;
|
|
}
|
|
|
|
if (r19flag && !copts.commonsubs)
|
|
return 0;
|
|
}
|
|
|
|
if (r19flag) {
|
|
IRO_InitList(&list);
|
|
obj = create_temp_object(r20->rtype);
|
|
IRO_FindVar(obj, 1, 1);
|
|
ass = IRO_NewLinear(IROLinearOp2Arg);
|
|
ass->u.diadic.left = IRO_TempReference(obj, &list);
|
|
ass->rtype = r20->rtype;
|
|
ass->nodetype = EASS;
|
|
ass->index = ++IRO_NumLinear;
|
|
ass->u.diadic.left->flags |= IROLF_Ind | IROLF_Assigned;
|
|
ass->u.diadic.left->u.monadic->flags |= IROLF_Ind | IROLF_Assigned;
|
|
ass->u.diadic.right = r20;
|
|
IRO_AddToList(ass, &list);
|
|
IRO_PasteAfter(list.head, list.tail, r20);
|
|
}
|
|
|
|
r16 = r24->u.diadic.left;
|
|
r15 = r24->u.diadic.right;
|
|
fnode->last->type = IROLinearNop;
|
|
fnode->last->expr = NULL;
|
|
if (node2->last->type == IROLinearGoto) {
|
|
node2->last->type = IROLinearNop;
|
|
node2->last->expr = NULL;
|
|
}
|
|
if (r28 || node1->numpred == 2) {
|
|
node1->first->type = IROLinearNop;
|
|
node1->first->expr = NULL;
|
|
}
|
|
|
|
if (r28 && r18) {
|
|
if (node1->last->type == IROLinearGoto) {
|
|
node1->last->type = IROLinearNop;
|
|
node1->last->expr = NULL;
|
|
}
|
|
if (r29->numpred == 2) {
|
|
r29->first->type = IROLinearNop;
|
|
r29->first->expr = NULL;
|
|
}
|
|
|
|
cond = IRO_NewLinear(IROLinearOp3Arg);
|
|
memcpy(cond, r24, sizeof(IROLinear));
|
|
cond->type = IROLinearOp3Arg;
|
|
cond->nodetype = ECOND;
|
|
cond->index = ++IRO_NumLinear;
|
|
cond->rtype = r16->rtype;
|
|
cond->flags |= IROLF_Reffed;
|
|
if (r19flag) {
|
|
IRO_InitList(&list);
|
|
r14 = IRO_TempReference(obj, &list);
|
|
IRO_Paste(list.head, list.tail, r31);
|
|
} else {
|
|
r14 = r20;
|
|
}
|
|
cond->u.args3.a = r14;
|
|
|
|
if (r23) {
|
|
cond->u.args3.b = r31->u.diadic.right;
|
|
cond->u.args3.c = r15;
|
|
} else {
|
|
cond->u.args3.b = r15;
|
|
cond->u.args3.c = r31->u.diadic.right;
|
|
}
|
|
|
|
r24->type = IROLinearNop;
|
|
r24->expr = NULL;
|
|
IRO_NopOut(r24->u.diadic.left);
|
|
IRO_Paste(cond, cond, r31);
|
|
r31->u.diadic.right = cond;
|
|
} else {
|
|
r24->type = IROLinearOp3Arg;
|
|
r24->nodetype = ECONDASS;
|
|
if (r19flag) {
|
|
IRO_InitList(&list);
|
|
r20 = IRO_TempReference(obj, &list);
|
|
IRO_Paste(list.head, list.tail, r24);
|
|
}
|
|
cond = r20;
|
|
if (r23) {
|
|
r18nd = IRO_NewLinear(IROLinearOp1Arg);
|
|
memcpy(r18nd, r20, sizeof(IROLinear));
|
|
r18nd->type = IROLinearOp1Arg;
|
|
r18nd->nodetype = ELOGNOT;
|
|
r18nd->index = ++IRO_NumLinear;
|
|
r18nd->rtype = logicalType();
|
|
r18nd->u.monadic = r20;
|
|
r18nd->flags |= IROLF_Reffed;
|
|
IRO_Paste(r18nd, r18nd, r24);
|
|
r20 = r18nd;
|
|
}
|
|
r24->u.args3.a = r20;
|
|
r24->u.args3.b = r16;
|
|
r24->u.args3.c = r15;
|
|
if (r28) {
|
|
r15 = r31->u.diadic.left;
|
|
r16 = r31->u.diadic.right;
|
|
if (node1->last->type == IROLinearGoto) {
|
|
node1->last->type = IROLinearNop;
|
|
node1->last->expr = NULL;
|
|
}
|
|
if (r29->numpred == 2) {
|
|
r29->first->type = IROLinearNop;
|
|
r29->first->expr = NULL;
|
|
}
|
|
r31->type = IROLinearOp3Arg;
|
|
r31->nodetype = ECONDASS;
|
|
if (r19flag) {
|
|
IRO_InitList(&list);
|
|
cond = IRO_TempReference(obj, &list);
|
|
IRO_Paste(list.head, list.tail, r31);
|
|
} else {
|
|
IRO_InitList(&list);
|
|
cond = IRO_DuplicateExpr(cond, &list);
|
|
IRO_Paste(list.head, list.tail, r31);
|
|
}
|
|
if (!r23) {
|
|
r14 = IRO_NewLinear(IROLinearOp1Arg);
|
|
memcpy(r14, cond, sizeof(IROLinear));
|
|
r14->type = IROLinearOp1Arg;
|
|
r14->nodetype = ELOGNOT;
|
|
r14->index = ++IRO_NumLinear;
|
|
r14->rtype = logicalType();
|
|
r14->u.monadic = cond;
|
|
r14->flags |= IROLF_Reffed;
|
|
IRO_Paste(r14, r14, r31);
|
|
cond = r14;
|
|
}
|
|
r31->u.args3.a = cond;
|
|
r31->u.args3.b = r15;
|
|
r31->u.args3.c = r16;
|
|
}
|
|
}
|
|
|
|
if (IRO_MergeFlowGraphNodes(fnode, node2))
|
|
node2 = fnode;
|
|
if ((r28 || node1->numpred == 1) && IRO_MergeFlowGraphNodes(node2, node1))
|
|
node1 = node2;
|
|
if (r28 && r29->numpred == 1)
|
|
IRO_MergeFlowGraphNodes(node1, r29);
|
|
return 1;
|
|
}
|
|
|
|
static void GenerateCondAssignments(void) {
|
|
IRONode *fnode;
|
|
|
|
fnode = IRO_FirstNode;
|
|
while (fnode && fnode->last) {
|
|
if (IsPossibleCondAssStart(fnode)) {
|
|
if (!GeneratePossibleCondAss(fnode))
|
|
fnode = fnode->nextnode;
|
|
} else {
|
|
fnode = fnode->nextnode;
|
|
}
|
|
}
|
|
|
|
IRO_CheckForUserBreak();
|
|
}
|
|
|
|
void IRO_RegenerateExpressions(void) {
|
|
IRO_UpdateFlagsOnInts();
|
|
IRO_ComputeSuccPred();
|
|
IRO_ComputeDom();
|
|
IRO_UseDef(0, 0);
|
|
|
|
if (copts.optimizationlevel > 0) {
|
|
IRO_Dump("Rebuilding ELORs and ELANDs\n");
|
|
RebuildLogicalExpressions();
|
|
IRO_DumpAfterPhase("RebuildLogicalExpressions", 0);
|
|
}
|
|
|
|
if (copts.optimizationlevel > 0) {
|
|
IRO_Dump("Rebuilding ECONDs\n");
|
|
RebuildCondExpressions();
|
|
IRO_DumpAfterPhase("RebuildCondExpressions", 0);
|
|
}
|
|
|
|
if (copts.optimizationlevel > 0) {
|
|
IRO_Dump("Generating ECONDASSes\n");
|
|
GenerateCondAssignments();
|
|
IRO_DumpAfterPhase("GenerateCondAssignments", 0);
|
|
}
|
|
}
|