diff options
author | Ash Wolf <ninji@wuffs.org> | 2023-01-26 11:30:47 +0000 |
---|---|---|
committer | Ash Wolf <ninji@wuffs.org> | 2023-01-26 11:30:47 +0000 |
commit | 094b96ca1df4a035b5f93c351f773306c0241f3f (patch) | |
tree | 95ce05e3ebe816c7ee7996206bb37ea17d8ca33c /compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/CodeMotion.c | |
parent | fc0c4c0df7b583b55a08317cf1ef6a71d27c0440 (diff) | |
download | MWCC-main.tar.gz MWCC-main.zip |
move lots of source files around to match their actual placement in the original treemain
Diffstat (limited to 'compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/CodeMotion.c')
-rw-r--r-- | compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/CodeMotion.c | 906 |
1 files changed, 906 insertions, 0 deletions
diff --git a/compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/CodeMotion.c b/compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/CodeMotion.c new file mode 100644 index 0000000..8ce2962 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/CodeMotion.c @@ -0,0 +1,906 @@ +#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 & (fIsRead | fIsWrite | fPCodeFlag20000 | fPCodeFlag40000)) { + if (pcode->alias) { + if (pcode->alias->type == AliasType2 || (pcode->flags & (fIsVolatile | fSideEffects))) + return 0; + + if (pcode->flags & fIsRead) { + 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 & fIsWrite) { + 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 & fIsWrite) && !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 & fIsRead) && ((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 & fIsWrite) { + 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 & (fIsCall | fIsPtrOp | fIsVolatile | fSideEffects)) && + !(nextInstr->flags & (fIsCall | fIsPtrOp | 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) & fRecordBit) { + 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) & (fIsCall | fIsPtrOp | fIsVolatile | fSideEffects | fRecordBit))) { + 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 & fIsBranch) || + 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 & fIsBranch) && instr->argCount) { + if ( + !(instr->flags & (fIsCall | fIsPtrOp | 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(); +} |