/*}}}*/ PRIVATE void tselection (treenode * tptr, const int joinlab) { treenode *specsptr = tptr; tptr = tspecs (tptr); if (TagOf (tptr) != S_SELECTION) badtag (genlocn, TagOf (tptr), "tselection"); tprocess (CondBodyOf (tptr)); tdespecs (specsptr); genbranch (I_J, joinlab); }
void genbrtrue(int dest) { gentext(); if (Q_cmp != cnone) { genbranch(dest, 1); return; } if (Q_bool != bnone) { genlogbr(dest, 0); return; } commit(); cgbrtrue(dest); }
void genbrtrue(int dest) { gentext(); if (Q_cmp != none) { genbranch(dest, 1); return; } commit(); cgbrtrue(dest); }
/***************************************************************************** * * tjumptable generates the code for selecting cases given a sorted array * of case values and labels. Our case values are * case[low .. high]. * *****************************************************************************/ PRIVATE void tjumptable (const int low, const int high, const BOOL nomorejumptables) { const int numcases = (high - low) + 1; const BOOL singlelength = fitsinword (selectortype); #ifdef DEBUG { int i; DEBUG_MSG (("tjumptable: low: %d, high: %d, numcases: %d, nomorejumptables: %d\n", low, high, numcases, nomorejumptables)); for (i = low; i <= high; i++) { DEBUG_MSG (("tjumptable: casetable[%2d].lowvalue = %8X\n", i, casetable[i].lowvalue)); } } #endif if ((numcases <= DELTA) || isquadlength (selectortype)) { /* bug INSdi02177 */ /*{{{ too few cases - output jumps */ int i; BOOL optimisedlast = FALSE; for (i = low; i < low + numcases; i++) { /*{{{ output a jump for casetable[i] */ caseentry *thiscase = &(casetable[i]); const int old = switch_to_temp_workspace (); treenode *snode = newdopnode (S_EQ, NOPOSN, selectorexp, thiscase->selectionexp, selectortype); switch_to_prev_workspace (old); if ((i == high) && (thiscase->lowvalue != 0) && (thiscase->lowvalue != MOSTNEG_INT32) && fitsinword (selectortype) && (!isinconstanttable (thiscase->selectionexp))) { /*{{{ optimise the last case */ tguard (snode, TRUE, defaultlab); genbranch (I_J, thiscase->label); thiscase->jumpdest = TRUE; optimisedlast = TRUE; /*}}} */ } else { tguard (snode, FALSE, thiscase->label); } /*}}} */ } if (!optimisedlast) { genbranch (I_J, defaultlab); defaultjumpdest = TRUE; } /*}}} */ } else { /*{{{ look for biggest jump table */ int bestlow = 0; int besthigh = 0; int bestsize = 0; if (!nomorejumptables && (!singlelength || (numcases >= MIN_JTAB_SIZE))) { /*{{{ look for best jump table */ int i, j; const int minjumps = singlelength ? MIN_JTAB_SIZE - 1 : DELTA; for (i = low; i < (low + numcases - DELTA); i++) { /*{{{ set j to minimum value possible for better subrange */ j = i + ((bestsize > minjumps) ? bestsize : minjumps); /*}}} */ /*{{{ test all possible subranges starting at i, ending at or past j */ { const int maxaccept = ((high - i) + 1) * DENSITY; if (singlelength) { /*{{{ single length */ while (j <= high) { /* bug TS/1589 - 04/11/92 this is a bug in gcc 1.36; changing diff to be a BIT32 seems to fix the problem; and is OK as a permanent work-around. */ /* bug TS/1575 05/11/92 - cast to BIT32 for unsigned arith */ /*const INT32 diff = casetable[j].lowvalue - casetable[i].lowvalue); */ /*const INT32 diff = (INT32)((BIT32)casetable[j].lowvalue - (BIT32)casetable[i].lowvalue); */ const BIT32 diff = (BIT32) casetable[j].lowvalue - (BIT32) casetable[i].lowvalue; /*DEBUG_MSG(("i: %2d, j: %2d, lowvalue: %8X, diff: %8X\n", i, j, casetable[j].lowvalue, diff)); */ /*if ((diff < 0) || (diff > maxaccept)) *//* TS/1589 04/11/92 */ if (diff > (BIT32) maxaccept) { DEBUG_MSG (("tjumptable: bombing: diff: %8X\n", diff)); j = high; /* no chance so exit */ } else { const int size = (j - i) + 1; DEBUG_MSG (("tjumptable: ok: diff: %8X\n", diff)); if (diff <= (int) (DENSITY * size)) { /* better subrange */ bestlow = i; besthigh = j; bestsize = size; } } j = j + 1; } /*}}} */ } else { /*{{{ double length */ while (j <= high) { BIT32 hdiff, ldiff; Int64Minus (&hdiff, &ldiff, casetable[j].highvalue, casetable[j].lowvalue, casetable[i].highvalue, casetable[i].lowvalue); if ((hdiff != 0) || (ldiff > maxaccept)) { j = high; /* no chance so exit */ } else { const int size = (j - i) + 1; if (ldiff <= (int) (DENSITY * size)) { /* better subrange */ bestlow = i; besthigh = j; bestsize = size; } } j = j + 1; } /*}}} */ } } /*}}} */ } /*}}} */ } if (bestsize == 0) { tbinchop (low, high); } else { /*{{{ do jump table */ int lesslab = 0, greaterlab = 0; caseentry *lowestcase = &(casetable[bestlow]); caseentry *highestcase = &(casetable[besthigh]); DEBUG_MSG (("generating jump table: bestsize = %d\n", bestsize)); /*{{{ test for below boundary */ { treenode *lselnexp = lowestcase->selectionexp; if (!is_typed_mostneg (selectortype, LoValOf (lselnexp), HiValOf (lselnexp))) { int l; const int old = switch_to_temp_workspace (); treenode *snode = newdopnode (S_GE, NOPOSN, selectorexp, lselnexp, selectortype); switch_to_prev_workspace (old); if (bestlow == low) l = defaultlab; else { lesslab = newlab (); l = lesslab; } tguard (snode, TRUE, l); } } /*}}} */ /*{{{ test for above boundary */ { treenode *hselnexp = highestcase->selectionexp; if (!is_typed_mostpos (selectortype, LoValOf (hselnexp), HiValOf (hselnexp))) { int l; const int old = switch_to_temp_workspace (); treenode *snode = newdopnode (S_LE, NOPOSN, selectorexp, hselnexp, selectortype); switch_to_prev_workspace (old); if (besthigh == high) l = defaultlab; else { greaterlab = newlab (); l = greaterlab; } tguard (snode, TRUE, l); } } /*}}} */ /*{{{ output jump table */ { #if 0 const int jlab = newlab (); const int l = newlab (); #endif treenode *snode; if (lowestcase->lowvalue != 0) { /*{{{ selectorexp; ldc lowvalue; diff */ const int old = switch_to_temp_workspace (); snode = newdopnode (S_MINUS, NOPOSN, /* selectorexp */ selectorexp, /* ldc selection */ lowestcase->selectionexp, /* diff */ S_INT); switch_to_prev_workspace (old); /*}}} */ } else { /*{{{ selectorexp */ snode = selectorexp; /* selectorexp */ /*}}} */ } texp (snode, MANY_REGS); #if 0 /* subsumed into genstartjumptable to allow optimisation */ genloadcasescale (); /* ldc casescale */ /*{{{ T9000_gamma_badmul */ if (T9000_gamma_badmul (&tx_global)) { gensecondary (I_NOP); gencomment0 ("Workaround a slow multiplier"); } /*}}} */ gensecondary (I_PROD); /* prod */ genlabeldiff (I_LDC, jlab, l); /* ldc jlab - l */ gensecondary (I_LDPI); /* ldpi */ setlab (l); /* l: */ gensecondary (I_BSUB); /* bsub */ gensecondary (I_GCALL); /* gcall */ setlab (jlab); /* jlab: */ #endif genstartjumptable (); /* includes jump into table */ genjumptableentry (I_J, lowestcase->label); lowestcase->jumpdest = TRUE; /* j lowestcase */ /*{{{ other cases j othercases .. */ { int i; for (i = bestlow + 1; i <= besthigh; i++) { int j; /* bug TS/1575 05/11/92 - cast to BIT32 for unsigned arith */ const int blanks = (int) ((BIT32) casetable[i].lowvalue - (BIT32) casetable[i - 1].lowvalue) - 1; for (j = 0; j < blanks; j++) { genjumptableentry (I_J, defaultlab); defaultjumpdest = TRUE; } genjumptableentry (I_J, casetable[i].label); casetable[i].jumpdest = TRUE; } } /*}}} */ genendjumptable (); /*}}} */ } if (bestlow > low) { /*{{{ case on lower values */ setlab (lesslab); tjumptable (low, bestlow - 1, FALSE); /*}}} */ } if (besthigh < high) { /*{{{ case on higher values */ setlab (greaterlab); tjumptable (besthigh + 1, high, FALSE); /*}}} */ } /*}}} */ } /*}}} */ } }