MWCC/compiler_and_linker/unsorted/CodeMotion.c

907 lines
30 KiB
C

#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();
}