2022-12-14 00:16:59 +00:00
|
|
|
#include "compiler/IroLoop.h"
|
|
|
|
#include "compiler/IroCSE.h"
|
|
|
|
#include "compiler/IroDump.h"
|
|
|
|
#include "compiler/IroFlowgraph.h"
|
|
|
|
#include "compiler/IroLinearForm.h"
|
|
|
|
#include "compiler/IroPropagate.h"
|
|
|
|
#include "compiler/IroSubable.h"
|
|
|
|
#include "compiler/IroUtil.h"
|
|
|
|
#include "compiler/IroVars.h"
|
|
|
|
#include "compiler/CFunc.h"
|
|
|
|
#include "compiler/CInt64.h"
|
|
|
|
#include "compiler/CMachine.h"
|
|
|
|
#include "compiler/objects.h"
|
|
|
|
#include "compiler/types.h"
|
|
|
|
|
|
|
|
IRONode *LoopNode;
|
|
|
|
Boolean ConditionalHeaderAtBottom;
|
|
|
|
IROLoopInd *FirstInd;
|
|
|
|
BitVector *InLoop;
|
|
|
|
IROList IRO_InitLList;
|
|
|
|
BitVector *InLoop_Exits;
|
|
|
|
BitVector *InLoop_Tails;
|
|
|
|
UInt32 LoopExitNumber;
|
|
|
|
UInt32 LoopTailNum;
|
|
|
|
IRONode *LoopExitSuccessor;
|
|
|
|
IRONode *LoopTail;
|
|
|
|
IROLoopMemRef *IRO_LoopMemRefFirst;
|
|
|
|
IROLoopMemRef *IRO_LoopMemRefCurrent;
|
|
|
|
static IROExpr *RisList;
|
|
|
|
static BitVector *AllKills;
|
|
|
|
static Boolean KnownBounds;
|
|
|
|
static SInt32 Times;
|
|
|
|
static IROLinear *PredInt;
|
|
|
|
static IROElmList *FirstAddendLinear;
|
|
|
|
static IROElmList *LastAddendLinear;
|
|
|
|
static int NoSubableSubs;
|
|
|
|
|
|
|
|
// forward decls
|
|
|
|
static void MyHandleLoop_Vector(IRONode *fnode);
|
|
|
|
static void MyHandleLoop_Motion(IRONode *fnode);
|
|
|
|
static void CheckAllLoopAddresses(IRONode *fnode, BitVector *bv, Boolean *resultFlag);
|
|
|
|
static void MakeLoopEntry(IROLinear *nd, IROAddrRecord *rec, Boolean mustreach1, Boolean flag2);
|
|
|
|
static void MoveInvarianceInAddressExpr(void);
|
|
|
|
static IROLinear *RearrangeInvarianceInAddressExpr(IROLinear *nd, IROList *list);
|
|
|
|
static UInt32 IsAssignmentReductionCandidate(IROLinear *nd);
|
|
|
|
|
|
|
|
void FindMustReach(void) {
|
|
|
|
IRONode *fnode;
|
|
|
|
IRONode *fnode2;
|
|
|
|
IRONode *pred;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
|
|
|
|
fnode->mustreach = 0;
|
|
|
|
if (Bv_IsBitSet(fnode->index, InLoop)) {
|
|
|
|
fnode->mustreach = 1;
|
|
|
|
|
|
|
|
for (i = 0; i < LoopNode->numpred; i++) {
|
|
|
|
pred = IRO_NodeTable[LoopNode->pred[i]];
|
|
|
|
if (Bv_IsBitSet(pred->index, InLoop) && !Bv_IsBitSet(fnode->index, pred->dom)) {
|
|
|
|
fnode->mustreach = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (fnode2 = IRO_FirstNode; fnode2; fnode2 = fnode2->nextnode) {
|
|
|
|
if (Bv_IsBitSet(fnode2->index, InLoop)) {
|
|
|
|
for (i = 0; i < fnode2->numsucc; i++) {
|
|
|
|
if (!Bv_IsBitSet(fnode2->succ[i], InLoop) && !Bv_IsBitSet(fnode->index, fnode2->dom)) {
|
|
|
|
fnode->mustreach = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!fnode->mustreach)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void FindMustReach1(IRONode *checkfnode) {
|
|
|
|
IRONode *fnode;
|
|
|
|
IRONode *fnode2;
|
|
|
|
|
|
|
|
for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
|
|
|
|
if (Bv_IsBitSet(fnode->index, InLoop)) {
|
|
|
|
fnode->mustreach1 = 1;
|
|
|
|
for (fnode2 = IRO_FirstNode; fnode2; fnode2 = fnode2->nextnode) {
|
|
|
|
if (Bv_IsBitSet(fnode2->index, InLoop)) {
|
|
|
|
if (Bv_IsBitSet(fnode2->index, InLoop_Tails) && !Bv_IsBitSet(fnode->index, fnode2->dom))
|
|
|
|
fnode->mustreach1 = 0;
|
|
|
|
|
|
|
|
if (Bv_IsBitSet(fnode2->index, InLoop_Exits) && fnode2 != checkfnode && !Bv_IsBitSet(fnode->index, fnode2->dom))
|
|
|
|
fnode->mustreach1 = 0;
|
|
|
|
|
|
|
|
if (!fnode->mustreach1)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void IRO_FindLoopTailsAndExits(IRONode *fnode) {
|
|
|
|
IRONode *scan;
|
|
|
|
IRONode *succ;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (scan = IRO_FirstNode; scan; scan = scan->nextnode) {
|
|
|
|
if (Bv_IsBitSet(scan->index, InLoop)) {
|
|
|
|
for (i = 0; i < scan->numsucc; i++) {
|
|
|
|
succ = IRO_NodeTable[scan->succ[i]];
|
|
|
|
if (succ == fnode) {
|
|
|
|
Bv_SetBit(scan->index, InLoop_Tails);
|
|
|
|
LoopTail = scan;
|
|
|
|
LoopTailNum++;
|
|
|
|
}
|
|
|
|
if (!Bv_IsBitSet(succ->index, InLoop)) {
|
|
|
|
LoopExitNumber++;
|
|
|
|
LoopExitSuccessor = succ;
|
|
|
|
Bv_SetBit(scan->index, InLoop_Exits);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
IRO_Dump("IRO_FindLoopTailsAndExits:For header %d, Loop exits and loop tails are \n", fnode->index);
|
|
|
|
IRO_DumpBits("Loop Exits: ", InLoop_Exits);
|
|
|
|
IRO_DumpBits("Loop Tails: ", InLoop_Tails);
|
|
|
|
IRO_Dump("LoopExitNum=%d: \n", LoopExitNumber);
|
|
|
|
if (LoopExitSuccessor)
|
|
|
|
IRO_Dump("LoopExitSuccessor node =%d: \n", LoopExitSuccessor->index);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int IsSafeTypcon(IROLinear *nd) {
|
|
|
|
Type *srcType;
|
|
|
|
Type *destType;
|
|
|
|
SInt32 srcSize;
|
|
|
|
SInt32 destSize;
|
|
|
|
Boolean srcUnsigned;
|
|
|
|
Boolean destUnsigned;
|
|
|
|
|
|
|
|
srcType = nd->u.monadic->rtype;
|
|
|
|
destType = nd->rtype;
|
|
|
|
if (!IS_TYPE_INT(srcType) || !IS_TYPE_INT(destType))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
srcSize = srcType->size;
|
|
|
|
destSize = destType->size;
|
|
|
|
srcUnsigned = IRO_IsUnsignedType(srcType);
|
|
|
|
destUnsigned = IRO_IsUnsignedType(destType);
|
|
|
|
|
|
|
|
if (srcUnsigned == destUnsigned && destSize >= srcSize)
|
|
|
|
return 1;
|
|
|
|
if (srcUnsigned == 1 && destUnsigned == 0 && destSize > srcSize)
|
|
|
|
return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int Reducable(IROLinear *nd, IROLinear **resultNd1, IROLinear **resultNd2, VarRecord **resultVar) {
|
|
|
|
IROLinear *indirect;
|
|
|
|
IROLinear *left;
|
|
|
|
IROLinear *right;
|
|
|
|
Boolean leftInvariant;
|
|
|
|
Boolean rightInvariant;
|
|
|
|
Boolean leftTypcon;
|
|
|
|
Boolean rightTypcon;
|
|
|
|
Object *obj;
|
|
|
|
ENode *enode;
|
|
|
|
IROLoopInd *ind;
|
|
|
|
CInt64 val64;
|
|
|
|
SInt32 val;
|
|
|
|
SInt32 div;
|
|
|
|
|
|
|
|
leftInvariant = 0;
|
|
|
|
rightInvariant = 0;
|
|
|
|
leftTypcon = 0;
|
|
|
|
rightTypcon = 0;
|
|
|
|
|
|
|
|
if (nd->type == IROLinearOp2Arg && nd->nodetype == EADD && (IS_TYPE_INT(nd->rtype) || IS_TYPE_POINTER_ONLY(nd->rtype))) {
|
|
|
|
left = nd->u.diadic.left;
|
|
|
|
right = nd->u.diadic.right;
|
|
|
|
if (left->type == IROLinearOp1Arg && left->nodetype == ETYPCON) {
|
|
|
|
leftTypcon = 1;
|
|
|
|
leftInvariant = (left->flags & IROLF_LoopInvariant) != 0;
|
|
|
|
left = left->u.monadic;
|
|
|
|
}
|
|
|
|
if (right->type == IROLinearOp1Arg && right->nodetype == ETYPCON) {
|
|
|
|
rightTypcon = 1;
|
|
|
|
rightInvariant = (right->flags & IROLF_LoopInvariant) != 0;
|
|
|
|
right = right->u.monadic;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (((left->flags & IROLF_LoopInvariant) || leftInvariant) && IRO_IsVariable(right)) {
|
|
|
|
if (leftInvariant || ((!(obj = IRO_IsVariable(left)) || !IRO_IsRegable(obj)) && !IRO_IsConstant(left))) {
|
|
|
|
if (
|
|
|
|
left->type == IROLinearOp2Arg &&
|
|
|
|
left->nodetype == EADD &&
|
|
|
|
(obj = IRO_IsVariable(left->u.diadic.left)) &&
|
|
|
|
IRO_IsRegable(obj) &&
|
|
|
|
IRO_IsConstant(left->u.diadic.right)
|
|
|
|
)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (rightTypcon) {
|
|
|
|
if (!IsSafeTypcon(nd->u.diadic.right))
|
|
|
|
return 0;
|
|
|
|
*resultNd2 = nd->u.diadic.right;
|
|
|
|
} else {
|
|
|
|
*resultNd2 = right;
|
|
|
|
}
|
|
|
|
|
|
|
|
indirect = right;
|
|
|
|
*resultNd1 = IRO_NewLinear(IROLinearOperand);
|
|
|
|
|
|
|
|
enode = IRO_NewENode(EINTCONST);
|
|
|
|
enode->data.intval = cint64_one;
|
|
|
|
enode->rtype = nd->u.diadic.right->rtype;
|
|
|
|
(*resultNd1)->rtype = nd->u.diadic.right->rtype;
|
|
|
|
(*resultNd1)->u.node = enode;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else if (
|
|
|
|
((left->flags & IROLF_LoopInvariant) || leftInvariant) &&
|
|
|
|
right->type == IROLinearOp2Arg &&
|
|
|
|
!rightTypcon &&
|
|
|
|
(right->nodetype == EMUL || right->nodetype == ESHL)
|
|
|
|
) {
|
|
|
|
if (IRO_IsConstant(right->u.diadic.right)) {
|
|
|
|
if (right->nodetype == ESHL) {
|
|
|
|
right->nodetype = EMUL;
|
|
|
|
right->u.diadic.right->u.node->data.intval = CInt64_Shl(cint64_one, right->u.diadic.right->u.node->data.intval);
|
|
|
|
}
|
|
|
|
if (right->u.diadic.left->type == IROLinearOp1Arg) {
|
|
|
|
if (IRO_IsVariable(right->u.diadic.left)) {
|
|
|
|
*resultNd2 = right->u.diadic.left;
|
|
|
|
indirect = right->u.diadic.left;
|
|
|
|
*resultNd1 = right->u.diadic.right;
|
|
|
|
} else if (right->u.diadic.left->nodetype == ETYPCON && IRO_IsVariable(right->u.diadic.left->u.monadic)) {
|
|
|
|
if (!IsSafeTypcon(right->u.diadic.left))
|
|
|
|
return 0;
|
|
|
|
*resultNd2 = right->u.diadic.left;
|
|
|
|
indirect = right->u.diadic.left->u.monadic;
|
|
|
|
*resultNd1 = right->u.diadic.right;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else if (
|
|
|
|
((right->flags & IROLF_LoopInvariant) || rightInvariant) &&
|
|
|
|
left->type == IROLinearOp2Arg &&
|
|
|
|
!leftTypcon &&
|
|
|
|
(left->nodetype == EMUL || left->nodetype == ESHL)
|
|
|
|
) {
|
|
|
|
if (IRO_IsConstant(left->u.diadic.right)) {
|
|
|
|
if (left->nodetype == ESHL) {
|
|
|
|
left->nodetype = EMUL;
|
|
|
|
left->u.diadic.right->u.node->data.intval = CInt64_Shl(cint64_one, left->u.diadic.right->u.node->data.intval);
|
|
|
|
}
|
|
|
|
if (left->u.diadic.left->type == IROLinearOp1Arg) {
|
|
|
|
if (IRO_IsVariable(left->u.diadic.left)) {
|
|
|
|
*resultNd2 = left->u.diadic.left;
|
|
|
|
indirect = left->u.diadic.left;
|
|
|
|
*resultNd1 = left->u.diadic.right;
|
|
|
|
} else if (left->u.diadic.left->nodetype == ETYPCON && IRO_IsVariable(left->u.diadic.left->u.monadic)) {
|
|
|
|
if (!IsSafeTypcon(left->u.diadic.left))
|
|
|
|
return 0;
|
|
|
|
*resultNd2 = left->u.diadic.left;
|
|
|
|
indirect = left->u.diadic.left->u.monadic;
|
|
|
|
*resultNd1 = left->u.diadic.right;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else if (
|
|
|
|
((right->flags & IROLF_LoopInvariant) || rightInvariant) &&
|
|
|
|
IRO_IsVariable(left)
|
|
|
|
) {
|
|
|
|
if (rightInvariant || ((!(obj = IRO_IsVariable(right)) || !IRO_IsRegable(obj)) && !IRO_IsConstant(right))) {
|
|
|
|
if (
|
|
|
|
right->type == IROLinearOp2Arg &&
|
|
|
|
right->nodetype == EADD &&
|
|
|
|
(obj = IRO_IsVariable(right->u.diadic.left)) &&
|
|
|
|
IRO_IsRegable(obj) &&
|
|
|
|
IRO_IsConstant(right->u.diadic.right)
|
|
|
|
)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (leftTypcon) {
|
|
|
|
if (!IsSafeTypcon(nd->u.diadic.left))
|
|
|
|
return 0;
|
|
|
|
*resultNd2 = nd->u.diadic.left;
|
|
|
|
} else {
|
|
|
|
*resultNd2 = left;
|
|
|
|
}
|
|
|
|
|
|
|
|
indirect = left;
|
|
|
|
*resultNd1 = IRO_NewLinear(IROLinearOperand);
|
|
|
|
|
|
|
|
enode = IRO_NewENode(EINTCONST);
|
|
|
|
enode->data.intval = cint64_one;
|
|
|
|
enode->rtype = nd->u.diadic.left->rtype;
|
|
|
|
(*resultNd1)->rtype = nd->u.diadic.left->rtype;
|
|
|
|
(*resultNd1)->u.node = enode;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else if (nd->type == IROLinearOp2Arg && (nd->nodetype == EMUL || nd->nodetype == ESHL) && nd->rtype->size <= 4 && (IS_TYPE_INT(nd->rtype) || IS_TYPE_POINTER_ONLY(nd->rtype))) {
|
|
|
|
left = nd->u.diadic.left;
|
|
|
|
right = nd->u.diadic.right;
|
|
|
|
|
|
|
|
if (IRO_IsConstant(right) && IRO_IsVariable(left)) {
|
|
|
|
*resultNd2 = left;
|
|
|
|
indirect = left;
|
|
|
|
*resultNd1 = right;
|
|
|
|
} else if (IRO_IsConstant(nd->u.diadic.right) && left->type == IROLinearOp1Arg && left->nodetype == ETYPCON &&
|
|
|
|
IRO_IsVariable(left->u.monadic)) {
|
|
|
|
if (!IsSafeTypcon(left))
|
|
|
|
return 0;
|
|
|
|
*resultNd2 = left;
|
|
|
|
indirect = left->u.monadic;
|
|
|
|
*resultNd1 = right;
|
|
|
|
} else {
|
|
|
|
if (nd->type == IROLinearOp2Arg && nd->nodetype == ESHL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (nd->u.diadic.right->flags & IROLF_LoopInvariant) {
|
|
|
|
if (IRO_IsVariable(left)) {
|
|
|
|
*resultNd2 = left;
|
|
|
|
indirect = left;
|
|
|
|
*resultNd1 = right;
|
|
|
|
} else if (left->type == IROLinearOp1Arg && left->nodetype == ETYPCON && IRO_IsVariable(left->u.monadic)) {
|
|
|
|
if (!IsSafeTypcon(left))
|
|
|
|
return 0;
|
|
|
|
*resultNd2 = left;
|
|
|
|
indirect = left->u.monadic;
|
|
|
|
*resultNd1 = right;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else if (nd->u.diadic.left->flags & IROLF_LoopInvariant) {
|
|
|
|
if (IRO_IsVariable(right)) {
|
|
|
|
*resultNd2 = right;
|
|
|
|
indirect = right;
|
|
|
|
*resultNd1 = left;
|
|
|
|
} else if (right->type == IROLinearOp1Arg && right->nodetype == ETYPCON && IRO_IsVariable(right->u.monadic) && nd->type == IROLinearOp2Arg && nd->nodetype == EMUL) {
|
|
|
|
if (!IsSafeTypcon(right))
|
|
|
|
return 0;
|
|
|
|
*resultNd2 = right;
|
|
|
|
indirect = right->u.monadic;
|
|
|
|
*resultNd1 = left;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (nd->type == IROLinearOp2Arg && (nd->nodetype == EDIV || nd->nodetype == ESHR) && nd->rtype->size <= 4 && IS_TYPE_INT(nd->rtype)) {
|
|
|
|
if (IRO_IsVariable(nd->u.diadic.left) && IRO_IsConstant(nd->u.diadic.right)) {
|
|
|
|
val64 = nd->u.diadic.right->u.node->data.intval;
|
|
|
|
if (nd->type == IROLinearOp2Arg && nd->nodetype == ESHR) {
|
|
|
|
CInt64_GetULong(&val64);
|
|
|
|
if (CInt64_GetULong(&val64) > 32 || CTool_EndianReadWord32(&val64.hi))
|
|
|
|
return 0;
|
|
|
|
val64 = CInt64_Shl(cint64_one, val64);
|
|
|
|
}
|
|
|
|
*resultNd2 = nd->u.diadic.left;
|
|
|
|
indirect = nd->u.diadic.left;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (
|
|
|
|
nd->type == IROLinearOp2Arg &&
|
|
|
|
nd->nodetype == ESHL &&
|
|
|
|
(
|
|
|
|
!IRO_IsConstant(*resultNd1) ||
|
|
|
|
(SInt32) CInt64_GetULong(&(*resultNd1)->u.node->data.intval) < 0 ||
|
|
|
|
(SInt32) CInt64_GetULong(&(*resultNd1)->u.node->data.intval) > 32 ||
|
|
|
|
CTool_EndianReadWord32(&(*resultNd1)->u.node->data.intval.hi)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
return 0;
|
|
|
|
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_ASSERT(802, indirect->u.monadic->u.node != NULL);
|
2022-12-14 00:16:59 +00:00
|
|
|
*resultVar = IRO_FindVar(indirect->u.monadic->u.node->data.objref, 0, 1);
|
|
|
|
if (!*resultVar || (*resultVar)->xA != 2)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (copts.ANSI_strict || copts.opt_strength_reduction_strict) {
|
|
|
|
Type *type = (*resultVar)->object->type;
|
|
|
|
if (IRO_IsUnsignedType(type) && type->size < stunsignedlong.size)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nd->type == IROLinearOp2Arg && (nd->nodetype == ESHR || nd->nodetype == EDIV)) {
|
|
|
|
ind = FirstInd;
|
|
|
|
while (ind && ind->var != *resultVar)
|
|
|
|
ind = ind->next;
|
|
|
|
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_ASSERT(845, ind != NULL);
|
2022-12-14 00:16:59 +00:00
|
|
|
|
|
|
|
if (ind->addNode == NULL) {
|
|
|
|
if (ind->addConst < (val = CInt64_GetULong(&val64)))
|
|
|
|
return 0;
|
|
|
|
if ((div = ind->addConst / val) <= 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
*resultNd1 = IRO_NewLinear(IROLinearOperand);
|
|
|
|
enode = IRO_NewENode(EINTCONST);
|
|
|
|
CInt64_SetULong(&enode->data.intval, div);
|
|
|
|
enode->rtype = nd->u.diadic.left->rtype;
|
|
|
|
(*resultNd1)->rtype = nd->u.diadic.left->rtype;
|
|
|
|
(*resultNd1)->u.node = enode;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void IRO_RemoveExpr_Action(IROLinear *linear, Boolean isFirst) {
|
|
|
|
if (isFirst && linear->expr)
|
|
|
|
IRO_RemoveExpr(linear->expr);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void IRO_ActUnmarkRISCandidate(IROLinear *linear, Boolean isFirst) {
|
|
|
|
if (isFirst && linear->expr)
|
|
|
|
linear->flags &= ~IROLF_Ris;
|
|
|
|
}
|
|
|
|
|
|
|
|
static IROExpr *CreateRIS(IROExpr *expr, IROLinear *nd1, IROLinear *nd2, IROLoopInd *induction, int unk) {
|
|
|
|
Object *tempObj;
|
|
|
|
Type *type;
|
|
|
|
Boolean flag23;
|
|
|
|
Object *tempObj2;
|
|
|
|
IROLinear *firstnode;
|
|
|
|
IROLinear *fourthnode;
|
|
|
|
IROLinear *fifthnode;
|
|
|
|
IROLinear *secondnode;
|
|
|
|
IROLinear *thirdnode;
|
|
|
|
IROLinear *tmp;
|
|
|
|
ENode *enode;
|
|
|
|
IROList list1;
|
|
|
|
IROList list2;
|
|
|
|
|
|
|
|
flag23 = 0;
|
|
|
|
type = expr->linear->rtype;
|
|
|
|
tempObj = create_temp_object(type);
|
|
|
|
IRO_FindVar(tempObj, 1, 1);
|
|
|
|
IRO_InitList(&list1);
|
|
|
|
|
|
|
|
if (IS_LINEAR_DIADIC(expr->linear, EADD)) {
|
|
|
|
firstnode = IRO_DuplicateExpr(expr->linear, &list1);
|
|
|
|
} else if (IS_LINEAR_DIADIC_2(expr->linear, EDIV, ESHR)) {
|
|
|
|
firstnode = IRO_DuplicateExpr(expr->linear, &list1);
|
|
|
|
} else {
|
|
|
|
firstnode = IRO_NewLinear(IROLinearOp2Arg);
|
|
|
|
firstnode->index = ++IRO_NumLinear;
|
|
|
|
firstnode->rtype = type;
|
|
|
|
firstnode->nodetype = EMUL;
|
|
|
|
firstnode->u.diadic.left = IRO_DuplicateExpr(nd1, &list1);
|
|
|
|
if (unk)
|
|
|
|
firstnode->u.diadic.right = IRO_DuplicateExpr(nd1, &list1);
|
|
|
|
else
|
|
|
|
firstnode->u.diadic.right = IRO_DuplicateExpr(nd2, &list1);
|
|
|
|
IRO_AddToList(firstnode, &list1);
|
|
|
|
}
|
|
|
|
|
|
|
|
secondnode = IRO_NewLinear(IROLinearOp2Arg);
|
|
|
|
secondnode->index = ++IRO_NumLinear;
|
|
|
|
secondnode->rtype = type;
|
|
|
|
secondnode->nodetype = EASS;
|
|
|
|
secondnode->u.diadic.left = IRO_TempReference(tempObj, &list1);
|
|
|
|
secondnode->u.diadic.left->flags |= IROLF_Ind | IROLF_Assigned;
|
|
|
|
secondnode->u.diadic.left->u.monadic->flags |= IROLF_Ind | IROLF_Assigned;
|
|
|
|
secondnode->u.diadic.right = firstnode;
|
|
|
|
IRO_AddToList(secondnode, &list1);
|
|
|
|
IRO_Paste(list1.head, list1.tail, PredInt);
|
|
|
|
if (
|
|
|
|
!IS_LINEAR_DIADIC_2(expr->linear, EDIV, ESHR) &&
|
|
|
|
induction->addConst != 1 &&
|
|
|
|
(induction->addNode || !IRO_IsConstant(nd2))
|
|
|
|
) {
|
|
|
|
flag23 = 1;
|
|
|
|
IRO_InitList(&list1);
|
|
|
|
thirdnode = IRO_NewLinear(IROLinearOp2Arg);
|
|
|
|
thirdnode->index = ++IRO_NumLinear;
|
|
|
|
thirdnode->rtype = nd2->rtype;
|
|
|
|
thirdnode->nodetype = EMUL;
|
|
|
|
|
|
|
|
if (!induction->addNode) {
|
|
|
|
thirdnode->u.diadic.left = IRO_DuplicateExpr(nd2, &list1);
|
|
|
|
thirdnode->u.diadic.right = IRO_NewLinear(IROLinearOperand);
|
|
|
|
thirdnode->u.diadic.right->index = ++IRO_NumLinear;
|
|
|
|
enode = IRO_NewENode(EINTCONST);
|
|
|
|
enode->rtype = nd2->rtype;
|
|
|
|
thirdnode->u.diadic.right->rtype = nd2->rtype;
|
|
|
|
CInt64_SetLong(&enode->data.intval, induction->addConst);
|
|
|
|
thirdnode->u.diadic.right->u.node = enode;
|
|
|
|
IRO_AddToList(thirdnode->u.diadic.right, &list1);
|
|
|
|
} else {
|
|
|
|
thirdnode->u.diadic.left = IRO_DuplicateExpr(nd2, &list1);
|
|
|
|
thirdnode->u.diadic.right = IRO_DuplicateExpr(induction->addNode, &list1);
|
|
|
|
if (nd2->rtype != induction->addNode->rtype) {
|
|
|
|
tmp = IRO_NewLinear(IROLinearOp1Arg);
|
|
|
|
tmp->nodetype = ETYPCON;
|
|
|
|
tmp->index = ++IRO_NumLinear;
|
|
|
|
tmp->rtype = nd2->rtype;
|
|
|
|
tmp->u.monadic = thirdnode->u.diadic.right;
|
|
|
|
IRO_AddToList(tmp, &list1);
|
|
|
|
thirdnode->u.diadic.right = tmp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
IRO_AddToList(thirdnode, &list1);
|
|
|
|
|
|
|
|
tempObj2 = create_temp_object(nd2->rtype);
|
|
|
|
|
|
|
|
fourthnode = IRO_NewLinear(IROLinearOp2Arg);
|
|
|
|
fourthnode->index = ++IRO_NumLinear;
|
|
|
|
fourthnode->rtype = nd2->rtype;
|
|
|
|
fourthnode->nodetype = EASS;
|
|
|
|
fourthnode->u.diadic.left = IRO_TempReference(tempObj2, &list1);
|
|
|
|
fourthnode->u.diadic.left->flags |= IROLF_Ind | IROLF_Assigned;
|
|
|
|
fourthnode->u.diadic.left->u.monadic->flags |= IROLF_Ind | IROLF_Assigned;
|
|
|
|
fourthnode->u.diadic.right = thirdnode;
|
|
|
|
IRO_AddToList(fourthnode, &list1);
|
|
|
|
IRO_Paste(list1.head, list1.tail, PredInt);
|
|
|
|
}
|
|
|
|
|
|
|
|
IRO_InitList(&list2);
|
|
|
|
fifthnode = IRO_NewLinear(IROLinearOp2Arg);
|
|
|
|
fifthnode->index = ++IRO_NumLinear;
|
|
|
|
fifthnode->rtype = type;
|
|
|
|
if (induction->nd->type == IROLinearOp2Arg) {
|
|
|
|
if (induction->nd->nodetype == EASS && IS_LINEAR_DIADIC(induction->nd->u.diadic.right, EADD))
|
|
|
|
fifthnode->nodetype = EADDASS;
|
|
|
|
else if (induction->nd->nodetype == EASS && IS_LINEAR_DIADIC(induction->nd->u.diadic.right, ESUB))
|
|
|
|
fifthnode->nodetype = ESUBASS;
|
|
|
|
else
|
|
|
|
fifthnode->nodetype = induction->nd->nodetype;
|
|
|
|
} else {
|
|
|
|
if (induction->nd->nodetype == EPREINC || induction->nd->nodetype == EPOSTINC)
|
|
|
|
fifthnode->nodetype = EADDASS;
|
|
|
|
else
|
|
|
|
fifthnode->nodetype = ESUBASS;
|
|
|
|
}
|
|
|
|
|
|
|
|
fifthnode->u.diadic.left = IRO_TempReference(tempObj, &list2);
|
|
|
|
fifthnode->u.diadic.left->flags |= IROLF_Ind | IROLF_Used | IROLF_Assigned;
|
|
|
|
fifthnode->u.diadic.left->u.monadic->flags |= IROLF_Ind | IROLF_Used | IROLF_Assigned;
|
|
|
|
if (!unk) {
|
|
|
|
if (!flag23) {
|
|
|
|
if (induction->addConst == 1 || IS_LINEAR_DIADIC_2(expr->linear, EDIV, ESHR)) {
|
|
|
|
fifthnode->u.diadic.right = IRO_DuplicateExpr(nd2, &list2);
|
|
|
|
} else {
|
|
|
|
fifthnode->u.diadic.right = IRO_NewLinear(IROLinearOperand);
|
|
|
|
fifthnode->u.diadic.right->index = ++IRO_NumLinear;
|
|
|
|
enode = IRO_NewENode(EINTCONST);
|
|
|
|
enode->rtype = nd2->rtype;
|
|
|
|
fifthnode->u.diadic.right->rtype = nd2->rtype;
|
|
|
|
CInt64_SetLong(&enode->data.intval, induction->addConst * CInt64_GetULong(&nd2->u.node->data.intval));
|
|
|
|
fifthnode->u.diadic.right->u.node = enode;
|
|
|
|
IRO_AddToList(fifthnode->u.diadic.right, &list2);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
fifthnode->u.diadic.right = IRO_TempReference(tempObj2, &list2);
|
|
|
|
fifthnode->u.diadic.right->flags |= IROLF_Used;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fifthnode->index = ++IRO_NumLinear;
|
|
|
|
IRO_AddToList(fifthnode, &list2);
|
|
|
|
IRO_Paste(list2.head, list2.tail, IRO_FindStart(induction->nd));
|
|
|
|
IRO_WalkTree(expr->linear, IRO_RemoveExpr_Action);
|
|
|
|
expr->x8 = tempObj;
|
|
|
|
expr->next = RisList;
|
|
|
|
RisList = expr;
|
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static IRONode *CreatePreHeader(IRONode *fnode1, IRONode *fnode2) {
|
|
|
|
IROLinear *labelnode;
|
|
|
|
IRONode *newfnode;
|
|
|
|
IRONode *iter;
|
|
|
|
CLabel *oldlabel;
|
|
|
|
CLabel *newlabel;
|
|
|
|
SwitchInfo *swinfo;
|
|
|
|
SwitchCase *swcase;
|
|
|
|
|
|
|
|
newfnode = oalloc(sizeof(IRONode));
|
|
|
|
memset(newfnode, 0, sizeof(IRONode));
|
|
|
|
newfnode->index = IRO_NumNodes;
|
|
|
|
IRO_NumNodes++;
|
|
|
|
|
|
|
|
labelnode = IRO_NewLinear(IROLinearLabel);
|
|
|
|
labelnode->index = IRO_NumLinear++;
|
|
|
|
labelnode->next = NULL;
|
|
|
|
labelnode->u.label.label = IRO_NewLabel();
|
|
|
|
labelnode->flags |= IROLF_1;
|
|
|
|
labelnode->u.label.label->stmt = (Statement *) newfnode;
|
|
|
|
newfnode->first = labelnode;
|
|
|
|
newfnode->last = labelnode;
|
|
|
|
|
|
|
|
if (fnode2) {
|
|
|
|
fnode2->last->next = labelnode;
|
|
|
|
labelnode->next = IRO_NewLinear(IROLinearNop);
|
|
|
|
labelnode->next->next = fnode1->first;
|
|
|
|
fnode2->nextnode = newfnode;
|
|
|
|
newfnode->nextnode = fnode1;
|
|
|
|
} else {
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_ASSERT(1254, fnode1->first->type == IROLinearLabel);
|
2022-12-14 00:16:59 +00:00
|
|
|
labelnode->next = IRO_NewLinear(IROLinearGoto);
|
|
|
|
labelnode->next->u.label.label = fnode1->first->u.label.label;
|
|
|
|
IRO_LastNode->last->next = labelnode;
|
|
|
|
IRO_LastNode->nextnode = newfnode;
|
|
|
|
IRO_LastNode = newfnode;
|
|
|
|
IRO_LastLinear = labelnode->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
newfnode->last = labelnode->next;
|
|
|
|
|
|
|
|
IRO_NodeTable = oalloc(sizeof(IRONode *) * IRO_NumNodes);
|
|
|
|
memset(IRO_NodeTable, 0, sizeof(IRONode *) * IRO_NumNodes);
|
|
|
|
for (iter = IRO_FirstNode; iter; iter = iter->nextnode)
|
|
|
|
IRO_NodeTable[iter->index] = iter;
|
|
|
|
|
|
|
|
if (fnode1->first->type == IROLinearLabel) {
|
|
|
|
oldlabel = fnode1->first->u.label.label;
|
|
|
|
newlabel = newfnode->first->u.label.label;
|
|
|
|
for (iter = IRO_FirstNode; iter; iter = iter->nextnode) {
|
|
|
|
if (!Bv_IsBitSet(iter->index, InLoop) && iter != newfnode) {
|
|
|
|
switch (iter->last->type) {
|
|
|
|
case IROLinearGoto:
|
|
|
|
if (iter->last->u.label.label == oldlabel)
|
|
|
|
iter->last->u.label.label = newlabel;
|
|
|
|
break;
|
|
|
|
case IROLinearIf:
|
|
|
|
case IROLinearIfNot:
|
|
|
|
if (iter->last->u.label.label == oldlabel)
|
|
|
|
iter->last->u.label.label = newlabel;
|
|
|
|
break;
|
|
|
|
case IROLinearSwitch:
|
|
|
|
swinfo = iter->last->u.swtch.info;
|
|
|
|
for (swcase = swinfo->cases; swcase; swcase = swcase->next) {
|
|
|
|
if (swcase->label == oldlabel)
|
|
|
|
swcase->label = newlabel;
|
|
|
|
}
|
|
|
|
if (swinfo->defaultlabel == oldlabel)
|
|
|
|
swinfo->defaultlabel = newlabel;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
IRO_ComputeSuccPred();
|
|
|
|
IRO_ComputeDom();
|
|
|
|
return newfnode;
|
|
|
|
}
|
|
|
|
|
|
|
|
static IRONode *CreateNewLoopExitSuccessor(IRONode *fnode1) {
|
|
|
|
IROLinear *labelnode;
|
|
|
|
IRONode *fnode2;
|
|
|
|
IRONode *newfnode;
|
|
|
|
Boolean flag;
|
|
|
|
IRONode *iter;
|
|
|
|
CLabel *oldlabel;
|
|
|
|
CLabel *newlabel;
|
|
|
|
SwitchInfo *swinfo;
|
|
|
|
SwitchCase *swcase;
|
|
|
|
UInt16 i;
|
|
|
|
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_ASSERT(1355, fnode1 != NULL && LoopExitNumber == 1);
|
2022-12-14 00:16:59 +00:00
|
|
|
|
|
|
|
fnode2 = NULL;
|
|
|
|
flag = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < fnode1->numpred; i++) {
|
|
|
|
iter = IRO_NodeTable[fnode1->pred[i]];
|
|
|
|
if (Bv_IsBitSet(iter->index, InLoop_Exits)) {
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_ASSERT(1366, fnode2 == NULL);
|
2022-12-14 00:16:59 +00:00
|
|
|
fnode2 = iter;
|
|
|
|
if (!flag) {
|
|
|
|
if (
|
|
|
|
!iter->last ||
|
|
|
|
!fnode1->first ||
|
|
|
|
fnode1->first->type != IROLinearLabel ||
|
|
|
|
(
|
|
|
|
(iter->last->type == IROLinearIf || iter->last->type == IROLinearIfNot) &&
|
|
|
|
iter->last->u.label.label != fnode1->first->u.label.label
|
|
|
|
))
|
|
|
|
flag = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_ASSERT(1382, fnode2 != NULL);
|
2022-12-14 00:16:59 +00:00
|
|
|
|
|
|
|
newfnode = oalloc(sizeof(IRONode));
|
|
|
|
memset(newfnode, 0, sizeof(IRONode));
|
|
|
|
newfnode->index = IRO_NumNodes;
|
|
|
|
IRO_NumNodes++;
|
|
|
|
|
|
|
|
labelnode = IRO_NewLinear(IROLinearLabel);
|
|
|
|
labelnode->index = IRO_NumLinear++;
|
|
|
|
labelnode->next = NULL;
|
|
|
|
labelnode->u.label.label = IRO_NewLabel();
|
|
|
|
labelnode->flags |= IROLF_1;
|
|
|
|
labelnode->u.label.label->stmt = (Statement *) newfnode;
|
|
|
|
newfnode->first = labelnode;
|
|
|
|
newfnode->last = labelnode;
|
|
|
|
|
|
|
|
if (flag) {
|
|
|
|
fnode2->last->next = labelnode;
|
|
|
|
labelnode->next = IRO_NewLinear(IROLinearNop);
|
|
|
|
labelnode->next->next = fnode1->first;
|
|
|
|
fnode2->nextnode = newfnode;
|
|
|
|
newfnode->nextnode = fnode1;
|
|
|
|
} else {
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_ASSERT(1422, fnode1->first->type == IROLinearLabel);
|
2022-12-14 00:16:59 +00:00
|
|
|
labelnode->next = IRO_NewLinear(IROLinearGoto);
|
|
|
|
labelnode->next->u.label.label = fnode1->first->u.label.label;
|
|
|
|
IRO_LastNode->last->next = labelnode;
|
|
|
|
IRO_LastNode->nextnode = newfnode;
|
|
|
|
IRO_LastNode = newfnode;
|
|
|
|
IRO_LastLinear = labelnode->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
newfnode->last = labelnode->next;
|
|
|
|
|
|
|
|
IRO_NodeTable = oalloc(sizeof(IRONode *) * IRO_NumNodes);
|
|
|
|
memset(IRO_NodeTable, 0, sizeof(IRONode *) * IRO_NumNodes);
|
|
|
|
for (iter = IRO_FirstNode; iter; iter = iter->nextnode)
|
|
|
|
IRO_NodeTable[iter->index] = iter;
|
|
|
|
|
|
|
|
if (fnode1->first->type == IROLinearLabel) {
|
|
|
|
oldlabel = fnode1->first->u.label.label;
|
|
|
|
newlabel = newfnode->first->u.label.label;
|
|
|
|
switch (fnode2->last->type) {
|
|
|
|
case IROLinearGoto:
|
|
|
|
if (fnode2->last->u.label.label == oldlabel)
|
|
|
|
fnode2->last->u.label.label = newlabel;
|
|
|
|
break;
|
|
|
|
case IROLinearIf:
|
|
|
|
case IROLinearIfNot:
|
|
|
|
if (fnode2->last->u.label.label == oldlabel)
|
|
|
|
fnode2->last->u.label.label = newlabel;
|
|
|
|
break;
|
|
|
|
case IROLinearSwitch:
|
|
|
|
swinfo = fnode2->last->u.swtch.info;
|
|
|
|
for (swcase = swinfo->cases; swcase; swcase = swcase->next) {
|
|
|
|
if (swcase->label == oldlabel)
|
|
|
|
swcase->label = newlabel;
|
|
|
|
}
|
|
|
|
if (swinfo->defaultlabel == oldlabel)
|
|
|
|
swinfo->defaultlabel = newlabel;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
IRO_ComputeSuccPred();
|
|
|
|
IRO_ComputeDom();
|
|
|
|
return newfnode;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AddPreds(IRONode *fnode) {
|
|
|
|
IRONode *pred;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < fnode->numpred; i++) {
|
|
|
|
pred = IRO_NodeTable[fnode->pred[i]];
|
|
|
|
if (!Bv_IsBitSet(pred->index, InLoop)) {
|
|
|
|
Bv_SetBit(pred->index, InLoop);
|
|
|
|
AddPreds(pred);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void RemoveNoopsFromExprList(void) {
|
|
|
|
IROExpr *expr;
|
|
|
|
IROExpr *prev;
|
|
|
|
|
|
|
|
expr = IRO_FirstExpr;
|
|
|
|
prev = NULL;
|
|
|
|
while (expr) {
|
|
|
|
if (expr->linear->type == IROLinearNop) {
|
|
|
|
if (prev)
|
|
|
|
prev->next = expr->next;
|
|
|
|
else
|
|
|
|
IRO_FirstExpr = expr->next;
|
|
|
|
expr = expr->next;
|
|
|
|
} else {
|
|
|
|
prev = expr;
|
|
|
|
expr = expr->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void IncLoopDepth(void) {
|
|
|
|
IRONode *fnode;
|
|
|
|
|
|
|
|
for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
|
|
|
|
if (Bv_IsBitSet(fnode->index, InLoop))
|
|
|
|
fnode->loopdepth++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void IRO_SetLoopDepth(void) {
|
|
|
|
IRONode *fnode;
|
|
|
|
IRONode *pred;
|
|
|
|
UInt16 i;
|
|
|
|
UInt16 flag;
|
|
|
|
|
|
|
|
for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode)
|
|
|
|
fnode->loopdepth = 0;
|
|
|
|
|
|
|
|
for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
|
|
|
|
flag = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < fnode->numpred; i++) {
|
|
|
|
pred = IRO_NodeTable[fnode->pred[i]];
|
|
|
|
if (Bv_IsBitSet(fnode->index, pred->dom)) {
|
|
|
|
if (!flag) {
|
|
|
|
Bv_AllocVector(&InLoop, IRO_NumNodes + 1);
|
|
|
|
Bv_Clear(InLoop);
|
|
|
|
Bv_SetBit(fnode->index, InLoop);
|
|
|
|
}
|
|
|
|
flag = 1;
|
|
|
|
Bv_SetBit(pred->index, InLoop);
|
|
|
|
if (pred != fnode)
|
|
|
|
AddPreds(pred);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flag)
|
|
|
|
IncLoopDepth();
|
|
|
|
}
|
|
|
|
|
|
|
|
IRO_CheckForUserBreak();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void InsertBranchAroundLoopPreheaders(void) {
|
|
|
|
IRONode *fnode;
|
|
|
|
CLabel *label;
|
|
|
|
IRONode *iter;
|
|
|
|
IROLinear *endnode;
|
|
|
|
IROLinear *labelnode;
|
|
|
|
|
|
|
|
if (IRO_EndNode && IRO_EndNode->last && IRO_EndNode->last->type == IROLinearEnd) {
|
|
|
|
label = IRO_NewLabel();
|
|
|
|
fnode = IRO_NewFlowGraphNode();
|
|
|
|
IRO_LastNode->nextnode = fnode;
|
|
|
|
label->stmt = (Statement *) fnode;
|
|
|
|
|
|
|
|
IRO_NodeTable = oalloc(sizeof(IRONode *) * IRO_NumNodes);
|
|
|
|
memset(IRO_NodeTable, 0, sizeof(IRONode *) * IRO_NumNodes);
|
|
|
|
for (iter = IRO_FirstNode; iter; iter = iter->nextnode)
|
|
|
|
IRO_NodeTable[iter->index] = iter;
|
|
|
|
|
|
|
|
labelnode = IRO_NewLinear(IROLinearLabel);
|
|
|
|
labelnode->index = ++IRO_NumLinear;
|
|
|
|
labelnode->u.label.label = label;
|
|
|
|
labelnode->flags |= IROLF_1;
|
|
|
|
fnode->first = labelnode;
|
|
|
|
IRO_LastLinear->next = labelnode;
|
|
|
|
|
|
|
|
endnode = IRO_NewLinear(IROLinearEnd);
|
|
|
|
memcpy(endnode, IRO_EndNode->last, sizeof(IROLinear));
|
|
|
|
endnode->index = ++IRO_NumLinear;
|
|
|
|
endnode->next = NULL;
|
|
|
|
fnode->last = endnode;
|
|
|
|
labelnode->next = endnode;
|
|
|
|
IRO_LastLinear = endnode;
|
|
|
|
|
|
|
|
IRO_EndNode->last->type = IROLinearGoto;
|
|
|
|
IRO_EndNode->last->u.label.label = label;
|
|
|
|
IRO_LastNode = fnode;
|
|
|
|
IRO_EndNode = fnode;
|
|
|
|
|
|
|
|
IRO_ComputeSuccPred();
|
|
|
|
IRO_ComputeDom();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void IRO_FindLoops(void) {
|
|
|
|
IRONode *fnode;
|
|
|
|
IRONode *pred;
|
|
|
|
UInt16 i;
|
|
|
|
UInt16 flag;
|
|
|
|
|
|
|
|
for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
|
|
|
|
flag = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < fnode->numpred; i++) {
|
|
|
|
pred = IRO_NodeTable[fnode->pred[i]];
|
|
|
|
if (Bv_IsBitSet(fnode->index, pred->dom)) {
|
|
|
|
if (!flag) {
|
|
|
|
Bv_AllocVector(&InLoop, IRO_NumNodes + 1);
|
|
|
|
Bv_Clear(InLoop);
|
|
|
|
Bv_SetBit(fnode->index, InLoop);
|
|
|
|
}
|
|
|
|
flag = 1;
|
|
|
|
Bv_SetBit(pred->index, InLoop);
|
|
|
|
if (pred != fnode)
|
|
|
|
AddPreds(pred);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flag) {
|
|
|
|
IncLoopDepth();
|
|
|
|
IRO_Dump("IRO_FindLoops:Found loop with header %d\n", fnode->index);
|
|
|
|
IRO_DumpBits("Loop includes: ", InLoop);
|
|
|
|
MyHandleLoop_Motion(fnode);
|
|
|
|
IRO_UpdateFlagsOnInts();
|
|
|
|
MyHandleLoop_Vector(fnode);
|
|
|
|
RemoveNoopsFromExprList();
|
|
|
|
IRO_UpdateFlagsOnInts();
|
|
|
|
IRO_UpdateVars();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!IRO_FunctionHasReturn && IRO_EndNode != IRO_LastNode)
|
|
|
|
InsertBranchAroundLoopPreheaders();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void CheckSubableSub(IROLinear *linear, Boolean isFirst) {
|
|
|
|
if (isFirst && IRO_IsSubableExpression(linear)) {
|
|
|
|
IRO_Dump("Subable Expression is %d\n", linear->index);
|
|
|
|
NoSubableSubs = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int NoSubableSubExprs(IROLinear *nd) {
|
|
|
|
NoSubableSubs = 1;
|
|
|
|
IRO_WalkTree(nd, CheckSubableSub);
|
|
|
|
return NoSubableSubs;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ComputeLoopKills(void) {
|
|
|
|
IRONode *fnode;
|
|
|
|
IROLinear *nd;
|
|
|
|
|
|
|
|
Bv_AllocVector(&AllKills, IRO_NumVars + 1);
|
|
|
|
Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1);
|
|
|
|
|
|
|
|
for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
|
|
|
|
if (Bv_IsBitSet(fnode->index, InLoop) && (nd = fnode->first)) {
|
|
|
|
Bv_AllocVector(&fnode->x16, IRO_NumVars + 1);
|
|
|
|
Bv_AllocVector(&fnode->x1E, IRO_NumVars + 1);
|
|
|
|
while (1) {
|
|
|
|
Bv_Clear(IRO_VarKills);
|
|
|
|
IRO_GetKills(nd);
|
|
|
|
Bv_Or(IRO_VarKills, AllKills);
|
|
|
|
if (nd == fnode->last)
|
|
|
|
break;
|
|
|
|
nd = nd->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ComputeLoopInvariance(void) {
|
|
|
|
IRONode *fnode;
|
|
|
|
IROLinear *nd;
|
|
|
|
|
|
|
|
IRO_Depends = IRO_VarKills;
|
|
|
|
|
|
|
|
for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
|
|
|
|
if (Bv_IsBitSet(fnode->index, InLoop) && (nd = fnode->first)) {
|
|
|
|
nd->flags &= ~IROLF_LoopInvariant;
|
|
|
|
while (1) {
|
|
|
|
if ((nd->flags & IROLF_Reffed) && nd->type != IROLinearNop) {
|
|
|
|
IRO_FindDepends_NoAlloc(nd);
|
|
|
|
if (!IRO_IsVolatile && !Bv_BitsInCommon(IRO_Depends, AllKills))
|
|
|
|
nd->flags |= IROLF_LoopInvariant;
|
|
|
|
|
|
|
|
if (IRO_CouldError)
|
|
|
|
nd->flags |= IROLF_CouldError;
|
|
|
|
else
|
|
|
|
nd->flags &= ~IROLF_CouldError;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nd == fnode->last)
|
|
|
|
break;
|
|
|
|
nd = nd->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ComputeLoopInduction(void) {
|
|
|
|
IRONode *fnode;
|
|
|
|
IROLinear *nd;
|
|
|
|
Boolean flag;
|
|
|
|
Object *obj;
|
|
|
|
Object *obj2;
|
|
|
|
Object *obj3;
|
|
|
|
VarRecord *var;
|
|
|
|
IROLinear *tmpnd;
|
|
|
|
IROLoopInd *ind;
|
|
|
|
Boolean isUnsigned;
|
|
|
|
|
|
|
|
Bv_AllocVector(&AllKills, IRO_NumVars + 1);
|
|
|
|
Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1);
|
|
|
|
|
|
|
|
for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
|
|
|
|
if (Bv_IsBitSet(fnode->index, InLoop) && (nd = fnode->first)) {
|
|
|
|
while (1) {
|
|
|
|
Bv_Clear(IRO_VarKills);
|
|
|
|
IRO_GetKills(nd);
|
|
|
|
Bv_Or(IRO_VarKills, AllKills);
|
|
|
|
flag = 0;
|
|
|
|
if (
|
|
|
|
(
|
|
|
|
nd->type == IROLinearOp2Arg &&
|
|
|
|
nd->rtype->size <= 4 &&
|
|
|
|
(nd->nodetype == EADDASS || nd->nodetype == ESUBASS) &&
|
|
|
|
(obj = IRO_IsVariable(nd->u.diadic.left)) &&
|
|
|
|
obj->type->size == nd->rtype->size &&
|
|
|
|
IS_TYPE_INT(obj->type) &&
|
|
|
|
(
|
|
|
|
(IRO_IsIntConstant(nd->u.diadic.right) && CInt64_GetULong(&nd->u.diadic.right->u.node->data.intval))
|
|
|
|
||
|
|
|
|
(nd->u.diadic.right->flags & IROLF_LoopInvariant)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
||
|
|
|
|
(
|
|
|
|
nd->type == IROLinearOp1Arg &&
|
|
|
|
nd->rtype->size <= 4 &&
|
|
|
|
(nd->nodetype == EPOSTINC || nd->nodetype == EPOSTDEC || nd->nodetype == EPREINC || nd->nodetype == EPREDEC) &&
|
|
|
|
(obj = IRO_IsVariable(nd->u.monadic)) &&
|
|
|
|
obj->type->size == nd->rtype->size &&
|
|
|
|
IS_TYPE_INT(obj->type)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
{
|
|
|
|
flag = 1;
|
|
|
|
}
|
|
|
|
else if (
|
|
|
|
nd->type == IROLinearOp2Arg &&
|
|
|
|
nd->rtype->size <= 4 &&
|
|
|
|
nd->nodetype == EASS &&
|
|
|
|
(obj = IRO_IsVariable(nd->u.diadic.left)) &&
|
|
|
|
obj->type->size == nd->rtype->size &&
|
|
|
|
IS_TYPE_INT(obj->type) &&
|
|
|
|
nd->u.diadic.right->type == IROLinearOp2Arg &&
|
|
|
|
(nd->u.diadic.right->nodetype == EADD || nd->u.diadic.right->nodetype == ESUB)
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if (nd->u.diadic.right->nodetype == EADD) {
|
|
|
|
obj2 = IRO_IsVariable(nd->u.diadic.right->u.diadic.left);
|
|
|
|
obj3 = IRO_IsVariable(nd->u.diadic.right->u.diadic.right);
|
|
|
|
if (obj2 == obj && obj3 != obj && (nd->u.diadic.right->u.diadic.right->flags & IROLF_LoopInvariant))
|
|
|
|
flag = 1;
|
|
|
|
|
|
|
|
if (obj3 == obj && obj2 != obj && (nd->u.diadic.right->u.diadic.left->flags & IROLF_LoopInvariant)) {
|
|
|
|
flag = 1;
|
|
|
|
tmpnd = nd->u.diadic.right->u.diadic.left;
|
|
|
|
nd->u.diadic.right->u.diadic.left = nd->u.diadic.right->u.diadic.right;
|
|
|
|
nd->u.diadic.right->u.diadic.right = tmpnd;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
obj2 = IRO_IsVariable(nd->u.diadic.right->u.diadic.left);
|
|
|
|
obj3 = IRO_IsVariable(nd->u.diadic.right->u.diadic.right);
|
|
|
|
if (obj2 == obj && obj3 != obj && (nd->u.diadic.right->u.diadic.right->flags & IROLF_LoopInvariant))
|
|
|
|
flag = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flag) {
|
|
|
|
if ((var = IRO_FindAssigned(nd))) {
|
|
|
|
if (var->xA == 2)
|
|
|
|
var->xA = 0;
|
|
|
|
else if (var->xA == 1)
|
|
|
|
var->xA = 2;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (var = IRO_FirstVar; var; var = var->next) {
|
|
|
|
if (Bv_IsBitSet(var->index, IRO_VarKills))
|
|
|
|
var->xA = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nd == fnode->last)
|
|
|
|
break;
|
|
|
|
nd = nd->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
IRO_DumpBits("Killed in loop: ", AllKills);
|
|
|
|
|
|
|
|
for (fnode = IRO_FirstNode, FirstInd = NULL; fnode; fnode = fnode->nextnode) {
|
|
|
|
if (Bv_IsBitSet(fnode->index, InLoop) && (nd = fnode->first)) {
|
|
|
|
while (1) {
|
|
|
|
if (
|
|
|
|
(
|
|
|
|
nd->type == IROLinearOp2Arg &&
|
|
|
|
(nd->nodetype == EADDASS || nd->nodetype == ESUBASS || nd->nodetype == EASS)
|
|
|
|
)
|
|
|
|
||
|
|
|
|
(
|
|
|
|
nd->type == IROLinearOp1Arg &&
|
|
|
|
(nd->nodetype == EPOSTINC || nd->nodetype == EPOSTDEC || nd->nodetype == EPREINC || nd->nodetype == EPREDEC)
|
|
|
|
)
|
|
|
|
) {
|
|
|
|
if ((var = IRO_FindAssigned(nd)) && var->xA == 2 && var->object->type->size <= 4) {
|
|
|
|
ind = oalloc(sizeof(IROLoopInd));
|
|
|
|
ind->fnode = fnode;
|
|
|
|
ind->var = var;
|
|
|
|
ind->nd = nd;
|
|
|
|
ind->next = FirstInd;
|
|
|
|
ind->addNode = NULL;
|
|
|
|
ind->addConst = 0;
|
|
|
|
ind->flags = 0;
|
|
|
|
|
|
|
|
if (nd->type == IROLinearOp2Arg) {
|
|
|
|
isUnsigned = IRO_IsUnsignedType(nd->rtype);
|
|
|
|
if (IRO_IsIntConstant(nd->u.diadic.right)) {
|
|
|
|
CInt64 val = nd->u.diadic.right->u.node->data.intval;
|
|
|
|
if (IS_LINEAR_DIADIC(nd, EADDASS) && CInt64_Less(val, cint64_zero)) {
|
|
|
|
nd->nodetype = ESUBASS;
|
|
|
|
nd->u.diadic.right->u.node->data.intval = CInt64_Neg(val);
|
|
|
|
}
|
|
|
|
if (isUnsigned) {
|
|
|
|
CInt64_ConvertUInt32(&nd->u.diadic.right->u.node->data.intval);
|
|
|
|
ind->addConst = CInt64_GetULong(&nd->u.diadic.right->u.node->data.intval);
|
|
|
|
} else {
|
|
|
|
CInt64_ConvertInt32(&nd->u.diadic.right->u.node->data.intval);
|
|
|
|
ind->addConst = CInt64_GetULong(&nd->u.diadic.right->u.node->data.intval);
|
|
|
|
}
|
|
|
|
ind->addNode = NULL;
|
|
|
|
} else if (nd->nodetype == EADDASS || nd->nodetype == ESUBASS) {
|
|
|
|
ind->addNode = nd->u.diadic.right;
|
|
|
|
} else if (nd->nodetype == EASS) {
|
|
|
|
ind->addNode = nd->u.diadic.right->u.diadic.right;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (IS_TYPE_POINTER_ONLY(nd->rtype))
|
|
|
|
ind->addConst = TPTR_TARGET(nd->rtype)->size;
|
|
|
|
else
|
|
|
|
ind->addConst = 1;
|
|
|
|
ind->addNode = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
FirstInd = ind;
|
|
|
|
|
|
|
|
if (IS_LINEAR_DIADIC_2(nd, EADDASS, ESUBASS)) {
|
|
|
|
if (nd->u.diadic.right->flags & IROLF_LoopInvariant)
|
|
|
|
IRO_Dump("Found induction variable the new way: %s\n", var->object->name->name);
|
|
|
|
else
|
|
|
|
IRO_Dump("Found induction variable the old way: %s\n", var->object->name->name);
|
|
|
|
} else if (nd->type == IROLinearOp2Arg && (nd->u.diadic.right->nodetype == EADD || nd->u.diadic.right->nodetype == ESUB)) {
|
|
|
|
IRO_Dump("Found induction variable the new way: %s\n", var->object->name->name);
|
|
|
|
} else {
|
|
|
|
IRO_Dump("Found induction variable the old way: %s\n", var->object->name->name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nd == fnode->last)
|
|
|
|
break;
|
|
|
|
nd = nd->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void IRO_ActUnmarkLoopInvariance(IROLinear *linear, Boolean isFirst) {
|
|
|
|
if (isFirst)
|
|
|
|
linear->flags &= ~IROLF_LoopInvariant;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void UnmarkSubexpressionsOfInvariantExpressions(void) {
|
|
|
|
IROExpr *expr;
|
|
|
|
|
|
|
|
for (expr = IRO_FirstExpr; expr; expr = expr->next) {
|
|
|
|
if (
|
|
|
|
Bv_IsBitSet(expr->node->index, InLoop) &&
|
|
|
|
!expr->notSubable &&
|
|
|
|
(!expr->couldError || expr->node->mustreach) &&
|
|
|
|
(expr->linear->flags & IROLF_LoopInvariant)
|
|
|
|
) {
|
|
|
|
IRO_WalkTree(expr->linear, IRO_ActUnmarkLoopInvariance);
|
|
|
|
expr->linear->flags |= IROLF_LoopInvariant;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void MyHandleLoop_Vector(IRONode *fnode) {
|
|
|
|
IRONode *pred;
|
|
|
|
UInt16 i;
|
|
|
|
IROExpr *expr;
|
|
|
|
IROExpr *removedExprs;
|
|
|
|
IROExpr *exprnext;
|
|
|
|
IROLoopInd *induction;
|
|
|
|
IROExpr *exprinner;
|
|
|
|
Boolean flag24;
|
|
|
|
IRONode *v2;
|
|
|
|
IRONode *node22;
|
|
|
|
int flag21;
|
|
|
|
IRONode *iter;
|
|
|
|
IROExpr *searchris;
|
|
|
|
IROLinear *reduceNd1;
|
|
|
|
VarRecord *var;
|
|
|
|
IROLinear *reduceNd2;
|
|
|
|
|
|
|
|
IRO_FirstExpr = NULL;
|
|
|
|
LoopNode = fnode;
|
|
|
|
FindMustReach();
|
|
|
|
|
|
|
|
for (var = IRO_FirstVar; var; var = var->next)
|
|
|
|
var->xA = 1;
|
|
|
|
|
|
|
|
ComputeLoopKills();
|
|
|
|
ComputeLoopInvariance();
|
|
|
|
ComputeLoopInduction();
|
|
|
|
LoopNode = fnode;
|
|
|
|
ConditionalHeaderAtBottom = 0;
|
|
|
|
|
|
|
|
v2 = NULL;
|
|
|
|
flag21 = 0;
|
|
|
|
node22 = NULL;
|
|
|
|
for (i = 0; i < LoopNode->numpred; i++) {
|
|
|
|
pred = IRO_NodeTable[LoopNode->pred[i]];
|
|
|
|
if (!Bv_IsBitSet(pred->index, InLoop)) {
|
|
|
|
if (flag21)
|
|
|
|
node22 = NULL;
|
|
|
|
else
|
|
|
|
node22 = pred;
|
|
|
|
flag21 = 1;
|
|
|
|
if (pred->nextnode == fnode) {
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_ASSERT(2880, v2 == NULL || pred == v2);
|
2022-12-14 00:16:59 +00:00
|
|
|
v2 = pred;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!flag21) {
|
|
|
|
IRO_Dump("No predecessor outside the loop\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!node22 || node22->last->type != IROLinearGoto)
|
|
|
|
node22 = CreatePreHeader(fnode, v2);
|
|
|
|
PredInt = node22->last;
|
|
|
|
|
|
|
|
if (PredInt->type == IROLinearGoto && PredInt->u.label.label != LoopNode->first->u.label.label) {
|
|
|
|
if (!KnownBounds || !Times) {
|
|
|
|
for (iter = IRO_FirstNode; iter; iter = iter->nextnode)
|
|
|
|
iter->mustreach = 0;
|
|
|
|
} else {
|
|
|
|
PredInt->u.label.label = LoopNode->first->u.label.label;
|
|
|
|
IRO_ComputeSuccPred();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (copts.opt_loop_invariants || copts.opt_strength_reduction) {
|
|
|
|
MoveInvarianceInAddressExpr();
|
|
|
|
IRO_DumpAfterPhase("MoveInvarianceInAddressExpr", 0);
|
|
|
|
IRO_FindExpressions(InLoop, 1);
|
|
|
|
IRO_DumpExprs();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (copts.opt_loop_invariants)
|
|
|
|
UnmarkSubexpressionsOfInvariantExpressions();
|
|
|
|
|
|
|
|
if (!copts.optimize_for_size && copts.opt_strength_reduction) {
|
|
|
|
for (expr = IRO_FirstExpr; expr; expr = expr->next) {
|
|
|
|
if (
|
|
|
|
!(expr->x0 & 4) &&
|
|
|
|
Bv_IsBitSet(expr->node->index, InLoop) &&
|
|
|
|
!expr->notSubable &&
|
|
|
|
(!expr->couldError || expr->node->mustreach) &&
|
|
|
|
Reducable(expr->linear, &reduceNd1, &reduceNd2, &var)
|
|
|
|
) {
|
|
|
|
IRO_WalkTree(expr->linear, IRO_ActUnmarkRISCandidate);
|
|
|
|
expr->linear->flags |= IROLF_Ris;
|
|
|
|
expr->x1A = reduceNd1;
|
|
|
|
expr->x1E = var;
|
|
|
|
expr->x22 = reduceNd2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!copts.optimize_for_size && copts.opt_strength_reduction) {
|
|
|
|
RisList = NULL;
|
|
|
|
for (expr = IRO_FirstExpr; expr; expr = exprnext) {
|
|
|
|
exprnext = expr->next;
|
|
|
|
if (!(expr->x0 & 4) && (expr->linear->flags & IROLF_Ris)) {
|
|
|
|
reduceNd1 = expr->x1A;
|
|
|
|
var = expr->x1E;
|
|
|
|
reduceNd2 = expr->x22;
|
|
|
|
|
|
|
|
induction = FirstInd;
|
|
|
|
while (induction && induction->var != var)
|
|
|
|
induction = induction->next;
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_ASSERT(3529, induction != NULL);
|
2022-12-14 00:16:59 +00:00
|
|
|
|
|
|
|
IRO_FindDepends(reduceNd1);
|
|
|
|
if (!Bv_BitsInCommon(IRO_Depends, AllKills)) {
|
|
|
|
IRO_Dump("Found reduction in strength: %d\n", expr->linear->index);
|
|
|
|
if (IS_LINEAR_DIADIC(expr->linear, ESHL)) {
|
|
|
|
expr->linear->nodetype = EMUL;
|
|
|
|
CInt64_SetULong(&reduceNd1->u.node->data.intval, 1 << CInt64_GetULong(&reduceNd1->u.node->data.intval));
|
|
|
|
reduceNd1->u.node->rtype = expr->linear->rtype;
|
|
|
|
}
|
|
|
|
|
|
|
|
searchris = RisList;
|
|
|
|
while (1) {
|
|
|
|
if (!searchris)
|
|
|
|
break;
|
|
|
|
if (IRO_ExprsSame(expr->linear, searchris->linear))
|
|
|
|
break;
|
|
|
|
searchris = searchris->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (searchris) {
|
|
|
|
IRO_Dump("Using existing RIS: %d\n", searchris->linear->index);
|
|
|
|
IRO_WalkTree(expr->linear, IRO_RemoveExpr_Action);
|
|
|
|
} else {
|
|
|
|
searchris = CreateRIS(expr, reduceNd2, reduceNd1, induction, 0);
|
|
|
|
}
|
|
|
|
IRO_ReplaceReference(expr->linear, searchris->x8, expr->linear);
|
|
|
|
IRO_ClipExpr(expr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RisList = NULL;
|
|
|
|
|
|
|
|
expr = IRO_FirstExpr;
|
|
|
|
removedExprs = NULL;
|
|
|
|
if (copts.opt_loop_invariants) {
|
|
|
|
while (expr) {
|
|
|
|
exprnext = expr->next;
|
|
|
|
flag24 = 0;
|
|
|
|
|
|
|
|
if (
|
|
|
|
Bv_IsBitSet(expr->node->index, InLoop) &&
|
|
|
|
!expr->notSubable &&
|
|
|
|
(!expr->couldError || expr->node->mustreach) &&
|
|
|
|
(expr->linear->flags & IROLF_LoopInvariant) &&
|
|
|
|
!(expr->x0 & 4)
|
|
|
|
) {
|
|
|
|
IRO_Dump("Found loop invariant: %d\n", expr->linear->index);
|
|
|
|
|
|
|
|
for (exprinner = removedExprs; exprinner; exprinner = exprinner->next) {
|
|
|
|
if (IRO_ExprsSame(exprinner->linear, expr->linear)) {
|
|
|
|
IRO_ReplaceReference(expr->linear, exprinner->x8, expr->linear);
|
|
|
|
IRO_NopOut(expr->linear);
|
|
|
|
IRO_Dump("Using already removed expr: %d\n", exprinner->linear->index);
|
|
|
|
IRO_RemoveExpr(expr);
|
|
|
|
flag24 = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!flag24 && !expr->x8) {
|
|
|
|
IRO_GetTemp(expr);
|
|
|
|
IRO_ReplaceReference(expr->linear, expr->x8, expr->linear);
|
|
|
|
IRO_MoveExpression(expr, PredInt);
|
|
|
|
IRO_AssignToTemp(expr);
|
|
|
|
IRO_RemoveExpr(expr);
|
|
|
|
expr->next = removedExprs;
|
|
|
|
removedExprs = expr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
expr = exprnext;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void MyHandleLoop_Motion(IRONode *fnode) {
|
|
|
|
IROLoopMemRef *memref;
|
|
|
|
IRONode *pred;
|
|
|
|
UInt16 i;
|
|
|
|
IRONode *v2;
|
|
|
|
IRONode *node21;
|
|
|
|
Object *tempobj;
|
|
|
|
int flag20;
|
|
|
|
IRONode *iter;
|
|
|
|
IROLinear *ass;
|
|
|
|
VarRecord *var;
|
|
|
|
Boolean checkflag;
|
|
|
|
IROLoop *loop;
|
|
|
|
IROList list;
|
|
|
|
IROElmList *refiter;
|
|
|
|
|
|
|
|
IRO_FirstExpr = NULL;
|
|
|
|
LoopNode = fnode;
|
|
|
|
FindMustReach();
|
|
|
|
|
|
|
|
for (var = IRO_FirstVar; var; var = var->next)
|
|
|
|
var->xA = 1;
|
|
|
|
|
|
|
|
ComputeLoopKills();
|
|
|
|
ComputeLoopInvariance();
|
|
|
|
ComputeLoopInduction();
|
|
|
|
LoopNode = fnode;
|
|
|
|
ConditionalHeaderAtBottom = 0;
|
|
|
|
|
|
|
|
v2 = NULL;
|
|
|
|
flag20 = 0;
|
|
|
|
node21 = NULL;
|
|
|
|
for (i = 0; i < LoopNode->numpred; i++) {
|
|
|
|
pred = IRO_NodeTable[LoopNode->pred[i]];
|
|
|
|
if (!Bv_IsBitSet(pred->index, InLoop)) {
|
|
|
|
if (flag20)
|
|
|
|
node21 = NULL;
|
|
|
|
else
|
|
|
|
node21 = pred;
|
|
|
|
flag20 = 1;
|
|
|
|
if (pred->nextnode == fnode) {
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_ASSERT(3880, v2 == NULL || pred == v2);
|
2022-12-14 00:16:59 +00:00
|
|
|
v2 = pred;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!flag20) {
|
|
|
|
IRO_Dump("No predecessor outside the loop\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!node21 || node21->last->type != IROLinearGoto)
|
|
|
|
node21 = CreatePreHeader(fnode, v2);
|
|
|
|
PredInt = node21->last;
|
|
|
|
|
|
|
|
if (PredInt->type == IROLinearGoto && PredInt->u.label.label != LoopNode->first->u.label.label) {
|
|
|
|
if (!KnownBounds || !Times) {
|
|
|
|
for (iter = IRO_FirstNode; iter; iter = iter->nextnode)
|
|
|
|
iter->mustreach = 0;
|
|
|
|
} else {
|
|
|
|
PredInt->u.label.label = LoopNode->first->u.label.label;
|
|
|
|
IRO_ComputeSuccPred();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (copts.opt_loop_invariants || copts.opt_strength_reduction) {
|
|
|
|
MoveInvarianceInAddressExpr();
|
|
|
|
IRO_DumpAfterPhase("MoveInvarianceInAddressExpr", 0);
|
|
|
|
IRO_FindExpressions(InLoop, 0);
|
|
|
|
IRO_DumpExprs();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (copts.opt_loop_invariants)
|
|
|
|
UnmarkSubexpressionsOfInvariantExpressions();
|
|
|
|
|
|
|
|
checkflag = 1;
|
|
|
|
Bv_AllocVector(&InLoop_Exits, IRO_NumNodes + 1);
|
|
|
|
Bv_AllocVector(&InLoop_Tails, IRO_NumNodes + 1);
|
|
|
|
LoopExitNumber = 0;
|
|
|
|
LoopExitSuccessor = NULL;
|
|
|
|
LoopTailNum = 0;
|
|
|
|
LoopTail = NULL;
|
|
|
|
IRO_FindLoopTailsAndExits(fnode);
|
|
|
|
FindMustReach1(fnode);
|
|
|
|
|
|
|
|
loop = NULL;
|
|
|
|
if (LoopTailNum == 1) {
|
|
|
|
if (fnode->last->type == IROLinearIf || fnode->last->type == IROLinearIfNot)
|
|
|
|
loop = ExtractLoopInfo(fnode);
|
|
|
|
else if (LoopTail->last->type == IROLinearIf || LoopTail->last->type == IROLinearIfNot)
|
|
|
|
loop = ExtractLoopInfo(LoopTail);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (loop && !(loop->flags & LP_IFEXPR_NON_CANONICAL) && LoopExitNumber == 1) {
|
|
|
|
IRO_LoopMemRefFirst = NULL;
|
|
|
|
IRO_LoopMemRefCurrent = NULL;
|
|
|
|
CheckAllLoopAddresses(IRO_FirstNode, InLoop, &checkflag);
|
|
|
|
CheckAllLoopAddresses(IRO_FirstNode, InLoop, &checkflag);
|
|
|
|
if (checkflag) {
|
|
|
|
for (memref = IRO_LoopMemRefFirst; memref; memref = memref->next) {
|
|
|
|
if (memref->flags & LoopMemRef_10)
|
|
|
|
memref->flags |= LoopMemRef_8;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (memref = IRO_LoopMemRefFirst; memref; memref = memref->next) {
|
|
|
|
IRO_Dump("Loop Motion Candidate:: Int= %d", memref->nd->index);
|
|
|
|
if (memref->flags & LoopMemRef_8)
|
|
|
|
IRO_Dump("<invalid>");
|
|
|
|
if (memref->flags & LoopMemRef_1)
|
|
|
|
IRO_Dump("<load>");
|
|
|
|
if (memref->flags & LoopMemRef_2)
|
|
|
|
IRO_Dump("<store>");
|
|
|
|
IRO_Dump("\n");
|
|
|
|
|
|
|
|
if (!(memref->flags & LoopMemRef_8)) {
|
|
|
|
tempobj = create_temp_object(memref->nd->rtype);
|
|
|
|
IRO_FindVar(tempobj, 1, 1);
|
|
|
|
if (IRO_FindVar(((IROLinear *) memref->rec->objRefs->element)->u.node->data.objref, 0, 1)) {
|
|
|
|
IRO_InitList(&list);
|
|
|
|
ass = IRO_NewLinear(IROLinearOp2Arg);
|
|
|
|
ass->index = ++IRO_NumLinear;
|
|
|
|
ass->rtype = memref->nd->rtype;
|
|
|
|
ass->nodetype = EASS;
|
|
|
|
ass->u.diadic.left = IRO_TempReference(tempobj, &list);
|
|
|
|
ass->u.diadic.left->flags |= IROLF_Ind | IROLF_Assigned;
|
|
|
|
ass->u.diadic.left->u.monadic->flags |= IROLF_Ind | IROLF_Assigned;
|
|
|
|
ass->u.diadic.right = IRO_DuplicateExpr(memref->nd, &list);
|
|
|
|
IRO_AddToList(ass, &list);
|
|
|
|
IRO_Paste(list.head, list.tail, PredInt);
|
|
|
|
} else {
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_FATAL(4123);
|
2022-12-14 00:16:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (LoopExitSuccessor->numpred != 1)
|
|
|
|
LoopExitSuccessor = CreateNewLoopExitSuccessor(LoopExitSuccessor);
|
|
|
|
|
|
|
|
IRO_InitList(&list);
|
|
|
|
ass = IRO_NewLinear(IROLinearOp2Arg);
|
|
|
|
ass->index = ++IRO_NumLinear;
|
|
|
|
ass->rtype = memref->nd->rtype;
|
|
|
|
ass->nodetype = EASS;
|
|
|
|
ass->u.diadic.left = IRO_DuplicateExpr(memref->nd, &list);
|
|
|
|
ass->u.diadic.left->flags |= IROLF_Ind | IROLF_Assigned;
|
|
|
|
ass->u.diadic.left->u.monadic->flags |= IROLF_Ind | IROLF_Assigned;
|
|
|
|
ass->u.diadic.right = IRO_TempReference(tempobj, &list);
|
|
|
|
IRO_AddToList(ass, &list);
|
|
|
|
|
|
|
|
if (LoopExitSuccessor->first->type == IROLinearLabel)
|
|
|
|
IRO_PasteAfter(list.head, list.tail, LoopExitSuccessor->first);
|
|
|
|
else
|
|
|
|
IRO_Paste(list.head, list.tail, LoopExitSuccessor->first);
|
|
|
|
|
|
|
|
for (refiter = memref->list; refiter; refiter = refiter->next) {
|
|
|
|
IRO_Dump("Loop Motion Candidate Reference at Int= %d\n", ((IROLinear *) refiter->element)->index);
|
|
|
|
IRO_InitList(&list);
|
|
|
|
IRO_TempReference(tempobj, &list);
|
|
|
|
IRO_Paste(list.head, list.tail, refiter->element);
|
|
|
|
IRO_LocateFather_Cut_And_Paste(refiter->element, list.tail);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
IRO_DumpAfterPhase("After Motion", 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Boolean CheckLoopAddress(IROLinear *nd, Boolean mustreach1) {
|
|
|
|
IROLoopMemRef *memref;
|
|
|
|
IROAddrRecord *rec;
|
|
|
|
IROAddrRecord *otherrec;
|
|
|
|
IROLinear *inner;
|
|
|
|
IROElmList *list;
|
|
|
|
Boolean flag;
|
|
|
|
|
|
|
|
inner = nd->u.monadic;
|
|
|
|
rec = IRO_InitAddrRecordPointer(inner);
|
|
|
|
if (IS_LINEAR_ENODE(inner, EOBJREF)) {
|
|
|
|
rec->numObjRefs++;
|
|
|
|
IRO_AddElmToList(inner, &rec->objRefs);
|
|
|
|
} else if (IS_LINEAR_DIADIC(inner, EADD)) {
|
|
|
|
IRO_DecomposeAddressExpression(inner, rec);
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rec->numObjRefs != 1)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
flag = (nd->flags & IROLF_CouldError) || !(nd->flags & IROLF_Reffed);
|
|
|
|
if (!IRO_LoopMemRefFirst) {
|
|
|
|
MakeLoopEntry(nd, rec, mustreach1, flag);
|
|
|
|
} else {
|
|
|
|
for (memref = IRO_LoopMemRefFirst; memref; memref = memref->next) {
|
|
|
|
otherrec = memref->rec;
|
|
|
|
if (((IROLinear *) rec->objRefs->element)->u.node->data.objref == ((IROLinear *) otherrec->objRefs->element)->u.node->data.objref) {
|
|
|
|
if (IRO_ExprsSame(inner, otherrec->linear)) {
|
|
|
|
list = oalloc(sizeof(IROElmList));
|
|
|
|
list->element = nd;
|
|
|
|
list->next = NULL;
|
|
|
|
if (!memref->list) {
|
|
|
|
memref->list = list;
|
|
|
|
} else {
|
|
|
|
list->next = memref->list;
|
|
|
|
memref->list = list;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
memref->flags |= LoopMemRef_8;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!mustreach1 && flag)
|
|
|
|
memref->flags |= LoopMemRef_8;
|
|
|
|
if (mustreach1 || flag)
|
|
|
|
memref->flags &= ~LoopMemRef_10;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!memref)
|
|
|
|
MakeLoopEntry(nd, rec, mustreach1, flag);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void CheckAllLoopAddresses(IRONode *fnode, BitVector *bv, Boolean *resultFlag) {
|
|
|
|
IROLinear *nd;
|
|
|
|
Boolean flag;
|
|
|
|
|
|
|
|
flag = *resultFlag;
|
|
|
|
while (fnode) {
|
|
|
|
if (Bv_IsBitSet(fnode->index, bv) && (nd = fnode->first)) {
|
|
|
|
while (flag) {
|
|
|
|
if (nd->type == IROLinearOp1Arg && nd->nodetype == EINDIRECT)
|
|
|
|
flag = CheckLoopAddress(nd, fnode->mustreach1);
|
|
|
|
else if (nd->type == IROLinearFunccall)
|
|
|
|
flag = 0;
|
|
|
|
|
|
|
|
if (nd == fnode->last)
|
|
|
|
break;
|
|
|
|
nd = nd->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!flag)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
fnode = fnode->nextnode;
|
|
|
|
}
|
|
|
|
*resultFlag = flag;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void MakeLoopEntry(IROLinear *nd, IROAddrRecord *rec, Boolean mustreach1, Boolean flag2) {
|
|
|
|
IROElmList *list;
|
|
|
|
|
|
|
|
if (!IRO_IsRegable(((IROLinear *) rec->objRefs->element)->u.node->data.objref) &&
|
|
|
|
(nd->u.monadic->flags & IROLF_LoopInvariant) &&
|
|
|
|
!IRO_HasSideEffect(nd)) {
|
|
|
|
if (!IRO_LoopMemRefFirst) {
|
|
|
|
IRO_LoopMemRefCurrent = IRO_LoopMemRefFirst = oalloc(sizeof(IROLoopMemRef));
|
|
|
|
} else {
|
|
|
|
IRO_LoopMemRefCurrent->next = oalloc(sizeof(IROLoopMemRef));
|
|
|
|
IRO_LoopMemRefCurrent = IRO_LoopMemRefCurrent->next;
|
|
|
|
}
|
|
|
|
IRO_LoopMemRefCurrent->flags = LoopMemRef_10;
|
|
|
|
IRO_LoopMemRefCurrent->nd = nd;
|
|
|
|
IRO_LoopMemRefCurrent->rec = rec;
|
|
|
|
IRO_LoopMemRefCurrent->next = NULL;
|
|
|
|
IRO_LoopMemRefCurrent->list = NULL;
|
|
|
|
|
|
|
|
list = oalloc(sizeof(IROElmList));
|
|
|
|
list->element = nd;
|
|
|
|
list->next = NULL;
|
|
|
|
if (!IRO_LoopMemRefCurrent->list) {
|
|
|
|
IRO_LoopMemRefCurrent->list = list;
|
|
|
|
} else {
|
|
|
|
list->next = IRO_LoopMemRefCurrent->list;
|
|
|
|
IRO_LoopMemRefCurrent->list = list;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (((IROLinear *) rec->objRefs->element)->flags & IROLF_Assigned) {
|
|
|
|
IRO_LoopMemRefCurrent->flags |= LoopMemRef_2;
|
|
|
|
if (((IROLinear *) rec->objRefs->element)->flags & IROLF_Used)
|
|
|
|
IRO_LoopMemRefCurrent->flags |= LoopMemRef_1;
|
|
|
|
} else {
|
|
|
|
IRO_LoopMemRefCurrent->flags |= LoopMemRef_1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!mustreach1 && flag2)
|
|
|
|
IRO_LoopMemRefCurrent->flags |= LoopMemRef_8;
|
|
|
|
|
|
|
|
if (mustreach1 || flag2)
|
|
|
|
IRO_LoopMemRefCurrent->flags &= ~LoopMemRef_10;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void FindAssignmenttoInductionVar(IROLoop *loop, IRONode *fnode) {
|
|
|
|
IROLinear *nd;
|
|
|
|
UInt32 index;
|
|
|
|
|
|
|
|
if (!loop->induction) {
|
|
|
|
loop->nd14 = NULL;
|
|
|
|
} else {
|
|
|
|
index = loop->induction->var->index;
|
|
|
|
for (nd = fnode->first; nd; nd = nd->next) {
|
|
|
|
Bv_Clear(IRO_VarKills);
|
|
|
|
IRO_GetKills(nd);
|
|
|
|
if (Bv_IsBitSet(index, IRO_VarKills))
|
|
|
|
loop->nd14 = nd;
|
|
|
|
|
|
|
|
if (nd == fnode->last)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (loop->nd14 && loop->nd14->type != IROLinearOp2Arg)
|
|
|
|
loop->nd14 = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ComputeIntWeight(IROLoop *loop, IROLinear *Int) {
|
|
|
|
loop->sizeBySomeMeasurement++;
|
|
|
|
}
|
|
|
|
|
|
|
|
static IROLinear *IsTypconVar(IROLinear *nd) {
|
|
|
|
if (IS_LINEAR_MONADIC(nd, ETYPCON) && IRO_IsVariable(nd->u.monadic))
|
|
|
|
return nd->u.monadic;
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
IROLoop *ExtractLoopInfo(IRONode *fnode) {
|
|
|
|
Boolean flag30;
|
|
|
|
Boolean flag29;
|
|
|
|
Boolean flag28;
|
|
|
|
UInt32 counter27;
|
|
|
|
IROLoopInd *ind23;
|
|
|
|
Object *obj;
|
|
|
|
IROLinear *nd21;
|
|
|
|
IRONode *scanfnode;
|
|
|
|
IROLinear *left19;
|
|
|
|
IROLinear *right18;
|
|
|
|
IROLinear *tmp18;
|
|
|
|
IROLinear *scannd;
|
|
|
|
IROLinear *tmp;
|
|
|
|
VarRecord *var;
|
|
|
|
IROLoopInd *scanind;
|
|
|
|
IROLinear *left;
|
|
|
|
IROLinear *right;
|
|
|
|
UInt32 counter2;
|
|
|
|
UInt32 i;
|
|
|
|
IROLoop *loop;
|
|
|
|
|
|
|
|
flag30 = 0;
|
|
|
|
flag29 = 0;
|
|
|
|
flag28 = 0;
|
|
|
|
counter27 = 0;
|
|
|
|
LoopNode = fnode;
|
|
|
|
|
|
|
|
loop = oalloc(sizeof(IROLoop));
|
|
|
|
loop->fnode = fnode;
|
|
|
|
nd21 = LoopNode->last->u.label.x4;
|
|
|
|
loop->nd18 = nd21;
|
|
|
|
loop->flags = 0;
|
|
|
|
loop->x8 = 0;
|
|
|
|
loop->nd14 = NULL;
|
|
|
|
loop->induction = NULL;
|
|
|
|
loop->index20 = -1;
|
|
|
|
loop->index24 = -1;
|
|
|
|
loop->sizeBySomeMeasurement = 0;
|
|
|
|
|
|
|
|
if (nd21->type == IROLinearOp2Arg && IS_TYPE_INT(nd21->rtype)) {
|
|
|
|
ind23 = NULL;
|
|
|
|
left19 = nd21->u.diadic.left;
|
|
|
|
right18 = nd21->u.diadic.right;
|
|
|
|
if (IRO_IsVariable(left19) || (left19 = IsTypconVar(left19))) {
|
|
|
|
if ((var = IRO_FindVar(left19->u.monadic->u.node->data.objref, 0, 1))) {
|
|
|
|
scanind = FirstInd;
|
|
|
|
while (scanind && scanind->var != var)
|
|
|
|
scanind = scanind->next;
|
|
|
|
if (scanind) {
|
|
|
|
ind23 = scanind;
|
|
|
|
loop->flags |= LoopFlags_1;
|
|
|
|
loop->induction = scanind;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IRO_IsVariable(right18) || (right18 = IsTypconVar(right18))) {
|
|
|
|
if ((var = IRO_FindVar(right18->u.monadic->u.node->data.objref, 0, 1))) {
|
|
|
|
scanind = FirstInd;
|
|
|
|
while (scanind && scanind->var != var)
|
|
|
|
scanind = scanind->next;
|
|
|
|
if (scanind) {
|
|
|
|
ind23 = scanind;
|
|
|
|
loop->flags &= ~LoopFlags_1;
|
|
|
|
loop->induction = scanind;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ind23 && ind23->addConst > 0) {
|
|
|
|
if (loop->flags & LoopFlags_1) {
|
|
|
|
if (
|
|
|
|
loop->nd18->type != IROLinearOp2Arg ||
|
|
|
|
!(loop->nd18->nodetype == ELESS || loop->nd18->nodetype == EGREATER || loop->nd18->nodetype == ELESSEQU || loop->nd18->nodetype == EGREATEREQU) ||
|
|
|
|
!loop->nd18->u.diadic.left ||
|
|
|
|
!loop->nd18->u.diadic.left->rtype ||
|
|
|
|
!IS_TYPE_INT(loop->nd18->u.diadic.left->rtype) ||
|
|
|
|
!loop->nd18->u.diadic.right ||
|
|
|
|
!loop->nd18->u.diadic.right->rtype ||
|
|
|
|
!IS_TYPE_INT(loop->nd18->u.diadic.right->rtype)
|
|
|
|
) {
|
|
|
|
loop->flags |= LP_IFEXPR_NON_CANONICAL;
|
|
|
|
return loop;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (
|
|
|
|
loop->nd18->type == IROLinearOp2Arg &&
|
|
|
|
(loop->nd18->nodetype == EGREATER || loop->nd18->nodetype == EGREATEREQU) &&
|
|
|
|
(left = loop->nd18->u.diadic.left) &&
|
|
|
|
left->rtype &&
|
|
|
|
IS_TYPE_INT(left->rtype) &&
|
|
|
|
(right = loop->nd18->u.diadic.right) &&
|
|
|
|
right->rtype &&
|
|
|
|
IS_TYPE_INT(right->rtype)
|
|
|
|
) {
|
|
|
|
loop->nd18->u.diadic.left = right;
|
|
|
|
loop->nd18->u.diadic.right = left;
|
|
|
|
if (loop->nd18->nodetype == EGREATER)
|
|
|
|
loop->nd18->nodetype = ELESS;
|
|
|
|
else if (loop->nd18->nodetype == EGREATEREQU)
|
|
|
|
loop->nd18->nodetype = ELESSEQU;
|
|
|
|
loop->flags |= LoopFlags_1;
|
|
|
|
} else if (
|
|
|
|
loop->nd18->type == IROLinearOp2Arg &&
|
|
|
|
(loop->nd18->nodetype == ELESS || loop->nd18->nodetype == ELESSEQU) &&
|
|
|
|
(left = loop->nd18->u.diadic.left) &&
|
|
|
|
left->rtype &&
|
|
|
|
IS_TYPE_INT(left->rtype) &&
|
|
|
|
(right = loop->nd18->u.diadic.right) &&
|
|
|
|
right->rtype &&
|
|
|
|
IS_TYPE_INT(right->rtype)
|
|
|
|
) {
|
|
|
|
loop->nd18->u.diadic.left = right;
|
|
|
|
loop->nd18->u.diadic.right = left;
|
|
|
|
if (loop->nd18->nodetype == ELESS)
|
|
|
|
loop->nd18->nodetype = EGREATER;
|
|
|
|
else if (loop->nd18->nodetype == ELESSEQU)
|
|
|
|
loop->nd18->nodetype = EGREATEREQU;
|
|
|
|
loop->flags |= LoopFlags_1;
|
|
|
|
} else {
|
|
|
|
loop->flags |= LP_IFEXPR_NON_CANONICAL;
|
|
|
|
return loop;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
loop->flags |= LP_INDUCTION_NOT_FOUND;
|
|
|
|
return loop;
|
|
|
|
}
|
|
|
|
} else if (nd21->type == IROLinearOp1Arg && IS_TYPE_INT(nd21->rtype)) {
|
|
|
|
if (nd21->nodetype == EPREINC || nd21->nodetype == EPOSTINC || nd21->nodetype == EPREDEC || nd21->nodetype == EPOSTDEC) {
|
|
|
|
if (IRO_IsVariable(nd21->u.monadic)) {
|
|
|
|
if ((var = IRO_FindVar(nd21->u.monadic->u.monadic->u.node->data.objref, 0, 1))) {
|
|
|
|
scanind = FirstInd;
|
|
|
|
while (scanind && scanind->var != var)
|
|
|
|
scanind = scanind->next;
|
|
|
|
if (scanind) {
|
|
|
|
ind23 = scanind;
|
|
|
|
loop->flags |= LoopFlags_10000;
|
|
|
|
loop->induction = scanind;
|
|
|
|
} else {
|
|
|
|
loop->flags |= LP_INDUCTION_NOT_FOUND;
|
|
|
|
return loop;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
loop->flags |= LP_INDUCTION_NOT_FOUND;
|
|
|
|
return loop;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
loop->flags |= LP_INDUCTION_NOT_FOUND;
|
|
|
|
return loop;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
loop->flags |= LP_INDUCTION_NOT_FOUND;
|
|
|
|
return loop;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
loop->flags |= LP_IFEXPR_NON_CANONICAL;
|
|
|
|
return loop;
|
|
|
|
}
|
|
|
|
|
|
|
|
counter2 = 0;
|
|
|
|
scanind = FirstInd;
|
|
|
|
while (scanind) {
|
|
|
|
scanind = scanind->next;
|
|
|
|
counter2++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (counter2 > 1)
|
|
|
|
loop->flags |= LP_HAS_MULTIPLE_INDUCTIONS;
|
|
|
|
|
|
|
|
if ((scanind = loop->induction)) {
|
|
|
|
nd21 = scanind->nd;
|
|
|
|
if (nd21->type == IROLinearOp2Arg) {
|
|
|
|
if (IS_LINEAR_DIADIC_2(loop->nd18, ELESS, ELESSEQU)) {
|
|
|
|
if (nd21->nodetype == EADDASS) {
|
|
|
|
if (scanind->addConst == 1)
|
2023-01-10 11:05:21 +00:00
|
|
|
loop->flags |= LP_LOOP_STEP_ISADD;
|
2022-12-14 00:16:59 +00:00
|
|
|
if (scanind->addConst > 0)
|
|
|
|
loop->flags |= LP_LOOP_STEP_ISPOS;
|
|
|
|
} else if (nd21->nodetype == EASS &&
|
|
|
|
IS_LINEAR_DIADIC(nd21->u.diadic.right, EADD) &&
|
|
|
|
IRO_IsIntConstant(tmp18 = nd21->u.diadic.right->u.diadic.right) &&
|
|
|
|
CTool_EndianReadWord32(&tmp18->u.node->data.intval.hi) == 0) {
|
|
|
|
if (CInt64_GetULong(&tmp18->u.node->data.intval) == 1)
|
2023-01-10 11:05:21 +00:00
|
|
|
loop->flags |= LP_LOOP_STEP_ISADD;
|
2022-12-14 00:16:59 +00:00
|
|
|
if (CInt64_GetULong(&tmp18->u.node->data.intval) > 0)
|
|
|
|
loop->flags |= LP_LOOP_STEP_ISPOS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (nd21->type == IROLinearOp1Arg) {
|
|
|
|
if (nd21->nodetype == EPREINC || nd21->nodetype == EPOSTINC) {
|
|
|
|
if (scanind->addConst == 1)
|
2023-01-10 11:05:21 +00:00
|
|
|
loop->flags |= LP_LOOP_STEP_ISADD;
|
2022-12-14 00:16:59 +00:00
|
|
|
if (scanind->addConst > 0)
|
|
|
|
loop->flags |= LP_LOOP_STEP_ISPOS;
|
|
|
|
}
|
|
|
|
if (nd21->nodetype == EPREDEC || nd21->nodetype == EPOSTDEC) {
|
|
|
|
if (scanind->addConst == 1)
|
|
|
|
loop->flags |= LoopFlags_2000;
|
|
|
|
if (scanind->addConst > 0)
|
|
|
|
loop->flags |= LP_LOOP_STEP_ISNEG;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
loop->index24 = nd21->index;
|
|
|
|
loop->index20 = IRO_FindStart(nd21)->index;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ind23) {
|
|
|
|
tmp = IRO_FindStart(fnode->last->u.diadic.right);
|
|
|
|
loop->flags |= LoopFlags_200;
|
|
|
|
if (loop->flags & LoopFlags_10000) {
|
|
|
|
for (scannd = loop->fnode->first; scannd && scannd != tmp; scannd = scannd->next) {
|
|
|
|
if (scannd->type != IROLinearLabel && scannd->type != IROLinearNop)
|
|
|
|
loop->flags &= ~LoopFlags_200;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (scannd = ind23->nd->next; scannd && scannd != tmp; scannd = scannd->next){
|
|
|
|
if (scannd->type != IROLinearLabel && scannd->type != IROLinearNop)
|
|
|
|
loop->flags &= ~LoopFlags_200;
|
|
|
|
}
|
|
|
|
for (scannd = loop->fnode->first; scannd && scannd != tmp; scannd = scannd->next){
|
|
|
|
if ((scannd->index < loop->index20 || scannd->index > loop->index24) && scannd->type != IROLinearLabel && scannd->type != IROLinearNop)
|
|
|
|
loop->flags &= ~LoopFlags_200;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (scanfnode = IRO_FirstNode; scanfnode; scanfnode = scanfnode->nextnode) {
|
|
|
|
if (Bv_IsBitSet(scanfnode->index, InLoop) && scanfnode != fnode && (scannd = scanfnode->first)) {
|
|
|
|
while (1) {
|
|
|
|
if (scannd->type == IROLinearFunccall)
|
|
|
|
flag30 = 1;
|
|
|
|
if (scannd->type == IROLinearGoto)
|
|
|
|
flag28++;
|
|
|
|
if (flag28 >= 1)
|
|
|
|
flag29 = 1;
|
|
|
|
if (scannd->type == IROLinearIf || scannd->type == IROLinearIfNot || scannd->type == IROLinearSwitch || scannd->type == IROLinearReturn)
|
|
|
|
flag29 = 1;
|
|
|
|
|
|
|
|
if (scannd->type == IROLinearAsm)
|
|
|
|
loop->flags |= LP_LOOP_HAS_ASM;
|
|
|
|
|
|
|
|
if (!(scannd->flags & IROLF_Reffed) && scannd->type != IROLinearNop && scannd->type != IROLinearLabel) {
|
|
|
|
if (!IRO_IsAssignOp[scannd->nodetype]) {
|
|
|
|
loop->flags |= LoopFlags_8;
|
|
|
|
} else if (scannd->index < loop->index20 || scannd->index > loop->index24) {
|
|
|
|
counter27++;
|
|
|
|
if (IsAssignmentReductionCandidate(scannd) && counter27 == 1)
|
|
|
|
loop->flags |= LoopFlags_40000;
|
|
|
|
if (counter27 > 1)
|
|
|
|
loop->flags &= ~LoopFlags_40000;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (scannd->index < loop->index20 || scannd->index > loop->index24) {
|
|
|
|
if (IS_LINEAR_ENODE(scannd, EOBJREF)) {
|
|
|
|
obj = scannd->u.node->data.objref;
|
|
|
|
if ((scannd->flags & IROLF_Ind) && obj && obj == loop->induction->var->object) {
|
|
|
|
if (!(scannd->flags & IROLF_Assigned) && (scannd->flags & IROLF_Used)) {
|
|
|
|
IRO_Dump("Induction Used in loop\n");
|
|
|
|
loop->flags |= LoopFlags_800;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IS_LINEAR_DIADIC(scannd, ESHR) &&
|
|
|
|
(obj = IRO_IsVariable(scannd->u.diadic.left)) &&
|
|
|
|
IRO_IsConstant(scannd->u.diadic.right)) {
|
|
|
|
for (scanind = FirstInd; scanind; scanind = scanind->next) {
|
|
|
|
if (scanind->var->object == obj) {
|
|
|
|
IRO_Dump("Induction has DIV: %s\n", obj->name->name);
|
2023-01-10 11:05:21 +00:00
|
|
|
scanind->flags |= LoopInd_HasDiv;
|
2022-12-14 00:16:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IS_LINEAR_DIADIC(scannd, EAND) &&
|
|
|
|
(obj = IRO_IsVariable(scannd->u.diadic.left)) &&
|
|
|
|
IRO_IsConstant(scannd->u.diadic.right)) {
|
|
|
|
for (scanind = FirstInd; scanind && obj; scanind = scanind->next) {
|
|
|
|
if (scanind->var->object == obj) {
|
|
|
|
IRO_Dump("Induction has MOD: %s\n", obj->name->name);
|
2023-01-10 11:05:21 +00:00
|
|
|
scanind->flags |= LoopInd_HasMod;
|
2022-12-14 00:16:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ComputeIntWeight(loop, scannd);
|
|
|
|
if (scannd == scanfnode->last)
|
|
|
|
break;
|
|
|
|
scannd = scannd->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flag30)
|
|
|
|
loop->flags |= LP_LOOP_HAS_CALLS;
|
|
|
|
if (flag29)
|
|
|
|
loop->flags |= LP_LOOP_HAS_CNTRLFLOW;
|
|
|
|
|
|
|
|
for (i = 0; i < scanfnode->numsucc && scanfnode != fnode; i++) {
|
|
|
|
if (Bv_IsBitSet(scanfnode->index, InLoop) && !Bv_IsBitSet(scanfnode->succ[i], InLoop)) {
|
|
|
|
IRO_Dump("Node %d has an out of loop successor %d\n", scanfnode->index, scanfnode->succ[i]);
|
|
|
|
IRO_DumpBits("Loop includes: ", InLoop);
|
|
|
|
IRO_Dump("loop has multiple exits\n");
|
|
|
|
loop->flags |= LoopFlags_1000;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return loop;
|
|
|
|
}
|
|
|
|
|
|
|
|
CLabel *BuildLabel(IROList *list) {
|
|
|
|
IROLinear *nd;
|
|
|
|
|
|
|
|
nd = IRO_NewLinear(IROLinearLabel);
|
|
|
|
nd->index = IRO_NumLinear++;
|
|
|
|
nd->u.label.label = IRO_NewLabel();
|
|
|
|
nd->flags |= IROLF_1;
|
|
|
|
IRO_AddToList(nd, list);
|
|
|
|
return nd->u.label.label;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void MoveInvarianceInAddressExpr(void) {
|
|
|
|
IRONode *fnode;
|
|
|
|
IROLinear *nd;
|
|
|
|
IROLinear *start;
|
|
|
|
IROList list;
|
|
|
|
|
|
|
|
IRO_FirstExpr = IRO_LastExpr = NULL;
|
|
|
|
IRO_NumExprs = 0;
|
|
|
|
|
|
|
|
for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) {
|
|
|
|
if (Bv_IsBitSet(fnode->index, InLoop)) {
|
|
|
|
for (nd = fnode->first; nd; nd = nd->next) {
|
|
|
|
if (nd->type == IROLinearOp1Arg &&
|
|
|
|
(nd->nodetype == EINDIRECT || nd->nodetype == EINDIRECT) &&
|
|
|
|
IS_LINEAR_DIADIC(nd->u.monadic, EADD)) {
|
|
|
|
RearrangeInvarianceInAddressExpr(nd->u.monadic, &list);
|
|
|
|
start = IRO_FindStart(nd->u.monadic);
|
|
|
|
IRO_LocateFather_Cut_And_Paste(nd->u.monadic, list.tail);
|
|
|
|
IRO_Paste(list.head, list.tail, start);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nd == fnode->last)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
IRO_UpdateFlagsOnInts();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void AddAddendLinear(IROLinear *nd) {
|
|
|
|
IROElmList *list;
|
|
|
|
|
|
|
|
if (IS_LINEAR_DIADIC(nd, EADD)) {
|
|
|
|
AddAddendLinear(nd->u.diadic.left);
|
|
|
|
AddAddendLinear(nd->u.diadic.right);
|
|
|
|
} else {
|
|
|
|
list = oalloc(sizeof(IROElmList));
|
|
|
|
list->element = nd;
|
|
|
|
list->next = NULL;
|
|
|
|
if (FirstAddendLinear)
|
|
|
|
LastAddendLinear->next = list;
|
|
|
|
else
|
|
|
|
FirstAddendLinear = list;
|
|
|
|
LastAddendLinear = list;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static IROLinear *RearrangeInvarianceInAddressExpr(IROLinear *nd, IROList *list) {
|
|
|
|
IROLinear *result;
|
|
|
|
IROElmList *scanlist;
|
|
|
|
IROElmList *elist;
|
|
|
|
IROLinear *scannd;
|
|
|
|
|
|
|
|
IRO_InitList(list);
|
|
|
|
FirstAddendLinear = LastAddendLinear = NULL;
|
|
|
|
AddAddendLinear(nd->u.diadic.left);
|
|
|
|
AddAddendLinear(nd->u.diadic.right);
|
|
|
|
|
|
|
|
elist = NULL;
|
|
|
|
result = NULL;
|
|
|
|
for (scanlist = FirstAddendLinear; scanlist; scanlist = scanlist->next) {
|
|
|
|
scannd = scanlist->element;
|
|
|
|
if (!IRO_IsIntConstant(scannd) && (scannd->flags & IROLF_LoopInvariant)) {
|
|
|
|
if (result) {
|
|
|
|
IROLinear *tmp = IRO_NewLinear(IROLinearOp2Arg);
|
|
|
|
tmp->index = ++IRO_NumLinear;
|
|
|
|
tmp->nodetype = EADD;
|
|
|
|
tmp->u.diadic.left = result;
|
|
|
|
tmp->u.diadic.right = IRO_DuplicateExpr(scannd, list);
|
|
|
|
IRO_AddToList(tmp, list);
|
|
|
|
tmp->flags |= IROLF_LoopInvariant;
|
|
|
|
tmp->flags |= IROLF_Reffed;
|
|
|
|
tmp->rtype = result->rtype;
|
|
|
|
result = tmp;
|
|
|
|
} else {
|
|
|
|
result = IRO_DuplicateExpr(scannd, list);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (elist)
|
|
|
|
elist->next = scanlist->next;
|
|
|
|
else
|
|
|
|
FirstAddendLinear = scanlist->next;
|
|
|
|
} else {
|
|
|
|
elist = scanlist;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (scanlist = FirstAddendLinear, elist = NULL; scanlist; scanlist = scanlist->next) {
|
|
|
|
scannd = scanlist->element;
|
|
|
|
if (!IRO_IsIntConstant(scannd)) {
|
|
|
|
if (result) {
|
|
|
|
IROLinear *tmp = IRO_NewLinear(IROLinearOp2Arg);
|
|
|
|
tmp->index = ++IRO_NumLinear;
|
|
|
|
tmp->nodetype = EADD;
|
|
|
|
tmp->u.diadic.left = result;
|
|
|
|
tmp->u.diadic.right = IRO_DuplicateExpr(scannd, list);
|
|
|
|
IRO_AddToList(tmp, list);
|
|
|
|
tmp->flags |= IROLF_Reffed;
|
|
|
|
tmp->rtype = result->rtype;
|
|
|
|
result = tmp;
|
|
|
|
} else {
|
|
|
|
result = IRO_DuplicateExpr(scannd, list);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (elist)
|
|
|
|
elist->next = scanlist->next;
|
|
|
|
else
|
|
|
|
FirstAddendLinear = scanlist->next;
|
|
|
|
} else {
|
|
|
|
elist = scanlist;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (scanlist = FirstAddendLinear; scanlist; scanlist = scanlist->next) {
|
|
|
|
scannd = scanlist->element;
|
|
|
|
if (result) {
|
|
|
|
IROLinear *tmp = IRO_NewLinear(IROLinearOp2Arg);
|
|
|
|
tmp->index = ++IRO_NumLinear;
|
|
|
|
tmp->nodetype = EADD;
|
|
|
|
tmp->u.diadic.left = result;
|
|
|
|
tmp->u.diadic.right = scannd;
|
|
|
|
tmp->u.diadic.right = IRO_DuplicateExpr(scannd, list);
|
|
|
|
IRO_AddToList(tmp, list);
|
|
|
|
tmp->flags |= IROLF_Reffed;
|
|
|
|
tmp->rtype = result->rtype;
|
|
|
|
result = tmp;
|
|
|
|
} else {
|
|
|
|
result = IRO_DuplicateExpr(scannd, list);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static IROLinear *FindAddendForReductionPattern(IROLinear *a, IROLinear *b, Boolean *resultFlag) {
|
|
|
|
IROLinear *left;
|
|
|
|
IROLinear *right;
|
|
|
|
IROLinear *node28;
|
|
|
|
Boolean subflag;
|
|
|
|
|
|
|
|
left = b->u.diadic.left;
|
|
|
|
right = b->u.diadic.right;
|
|
|
|
if (b->nodetype == EADD || b->nodetype == ESUB) {
|
|
|
|
node28 = left;
|
|
|
|
while (IS_LINEAR_MONADIC(node28, ETYPCON))
|
|
|
|
node28 = node28->u.monadic;
|
|
|
|
|
|
|
|
if (IS_LINEAR_MONADIC(node28, EINDIRECT) && (node28->u.monadic->flags & IROLF_LoopInvariant) && IRO_ExprsSame(a, node28)) {
|
|
|
|
*resultFlag = 1;
|
|
|
|
return left;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IS_LINEAR_DIADIC_2(node28, EADD, ESUB)) {
|
|
|
|
if ((node28 = FindAddendForReductionPattern(a, node28, &subflag))) {
|
|
|
|
*resultFlag = 1;
|
|
|
|
return node28;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*resultFlag = 0;
|
|
|
|
if (b->nodetype == EADD) {
|
|
|
|
node28 = right;
|
|
|
|
while (IS_LINEAR_MONADIC(node28, ETYPCON))
|
|
|
|
node28 = node28->u.monadic;
|
|
|
|
|
|
|
|
if (IS_LINEAR_MONADIC(node28, EINDIRECT) && (node28->u.monadic->flags & IROLF_LoopInvariant) && IRO_ExprsSame(a, node28)) {
|
|
|
|
return right;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IS_LINEAR_DIADIC_2(node28, EADD, ESUB)) {
|
|
|
|
if ((node28 = FindAddendForReductionPattern(a, node28, &subflag))) {
|
|
|
|
return node28;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ReorderOperandsForReductionPattern(IROLinear *a, IROLinear *b) {
|
|
|
|
IROLinear *left;
|
|
|
|
IROLinear *right;
|
|
|
|
IROLinear *addend;
|
|
|
|
IROLinear *tmp;
|
|
|
|
Boolean flag;
|
|
|
|
|
|
|
|
left = b->u.diadic.left;
|
|
|
|
right = b->u.diadic.right;
|
|
|
|
|
|
|
|
if (b->nodetype == EADD && (addend = FindAddendForReductionPattern(a, b, &flag)) && addend != left) {
|
|
|
|
if (flag && IS_LINEAR_DIADIC_2(left, EADD, ESUB) && addend->rtype == right->rtype) {
|
|
|
|
tmp = left;
|
|
|
|
b->u.diadic.left = right;
|
|
|
|
left = right;
|
|
|
|
b->u.diadic.right = tmp;
|
|
|
|
right = tmp;
|
|
|
|
flag = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!flag && IS_LINEAR_DIADIC_2(right, EADD, ESUB) && addend->rtype == left->rtype) {
|
|
|
|
if (IRO_LocateFather_Cut_And_Paste_Without_Nopping(addend, left))
|
|
|
|
b->u.diadic.left = addend;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static UInt32 IsAssignmentReductionCandidate(IROLinear *nd) {
|
|
|
|
IROLinear *left;
|
|
|
|
IROLinear *right;
|
|
|
|
IROLinear *tmp;
|
|
|
|
|
|
|
|
if (nd->type == IROLinearOp2Arg) {
|
|
|
|
if (nd->nodetype == EASS) {
|
|
|
|
left = nd->u.diadic.left;
|
|
|
|
right = nd->u.diadic.right;
|
|
|
|
if (IS_LINEAR_MONADIC(left, EINDIRECT) && (left->u.monadic->flags & IROLF_LoopInvariant)) {
|
|
|
|
if (IS_LINEAR_MONADIC(right, ETYPCON) &&
|
|
|
|
right->rtype->type == right->u.monadic->rtype->type &&
|
|
|
|
IS_TYPE_INT(right->rtype) &&
|
|
|
|
right->rtype->size < right->u.monadic->rtype->size)
|
|
|
|
right = right->u.monadic;
|
|
|
|
|
|
|
|
if (IS_LINEAR_DIADIC_2(right, EADD, ESUB)) {
|
|
|
|
ReorderOperandsForReductionPattern(left, right);
|
|
|
|
tmp = right->u.diadic.left;
|
|
|
|
if (IS_LINEAR_MONADIC(tmp, ETYPCON))
|
|
|
|
tmp = tmp->u.monadic;
|
|
|
|
if (IS_LINEAR_MONADIC(tmp, EINDIRECT) &&
|
|
|
|
(tmp->u.monadic->flags & IROLF_LoopInvariant) &&
|
|
|
|
IRO_ExprsSame(left, tmp) &&
|
|
|
|
right->u.diadic.right->type == IROLinearOp2Arg) {
|
|
|
|
if (right->u.diadic.right->nodetype == EADD)
|
|
|
|
return 1;
|
|
|
|
if (right->u.diadic.right->nodetype == ESUB)
|
|
|
|
return 1;
|
|
|
|
if (right->u.diadic.right->nodetype == EMUL)
|
|
|
|
return 1;
|
|
|
|
if (right->u.diadic.right->nodetype == EDIV)
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (nd->nodetype == EADDASS || nd->nodetype == ESUBASS) {
|
|
|
|
left = nd->u.diadic.left;
|
|
|
|
right = nd->u.diadic.right;
|
|
|
|
|
|
|
|
if (IS_LINEAR_MONADIC(right, ETYPCON) &&
|
|
|
|
right->rtype->type == right->u.monadic->rtype->type &&
|
|
|
|
IS_TYPE_INT(right->rtype) &&
|
|
|
|
right->rtype->size < right->u.monadic->rtype->size)
|
|
|
|
right = right->u.monadic;
|
|
|
|
|
|
|
|
if (IS_LINEAR_MONADIC(left, EINDIRECT) &&
|
|
|
|
(left->u.monadic->flags & IROLF_LoopInvariant) &&
|
|
|
|
right->type == IROLinearOp2Arg) {
|
|
|
|
if (right->nodetype == EADD)
|
|
|
|
return 1;
|
|
|
|
if (right->nodetype == ESUB)
|
|
|
|
return 1;
|
|
|
|
if (right->nodetype == EMUL)
|
|
|
|
return 1;
|
|
|
|
if (right->nodetype == EDIV)
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|