mirror of https://git.wuffs.org/MWCC
565 lines
22 KiB
C
565 lines
22 KiB
C
#include "compiler/UseDefChains.h"
|
|
#include "compiler/Alias.h"
|
|
#include "compiler/BitVectors.h"
|
|
#include "compiler/CompilerTools.h"
|
|
#include "compiler/PCode.h"
|
|
#include "compiler/Registers.h"
|
|
#include "compiler/objects.h"
|
|
#include "compiler/types.h"
|
|
|
|
int number_of_Defs;
|
|
UseOrDef *Defs;
|
|
RegUseOrDef **reg_Defs[RegClassMax];
|
|
int number_of_Uses;
|
|
UseOrDef *Uses;
|
|
RegUseOrDef **reg_Uses[RegClassMax];
|
|
UseDefInfo *usedefinfo;
|
|
ObjectUseDef *objectusedefs;
|
|
ObjectUseDef *objectusedeflist;
|
|
|
|
ObjectUseDef *findobjectusedef(Object *object) {
|
|
ObjectUseDef *oud;
|
|
|
|
oud = objectusedefs;
|
|
while (oud) {
|
|
if (((unsigned long) object) < ((unsigned long) oud->object))
|
|
oud = oud->leftchild;
|
|
else if (((unsigned long) object) > ((unsigned long) oud->object))
|
|
oud = oud->rightchild;
|
|
else
|
|
return oud;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static void addobjectusedef(Object *object) {
|
|
ObjectUseDef **ptr;
|
|
ObjectUseDef *list;
|
|
|
|
ptr = &objectusedefs;
|
|
while (*ptr) {
|
|
if (((unsigned long) object) < ((unsigned long) (*ptr)->object))
|
|
ptr = &(*ptr)->leftchild;
|
|
else if (((unsigned long) object) > ((unsigned long) (*ptr)->object))
|
|
ptr = &(*ptr)->rightchild;
|
|
else
|
|
return;
|
|
}
|
|
|
|
list = oalloc(sizeof(ObjectUseDef));
|
|
list->leftchild = list->rightchild = NULL;
|
|
list->object = object;
|
|
list->uses = list->defs = NULL;
|
|
list->next = objectusedeflist;
|
|
objectusedeflist = list;
|
|
*ptr = list;
|
|
}
|
|
|
|
static void addaliasusedef(Alias *alias) {
|
|
AliasMember *member;
|
|
|
|
if (alias && alias != worst_case) {
|
|
if (alias->type == AliasType2) {
|
|
for (member = alias->parents; member; member = member->nextParent)
|
|
addaliasusedef(member->child);
|
|
} else {
|
|
addobjectusedef(alias->object);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void addworstcase(void) {
|
|
addobjectusedef(&worst_case_obj);
|
|
}
|
|
|
|
static void precomputememoryusedefs(void) {
|
|
PCodeBlock *block;
|
|
PCode *pcode;
|
|
|
|
objectusedeflist = NULL;
|
|
objectusedefs = NULL;
|
|
|
|
for (block = pcbasicblocks; block; block = block->nextBlock) {
|
|
for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) {
|
|
if (pcode->flags & (fIsRead | fIsWrite)) {
|
|
if (pcode->alias) {
|
|
if (pcode->alias->type == AliasType2 || pcode->alias->size != nbytes_loaded_or_stored_by(pcode))
|
|
pcode->flags |= fIsPtrOp;
|
|
addaliasusedef(pcode->alias);
|
|
} else {
|
|
pcode->flags |= fIsPtrOp;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
addworstcase();
|
|
}
|
|
|
|
static void precomputeusedefcounts(int flag) {
|
|
PCodeBlock *block;
|
|
PCode *pcode;
|
|
PCodeArg *op;
|
|
int i;
|
|
ObjectUseDef *oud;
|
|
|
|
number_of_Defs = 0;
|
|
number_of_Uses = 0;
|
|
|
|
for (block = pcbasicblocks; block; block = block->nextBlock) {
|
|
for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) {
|
|
if (!(pcode->flags & fIsBranch) && pcode->argCount) {
|
|
pcode->useID = number_of_Uses;
|
|
pcode->defID = number_of_Defs;
|
|
op = pcode->args;
|
|
i = pcode->argCount;
|
|
while (i--) {
|
|
if (op->kind == PCOp_REGISTER && op->data.reg.reg >= n_real_registers[op->arg]) {
|
|
if (op->data.reg.effect & EffectRead)
|
|
number_of_Uses++;
|
|
if (op->data.reg.effect & EffectWrite)
|
|
number_of_Defs++;
|
|
}
|
|
op++;
|
|
}
|
|
|
|
if (flag) {
|
|
if (pcode->flags & fIsRead) {
|
|
if (pcode->flags & fIsPtrOp) {
|
|
for (oud = objectusedeflist; oud; oud = oud->next) {
|
|
if (may_alias_object(pcode, oud->object))
|
|
number_of_Uses++;
|
|
}
|
|
} else {
|
|
number_of_Uses++;
|
|
}
|
|
} else if (pcode->flags & fIsWrite) {
|
|
if (pcode->flags & fIsPtrOp) {
|
|
for (oud = objectusedeflist; oud; oud = oud->next) {
|
|
if (may_alias_object(pcode, oud->object))
|
|
number_of_Defs++;
|
|
}
|
|
} else {
|
|
number_of_Defs++;
|
|
}
|
|
} else if (pcode->flags & fIsCall) {
|
|
for (oud = objectusedeflist; oud; oud = oud->next) {
|
|
if (
|
|
oud->object->datatype == DDATA ||
|
|
oud->object->datatype == DNONLAZYPTR ||
|
|
(oud->object->datatype == DLOCAL && (
|
|
oud->object->u.var.info->noregister ||
|
|
IS_TYPE_ARRAY(oud->object->type) ||
|
|
IS_TYPE_NONVECTOR_STRUCT(oud->object->type) ||
|
|
IS_TYPE_CLASS(oud->object->type) ||
|
|
IS_TYPE_12BYTES_MEMBERPOINTER(oud->object->type)
|
|
))
|
|
) {
|
|
number_of_Uses++;
|
|
number_of_Defs++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void computeusedeflists(int flag) {
|
|
ObjectUseDef *oud;
|
|
RegUseOrDef *list;
|
|
PCodeBlock *block;
|
|
PCode *pcode;
|
|
PCodeArg *op;
|
|
int i;
|
|
UseOrDef *use;
|
|
UseOrDef *def;
|
|
int useID;
|
|
int defID;
|
|
ObjectUseDef *tmp;
|
|
Object *object;
|
|
|
|
Uses = oalloc(sizeof(UseOrDef) * number_of_Uses);
|
|
Defs = oalloc(sizeof(UseOrDef) * number_of_Defs);
|
|
|
|
reg_Uses[RegClass_GPR] = oalloc(sizeof(RegUseOrDef *) * used_virtual_registers[RegClass_GPR]);
|
|
reg_Defs[RegClass_GPR] = oalloc(sizeof(RegUseOrDef *) * used_virtual_registers[RegClass_GPR]);
|
|
for (i = 0; i < used_virtual_registers[RegClass_GPR]; i++) {
|
|
reg_Uses[RegClass_GPR][i] = NULL;
|
|
reg_Defs[RegClass_GPR][i] = NULL;
|
|
}
|
|
|
|
reg_Uses[RegClass_FPR] = oalloc(sizeof(RegUseOrDef *) * used_virtual_registers[RegClass_FPR]);
|
|
reg_Defs[RegClass_FPR] = oalloc(sizeof(RegUseOrDef *) * used_virtual_registers[RegClass_FPR]);
|
|
for (i = 0; i < used_virtual_registers[RegClass_FPR]; i++) {
|
|
reg_Uses[RegClass_FPR][i] = NULL;
|
|
reg_Defs[RegClass_FPR][i] = NULL;
|
|
}
|
|
|
|
reg_Uses[RegClass_VR] = oalloc(sizeof(RegUseOrDef *) * used_virtual_registers[RegClass_VR]);
|
|
reg_Defs[RegClass_VR] = oalloc(sizeof(RegUseOrDef *) * used_virtual_registers[RegClass_VR]);
|
|
for (i = 0; i < used_virtual_registers[RegClass_VR]; i++) {
|
|
reg_Uses[RegClass_VR][i] = NULL;
|
|
reg_Defs[RegClass_VR][i] = NULL;
|
|
}
|
|
|
|
for (block = pcbasicblocks; block; block = block->nextBlock) {
|
|
for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) {
|
|
if (!(pcode->flags & fIsBranch) && pcode->argCount) {
|
|
use = &Uses[useID = pcode->useID];
|
|
def = &Defs[defID = pcode->defID];
|
|
|
|
op = pcode->args;
|
|
i = pcode->argCount;
|
|
while (i--) {
|
|
if (op->kind == PCOp_REGISTER && op->data.reg.reg >= n_real_registers[op->arg]) {
|
|
if (op->data.reg.effect & EffectRead) {
|
|
use->pcode = pcode;
|
|
use->v.kind = op->kind;
|
|
use->v.arg = op->arg;
|
|
use->v.u.reg = op->data.reg.reg;
|
|
list = oalloc(sizeof(RegUseOrDef));
|
|
list->id = useID;
|
|
list->next = reg_Uses[op->arg][op->data.reg.reg];
|
|
reg_Uses[op->arg][op->data.reg.reg] = list;
|
|
use++;
|
|
useID++;
|
|
}
|
|
if (op->data.reg.effect & EffectWrite) {
|
|
def->pcode = pcode;
|
|
def->v.kind = op->kind;
|
|
def->v.arg = op->arg;
|
|
def->v.u.reg = op->data.reg.reg;
|
|
list = oalloc(sizeof(RegUseOrDef));
|
|
list->id = defID;
|
|
list->next = reg_Defs[op->arg][op->data.reg.reg];
|
|
reg_Defs[op->arg][op->data.reg.reg] = list;
|
|
def++;
|
|
defID++;
|
|
}
|
|
}
|
|
op++;
|
|
}
|
|
|
|
if (flag) {
|
|
if (pcode->flags & fIsRead) {
|
|
if (pcode->flags & fIsPtrOp) {
|
|
for (oud = objectusedeflist; oud; oud = oud->next) {
|
|
if (may_alias_object(pcode, object = oud->object)) {
|
|
use->pcode = pcode;
|
|
use->v.kind = PCOp_MEMORY;
|
|
use->v.arg = 1;
|
|
use->v.u.object = object;
|
|
list = oalloc(sizeof(RegUseOrDef));
|
|
list->id = useID;
|
|
list->next = oud->uses;
|
|
oud->uses = list;
|
|
use++;
|
|
useID++;
|
|
}
|
|
}
|
|
} else {
|
|
object = pcode->alias->object;
|
|
use->pcode = pcode;
|
|
use->v.kind = PCOp_MEMORY;
|
|
use->v.arg = 0;
|
|
use->v.u.object = object;
|
|
list = oalloc(sizeof(RegUseOrDef));
|
|
list->id = useID;
|
|
tmp = findobjectusedef(object);
|
|
list->next = tmp->uses;
|
|
tmp->uses = list;
|
|
}
|
|
} else if (pcode->flags & fIsWrite) {
|
|
if (pcode->flags & fIsPtrOp) {
|
|
for (oud = objectusedeflist; oud; oud = oud->next) {
|
|
if (may_alias_object(pcode, object = oud->object)) {
|
|
def->pcode = pcode;
|
|
def->v.kind = PCOp_MEMORY;
|
|
def->v.arg = 1;
|
|
def->v.u.object = object;
|
|
list = oalloc(sizeof(RegUseOrDef));
|
|
list->id = defID;
|
|
list->next = oud->defs;
|
|
oud->defs = list;
|
|
def++;
|
|
defID++;
|
|
}
|
|
}
|
|
} else {
|
|
object = pcode->alias->object;
|
|
def->pcode = pcode;
|
|
def->v.kind = PCOp_MEMORY;
|
|
def->v.arg = 0;
|
|
def->v.u.object = object;
|
|
list = oalloc(sizeof(RegUseOrDef));
|
|
list->id = useID;
|
|
tmp = findobjectusedef(object);
|
|
list->next = tmp->defs;
|
|
tmp->defs = list;
|
|
}
|
|
} else if (pcode->flags & fIsCall) {
|
|
for (oud = objectusedeflist; oud; oud = oud->next) {
|
|
object = oud->object;
|
|
if (
|
|
object->datatype == DDATA ||
|
|
object->datatype == DNONLAZYPTR ||
|
|
(object->datatype == DLOCAL && (
|
|
object->u.var.info->noregister ||
|
|
IS_TYPE_ARRAY(object->type) ||
|
|
IS_TYPE_NONVECTOR_STRUCT(object->type) ||
|
|
IS_TYPE_CLASS(oud->object->type) ||
|
|
IS_TYPE_12BYTES_MEMBERPOINTER(object->type)
|
|
))
|
|
) {
|
|
use->pcode = pcode;
|
|
use->v.kind = PCOp_MEMORY;
|
|
use->v.arg = 1;
|
|
use->v.u.object = object;
|
|
|
|
list = oalloc(sizeof(RegUseOrDef));
|
|
list->id = useID;
|
|
list->next = oud->uses;
|
|
oud->uses = list;
|
|
|
|
def->pcode = pcode;
|
|
def->v.kind = PCOp_MEMORY;
|
|
def->v.arg = 1;
|
|
def->v.u.object = object;
|
|
|
|
use++;
|
|
useID++;
|
|
|
|
list = oalloc(sizeof(RegUseOrDef));
|
|
list->id = defID;
|
|
list->next = oud->defs;
|
|
oud->defs = list;
|
|
|
|
def++;
|
|
defID++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void allocateusedefinfo(void) {
|
|
UseDefInfo *info;
|
|
int i;
|
|
|
|
usedefinfo = oalloc(pcblockcount * sizeof(UseDefInfo));
|
|
for (i = 0, info = usedefinfo; i < pcblockcount; i++, info++) {
|
|
info->defvec0 = oalloc(4 * ((number_of_Defs + 31) >> 5));
|
|
info->defvec4 = oalloc(4 * ((number_of_Defs + 31) >> 5));
|
|
info->defvec8 = oalloc(4 * ((number_of_Defs + 31) >> 5));
|
|
info->defvecC = oalloc(4 * ((number_of_Defs + 31) >> 5));
|
|
info->usevec10 = oalloc(4 * ((number_of_Uses + 31) >> 5));
|
|
info->usevec14 = oalloc(4 * ((number_of_Uses + 31) >> 5));
|
|
info->usevec18 = oalloc(4 * ((number_of_Uses + 31) >> 5));
|
|
info->usevec1C = oalloc(4 * ((number_of_Uses + 31) >> 5));
|
|
}
|
|
}
|
|
|
|
static void computelocalusedefinfo(void) {
|
|
PCodeBlock *block; // r28
|
|
PCode *pcode; // r27
|
|
UInt32 *defvec0; // r26
|
|
UInt32 *defvec4; // r25
|
|
UInt32 *usevec10; // r24
|
|
UInt32 *usevec14; // r23
|
|
UseOrDef *use; // r22
|
|
UseOrDef *def; // r22
|
|
int useID; // r15
|
|
int defID; // r21
|
|
ObjectUseDef *oud; // r17
|
|
RegUseOrDef *list; // r16
|
|
UseDefInfo *info; // r15
|
|
|
|
for (block = pcbasicblocks; block; block = block->nextBlock) {
|
|
info = &usedefinfo[block->blockIndex];
|
|
defvec0 = info->defvec0;
|
|
defvec4 = info->defvec4;
|
|
usevec10 = info->usevec10;
|
|
usevec14 = info->usevec14;
|
|
bitvectorinitialize(defvec0, number_of_Defs, 0);
|
|
bitvectorinitialize(defvec4, number_of_Defs, 0);
|
|
bitvectorinitialize(usevec10, number_of_Uses, 0);
|
|
bitvectorinitialize(usevec14, number_of_Uses, 0);
|
|
bitvectorinitialize(info->defvec8, number_of_Defs, 0);
|
|
bitvectorinitialize(info->defvecC, number_of_Defs, 0);
|
|
bitvectorinitialize(info->usevec18, number_of_Uses, 0);
|
|
bitvectorinitialize(info->usevec1C, number_of_Uses, 0);
|
|
|
|
for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) {
|
|
if (!(pcode->flags & fIsBranch) && pcode->argCount) {
|
|
for (use = &Uses[useID = pcode->useID]; useID < number_of_Uses && use->pcode == pcode; use++, useID++) {
|
|
bitvectorsetbit(useID, usevec10);
|
|
if (use->v.kind == PCOp_REGISTER) {
|
|
for (list = reg_Defs[use->v.arg][use->v.u.reg]; list; list = list->next) {
|
|
if (bitvectorgetbit(list->id, defvec0))
|
|
bitvectorclearbit(useID, usevec10);
|
|
}
|
|
} else {
|
|
for (list = findobjectusedef(use->v.u.object)->defs; list; list = list->next) {
|
|
if (uniquely_aliases(pcode, Defs[list->id].pcode)) {
|
|
if (Defs[list->id].v.arg == 0 && bitvectorgetbit(list->id, defvec0))
|
|
bitvectorclearbit(useID, usevec10);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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) {
|
|
if (Uses[list->id].pcode->block != block)
|
|
bitvectorsetbit(list->id, usevec14);
|
|
}
|
|
for (list = reg_Defs[def->v.arg][def->v.u.reg]; list; list = list->next) {
|
|
if (Defs[list->id].pcode->block != block)
|
|
bitvectorsetbit(list->id, defvec4);
|
|
else
|
|
bitvectorclearbit(list->id, defvec0);
|
|
}
|
|
} else if (def->v.arg == 0) {
|
|
oud = findobjectusedef(use->v.u.object);
|
|
for (list = oud->uses; list; list = list->next) {
|
|
if (may_alias(pcode, Uses[list->id].pcode)) {
|
|
if (Uses[list->id].pcode->block != block)
|
|
bitvectorsetbit(list->id, usevec14);
|
|
}
|
|
}
|
|
for (list = oud->defs; list; list = list->next) {
|
|
if (uniquely_aliases(pcode, Defs[list->id].pcode)) {
|
|
if (Defs[list->id].pcode->block != block)
|
|
bitvectorsetbit(list->id, defvec4);
|
|
else
|
|
bitvectorclearbit(list->id, defvec0);
|
|
}
|
|
}
|
|
}
|
|
|
|
bitvectorsetbit(defID, defvec0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void computeglobalusedefinfo(void) {
|
|
UseDefInfo *udi;
|
|
UInt32 *defVec0;
|
|
UInt32 *defVec4;
|
|
UInt32 *defVec8;
|
|
UInt32 *defVecC;
|
|
int bitvecsize;
|
|
int i;
|
|
int j;
|
|
int flag;
|
|
PCLink *preds;
|
|
UInt32 val;
|
|
|
|
bitvecsize = (number_of_Defs + 31) >> 5;
|
|
flag = 1;
|
|
while (flag) {
|
|
flag = 0;
|
|
for (i = 0; i < pcblockcount; i++) {
|
|
if (depthfirstordering[i]) {
|
|
udi = &usedefinfo[depthfirstordering[i]->blockIndex];
|
|
if ((preds = depthfirstordering[i]->predecessors)) {
|
|
defVec8 = udi->defvec8;
|
|
bitvectorcopy(defVec8, usedefinfo[preds->block->blockIndex].defvecC, number_of_Defs);
|
|
for (preds = preds->nextLink; preds; preds = preds->nextLink)
|
|
bitvectorunion(defVec8, usedefinfo[preds->block->blockIndex].defvecC, number_of_Defs);
|
|
}
|
|
|
|
defVecC = udi->defvecC;
|
|
defVec8 = udi->defvec8;
|
|
defVec0 = udi->defvec0;
|
|
defVec4 = udi->defvec4;
|
|
for (j = 0; j < bitvecsize; j++) {
|
|
val = *defVec0 | (*defVec8 & ~*defVec4);
|
|
if (val != *defVecC) {
|
|
*defVecC = val;
|
|
flag = 1;
|
|
}
|
|
defVec8++;
|
|
defVecC++;
|
|
defVec4++;
|
|
defVec0++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void computeglobaldefuseinfo(void) {
|
|
UseDefInfo *udi;
|
|
UInt32 *useVec10;
|
|
UInt32 *useVec14;
|
|
UInt32 *useVec18;
|
|
UInt32 *useVec1C;
|
|
int bitvecsize;
|
|
int i;
|
|
int j;
|
|
int flag;
|
|
PCLink *succs;
|
|
UInt32 val;
|
|
PCodeBlock *block;
|
|
|
|
bitvecsize = (number_of_Uses + 31) >> 5;
|
|
flag = 1;
|
|
while (flag) {
|
|
flag = 0;
|
|
i = pcblockcount;
|
|
while (i) {
|
|
if ((block = depthfirstordering[--i])) {
|
|
udi = &usedefinfo[block->blockIndex];
|
|
if ((succs = block->successors)) {
|
|
useVec1C = udi->usevec1C;
|
|
bitvectorcopy(useVec1C, usedefinfo[succs->block->blockIndex].usevec18, number_of_Uses);
|
|
for (succs = succs->nextLink; succs; succs = succs->nextLink)
|
|
bitvectorunion(useVec1C, usedefinfo[succs->block->blockIndex].usevec18, number_of_Uses);
|
|
}
|
|
|
|
useVec1C = udi->usevec1C;
|
|
useVec18 = udi->usevec18;
|
|
useVec10 = udi->usevec10;
|
|
useVec14 = udi->usevec14;
|
|
for (j = 0; j < bitvecsize; j++) {
|
|
val = *useVec10 | (*useVec1C & ~*useVec14);
|
|
if (val != *useVec18) {
|
|
*useVec18 = val;
|
|
flag = 1;
|
|
}
|
|
useVec18++;
|
|
useVec1C++;
|
|
useVec14++;
|
|
useVec10++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void computeusedefchains(int flag) {
|
|
if (flag) {
|
|
gather_alias_info();
|
|
precomputememoryusedefs();
|
|
}
|
|
|
|
precomputeusedefcounts(flag);
|
|
computeusedeflists(flag);
|
|
allocateusedefinfo();
|
|
computelocalusedefinfo();
|
|
computedepthfirstordering();
|
|
computeglobalusedefinfo();
|
|
computeglobaldefuseinfo();
|
|
}
|
|
|