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