#include "compiler/CopyPropagation.h" #include "compiler/CMangler.h" #include "compiler/CParser.h" #include "compiler/CodeGen.h" #include "compiler/CompilerTools.h" #include "compiler/UseDefChains.h" #include "compiler/PCode.h" #include "compiler/RegisterInfo.h" #include "compiler/BitVectors.h" // TODO move me extern void pclistblocks(char *, char *); 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 & fPCodeFlag1) && 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 & fPCodeFlag2 | fPCodeFlag4) && (pcode->flags & fPCodeFlag2000000)) { 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->kind == PCOp_REGISTER) { for (list = reg_Uses[def->arg][def->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->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 & fPCodeFlag1) && 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 & fPCodeFlag1) && 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 j; 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 (i = 0; i < pcblockcount; i++) { if (depthfirstordering[i]) { info = &propinfo[depthfirstordering[i]->blockIndex]; if ((preds = depthfirstordering[i]->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 (j = 0; j < bitvecsize; j++) { 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) & (fPCodeFlag20000000 | 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 & fPCodeFlag10) && (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; char 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 & fPCodeFlag10) 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; unsigned char 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[(char) 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 == (char) 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, ©propagatestouse, &propagateandremovecopy, "COPY", "COPIES", "c%ld", 0 }; void propagatecopyinstructions(Object *proc, int flag) { moreaggressiveoptimization = flag; propagateinstructions(proc, ©_prop, 1, 0); propagatedcopies = propagated_instructions; }