summaryrefslogtreecommitdiff
path: root/compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/LoopDetection.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/LoopDetection.c
parentfc0c4c0df7b583b55a08317cf1ef6a71d27c0440 (diff)
downloadMWCC-094b96ca1df4a035b5f93c351f773306c0241f3f.tar.gz
MWCC-094b96ca1df4a035b5f93c351f773306c0241f3f.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/LoopDetection.c')
-rw-r--r--compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/LoopDetection.c885
1 files changed, 885 insertions, 0 deletions
diff --git a/compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/LoopDetection.c b/compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/LoopDetection.c
new file mode 100644
index 0000000..6bb2d51
--- /dev/null
+++ b/compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/LoopDetection.c
@@ -0,0 +1,885 @@
+#include "compiler/LoopDetection.h"
+#include "compiler/CFunc.h"
+#include "compiler/PCode.h"
+#include "compiler/TOC.h"
+#include "compiler/UseDefChains.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/BitVectors.h"
+#include "compiler/enode.h"
+#include "compiler/objects.h"
+
+Loop *loopsinflowgraph;
+int loopdetection_nblocks;
+static UInt32 **dominators;
+static BlockList *loopheaders;
+static int nloopheaders;
+static PCodeBlock **loopstack;
+BitVector *LoopTemp;
+struct LoopList *LoopList_First;
+
+static void computedominators(void) {
+ int i;
+ PCodeBlock *block;
+ int blockCount;
+ int flag;
+ UInt32 *myvec;
+ PCLink *link;
+
+ blockCount = pcblockcount;
+ flag = 1;
+
+ dominators = oalloc(sizeof(UInt32 *) * pcblockcount);
+ for (i = 0; i < pcblockcount; i++)
+ dominators[i] = oalloc(4 * ((blockCount + 31) >> 5));
+
+ myvec = oalloc(4 * ((blockCount + 31) >> 5));
+
+ bitvectorinitialize(dominators[pcbasicblocks->blockIndex], blockCount, 0);
+ //dominators[pcbasicblocks->blockIndex][0] |= 1;
+ bitvectorsetbit(0, dominators[pcbasicblocks->blockIndex]);
+
+ for (block = pcbasicblocks->nextBlock; block; block = block->nextBlock)
+ bitvectorinitialize(dominators[block->blockIndex], blockCount, 0xFFFFFFFF);
+
+ computedepthfirstordering();
+
+ while (flag) {
+ flag = 0;
+ for (i = 0; i < pcblockcount; i++) {
+ block = depthfirstordering[i];
+ if (block && block->blockIndex != pcbasicblocks->blockIndex) {
+ bitvectorcopy(myvec, dominators[block->predecessors->block->blockIndex], blockCount);
+ for (link = block->predecessors->nextLink; link; link = link->nextLink)
+ bitvectorintersect(myvec, dominators[link->block->blockIndex], blockCount);
+ //myvec[block->blockIndex >> 5] |= 1 << (block->blockIndex & 31);
+ bitvectorsetbit(block->blockIndex, myvec);
+
+ if (bitvectorchanged(dominators[block->blockIndex], myvec, blockCount))
+ flag = 1;
+ }
+ }
+ }
+}
+
+static BlockList *findloopheaders(void) {
+ PCodeBlock *block;
+ PCLink *link;
+ BlockList *list;
+
+ loopheaders = NULL;
+ nloopheaders = 0;
+
+ for (block = pcbasicblocks->nextBlock; block; block = block->nextBlock) {
+ for (link = block->predecessors; link; link = link->nextLink) {
+ //if ((1 << (block->blockIndex & 31)) & dominators[link->block->blockIndex][block->blockIndex >> 5])
+ if (bitvectorgetbit(block->blockIndex, dominators[link->block->blockIndex]))
+ break;
+ }
+
+ if (link) {
+ list = oalloc(sizeof(BlockList));
+ list->block = block;
+ list->next = loopheaders;
+ loopheaders = list;
+ nloopheaders++;
+ }
+ }
+
+ return loopheaders;
+}
+
+void addblocktoloop(Loop *loop, PCodeBlock *block) {
+ BlockList *list = lalloc(sizeof(BlockList));
+
+ //loop->memberblocks[block->blockIndex >> 5] |= 1 << (block->blockIndex & 31);
+ bitvectorsetbit(block->blockIndex, loop->memberblocks);
+
+ list->block = block;
+ list->next = loop->blocks;
+ loop->blocks = list;
+}
+
+static void findnaturalloop(Loop *loop) {
+ BlockList *list;
+ BlockList *list2;
+ PCLink *link;
+ PCodeBlock *block;
+ int i;
+
+ i = 0;
+ addblocktoloop(loop, loop->body);
+ for (link = loop->body->predecessors; link; link = link->nextLink) {
+ if (bitvectorgetbit(loop->body->blockIndex, dominators[link->block->blockIndex]) && link->block != loop->body) {
+ addblocktoloop(loop, link->block);
+ loopstack[i++] = link->block;
+ }
+ }
+
+ while (i) {
+ link = loopstack[--i]->predecessors;
+ while (link) {
+ if (!bitvectorgetbit(link->block->blockIndex, loop->memberblocks)) {
+ addblocktoloop(loop, link->block);
+ loopstack[i++] = link->block;
+ }
+ link = link->nextLink;
+ }
+ }
+
+ for (list = loop->blocks; list; list = list->next) {
+ block = list->block;
+ for (link = block->successors; link; link = link->nextLink) {
+ if (!bitvectorgetbit(link->block->blockIndex, loop->memberblocks)) {
+ bitvectorsetbit(block->blockIndex, loop->vec24);
+ break;
+ }
+ }
+ }
+
+ for (list = loop->blocks; list; list = list->next) {
+ for (list2 = loop->blocks; list2; list2 = list2->next) {
+ if (bitvectorgetbit(list2->block->blockIndex, loop->vec24) &&
+ !bitvectorgetbit(list->block->blockIndex, dominators[list2->block->blockIndex]))
+ break;
+ }
+
+ if (!list2)
+ bitvectorsetbit(list->block->blockIndex, loop->vec28);
+ }
+
+ for (list = loop->blocks; list; list = list->next) {
+ for (link = loop->body->predecessors; link; link = link->nextLink) {
+ if (bitvectorgetbit(link->block->blockIndex, loop->memberblocks) &&
+ !bitvectorgetbit(list->block->blockIndex, dominators[link->block->blockIndex]))
+ break;
+ }
+
+ if (!link)
+ bitvectorsetbit(list->block->blockIndex, loop->vec2C);
+ }
+}
+
+static void addlooptolist(Loop *loop, Loop **list) {
+ Loop **scan;
+ Loop *scanloop;
+
+ scan = list;
+ while ((scanloop = *scan)) {
+ if (bitvectorgetbit(loop->body->blockIndex, scanloop->memberblocks)) {
+ loop->parent = scanloop;
+ addlooptolist(loop, &scanloop->children);
+ return;
+ }
+
+ if (bitvectorgetbit(scanloop->body->blockIndex, loop->memberblocks)) {
+ *scan = scanloop->nextSibling;
+ scanloop->parent = loop;
+ scanloop->nextSibling = loop->children;
+ loop->children = scanloop;
+ } else {
+ scan = &scanloop->nextSibling;
+ }
+ }
+
+ loop->nextSibling = *list;
+ *list = loop;
+}
+
+static void findnaturalloops(void) {
+ Loop *loop;
+ int size;
+
+ loopdetection_nblocks = pcblockcount + 5 * nloopheaders;
+ loopstack = oalloc(sizeof(PCodeBlock *) * pcblockcount);
+ while (loopheaders) {
+ loop = lalloc(sizeof(Loop));
+ loop->parent = loop->nextSibling = loop->children = NULL;
+ loop->body = loopheaders->block;
+ loop->preheader = NULL;
+ loop->blocks = NULL;
+ loop->basicInductionVars = NULL;
+ loop->footer = NULL;
+ loop->pc18 = NULL;
+ loop->loopWeight = loop->body->loopWeight;
+
+ bitvectorinitialize(loop->memberblocks = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0);
+ bitvectorinitialize(loop->vec24 = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0);
+ bitvectorinitialize(loop->vec28 = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0);
+ bitvectorinitialize(loop->vec2C = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0);
+
+ findnaturalloop(loop);
+ addlooptolist(loop, &loopsinflowgraph);
+
+ loopheaders = loopheaders->next;
+ }
+}
+
+static PCodeBlock *makepreheaderblock(void) {
+ PCodeLabel *label;
+ PCodeBlock *block;
+
+ label = makepclabel();
+ block = lalloc(sizeof(PCodeBlock));
+ block->nextBlock = NULL;
+ block->prevBlock = NULL;
+ block->labels = NULL;
+ block->successors = NULL;
+ block->predecessors = NULL;
+ block->firstPCode = block->lastPCode = NULL;
+ block->pcodeCount = 0;
+ block->flags = 0;
+ block->blockIndex = pcblockcount++;
+ pclabel(block, label);
+ return block;
+}
+
+static void insertpreheaderbefore(PCodeBlock *a, PCodeBlock *b) {
+ a->nextBlock = b;
+ a->prevBlock = b->prevBlock;
+ b->prevBlock->nextBlock = a;
+ b->prevBlock = a;
+}
+
+void insertpreheaderblock(Loop *loop) {
+ PCodeBlock *preheader;
+ PCodeBlock *block29;
+ PCodeBlock *block28;
+ PCode *pcode27;
+ PCLink *link; // r26
+ PCLink **linkptr; // r25
+ PCodeLabel *newlabel; // r23
+ PCLink *innerlink;
+ PCodeBlock *block;
+ PCodeArg *arg;
+ int i;
+
+ preheader = loop->preheader = makepreheaderblock();
+ block29 = NULL;
+ block28 = loop->body;
+
+ if (!block28->labels)
+ pclabel(block28, makepclabel());
+
+ appendpcode(preheader, makepcode(PC_B, block28->labels));
+ preheader->loopWeight = loop->parent ? loop->parent->loopWeight : 1;
+
+ linkptr = &block28->predecessors;
+ while ((link = *linkptr)) {
+ if (bitvectorgetbit(link->block->blockIndex, loop->memberblocks)) {
+ linkptr = &link->nextLink;
+ } else {
+ if (link->block->pcodeCount) {
+ pcode27 = link->block->lastPCode;
+ if (pcode27->op == PC_B) {
+ CError_ASSERT(462, pcode27->args[0].kind == PCOp_LABEL);
+ if (pcode27->args[0].data.label.label->block == block28)
+ pcode27->args[0].data.label.label = preheader->labels;
+ } else if (pcode27->op == PC_BT || pcode27->op == PC_BF) {
+ CError_ASSERT(474, pcode27->args[2].kind == PCOp_LABEL);
+ if (pcode27->args[2].data.label.label->block == block28)
+ pcode27->args[2].data.label.label = preheader->labels;
+ } else if (pcode27->op == PC_BCTR) {
+ if (pcode27->argCount > 1 && pcode27->args[1].kind == PCOp_MEMORY) {
+ Object *obj = pcode27->args[1].data.mem.obj;
+ UInt32 *array = (UInt32 *) obj->u.data.u.switchtable.data;
+ int i;
+ for (i = 0; i < obj->u.data.u.switchtable.size; i++) {
+ if (((PCodeLabel *) CTool_ResolveIndexToPointer(array[i]))->block == block28)
+ array[i] = CTool_CreateIndexFromPointer(preheader->labels);
+ }
+ } else {
+ CodeLabelList *cll;
+ for (cll = codelabellist; cll; cll = cll->next) {
+ if (cll->label->pclabel->block == block28)
+ cll->label->pclabel = preheader->labels;
+ }
+ }
+ } else {
+ CError_ASSERT(505, link->block->nextBlock == block28);
+ }
+ }
+
+ for (innerlink = link->block->successors; innerlink; innerlink = innerlink->nextLink) {
+ if (innerlink->block == block28)
+ innerlink->block = preheader;
+ }
+
+ *linkptr = link->nextLink;;
+ link->nextLink = preheader->predecessors;
+ preheader->predecessors = link;
+ }
+ }
+
+ if (!bitvectorgetbit(block28->prevBlock->blockIndex, loop->memberblocks)) {
+ insertpreheaderbefore(preheader, block28);
+
+ if (
+ (!block28->nextBlock || !bitvectorgetbit(block28->nextBlock->blockIndex, loop->memberblocks)) &&
+ block28->lastPCode &&
+ (block28->lastPCode->flags & fIsBranch) &&
+ block28->lastPCode->op != PC_BDNZ
+ ) {
+ i = block28->lastPCode->argCount;
+ arg = block28->lastPCode->args;
+ while (i && arg->kind != PCOp_LABEL) {
+ arg++;
+ i--;
+ }
+
+ if (i && arg->kind == PCOp_LABEL && arg->data.label.label->block == block28) {
+ block29 = makepreheaderblock();
+ insertpreheaderbefore(block29, block28);
+ newlabel = makepclabel();
+ pclabel(block29, newlabel);
+ arg->data.label.label = newlabel;
+
+ link = lalloc(sizeof(PCLink));
+ link->block = block28;
+ link->nextLink = block29->predecessors;
+ block29->predecessors = link;
+
+ link = lalloc(sizeof(PCLink));
+ link->block = block28;
+ link->nextLink = block29->successors;
+ block29->successors = link;
+
+ for (link = block28->successors; link; link = link->nextLink) {
+ if (link->block == block28)
+ link->block = block29;
+ }
+ for (link = block28->predecessors; link; link = link->nextLink) {
+ if (link->block == block28)
+ link->block = block29;
+ }
+
+ bitvectorsetbit(block29->blockIndex, loop->vec2C);
+ addblocktoloop(loop, block29);
+ }
+ }
+ } else {
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ if (bitvectorgetbit(block->blockIndex, loop->memberblocks))
+ break;
+ }
+ insertpreheaderbefore(preheader, block);
+ }
+
+ link = lalloc(sizeof(PCLink));
+ link->block = preheader;
+ link->nextLink = block28->predecessors;
+ block28->predecessors = link;
+
+ link = lalloc(sizeof(PCLink));
+ link->block = block28;
+ link->nextLink = preheader->successors;
+ preheader->successors = link;
+
+ for (loop = loop->parent; loop; loop = loop->parent) {
+ addblocktoloop(loop, preheader);
+ if (bitvectorgetbit(block28->blockIndex, loop->vec28)) {
+ bitvectorsetbit(preheader->blockIndex, loop->vec28);
+ if (block29)
+ bitvectorsetbit(block29->blockIndex, loop->vec28);
+ }
+ if (bitvectorgetbit(block28->blockIndex, loop->vec2C)) {
+ bitvectorsetbit(preheader->blockIndex, loop->vec2C);
+ if (block29)
+ bitvectorsetbit(block29->blockIndex, loop->vec2C);
+ }
+ }
+}
+
+static void insertpreheaderblocks(Loop *loop) {
+ while (loop) {
+ if (loop->children)
+ insertpreheaderblocks(loop->children);
+ insertpreheaderblock(loop);
+ loop = loop->nextSibling;
+ }
+}
+
+void findloopsinflowgraph(void) {
+ loopsinflowgraph = NULL;
+ computedominators();
+ if (findloopheaders()) {
+ findnaturalloops();
+ insertpreheaderblocks(loopsinflowgraph);
+ }
+ freeoheap();
+}
+
+static int checklooplimits(SInt32 opcode, SInt32 condition, SInt32 c, SInt32 d, SInt32 addend, SInt32 *result) {
+ if (opcode == PC_BT) {
+ if (condition == 0) {
+ if (addend <= 0)
+ return 0;
+ if (c < d)
+ *result = (d - c + addend - 1) / addend;
+ else
+ *result = 0;
+ } else if (condition == 1) {
+ if (addend >= 0)
+ return 0;
+ if (c > d)
+ *result = (c - d - addend - 1) / -addend;
+ else
+ *result = 0;
+ } else {
+ return 0;
+ }
+ } else {
+ if (condition == 0) {
+ if (addend >= 0)
+ return 0;
+ if (c >= d)
+ *result = (c - d - addend) / -addend;
+ else
+ *result = 0;
+ } else if (condition == 1) {
+ if (addend <= 0)
+ return 0;
+ if (c <= d)
+ *result = (d - c + addend) / addend;
+ else
+ *result = 0;
+ } else if (c < d) {
+ if (addend <= 0)
+ return 0;
+ if ((d - c) % addend)
+ return 0;
+ *result = (d - c) / addend;
+ } else if (c > d) {
+ if (addend >= 0)
+ return 0;
+ if ((c - d) % -addend)
+ return 0;
+ *result = (c - d) / -addend;
+ } else {
+ *result = 0;
+ }
+ }
+
+ return 1;
+}
+
+static int checkunsignedlooplimits(SInt32 opcode, SInt32 condition, UInt32 c, UInt32 d, SInt32 addend, UInt32 *result) {
+ if (opcode == PC_BT) {
+ if (condition == 0) {
+ if (addend <= 0)
+ return 0;
+ if (c < d)
+ *result = (d - c + addend - 1) / addend;
+ else
+ *result = 0;
+ } else if (condition == 1) {
+ if (addend >= 0)
+ return 0;
+ if (c > d)
+ *result = (c - d - addend - 1) / -addend;
+ else
+ *result = 0;
+ } else {
+ return 0;
+ }
+ } else {
+ if (condition == 0) {
+ if (addend >= 0)
+ return 0;
+ if (c >= d)
+ *result = (c - d - addend) / -addend;
+ else
+ *result = 0;
+ } else if (condition == 1) {
+ if (addend <= 0)
+ return 0;
+ if (c <= d)
+ *result = (d - c + addend) / addend;
+ else
+ *result = 0;
+ } else if (c < d) {
+ if (addend <= 0)
+ return 0;
+ if ((d - c) % addend)
+ return 0;
+ *result = (d - c) / addend;
+ } else if (c > d) {
+ if (addend >= 0)
+ return 0;
+ if ((c - d) % -addend)
+ return 0;
+ *result = (c - d) / -addend;
+ } else {
+ *result = 0;
+ }
+ }
+
+ return (*result & 0x80000000) == 0;
+}
+
+static int checkunknownloop(int a, int b, int c, unsigned char *op) {
+ if (a == PC_BT) {
+ if (b == 0) {
+ if (c <= 0)
+ return 0;
+ *op = ELESS;
+ } else if (b == 1) {
+ if (c >= 0)
+ return 0;
+ *op = EGREATER;
+ } else {
+ return 0;
+ }
+ } else {
+ if (b == 0) {
+ if (c >= 0)
+ return 0;
+ *op = EGREATEREQU;
+ } else if (b == 1) {
+ if (c <= 0)
+ return 0;
+ *op = ELESSEQU;
+ } else if (c == 1) {
+ *op = ENOTEQU;
+ } else if (c == -1) {
+ *op = ENOTEQU;
+ } else {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static void checkcountingloop(Loop *loop) {
+ RegUseOrDef *list;
+ PCode *lastpcode;
+ PCode *prevpcode;
+ PCode *pc8;
+ PCode *check;
+ short op12;
+ short reg11;
+ SInt16 reg4;
+ short reg11b;
+ Loop *child;
+
+ 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 (bitvectorgetbit(loop->body->nextBlock->blockIndex, loop->memberblocks))
+ return;
+
+ reg11 = lastpcode->args[0].data.reg.reg;
+ reg4 = lastpcode->args[1].data.imm.value;
+ prevpcode = lastpcode->prevPCode;
+ if (!prevpcode)
+ return;
+
+ op12 = prevpcode->op;
+ if (op12 == PC_ADDI && prevpcode->args[2].kind == PCOp_IMMEDIATE) {
+ pc8 = prevpcode;
+ prevpcode = prevpcode->prevPCode;
+ if (!prevpcode)
+ return;
+
+ op12 = prevpcode->op;
+ if (pc8->args[0].data.reg.reg != pc8->args[1].data.reg.reg)
+ return;
+ if (op12 != PC_CMP && op12 != PC_CMPL && op12 != PC_CMPI && op12 != PC_CMPLI)
+ return;
+ if (prevpcode->args[1].data.reg.reg != pc8->args[0].data.reg.reg)
+ return;
+ if ((loop->step = pc8->args[2].data.imm.value) == 0)
+ return;
+ }
+
+ if (op12 != PC_CMP && op12 != PC_CMPL && op12 != PC_CMPI && op12 != PC_CMPLI)
+ return;
+
+ if (prevpcode->args[0].data.reg.reg != reg11)
+ return;
+
+ reg11b = prevpcode->args[1].data.reg.reg;
+ if (reg11b < 32)
+ return;
+
+ if (loop->preheader->nextBlock != lastpcode->args[2].data.label.label->block)
+ return;
+
+ if (op12 == PC_CMPI) {
+ if (prevpcode->prevPCode)
+ return;
+ loop->upper = prevpcode->args[2].data.imm.value;
+ loop->upperType = LOOP_BOUND_CONSTANT;
+ } else if (op12 == PC_CMPLI) {
+ if (prevpcode->prevPCode)
+ return;
+ loop->upper = prevpcode->args[2].data.imm.value & 0xFFFF;
+ loop->upperType = LOOP_BOUND_CONSTANT;
+ } else if (op12 == PC_CMP || op12 == PC_CMPL) {
+ if (prevpcode->prevPCode) {
+ if (
+ prevpcode->prevPCode->op == PC_LI &&
+ prevpcode->prevPCode->args[1].kind == PCOp_IMMEDIATE &&
+ prevpcode->prevPCode->args[0].data.reg.reg == prevpcode->args[2].data.reg.reg &&
+ !prevpcode->prevPCode->prevPCode
+ ) {
+ loop->upper = prevpcode->prevPCode->args[1].data.imm.value;
+ loop->upperType = LOOP_BOUND_CONSTANT;
+ } else if (
+ prevpcode->prevPCode->op == PC_LIS &&
+ prevpcode->prevPCode->args[1].kind == PCOp_IMMEDIATE &&
+ prevpcode->prevPCode->args[0].data.reg.reg == prevpcode->args[2].data.reg.reg &&
+ !prevpcode->prevPCode->prevPCode
+ ) {
+ loop->upper = prevpcode->prevPCode->args[1].data.imm.value << 16;
+ loop->upperType = LOOP_BOUND_CONSTANT;
+ } else if (
+ prevpcode->prevPCode->op == PC_ADDI &&
+ prevpcode->prevPCode->args[2].kind == PCOp_IMMEDIATE &&
+ prevpcode->prevPCode->args[0].data.reg.reg == prevpcode->args[2].data.reg.reg &&
+ prevpcode->prevPCode->args[1].data.reg.reg == prevpcode->args[2].data.reg.reg &&
+ prevpcode->prevPCode->prevPCode &&
+ prevpcode->prevPCode->prevPCode->op == PC_LIS &&
+ prevpcode->prevPCode->prevPCode->args[1].kind == PCOp_IMMEDIATE &&
+ prevpcode->prevPCode->prevPCode->args[0].data.reg.reg == prevpcode->args[2].data.reg.reg &&
+ !prevpcode->prevPCode->prevPCode->prevPCode
+ ) {
+ loop->upper = prevpcode->prevPCode->args[2].data.imm.value +
+ (prevpcode->prevPCode->prevPCode->args[1].data.imm.value << 16);
+ loop->upperType = LOOP_BOUND_CONSTANT;
+ } else {
+ return;
+ }
+ } else {
+ pc8 = NULL;
+ for (list = reg_Defs[RegClass_GPR][prevpcode->args[2].data.reg.reg]; list; list = list->next) {
+ if (bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks))
+ return;
+ }
+ for (list = reg_Defs[RegClass_GPR][prevpcode->args[2].data.reg.reg]; list; list = list->next) {
+ if (bitvectorgetbit(list->id, usedefinfo[loop->preheader->blockIndex].defvec8)) {
+ if (!pc8) {
+ pc8 = Defs[list->id].pcode;
+ if (
+ pc8->op == PC_LI &&
+ pc8->args[1].kind == PCOp_IMMEDIATE
+ ) {
+ loop->upper = pc8->args[1].data.imm.value;
+ loop->upperType = LOOP_BOUND_CONSTANT;
+ } else if (
+ pc8->op == PC_LIS &&
+ pc8->args[1].kind == PCOp_IMMEDIATE
+ ) {
+ loop->upper = pc8->args[1].data.imm.value << 16;
+ loop->upperType = LOOP_BOUND_CONSTANT;
+ } else if (
+ pc8->op == PC_ADDI &&
+ pc8->args[2].kind == PCOp_IMMEDIATE &&
+ pc8->args[1].data.reg.reg == prevpcode->args[2].data.reg.reg &&
+ pc8->prevPCode &&
+ pc8->prevPCode->op == PC_LIS &&
+ pc8->prevPCode->args[1].kind == PCOp_IMMEDIATE &&
+ pc8->prevPCode->args[0].data.reg.reg == prevpcode->args[2].data.reg.reg
+ ) {
+ loop->upper = pc8->args[2].data.imm.value +
+ (pc8->prevPCode->args[1].data.imm.value << 16);
+ loop->upperType = LOOP_BOUND_CONSTANT;
+ } else {
+ loop->upperType = LOOP_BOUND_VARIABLE;
+ break;
+ }
+ } else {
+ loop->upperType = LOOP_BOUND_VARIABLE;
+ break;
+ }
+ }
+ }
+
+ if (loop->upperType == LOOP_BOUND_INDETERMINATE)
+ loop->upperType = LOOP_BOUND_VARIABLE;
+ }
+ }
+
+ pc8 = NULL;
+
+ for (list = reg_Defs[RegClass_GPR][reg11b]; list; list = list->next) {
+ check = Defs[list->id].pcode;
+ if (bitvectorgetbit(check->block->blockIndex, loop->memberblocks)) {
+ if (!pc8) {
+ pc8 = check;
+ if (check->op != PC_ADDI)
+ return;
+ if (check->args[1].data.reg.reg != reg11b)
+ return;
+ if (check->args[2].kind != PCOp_IMMEDIATE)
+ return;
+ if ((loop->step = check->args[2].data.imm.value) == 0)
+ return;
+ } else {
+ return;
+ }
+ }
+ }
+
+ if (!pc8)
+ return;
+
+ if (pc8->block != prevpcode->block && !bitvectorgetbit(prevpcode->block->blockIndex, loop->vec2C))
+ return;
+
+ if (loop->children) {
+ for (child = loop->children; child; child = child->nextSibling) {
+ if (bitvectorgetbit(pc8->block->blockIndex, child->memberblocks))
+ return;
+ }
+ }
+
+ loop->pc18 = pc8;
+
+ pc8 = NULL;
+
+ for (list = reg_Defs[RegClass_GPR][reg11b]; list; list = list->next) {
+ if (bitvectorgetbit(list->id, usedefinfo[loop->preheader->blockIndex].defvec8)) {
+ if (!pc8) {
+ pc8 = Defs[list->id].pcode;
+ if (
+ pc8->op == PC_LI &&
+ pc8->args[1].kind == PCOp_IMMEDIATE
+ ) {
+ loop->lower = pc8->args[1].data.imm.value;
+ loop->lowerType = LOOP_BOUND_CONSTANT;
+ } else if (
+ pc8->op == PC_LIS &&
+ pc8->args[1].kind == PCOp_IMMEDIATE
+ ) {
+ loop->lower = pc8->args[1].data.imm.value << 16;
+ loop->lowerType = LOOP_BOUND_CONSTANT;
+ } else if (
+ pc8->op == PC_ADDI &&
+ pc8->args[2].kind == PCOp_IMMEDIATE &&
+ pc8->args[1].data.reg.reg == reg11b &&
+ pc8->prevPCode &&
+ pc8->prevPCode->op == PC_LIS &&
+ pc8->prevPCode->args[1].kind == PCOp_IMMEDIATE &&
+ pc8->prevPCode->args[0].data.reg.reg == reg11b
+ ) {
+ loop->lower = pc8->args[2].data.imm.value +
+ (pc8->prevPCode->args[1].data.imm.value << 16);
+ loop->lowerType = LOOP_BOUND_CONSTANT;
+ } else {
+ loop->lowerType = LOOP_BOUND_VARIABLE;
+ break;
+ }
+ } else {
+ loop->lowerType = LOOP_BOUND_INDETERMINATE;
+ break;
+ }
+ }
+ }
+
+ if (loop->lowerType == LOOP_BOUND_INDETERMINATE)
+ loop->lowerType = LOOP_BOUND_VARIABLE;
+
+ if (loop->lowerType == LOOP_BOUND_CONSTANT && loop->upperType == LOOP_BOUND_CONSTANT) {
+ if (op12 == PC_CMP || op12 == PC_CMPI) {
+ if (!checklooplimits(lastpcode->op, reg4, loop->lower, loop->upper, loop->step, &loop->iterationCount))
+ return;
+ } else {
+ if (!checkunsignedlooplimits(lastpcode->op, reg4, loop->lower, loop->upper, loop->step, (UInt32 *) &loop->iterationCount))
+ return;
+ }
+ loop->isKnownCountingLoop = 1;
+ } else if (loop->lowerType != LOOP_BOUND_INDETERMINATE || loop->upperType != LOOP_BOUND_INDETERMINATE) {
+ if (!checkunknownloop(lastpcode->op, reg4, loop->step, &loop->unknownCondition))
+ return;
+ loop->isUnknownCountingLoop = 1;
+ }
+}
+
+void analyzeForCountableLoops(Loop *loop) {
+ if (!loop)
+ return;
+
+ while (loop) {
+ if (loop->children)
+ analyzeForCountableLoops(loop->children);
+ checkcountingloop(loop);
+ loop = loop->nextSibling;
+ }
+}
+
+void analyzeloop(Loop *loop) {
+ BlockList *list;
+ PCodeBlock *block;
+ PCode *pcode;
+
+ loop->bodySize = 0;
+ loop->x4D = 0;
+ loop->x4E = 0;
+ loop->x4F = 1;
+ loop->isKnownCountingLoop = 0;
+ loop->isUnknownCountingLoop = 0;
+ loop->lowerType = LOOP_BOUND_INDETERMINATE;
+ loop->upperType = LOOP_BOUND_INDETERMINATE;
+ loop->iterationCount = -1;
+ loop->x57 = 0;
+ loop->x52 = 0;
+
+ for (list = loop->blocks; list; list = list->next) {
+ block = list->block;
+ if (!loop->children)
+ block->flags |= fPCBlockFlag2000;
+ loop->bodySize += block->pcodeCount;
+
+ if (block != loop->body) {
+ if (!block->successors || !block->predecessors || block->successors->nextLink || block->predecessors->nextLink)
+ loop->x4F = 0;
+ }
+
+ if ((block->flags & fPCBlockFlag4000) == fPCBlockFlag4000)
+ loop->x52 = 1;
+
+ for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) {
+ if (PCODE_FLAG_SET_T(pcode) & fLink)
+ loop->x4D = 1;
+
+ if (pcode->op == PC_BCTRL || pcode->op == PC_BCTR || pcode->op == PC_BCCTR || pcode->op == PC_MTCTR || pcode->op == PC_MFCTR) {
+ loop->x4E = 1;
+ } else if (pcode->flags & fIsRead) {
+ if (pcode->op == PC_LBZX || pcode->op == PC_LHZX || pcode->op == PC_LHAX || pcode->op == PC_LWZX || pcode->op == PC_LFSX || pcode->op == PC_LFDX)
+ loop->x53 = 1;
+ } else if (pcode->flags & fIsWrite) {
+ if (pcode->op == PC_STBX || pcode->op == PC_STHX || pcode->op == PC_STWX || pcode->op == PC_STFSX || pcode->op == PC_STFDX)
+ loop->x54 = 1;
+ } else {
+ if (pcode->op == PC_EIEIO || pcode->op == PC_SYNC || pcode->op == PC_ISYNC)
+ loop->x57 = 1;
+ }
+ }
+ }
+
+ if (!loop->children && !loop->x4D && loop->bodySize < 32) {
+ for (list = loop->blocks; list; list = list->next)
+ list->block->flags |= fPCBlockFlag2000;
+ }
+}
+
+static void analyzeloops(Loop *loop) {
+ while (loop) {
+ if (loop->children)
+ analyzeloops(loop->children);
+ analyzeloop(loop);
+ loop = loop->nextSibling;
+ }
+}
+
+void analyzeloopsinflowgraph(void) {
+ if (loopsinflowgraph)
+ analyzeloops(loopsinflowgraph);
+}