#include "compiler/CodeMotion.h" #include "compiler/Alias.h" #include "compiler/BitVectors.h" #include "compiler/LoopDetection.h" #include "compiler/LoopOptimization.h" #include "compiler/CompilerTools.h" #include "compiler/PCode.h" #include "compiler/UseDefChains.h" #include "compiler/RegisterInfo.h" int movedloopinvariantcode; int unswitchedinvariantcode; static int isloopinvariant(PCode *pcode, Loop *loop, UInt32 *vec, int flag1, int flag2) { PCodeArg *op; RegUseOrDef *list; int i; if (pcode->flags & (fPCodeFlag2 | fPCodeFlag4 | fPCodeFlag20000 | fPCodeFlag40000)) { if (pcode->alias) { if (pcode->alias->type == AliasType2 || (pcode->flags & (fIsVolatile | fSideEffects))) return 0; if (pcode->flags & fPCodeFlag2) { for (list = findobjectusedef(pcode->alias->object)->defs; list; list = list->next) { if ( may_alias(pcode, Defs[list->id].pcode) && bitvectorgetbit(list->id, vec) && bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks) ) return 0; } } if (pcode->flags & fPCodeFlag4) { for (list = findobjectusedef(pcode->alias->object)->uses; list; list = list->next) { if ( may_alias(pcode, Uses[list->id].pcode) && bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks) ) return 0; } } } else { return 0; } } if ((pcode->flags & fPCodeFlag4) && !bitvectorgetbit(pcode->block->blockIndex, loop->vec2C)) return 0; op = pcode->args; i = pcode->argCount; while (i--) { switch (op->kind) { case PCOp_MEMORY: if ((pcode->flags & fPCodeFlag2) && ((pcode->flags == 0) & 0x40)) { for (list = findobjectusedef(op->data.mem.obj)->defs; list; list = list->next) { if ( may_alias(pcode, Defs[list->id].pcode) && bitvectorgetbit(list->id, vec) && bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks) ) return 0; } } if (pcode->flags & fPCodeFlag4) { for (list = findobjectusedef(op->data.mem.obj)->uses; list; list = list->next) { if ( may_alias(pcode, Uses[list->id].pcode) && bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks) ) return 0; } } break; case PCOp_REGISTER: if (op->data.reg.effect & (EffectRead | EffectWrite)) { if (op->kind == PCOp_REGISTER && op->arg == RegClass_GPR) { if (op->data.reg.reg == _FP_) break; if (op->data.reg.reg == _CALLER_SP_) break; if (op->data.reg.reg == 2) break; } if (op->data.reg.reg < n_real_registers[op->arg]) { if (op->arg == RegClass_CRFIELD) { if (!flag2 || (op->data.reg.effect & EffectRead)) return 0; } else if (op->arg == RegClass_SPR) { if (!flag1) return 0; } else { return 0; } } else if (op->data.reg.effect & EffectRead) { if (flag1 && op->kind == PCOp_REGISTER && op->arg == RegClass_SPR) break; if (op->kind == PCOp_REGISTER && op->arg == RegClass_GPR) { if (op->data.reg.reg == _FP_) break; if (op->data.reg.reg == _CALLER_SP_) break; if (op->data.reg.reg == 2) break; } for (list = reg_Defs[op->arg][op->data.reg.reg]; list; list = list->next) { if ( bitvectorgetbit(list->id, vec) && bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks) ) return 0; } } } break; } op++; } return 1; } static int isuniquedefinition(PCode *pcode, Loop *loop) { RegUseOrDef *list; int defID; UseOrDef *def; defID = pcode->defID; def = &Defs[defID]; if (defID >= number_of_Defs) return 0; if (def->pcode != pcode) return 0; if ((defID + 1) < number_of_Defs && def[1].pcode == pcode) return 0; if (def->v.kind == PCOp_REGISTER) { for (list = reg_Defs[def->v.arg][def->v.u.reg]; list; list = list->next) { if ( bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks) && list->id != defID ) return 0; } } else if (def->v.kind == PCOp_MEMORY) { for (list = findobjectusedef(def->v.u.object)->defs; list; list = list->next) { if ( may_alias(pcode, Defs[list->id].pcode) && bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks) && list->id != defID ) return 0; } } else { CError_FATAL(292); } return 1; } static int uniquelyreachesuse(int defID, int useID) { UseOrDef *def; UseOrDef *use; RegUseOrDef *list; PCode *pcode; def = &Defs[defID]; use = &Uses[useID]; if (def->v.kind == PCOp_REGISTER) { for (list = reg_Defs[def->v.arg][def->v.u.reg]; list; list = list->next) { if ( list->id != defID && bitvectorgetbit(list->id, usedefinfo[use->pcode->block->blockIndex].defvec8) ) break; } } else if (def->v.kind == PCOp_MEMORY) { for (list = findobjectusedef(def->v.u.object)->defs; list; list = list->next) { if ( may_alias(def->pcode, Defs[list->id].pcode) && list->id != defID && bitvectorgetbit(list->id, usedefinfo[use->pcode->block->blockIndex].defvec8) ) break; } } if (!list) return 1; if (def->pcode->block == use->pcode->block) { for (pcode = use->pcode->prevPCode; pcode; pcode = pcode->prevPCode) { if (pcode == def->pcode) return 1; } } return 0; } static int uniquelyreachesalluses(int defID, Loop *loop) { UseOrDef *def; RegUseOrDef *list; def = &Defs[defID]; if (def->v.kind == PCOp_REGISTER) { for (list = reg_Uses[def->v.arg][def->v.u.reg]; list; list = list->next) { if ( bitvectorgetbit(list->id, usedefinfo[loop->preheader->blockIndex].usevec1C) || (bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks) && !uniquelyreachesuse(defID, list->id)) ) return 0; } } else if (def->v.kind == PCOp_MEMORY) { for (list = findobjectusedef(def->v.u.object)->uses; list; list = list->next) { if (may_alias(def->pcode, Uses[list->id].pcode)) { if ( bitvectorgetbit(list->id, usedefinfo[loop->preheader->blockIndex].usevec1C) || (bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks) && !uniquelyreachesuse(defID, list->id)) ) return 0; } } } else { CError_FATAL(382); } return 1; } static int isliveonexit(TinyValue *v, Loop *loop) { RegUseOrDef *list; UInt32 *vec; vec = usedefinfo[loop->preheader->blockIndex].usevec1C; if (v->kind == PCOp_REGISTER) { for (list = reg_Uses[v->arg][v->u.reg]; list; list = list->next) { if ( bitvectorgetbit(list->id, vec) && !bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks) ) return 1; } } else if (v->kind == PCOp_MEMORY) { for (list = findobjectusedef(v->u.object)->uses; list; list = list->next) { if ( bitvectorgetbit(list->id, vec) && !bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks) ) return 1; } } return 0; } static int dominatesallexits(PCode *pcode, Loop *loop) { return bitvectorgetbit(pcode->block->blockIndex, loop->vec28) != 0; } static int maymove(PCode *pcode, Loop *loop) { short reg; if (!isuniquedefinition(pcode, loop)) return 0; if (!uniquelyreachesalluses(pcode->defID, loop)) return 0; if (!dominatesallexits(pcode, loop) && isliveonexit(&Defs[pcode->defID].v, loop)) return 0; if (loop->bodySize > 25) { switch (pcode->op) { case PC_LI: if ( pcode->nextPCode && pcode->nextPCode->op == PC_LVX && (pcode->nextPCode->flags & fIsConst) ) { reg = pcode->args[0].data.reg.reg; if (pcode->nextPCode->args[1].data.reg.reg == reg || pcode->nextPCode->args[2].data.reg.reg == reg) return 1; } case PC_VSPLTISB: case PC_VSPLTISH: case PC_VSPLTISW: return 0; default: if (!bitvectorgetbit(pcode->block->blockIndex, loop->vec2C)) return 0; } } return 1; } static void moveinvariantcomputation(PCode *pcode, Loop *loop) { ObjectUseDef *oud; BlockList *blocklist; RegUseOrDef *list; UseOrDef *def; int defID; defID = pcode->defID; def = &Defs[defID]; deletepcode(pcode); insertpcodebefore(loop->preheader->lastPCode, pcode); loop->bodySize--; movedloopinvariantcode = 1; if (def->v.kind == PCOp_REGISTER) { for (blocklist = loop->blocks; blocklist; blocklist = blocklist->next) { for (list = reg_Defs[def->v.arg][def->v.u.reg]; list; list = list->next) bitvectorclearbit(list->id, usedefinfo[blocklist->block->blockIndex].defvec8); bitvectorsetbit(defID, usedefinfo[blocklist->block->blockIndex].defvec8); } } else if (def->v.kind == PCOp_MEMORY) { oud = findobjectusedef(def->v.u.object); for (blocklist = loop->blocks; blocklist; blocklist = blocklist->next) { for (list = oud->defs; list; list = list->next) { if (uniquely_aliases(pcode, Defs[list->id].pcode)) bitvectorclearbit(list->id, usedefinfo[blocklist->block->blockIndex].defvec8); } bitvectorsetbit(defID, usedefinfo[blocklist->block->blockIndex].defvec8); } } else { CError_FATAL(545); } } static int srawi_addze_maymove(PCode *pcode, Loop *loop) { RegUseOrDef *list; UseOrDef *def; int defID; int nextDefID; defID = pcode->defID; nextDefID = pcode->nextPCode->defID; def = &Defs[defID]; if (defID >= number_of_Defs) return 0; if (def->pcode != pcode) return 0; if ((defID + 1) < number_of_Defs && def[1].pcode == pcode) return 0; if (def->v.kind == PCOp_REGISTER && def->v.arg == RegClass_GPR) { for (list = reg_Defs[RegClass_GPR][def->v.u.reg]; list; list = list->next) { if ( bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks) && list->id != defID && list->id != nextDefID ) return 0; } } else { CError_FATAL(582); } if (!uniquelyreachesalluses(pcode->defID, loop)) return 0; if (!dominatesallexits(pcode, loop) && isliveonexit(&Defs[pcode->defID].v, loop)) return 0; if (!dominatesallexits(pcode->nextPCode, loop) && isliveonexit(&Defs[pcode->nextPCode->defID].v, loop)) return 0; return 1; } static int srawi_addze_isloopinvariant(PCode *pcode, Loop *loop, UInt32 *vec) { static PCode *oldNextInstr; PCode *nextInstr; nextInstr = pcode->nextPCode; if ( pcode->op == PC_ADDZE && oldNextInstr == pcode ) { oldNextInstr = NULL; return 1; } else if ( pcode->op == PC_SRAWI && nextInstr && nextInstr->op == PC_ADDZE && pcode->args[0].data.reg.reg == nextInstr->args[0].data.reg.reg && nextInstr->args[0].data.reg.reg == nextInstr->args[1].data.reg.reg && !(pcode->flags & (fPCodeFlag8 | fPCodeFlag20 | fIsVolatile | fSideEffects)) && !(nextInstr->flags & (fPCodeFlag8 | fPCodeFlag20 | fIsVolatile | fSideEffects)) && isloopinvariant(pcode, loop, vec, 1, 0) && srawi_addze_maymove(pcode, loop) ) { oldNextInstr = nextInstr; return 1; } else { oldNextInstr = NULL; return 0; } } static void removeblockfromloop(Loop *loop, PCodeBlock *block) { BlockList *list; BlockList **ptr; bitvectorclearbit(block->blockIndex, loop->memberblocks); bitvectorclearbit(block->blockIndex, loop->vec24); bitvectorclearbit(block->blockIndex, loop->vec28); bitvectorclearbit(block->blockIndex, loop->vec2C); loop->bodySize -= block->pcodeCount; ptr = &loop->blocks; while ((list = *ptr)) { if (list->block == block) *ptr = list->next; else ptr = &list->next; } } static void changesuccessor(PCodeBlock *block, PCodeBlock *from, PCodeBlock *to) { PCLink **ptr; PCLink *link; for (link = block->successors; link; link = link->nextLink) { if (link->block == from) link->block = to; } ptr = &from->predecessors; while ((link = *ptr)) { if (link->block == block) { *ptr = link->nextLink; link->nextLink = to->predecessors; to->predecessors = link; } else { ptr = &link->nextLink; } } } static void movesuccessor(PCodeBlock *to, PCodeBlock *from, PCodeBlock *block) { PCLink **ptr; PCLink *link; for (link = block->predecessors; link; link = link->nextLink) { if (link->block == from) link->block = to; } ptr = &from->successors; while ((link = *ptr)) { if (link->block == block) { *ptr = link->nextLink; link->nextLink = to->successors; to->successors = link; } else { ptr = &link->nextLink; } } } static void movecmptopreheader(Loop *loop, PCodeBlock *block, PCode *pc1, PCode *pc2, PCodeArg *op) { PCodeBlock *preheader; PCode *pc3; preheader = loop->preheader; if (PCODE_FLAG_SET_F(pc1) & fPCodeFlag20000000) { moveinvariantcomputation(pc1, loop); } else { deletepcode(pc1); insertpcodebefore(loop->preheader->lastPCode, pc1); loop->bodySize--; movedloopinvariantcode = 1; } loop->preheader = NULL; insertpreheaderblock(loop); pc3 = preheader->lastPCode; CError_ASSERT(775, pc3->op == PC_B); deletepcode(pc3); deletepcode(pc2); appendpcode(preheader, pc2); movesuccessor(preheader, block, op->data.label.label->block); } static PCodeBlock *appendheadercopy(Loop *loop, PCodeBlock *block1, PCodeBlock *block2, PCodeBlock *block3) { PCodeBlock *newblock1; PCodeBlock *newblock2; PCLink *link; PCode *scan; newblock1 = lalloc(sizeof(PCodeBlock)); newblock2 = lalloc(sizeof(PCodeBlock)); newblock1->labels = NULL; newblock1->predecessors = newblock1->successors = NULL; newblock1->firstPCode = newblock1->lastPCode = NULL; newblock1->pcodeCount = 0; newblock1->loopWeight = loop->body->loopWeight; newblock1->flags = 0; newblock1->blockIndex = pcblockcount++; newblock2->labels = NULL; newblock2->predecessors = newblock2->successors = NULL; newblock2->firstPCode = newblock2->lastPCode = NULL; newblock2->pcodeCount = 0; newblock2->loopWeight = loop->body->loopWeight; newblock2->flags = 0; newblock2->blockIndex = pcblockcount++; newblock1->nextBlock = newblock2; newblock2->prevBlock = newblock1; newblock1->prevBlock = block1; newblock2->nextBlock = block1->nextBlock; block1->nextBlock = newblock1; newblock2->nextBlock->prevBlock = newblock2; pclabel(newblock1, makepclabel()); pclabel(newblock2, makepclabel()); changesuccessor(block1, block1->successors->block, newblock1); link = lalloc(sizeof(PCLink)); link->block = newblock2; link->nextLink = newblock1->successors; newblock1->successors = link; link = lalloc(sizeof(PCLink)); link->block = newblock1; link->nextLink = newblock2->predecessors; newblock2->predecessors = link; appendpcode(newblock2, makepcode(PC_B, block2->nextBlock->labels)); pcbranch(newblock2, block2->nextBlock->labels); pccomputepredecessors1(newblock2); for (scan = block2->firstPCode; scan; scan = scan->nextPCode) appendpcode(newblock1, copypcode(scan)); pcbranch(newblock1, block3->labels); link = lalloc(sizeof(PCLink)); link->block = newblock1; link->nextLink = block3->predecessors; block3->predecessors = link; addblocktoloop(loop, newblock1); if (bitvectorgetbit(block2->blockIndex, loop->vec28)) bitvectorsetbit(newblock1->blockIndex, loop->vec28); if (bitvectorgetbit(block2->blockIndex, loop->vec2C)) bitvectorsetbit(newblock1->blockIndex, loop->vec2C); for (loop = loop->parent; loop; loop = loop->parent) { addblocktoloop(loop, newblock1); if (bitvectorgetbit(block2->blockIndex, loop->vec28)) bitvectorsetbit(newblock1->blockIndex, loop->vec28); if (bitvectorgetbit(block2->blockIndex, loop->vec2C)) bitvectorsetbit(newblock1->blockIndex, loop->vec2C); addblocktoloop(loop, newblock2); if (bitvectorgetbit(block2->blockIndex, loop->vec28)) bitvectorsetbit(newblock2->blockIndex, loop->vec28); if (bitvectorgetbit(block2->blockIndex, loop->vec2C)) bitvectorsetbit(newblock2->blockIndex, loop->vec2C); } return newblock1; } static BlockList *findswitchpath(Loop *loop, PCodeBlock *block) { BlockList *head; BlockList *tail; BlockList *node; PCodeBlock *scan; head = NULL; tail = NULL; for (scan = block; scan && scan != loop->body; scan = scan->successors->block) { if (!bitvectorgetbit(scan->blockIndex, loop->memberblocks)) return NULL; if (scan->successors && scan->successors->nextLink) return NULL; node = oalloc(sizeof(BlockList)); node->block = scan; node->next = NULL; if (head) { tail->next = node; tail = node; } else { head = node; tail = node; } } return head; } static void simpleunswitchloop(Loop *loop) { PCode *pc29; PCodeArg *op27; UInt32 *myvec; PCodeBlock *block26; PCode *pc25; // r25 BlockList *path2_24; PCodeArg *op23; PCode *pc23; // r23 BlockList *scanlist; // r23 BlockList *bestpath1; // r23 BlockList *bestpath2; // r22 PCodeBlock *headercopy; // r22 Loop *newloop; // r21 PCodeBlock *preheader21; BlockList *path20; PCode *scan20; PCode *lastpcode; int i; BlockList *pathiter1; BlockList *pathiter2; if (!(lastpcode = loop->body->lastPCode)) return; if (lastpcode->op != PC_BT && lastpcode->op != PC_BF) return; if (lastpcode->args[2].kind != PCOp_LABEL) return; if (!bitvectorgetbit(lastpcode->args[2].data.label.label->block->blockIndex, loop->memberblocks)) return; if (loop->x57) return; if (loop->x4D) return; if (bitvectorgetbit(loop->body->nextBlock->blockIndex, loop->memberblocks)) return; for (block26 = pcbasicblocks; block26; block26 = block26->nextBlock) { if (bitvectorgetbit(block26->blockIndex, loop->memberblocks)) break; } if (!block26) return; myvec = oalloc(4 * ((number_of_Defs + 31) >> 5)); bitvectorcopy(myvec, usedefinfo[block26->blockIndex].defvec8, number_of_Defs); for (pc25 = loop->preheader->nextBlock->firstPCode; pc25; pc25 = pc25->nextPCode) { if (!(PCODE_FLAG_SET_F(pc25) & (fPCodeFlag8 | fPCodeFlag20 | fIsVolatile | fSideEffects | fPCodeFlag20000000))) { if (isloopinvariant(pc25, loop, myvec, 0, 1)) break; } } if (!pc25 || pc25->argCount < 1) return; if ( pc25->argCount < 1 || pc25->args[0].kind != PCOp_REGISTER || pc25->args[0].arg != RegClass_CRFIELD ) return; pc29 = pc25->block->lastPCode; if ( !pc29 || !(pc29->flags & fPCodeFlag1) || pc29->args[0].kind != PCOp_REGISTER || pc29->args[0].arg != RegClass_CRFIELD ) return; if (pc29->args[0].data.reg.reg != pc25->args[0].data.reg.reg) return; op27 = NULL; for (i = 0; i < pc29->argCount; i++) { if (pc29->args[i].kind == PCOp_LABEL) op27 = &pc29->args[i]; } if (op27) { preheader21 = loop->preheader; path20 = findswitchpath(loop, block26->nextBlock); if (!path20) return; path2_24 = findswitchpath(loop, op27->data.label.label->block); if (!path2_24) return; bestpath1 = NULL; bestpath2 = NULL; for (pathiter1 = path20; pathiter1; pathiter1 = pathiter1->next) { for (pathiter2 = path2_24; pathiter2; pathiter2 = pathiter2->next) { if (pathiter1->block == pathiter2->block) { bestpath1 = pathiter1; break; } } if (bestpath1) break; bestpath2 = pathiter1; } CError_ASSERT(1192, bestpath2->block); if (bestpath2->block->lastPCode && bestpath2->block->lastPCode->op == PC_B) deletepcode(bestpath2->block->lastPCode); while (bestpath1) { for (scan20 = bestpath1->block->firstPCode; scan20; scan20 = scan20->nextPCode) { if (scan20->op != PC_B) appendpcode(bestpath2->block, copypcode(scan20)); } bestpath1 = bestpath1->next; } headercopy = appendheadercopy(loop, bestpath2->block, loop->body, block26); movecmptopreheader(loop, block26, pc25, pc29, op27); if (block26->pcodeCount) { if (path2_24->block->firstPCode) { pc23 = path2_24->block->firstPCode; for (scan20 = block26->firstPCode; scan20; scan20 = scan20->nextPCode) { if (scan20->op != PC_B) insertpcodebefore(pc23, copypcode(scan20)); } } else { for (scan20 = block26->firstPCode; scan20; scan20 = scan20->nextPCode) { if (scan20->op != PC_B) appendpcode(path2_24->block, copypcode(scan20)); } } } op23 = NULL; for (i = 0; i < loop->body->lastPCode->argCount; i++) { if (loop->body->lastPCode->args[i].kind == PCOp_LABEL) op23 = &loop->body->lastPCode->args[i]; } CError_ASSERT(1250, op23 != NULL); changesuccessor(loop->body, op23->data.label.label->block, path2_24->block); op23->data.label.label = path2_24->block->labels; op23 = NULL; for (i = 0; i < preheader21->lastPCode->argCount; i++) { if (preheader21->lastPCode->args[i].kind == PCOp_LABEL) op23 = &preheader21->lastPCode->args[i]; } CError_ASSERT(1267, op23 != NULL); changesuccessor(preheader21, op23->data.label.label->block, loop->body); op23->data.label.label = loop->body->labels; op23 = NULL; for (i = 0; i < loop->preheader->lastPCode->argCount; i++) { if (loop->preheader->lastPCode->args[i].kind == PCOp_LABEL) op23 = &loop->preheader->lastPCode->args[i]; } CError_ASSERT(1284, op23 != NULL); changesuccessor(loop->preheader, op23->data.label.label->block, headercopy); op23->data.label.label = headercopy->labels; newloop = lalloc(sizeof(Loop)); newloop->parent = loop->parent; newloop->children = NULL; newloop->nextSibling = loop->nextSibling; loop->nextSibling = newloop; newloop->body = loop->body; newloop->preheader = NULL; newloop->blocks = NULL; newloop->basicInductionVars = NULL; newloop->footer = NULL; newloop->pc18 = NULL; newloop->loopWeight = loop->loopWeight; bitvectorinitialize(newloop->memberblocks = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0); bitvectorinitialize(newloop->vec24 = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0); bitvectorinitialize(newloop->vec28 = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0); bitvectorinitialize(newloop->vec2C = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0); removeblockfromloop(loop, newloop->body); addblocktoloop(newloop, newloop->body); bitvectorsetbit(newloop->body->blockIndex, newloop->vec24); bitvectorsetbit(newloop->body->blockIndex, newloop->vec2C); bitvectorsetbit(newloop->body->blockIndex, newloop->vec28); for (scanlist = path2_24; scanlist; scanlist = scanlist->next) { removeblockfromloop(loop, scanlist->block); addblocktoloop(newloop, scanlist->block); bitvectorsetbit(scanlist->block->blockIndex, newloop->vec2C); } newloop->preheader = NULL; insertpreheaderblock(newloop); analyzeloop(newloop); loop->body = headercopy; for (scanlist = loop->blocks; scanlist; scanlist = scanlist->next) bitvectorsetbit(scanlist->block->blockIndex, loop->vec2C); bitvectorsetbit(headercopy->blockIndex, loop->vec24); analyzeloop(loop); unswitchedinvariantcode = 1; } } static void simpleunswitchloops(Loop *loop) { while (loop) { if (loop->children) simpleunswitchloops(loop->children); else if (!loop->x4F) simpleunswitchloop(loop); loop = loop->nextSibling; } } static void moveinvariantsfromloop(Loop *loop) { RegUseOrDef *list; BlockList *blocklist; PCode *instr; PCode *nextInstr; UInt32 *myvec; UseOrDef *def; int defID; int flag; PCodeBlock *block; myvec = oalloc(4 * ((number_of_Defs + 31) >> 5)); do { flag = 0; for (blocklist = loop->blocks; blocklist; blocklist = blocklist->next) { block = blocklist->block; bitvectorcopy(myvec, usedefinfo[block->blockIndex].defvec8, number_of_Defs); for (instr = block->firstPCode; instr; instr = nextInstr) { nextInstr = instr->nextPCode; if (!(instr->flags & fPCodeFlag1) && instr->argCount) { if ( !(instr->flags & (fPCodeFlag8 | fPCodeFlag20 | fIsVolatile | fSideEffects)) && isloopinvariant(instr, loop, myvec, 0, 0) && maymove(instr, loop) ) { moveinvariantcomputation(instr, loop); flag = 1; } else if (srawi_addze_isloopinvariant(instr, loop, myvec)) { moveinvariantcomputation(instr, loop); flag = 1; } for (def = &Defs[defID = instr->defID]; defID < number_of_Defs && def->pcode == instr; def++, defID++) { if (def->v.kind == PCOp_REGISTER) { for (list = reg_Defs[def->v.arg][def->v.u.reg]; list; list = list->next) bitvectorclearbit(list->id, myvec); } else if (def->v.kind == PCOp_MEMORY) { if (def->v.arg == PCOpMemory0) { for (list = findobjectusedef(def->v.u.object)->defs; list; list = list->next) { if (uniquely_aliases(instr, Defs[list->id].pcode)) bitvectorclearbit(list->id, myvec); } } } else { CError_FATAL(1434); } bitvectorsetbit(defID, myvec); } } } } } while (flag); } static void moveinvariantsfromloops(Loop *loop) { while (loop) { if (loop->children) moveinvariantsfromloops(loop->children); moveinvariantsfromloop(loop); loop = loop->nextSibling; } } void moveloopinvariantcode(void) { unswitchedinvariantcode = 0; movedloopinvariantcode = 0; if (loopsinflowgraph) { moveinvariantsfromloops(loopsinflowgraph); simpleunswitchloops(loopsinflowgraph); } freeoheap(); }