static void PruneInductionCandidate(int tnum, LOOP *l) { if (tempInfo[tnum]->size >= ISZ_FLOAT) { briggsReset(candidates, tnum); } else { QUAD *I = tempInfo[tnum]->instructionDefines; switch(I->dc.opcode) { case i_phi: { PHIDATA *pd = I->dc.v.phi; struct _phiblock *pb = pd->temps; while (pb) { if (!briggsTest(candidates, pb->Tn) && !isInvariant(pb->Tn, l)) { briggsReset(candidates, tnum); break; } pb = pb->next; } } break; case i_add: case i_sub: if (I->temps & TEMP_RIGHT) { int tn2 = I->dc.right->offset->v.sp->value.i; if (!briggsTest(candidates, tn2)) briggsReset(candidates, tnum); } /* FALLTHROUGH */ case i_neg: case i_assn: if (I->temps & TEMP_LEFT) { int tn2 = I->dc.left->offset->v.sp->value.i; if (!briggsTest(candidates, tn2)) briggsReset(candidates, tnum); } break; default: diag("PruneInductionCandidate: invalid form"); break; } } }
int briggsIntersect(BRIGGS_SET *s1, BRIGGS_SET *s2) { int i; for (i=s1->top-1; i >= 0; i--) { if (!briggsTest(s2, s1->data[i])) { briggsReset(s1, s1->data[i]); } } return 0; }
/* finds all the successors to the loop */ static void CalculateSuccessors(LOOP *lp) { LIST *contains; contains = lp->contains; while(contains) { LOOP *current = (LOOP *)contains->data; if (lp->type != LT_BLOCK) CalculateSuccessors(current); contains = contains->next; } contains = lp->contains; while (contains) { LOOP *inner = (LOOP *)contains->data; if (inner->type == LT_BLOCK) { BLOCKLIST *bl = inner->entry->succ; while (bl) { BLOCKLIST *newExit = oAlloc(sizeof(BLOCKLIST)); newExit->next = lp->successors; lp->successors = newExit; newExit->block = bl->block; bl = bl->next; } } else { /* only have to add blocks that exited an inner loop * and only if they also exit this loop */ BLOCKLIST *prevSuccessors = inner->successors; while (prevSuccessors) { if (!briggsTest(inner->blocks, prevSuccessors->block->blocknum)) { BLOCKLIST *newExit = oAlloc(sizeof(BLOCKLIST)); newExit->next = lp->successors; lp->successors = newExit; newExit->block = prevSuccessors->block; } prevSuccessors = prevSuccessors->next; } } contains = contains->next; } }
/* this returns a two-layer list * the top layer is a linked list of strong regions * each secondary layer is the induction set for the region * first element of list is the anchors */ static LIST *strongRegions(LOOP *lp, LIST **anchors) { int i; QUAD *head; LIST *rv = NULL; *anchors = NULL; strongStack = oAlloc(sizeof(unsigned short) *tempCount); max_dfs = 0; strongStackTop = 0; for (i=0; i < tempCount; i++) { tempInfo[i]->dfstOrder = 0; tempInfo[i]->visiteddfst = FALSE; tempInfo[i]->temp = INT_MAX; } head = lp->entry->head->fwd; while (head != lp->entry->tail->fwd && (head->ignoreMe || head->dc.opcode == i_label)) head = head->fwd; while (head != lp->entry->tail->fwd && head->dc.opcode == i_phi) { PHIDATA *pd = head->dc.v.phi; if (briggsTest(candidates, pd->T0) && tempInfo[pd->T0]->size < ISZ_FLOAT) { LIST *l1 = strongRegiondfs(pd->T0); if (l1) { l1->next = rv; rv = l1; } l1 = oAlloc(sizeof(LIST)); l1->data = (void *)pd->T0; l1->next = *anchors; *anchors = l1; } head = head->fwd; } return rv; }
static void removeDeadBlocks(BRIGGS_SET *brs, BLOCK *back, BLOCK *b) { if (b->temp) return; b->temp = TRUE; if (!briggsTest(brs, b->blocknum) && b->blocknum != exitBlock) { BLOCKLIST *bl2 = b->succ; while (bl2) { removeDeadBlocks(brs, b, bl2->block); if (!bl2->block->dead) { BLOCKLIST **bl3 = &bl2->block->pred; int n = 0; while (*bl3) { if ((*bl3)->block == b) { QUAD *head = bl2->block->head->fwd; *bl3 = (*bl3)->next; while (head != bl2->block->tail->fwd && (head->dc.opcode == i_label || head->ignoreMe)) { head = head->fwd; } while (head->dc.opcode == i_phi && head != bl2->block->tail->fwd) { PHIDATA *pd = head->dc.v.phi; struct _phiblock **pb = &pd->temps; int i; for (i=0; i < n; i++, pb = &(*pb)->next) ; (*pb) = (*pb)->next; head = head->fwd; } break; } n++; bl3 = &(*bl3)->next; } } bl2 = bl2->next; } b->head->fwd = b->tail->fwd; b->tail->fwd->back = b->head; b->tail = b->head; b->succ = b->pred = NULL; b->dead = TRUE; b->critical = FALSE; blockArray[b->blocknum] = NULL; } else { QUAD *head ; int n = 0; BLOCKLIST **bl = &b->pred; while (bl) { if ((*bl)->block == back) { *bl = (*bl)->next; break; } n++; bl = &(*bl)->next; } head = b->head->fwd; while (head != b->tail->fwd && (head->dc.opcode == i_label || head->ignoreMe)) { head = head->fwd; } while (head->dc.opcode == i_phi && head != b->tail->fwd) { PHIDATA *pd = head->dc.v.phi; struct _phiblock **pb = &pd->temps; int i; for (i=0; i < n; i++, pb = &(*pb)->next) ; (*pb) = (*pb)->next; head = head->fwd; } } }
/* minor problem: if an induction variable spans multiple loops * an induction set will be created for each loop. These sets will * be identical */ static void CalculateInductionCandidates(LOOP *l) { LIST *blocks , *p; int i; briggsClear(candidates); inductionCandidateStackTop = 0; /* done here just in case for some reason an induction set drills down * into a lower loop */ for (i=0; i < tempCount; i++) tempInfo[i]->onstack = FALSE; for (i=0; i < l->blocks->top; i++) { BLOCK *b = blockArray[l->blocks->data[i]]; if (b) { QUAD *head = b->head; while (head != b->tail->fwd) { switch(head->dc.opcode) { case i_add: case i_sub: if ((head->temps & TEMP_ANS) && head->ans->mode == i_direct) { if (head->dc.left->mode == i_immed || (head->temps & TEMP_LEFT) && head->dc.left->mode == i_direct)//FIXME && || if (head->dc.right->mode == i_immed || (head->temps & TEMP_RIGHT) && head->dc.right->mode == i_direct)//FIXME && || { if (head->ans->size < ISZ_FLOAT && head->dc.left->size < ISZ_FLOAT && head->dc.right->size < ISZ_FLOAT) { int tnum = head->ans->offset->v.sp->value.i; briggsSet(candidates, tnum); inductionCandidateStack[inductionCandidateStackTop++] = tnum; tempInfo[tnum]->onstack = TRUE; } } } break; case i_neg: case i_assn: if ((head->temps & TEMP_ANS) && head->ans->mode == i_direct) { if (head->dc.left->mode == i_immed || (head->temps & TEMP_LEFT) && head->dc.left->mode == i_direct)//FIXME && || { if (head->ans->size < ISZ_FLOAT && head->dc.left->size < ISZ_FLOAT) { int tnum = head->ans->offset->v.sp->value.i; briggsSet(candidates, tnum); inductionCandidateStack[inductionCandidateStackTop++] = tnum; tempInfo[tnum]->onstack = TRUE; } } } break; case i_phi: { PHIDATA *pd = head->dc.v.phi; int tnum = pd->T0; if (tempInfo[tnum]->size < ISZ_FLOAT) { briggsSet(candidates, tnum); inductionCandidateStack[inductionCandidateStackTop++] = tnum; tempInfo[tnum]->onstack = TRUE; } } break; } /* prep for reshaping */ switch (head->dc.opcode) { case i_add: case i_sub: case i_mul: case i_lsl: if (head->ans->size < ISZ_FLOAT && head->dc.left->size < ISZ_FLOAT) { if (head->temps & TEMP_ANS) { int tnum = head->ans->offset->v.sp->value.i; INSTRUCTIONLIST *l = tempInfo[tnum]->instructionUses; while (l) { if ((l->ins->temps & TEMP_ANS) && l->ins->ans->mode == i_ind) { if (tnum == l->ins->ans->offset->v.sp->value.i) { tempInfo[tnum]->expressionRoot = TRUE; } } if (l->ins->temps & TEMP_LEFT) { if (tnum == l->ins->dc.left->offset->v.sp->value.i) { if (l->ins->dc.left->mode == i_ind) tempInfo[tnum]->expressionRoot = TRUE; else if (head->dc.opcode != i_not && head->dc.opcode != i_neg) if (!matchesop(head->dc.opcode, l->ins->dc.opcode)) tempInfo[tnum]->expressionRoot = TRUE; } } if (l->ins->temps & TEMP_RIGHT) { if (tnum == l->ins->dc.right->offset->v.sp->value.i) { if (l->ins->dc.right->mode == i_ind) tempInfo[tnum]->expressionRoot = TRUE; else if (head->dc.opcode != i_not && head->dc.opcode != i_neg) if (!matchesop(head->dc.opcode, l->ins->dc.opcode)) tempInfo[tnum]->expressionRoot = TRUE; } } l = l->next; } } } break; } head = head->fwd; } } } while (inductionCandidateStackTop) { int tnum = inductionCandidateStack[--inductionCandidateStackTop]; tempInfo[tnum]->onstack = FALSE; PruneInductionCandidate(tnum, l); if (!briggsTest(candidates, tnum)) { INSTRUCTIONLIST *li = tempInfo[tnum]->instructionUses; while (li) { if (briggsTest(l->blocks, li->ins->block->blocknum)) { if (li->ins->temps & TEMP_ANS) { int tnum = li->ins->ans->offset->v.sp->value.i; if (briggsTest(candidates, tnum)) { if (!tempInfo[tnum]->onstack) inductionCandidateStack[inductionCandidateStackTop++] = tnum; } } } li = li->next; } } } }
static void FindBody(BLOCKLIST *gen, BLOCK *head, enum e_lt type) { LIST *queue = NULL, **qx; LOOP *lp, **lpp ; int i; if (!gen) return; briggsClear(loopItems); while (gen) { LOOP *l = LoopAncestor(gen->block); if (l && !briggsTest(loopItems, l->loopnum)) { LIST *bl = oAlloc(sizeof(LIST)); bl->data = l; bl->next = queue; queue = bl; briggsSet(loopItems, l->loopnum); } gen = gen->next; } while (queue) { if (((LOOP *)queue->data)->entry) { BLOCKLIST *p = ((LOOP *)queue->data)->entry->pred; queue = queue->next; while (p) { if (p->block != head) { LOOP *l = LoopAncestor(p->block); if (l && !briggsTest(loopItems, l->loopnum)) { LIST *bl = oAlloc(sizeof(LIST)); bl->data = l; bl->next = queue; queue = bl; briggsSet(loopItems, l->loopnum); } } p = p->next; } } else queue = queue->next; } lp = oAlloc(sizeof(LOOP)); loopArray[loopCount] = lp; lp->type = type; lp->loopnum = loopCount++; lp->entry = head; lp->parent = NULL; head->loopParent = lp; qx = &lp->contains; *qx = oAlloc(sizeof(LIST)); (*qx)->data = head->loopName; qx = &(*qx)->next; for (i=0; i < loopItems->top; i++) { LIST *l = oAlloc(sizeof(LIST)); int n = loopItems->data[i]; l->data = loopArray[n]; *qx = l; qx = &(*qx)->next; if (loopArray[n]->type == LT_BLOCK) loopArray[n]->entry->loopParent = lp; else loopArray[n]->parent = lp; } }
static void markLiveInstruction(BRIGGS_SET *live, QUAD *ins) { switch(ins->dc.opcode) { case i_parmadj: case i_passthrough: case i_line: case i_varstart: case i_dbgblock: case i_dbgblockend: case i_func: case i_trap: case i_int: case i_ret: case i_fret: case i_rett: case i_cppini: case i_block: case i_blockend: case i_livein: case i_prologue: case i_epilogue: case i_pushcontext: case i_popcontext: case i_loadcontext: case i_unloadcontext: case i_tryblock: case i_loadstack: case i_savestack: case i_substack: case i_functailstart: case i_functailend: case i_swbranch: case i_skipcompare: ins->live = TRUE; break; case i_parm: case i_gosub: case i_label: case i_goto: ins->live = TRUE; break; case i_assnblock: case i_clrblock: case i_parmblock: ins->live = TRUE; break; case i_jne: case i_je: case i_jc: case i_ja: case i_jnc: case i_jbe: case i_jl: case i_jg: case i_jle: case i_jge: case i_coswitch: ins->live = TRUE; break; case i_phi: if (briggsTest(live, ins->dc.v.phi->T0)) { struct _phiblock *pb = ins->dc.v.phi->temps; ins->live = TRUE; while (pb) { briggsSet(live, pb->Tn); pb = pb->next; } } return; default: if (!(ins->temps & TEMP_ANS) || ins->ans->mode == i_ind) ins->live = TRUE; else if ((ins->temps & TEMP_ANS) && briggsTest(live, ins->ans->offset->v.sp->value.i)) ins->live = TRUE; break; } if (ins->live) { if (ins->temps & TEMP_ANS) { if (ins->ans->mode == i_direct) { briggsReset(live, ins->ans->offset->v.sp->value.i); } else if (ins->ans->mode == i_ind) { if (ins->ans->offset) briggsSet(live, ins->ans->offset->v.sp->value.i); if (ins->ans->offset2) briggsSet(live, ins->ans->offset2->v.sp->value.i); } } if (ins->temps & TEMP_LEFT) { if (ins->dc.left->mode == i_direct || ins->dc.left->mode == i_ind) { if (ins->dc.left->offset) briggsSet(live, ins->dc.left->offset->v.sp->value.i); if (ins->dc.left->offset2) briggsSet(live, ins->dc.left->offset2->v.sp->value.i); } } if (ins->temps & TEMP_RIGHT) { if (ins->dc.right->mode == i_direct || ins->dc.right->mode == i_ind) { if (ins->dc.right->offset) briggsSet(live, ins->dc.right->offset->v.sp->value.i); if (ins->dc.right->offset2) briggsSet(live, ins->dc.right->offset2->v.sp->value.i); } } } }
void CalculateConflictGraph(BRIGGS_SET *nodes, BOOLEAN optimize) { int i, j; BRIGGS_SET *live = briggsAllocc(tempCount); resetConflict(); for (i=0 ; i < blockCount; i++) { if (blockArray[i]) { BITINT *p = blockArray[i]->liveOut; QUAD *tail = blockArray[i]->tail ; QUAD *head = blockArray[i]->head ; int j, k; briggsClear(live); for (j=0; j < (tempCount + BITINTBITS-1)/BITINTBITS; j++,p++) if (*p) for (k=0; k < BITINTBITS; k++) if (*p & (1 << k)) { if (!nodes || briggsTest(nodes, j * BITINTBITS + k)) briggsSet(live, j * BITINTBITS + k); } do { if (chosenAssembler->gen->internalConflict) chosenAssembler->gen->internalConflict(tail); if (tail->dc.opcode == i_phi) { PHIDATA *pd = tail->dc.v.phi; struct _phiblock *pb = pd->temps; if (!nodes || briggsTest(nodes, pd->T0)) { for (j=0; j < live->top; j++) { insertConflict(live->data[j], pd->T0); } } while (pb) { if (!nodes || briggsTest(nodes, pb->Tn)) { struct _phiblock *pb2 = pd->temps; while (pb2) { if (!nodes || briggsTest(nodes, pb2->Tn)) { if (briggsTest(live, pb->Tn) || briggsTest(live, pb2->Tn)) insertConflict(pb->Tn, pb2->Tn); } pb2 = pb2->next; } } pb = pb->next; } pb = pd->temps; while (pb) { if (!nodes || briggsTest(nodes, pb->Tn)) { briggsSet(live, pb->Tn); } pb = pb->next; } } else if (tail->dc.opcode == i_assnblock) { if (tail->dc.right->offset->type == en_tempref && tail->dc.left->offset->type == en_tempref) { insertConflict(tail->dc.right->offset->v.sp->value.i, tail->dc.left->offset->v.sp->value.i); } } else if (tail->temps & TEMP_ANS) { if (tail->ans->mode == i_direct) { int tnum = tail->ans->offset->v.sp->value.i; int k = -1; if (!nodes || briggsTest(nodes, tnum)) { if (optimize) { if (tail->dc.opcode == i_assn) { if ((tail->temps &(TEMP_LEFT | TEMP_ANS)) == (TEMP_LEFT | TEMP_ANS)) { if (tail->dc.left->mode == i_direct && tail->ans->mode == i_direct && !tail->ans->bits && !tail->dc.left->bits && !tail->dc.left->retval) { if (tail->dc.left->size == tail->ans->size) { if (!tail->ans->offset->v.sp->pushedtotemp && !tail->dc.left->offset->v.sp->pushedtotemp) { k = tail->dc.left->offset->v.sp->value.i; } } } } } } briggsReset(live, tnum); // processor dependent if (tail->ans->size == ISZ_ULONGLONG || tail->ans->size == -ISZ_ULONGLONG) { if (tail->dc.left->mode == i_ind) { if (tail->dc.left->offset) insertConflict(tnum, tail->dc.left->offset->v.sp->value.i); if (tail->dc.left->offset2) insertConflict(tnum, tail->dc.left->offset2->v.sp->value.i); } if (tail->dc.right && tail->dc.right->mode == i_ind) { if (tail->dc.right->offset) insertConflict(tnum, tail->dc.right->offset->v.sp->value.i); if (tail->dc.right->offset2) insertConflict(tnum, tail->dc.right->offset2->v.sp->value.i); } } for (j=0; j < live->top; j++) { if (live->data[j] != k) insertConflict(live->data[j], tnum); } } } else if (tail->ans->mode == i_ind) { if (tail->ans->offset) { int tnum = tail->ans->offset->v.sp->value.i; if (!nodes || briggsTest(nodes, tnum)) { briggsSet(live, tnum); } } if (tail->ans->offset2) { int tnum = tail->ans->offset2->v.sp->value.i; if (!nodes || briggsTest(nodes, tnum)) { briggsSet(live, tnum); } } } } if ((tail->temps & TEMP_LEFT) && !tail->dc.left->retval) { if (tail->dc.left->offset) { int tnum = tail->dc.left->offset->v.sp->value.i; if (!nodes || briggsTest(nodes, tnum)) { briggsSet(live, tnum); } } if (tail->dc.left->offset2) { int tnum = tail->dc.left->offset2->v.sp->value.i; if (!nodes || briggsTest(nodes, tnum)) { briggsSet(live, tnum); } } } if (tail->temps & TEMP_RIGHT) { if (tail->dc.right->offset) { int tnum = tail->dc.right->offset->v.sp->value.i; if (!nodes || briggsTest(nodes, tnum)) { briggsSet(live, tnum); } } if (tail->dc.right->offset2) { int tnum = tail->dc.right->offset2->v.sp->value.i; if (!nodes || briggsTest(nodes, tnum)) { briggsSet(live, tnum); } } } if (tail != head) tail = tail->back ; } while (tail != head); } } }