summaryrefslogtreecommitdiff
path: root/compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/CodeMotion.c
diff options
context:
space:
mode:
authorAsh Wolf <ninji@wuffs.org>2023-01-26 11:30:47 +0000
committerAsh Wolf <ninji@wuffs.org>2023-01-26 11:30:47 +0000
commit094b96ca1df4a035b5f93c351f773306c0241f3f (patch)
tree95ce05e3ebe816c7ee7996206bb37ea17d8ca33c /compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/CodeMotion.c
parentfc0c4c0df7b583b55a08317cf1ef6a71d27c0440 (diff)
downloadMWCC-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.c906
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();
+}