#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; CError_ASSERT(802, indirect->u.monadic->u.node != NULL); *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; CError_ASSERT(845, ind != NULL); 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 { CError_ASSERT(1254, fnode1->first->type == IROLinearLabel); 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; CError_ASSERT(1355, fnode1 != NULL && LoopExitNumber == 1); fnode2 = NULL; flag = 0; for (i = 0; i < fnode1->numpred; i++) { iter = IRO_NodeTable[fnode1->pred[i]]; if (Bv_IsBitSet(iter->index, InLoop_Exits)) { CError_ASSERT(1366, fnode2 == NULL); 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; } } } CError_ASSERT(1382, fnode2 != NULL); 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 { CError_ASSERT(1422, fnode1->first->type == IROLinearLabel); 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) { CError_ASSERT(2880, v2 == NULL || pred == v2); 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; CError_ASSERT(3529, induction != NULL); 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) { CError_ASSERT(3880, v2 == NULL || pred == v2); 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(""); if (memref->flags & LoopMemRef_1) IRO_Dump(""); if (memref->flags & LoopMemRef_2) IRO_Dump(""); 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 { CError_FATAL(4123); } 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) loop->flags |= LoopFlags_100; 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) loop->flags |= LoopFlags_100; 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) loop->flags |= LoopFlags_100; 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); scanind->flags |= LoopInd_2; } } } 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); scanind->flags |= LoopInd_1; } } } } 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; }