MWCC/compiler_and_linker/unsorted/CopyPropagation.c

472 lines
16 KiB
C

#include "compiler/CopyPropagation.h"
#include "compiler/CMangler.h"
#include "compiler/CParser.h"
#include "compiler/BitVectors.h"
#include "compiler/CompilerTools.h"
#include "compiler/PCode.h"
#include "compiler/PCodeListing.h"
#include "compiler/RegisterInfo.h"
#include "compiler/UseDefChains.h"
int propagatedcopies;
int propagated_instructions;
int recursive_propagation;
int number_of_candidates;
Candidate *Candidates;
PropInfo *propinfo;
int *ncandidatesinblock;
int *firstcandidateinblock;
static int moreaggressiveoptimization;
static PropagateAndFinishFunc propagateandfinish;
static PropagatesToUseFunc propagatestouse;
static IsCandidateFunc is_candidate;
static void precomputecanidatecounts(void) {
PCodeBlock *block;
PCode *pcode;
int count;
ncandidatesinblock = oalloc(sizeof(int) * pcblockcount);
firstcandidateinblock = oalloc(sizeof(int) * pcblockcount);
number_of_candidates = 0;
for (block = pcbasicblocks; block; block = block->nextBlock) {
firstcandidateinblock[block->blockIndex] = number_of_candidates;
count = 0;
for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) {
if (is_candidate(pcode)) {
number_of_candidates++;
count++;
}
}
ncandidatesinblock[block->blockIndex] = count;
}
}
static void computecandidatelist(void) {
RegUseOrDef *list; // r23
PCodeBlock *block; // r22
PCode *pcode; // r21
Candidate *candidate; // r20
UInt32 *vec; // r19
int reg;
RegUseOrDef *newlist;
UseOrDef *def;
UseOrDef *use;
int defID;
int useID;
Candidates = oalloc(sizeof(Candidate) * number_of_candidates);
vec = oalloc(4 * ((number_of_Uses + 31) >> 5));
for (block = pcbasicblocks; block; block = block->nextBlock) {
if (ncandidatesinblock[block->blockIndex]) {
bitvectorcopy(vec, usedefinfo[block->blockIndex].usevec1C, number_of_Uses);
candidate = &Candidates[firstcandidateinblock[block->blockIndex] + ncandidatesinblock[block->blockIndex] - 1];
for (pcode = block->lastPCode; pcode; pcode = pcode->prevPCode) {
if (!(pcode->flags & fIsBranch) && pcode->argCount) {
if (is_candidate(pcode)) {
reg = pcode->args[0].data.reg.reg;
candidate->pcode = pcode;
candidate->list = NULL;
for (list = reg_Uses[pcode->args[0].arg][reg]; list; list = list->next) {
if (bitvectorgetbit(list->id, vec)) {
newlist = oalloc(sizeof(RegUseOrDef));
newlist->id = list->id;
newlist->next = candidate->list;
candidate->list = newlist;
}
}
if ((pcode->flags & fIsRead | fIsWrite) && (pcode->flags & fUpdatesPtr)) {
for (list = reg_Uses[pcode->args[1].arg][pcode->args[1].data.reg.reg]; list; list = list->next) {
if (bitvectorgetbit(list->id, vec)) {
newlist = oalloc(sizeof(RegUseOrDef));
newlist->id = list->id;
newlist->next = candidate->list;
candidate->list = newlist;
}
}
}
candidate--;
}
for (def = &Defs[defID = pcode->defID]; defID < number_of_Defs && def->pcode == pcode; def++, defID++) {
if (def->v.kind == PCOp_REGISTER) {
for (list = reg_Uses[def->v.arg][def->v.u.reg]; list; list = list->next)
bitvectorclearbit(list->id, vec);
}
}
for (use = &Uses[useID = pcode->useID]; useID < number_of_Uses && use->pcode == pcode; use++, useID++) {
if (use->v.kind == PCOp_REGISTER)
bitvectorsetbit(useID, vec);
}
}
}
}
}
}
static void allocatepropinfo(void) {
PropInfo *info;
int i;
propinfo = oalloc(sizeof(PropInfo) * pcblockcount);
for (i = 0, info = propinfo; i < pcblockcount; i++, info++) {
info->vec0 = oalloc(4 * ((number_of_candidates + 31) >> 5));
info->vec4 = oalloc(4 * ((number_of_candidates + 31) >> 5));
info->vec8 = oalloc(4 * ((number_of_candidates + 31) >> 5));
info->vecC = oalloc(4 * ((number_of_candidates + 31) >> 5));
}
}
static void computelocalpropinfo(Boolean flag) {
PropInfo *info;
PCode *pcode;
PCodeBlock *block;
UInt32 *vec0;
UInt32 *vec4;
int index;
PCodeArg *op;
PCodeArg *candOp;
int i;
int j;
int cndi;
Candidate *candidate;
for (block = pcbasicblocks; block; block = block->nextBlock) {
info = &propinfo[block->blockIndex];
vec0 = info->vec0;
vec4 = info->vec4;
bitvectorinitialize(vec0, number_of_candidates, 0);
bitvectorinitialize(vec4, number_of_candidates, 0);
index = firstcandidateinblock[block->blockIndex];
if (flag) {
for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) {
if (!(pcode->flags & fIsBranch) && pcode->argCount) {
i = pcode->argCount;
op = pcode->args;
while (i--) {
if (op->kind == PCOp_REGISTER && op->arg == RegClass_GPR && (op->data.reg.effect & EffectWrite)) {
for (cndi = 0, candidate = Candidates; cndi < number_of_candidates; cndi++, candidate++) {
for (j = 0; j < candidate->pcode->argCount; j++) {
candOp = candidate->pcode->args + j;
if (candOp->kind == PCOp_REGISTER && candOp->arg == RegClass_GPR && candOp->data.reg.reg == op->data.reg.reg) {
if (candidate->pcode->block == block)
bitvectorclearbit(cndi, vec0);
else
bitvectorsetbit(cndi, vec4);
break;
}
}
}
}
op++;
}
if (is_candidate(pcode)) {
bitvectorsetbit(index, vec0);
index++;
}
}
}
} else {
for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) {
if (!(pcode->flags & fIsBranch) && pcode->argCount) {
i = pcode->argCount;
op = pcode->args;
while (i--) {
if (op->kind == PCOp_REGISTER && (op->data.reg.effect & EffectWrite)) {
for (cndi = 0, candidate = Candidates; cndi < number_of_candidates; cndi++, candidate++) {
for (j = 0; j < candidate->pcode->argCount; j++) {
candOp = candidate->pcode->args + j;
if (candOp->kind == PCOp_REGISTER && candOp->arg == op->arg) {
if (candOp->data.reg.reg == op->data.reg.reg) {
if (candidate->pcode->block == block)
bitvectorclearbit(cndi, vec0);
else
bitvectorsetbit(cndi, vec4);
break;
}
} else {
if (j == 0)
break;
}
}
}
}
op++;
}
if (is_candidate(pcode)) {
bitvectorsetbit(index, vec0);
index++;
}
}
}
}
}
}
static void computeglobalpropinfo(void) {
PropInfo *info;
PCodeBlock *block;
int bitvecsize;
UInt32 *vec0;
UInt32 *vec4;
UInt32 *vec8;
UInt32 *vecC;
int i;
int blockIndex;
int flag;
PCLink *preds;
UInt32 val;
bitvecsize = (number_of_candidates + 31) >> 5;
flag = 1;
info = &propinfo[pcbasicblocks->blockIndex];
bitvectorinitialize(info->vec8, number_of_candidates, 0);
bitvectorcopy(info->vecC, info->vec0, number_of_candidates);
for (block = pcbasicblocks->nextBlock; block; block = block->nextBlock) {
info = &propinfo[block->blockIndex];
vecC = info->vecC;
vec4 = info->vec4;
for (i = 0; i < bitvecsize; vecC++, vec4++, i++)
*vecC = ~*vec4;
}
while (flag) {
flag = 0;
for (blockIndex = 0; blockIndex < pcblockcount; blockIndex++) {
if (depthfirstordering[blockIndex]) {
info = &propinfo[depthfirstordering[blockIndex]->blockIndex];
if ((preds = depthfirstordering[blockIndex]->predecessors)) {
vec8 = info->vec8;
bitvectorcopy(vec8, propinfo[preds->block->blockIndex].vecC, number_of_candidates);
for (preds = preds->nextLink; preds; preds = preds->nextLink)
bitvectorintersect(vec8, propinfo[preds->block->blockIndex].vecC, number_of_candidates);
}
vecC = info->vecC;
vec8 = info->vec8;
vec0 = info->vec0;
vec4 = info->vec4;
for (i = 0; i < bitvecsize; i++) {
val = *vec0 | (*vec8 & ~*vec4);
if (val != *vecC) {
*vecC = val;
flag = 1;
}
vec8++;
vecC++;
vec4++;
vec0++;
}
}
}
}
}
int precedes(PCode *a, PCode *b) {
PCode *scan;
for (scan = a->nextPCode; scan; scan = scan->nextPCode) {
if (scan == b)
return 1;
}
return 0;
}
static int canidatepropagatestoalluses(int id) {
RegUseOrDef *list;
if (PCODE_FLAG_SET_F(Candidates[id].pcode) & (fRecordBit | fSideEffects))
return 0;
for (list = Candidates[id].list; list; list = list->next) {
if (!propagatestouse(id, list->id))
return 0;
}
return 1;
}
static void propagatecandidates(void) {
int i;
for (i = 0; i < number_of_candidates; i++) {
if (canidatepropagatestoalluses(i))
propagateandfinish(i);
}
}
void propagateinstructions(Object *proc, Propagation *config, int passCount, Boolean localflag) {
char buf[64];
is_candidate = config->is_candidate;
propagatestouse = config->propagatestouse;
propagateandfinish = config->propagateandfinish;
propagated_instructions = 0;
while (1) {
recursive_propagation = 0;
precomputecanidatecounts();
if (number_of_candidates <= 0) {
freeoheap();
if (config->computesUseDefChains)
computeusedefchains(0);
return;
}
computeusedefchains(0);
computecandidatelist();
allocatepropinfo();
computelocalpropinfo(localflag);
computedepthfirstordering();
computeglobalpropinfo();
propagatecandidates();
passCount--;
if (propagated_instructions && copts.debuglisting) {
sprintf(buf, "AFTER %s PROPAGATION", config->name);
pclistblocks(CMangler_GetLinkName(proc)->name, buf);
}
if (!passCount || !recursive_propagation) {
if (!config->computesUseDefChains)
freeoheap();
return;
}
freeoheap();
}
}
static int is_copy(PCode *pcode) {
return (pcode->flags & fIsMove) && (pcode->args[0].data.reg.reg >= n_real_registers[pcode->args[0].arg]);
}
static int copypropagatestouse(int candidateID, int useID) {
UseOrDef *use;
short reg1;
short reg2;
RegClass rclass;
PCode *pcode;
int i;
PCode *scan;
PCodeArg *op;
pcode = Candidates[candidateID].pcode;
use = Uses + useID;
rclass = pcode->args[0].arg;
reg1 = pcode->args[0].data.reg.reg;
reg2 = pcode->args[1].data.reg.reg;
if (use->pcode->flags & fIsMove)
return 0;
if (rclass == RegClass_GPR && use->pcode->op == PC_RLWIMI && use->pcode->args[0].data.reg.reg == reg1)
return 0;
if (pcode->block == use->pcode->block && precedes(pcode, use->pcode)) {
for (scan = pcode->nextPCode; scan && scan != use->pcode; scan = scan->nextPCode) {
op = scan->args;
i = scan->argCount;
while (i--) {
if (
op->kind == PCOp_REGISTER &&
op->arg == rclass &&
(op->data.reg.effect & EffectWrite) &&
op->data.reg.reg == reg2
)
return 0;
op++;
}
}
} else {
if (!bitvectorgetbit(candidateID, propinfo[use->pcode->block->blockIndex].vec8))
return 0;
for (scan = use->pcode->block->firstPCode; scan; scan = scan->nextPCode) {
op = scan->args;
i = scan->argCount;
while (i--) {
if (
op->kind == PCOp_REGISTER &&
op->arg == rclass &&
(op->data.reg.effect & EffectWrite) &&
op->data.reg.reg == reg2
)
return 0;
op++;
}
if (scan == use->pcode)
break;
}
}
return 1;
}
static void propagateandremovecopy(int id) {
Candidate *candidate;
RegClass rclass;
short reg1;
short reg2;
RegUseOrDef *list;
int i;
PCodeArg *op;
candidate = &Candidates[id];
rclass = candidate->pcode->args[0].arg;
reg1 = candidate->pcode->args[0].data.reg.reg;
reg2 = candidate->pcode->args[1].data.reg.reg;
if (rclass == RegClass_GPR && reg1 >= 32 && reg1 <= last_exception_register[RegClass_GPR])
return;
if (!moreaggressiveoptimization && reg2 < n_real_registers[rclass])
return;
for (list = candidate->list; list; list = list->next) {
op = Uses[list->id].pcode->args;
i = Uses[list->id].pcode->argCount;
while (i--) {
if (
op->kind == PCOp_REGISTER &&
op->arg == rclass &&
op->data.reg.reg == reg1 &&
(op->data.reg.effect & EffectRead)
)
op->data.reg.reg = reg2;
op++;
}
}
deletepcode(candidate->pcode);
propagated_instructions = 1;
}
static Propagation copy_prop = {
&is_copy,
&copypropagatestouse,
&propagateandremovecopy,
"COPY",
"COPIES",
"c%ld",
0
};
void propagatecopyinstructions(Object *proc, int flag) {
moreaggressiveoptimization = flag;
propagateinstructions(proc, &copy_prop, 1, 0);
propagatedcopies = propagated_instructions;
}