Annotation of researchv10dc/cmd/gcc/fold-const.c, revision 1.1

1.1     ! root        1: /*@@ Fix lossage on folding division of big integers.  */
        !             2: 
        !             3: /*@@ This file should be rewritten to use an arbitary precision
        !             4:   @@ representation for "struct tree_int_cst" and "struct tree_real_cst".
        !             5:   @@ Perhaps the routines could also be used for bc/dc, and made a lib.
        !             6:   @@ The routines that translate from the ap rep should
        !             7:   @@ warn if precision et. al. is lost.
        !             8:   @@ This would also make life easier when this technology is used
        !             9:   @@ for cross-compilers.  */
        !            10: 
        !            11: /* Fold a constant sub-tree into a single node for C-compiler
        !            12:    Copyright (C) 1987, 1988 Free Software Foundation, Inc.
        !            13: 
        !            14: This file is part of GNU CC.
        !            15: 
        !            16: GNU CC is distributed in the hope that it will be useful,
        !            17: but WITHOUT ANY WARRANTY.  No author or distributor
        !            18: accepts responsibility to anyone for the consequences of using it
        !            19: or for whether it serves any particular purpose or works at all,
        !            20: unless he says so in writing.  Refer to the GNU CC General Public
        !            21: License for full details.
        !            22: 
        !            23: Everyone is granted permission to copy, modify and redistribute
        !            24: GNU CC, but only under the conditions described in the
        !            25: GNU CC General Public License.   A copy of this license is
        !            26: supposed to have been given to you along with GNU CC so you
        !            27: can know your rights and responsibilities.  It should be in a
        !            28: file named COPYING.  Among other things, the copyright notice
        !            29: and this notice must be preserved on all copies.  */
        !            30: 
        !            31: 
        !            32: /* There are only two entry points in this file:
        !            33:    fold and combine.
        !            34: 
        !            35:    fold takes a tree as argument and returns a simplified tree.
        !            36: 
        !            37:    combine takes a tree code for an arithmetic operation
        !            38:    and two operands that are trees for constant values
        !            39:    and returns the result of the specified operation on those values,
        !            40:    also as a tree.  */
        !            41:    
        !            42: #include <stdio.h>
        !            43: #include "config.h"
        !            44: #include "tree.h"
        !            45: 
        !            46: static void lshift_double ();
        !            47: static void rshift_double ();
        !            48: static void lrotate_double ();
        !            49: static void rrotate_double ();
        !            50: 
        !            51: /* To do constant folding on INTEGER_CST nodes requires 64-bit arithmetic.
        !            52:    We do that by representing the 64-bit integer as 8 shorts,
        !            53:    with only 8 bits stored in each short, as a positive number.  */
        !            54: 
        !            55: /* Unpack a 64-bit integer into 8 shorts.
        !            56:    LOW and HI are the integer, as two `int' pieces.
        !            57:    SHORTS points to the array of shorts.  */
        !            58: 
        !            59: static void
        !            60: encode (shorts, low, hi)
        !            61:      short *shorts;
        !            62:      int low, hi;
        !            63: {
        !            64:   shorts[0] = low & 0xff;
        !            65:   shorts[1] = (low >> 8) & 0xff;
        !            66:   shorts[2] = (low >> 16) & 0xff;
        !            67:   shorts[3] = (low >> 24) & 0xff;
        !            68:   shorts[4] = hi & 0xff;
        !            69:   shorts[5] = (hi >> 8) & 0xff;
        !            70:   shorts[6] = (hi >> 16) & 0xff;
        !            71:   shorts[7] = (hi >> 24) & 0xff;
        !            72: }
        !            73: 
        !            74: /* Pack an array of 8 shorts into a 64-bit integer.
        !            75:    SHORTS points to the array of shorts.
        !            76:    The integer is stored into *LOW and *HI as two `int' pieces.  */
        !            77: 
        !            78: static void
        !            79: decode (shorts, low, hi)
        !            80:      short *shorts;
        !            81:      int *low, *hi;
        !            82: {
        !            83:   *low = (shorts[3] << 24) | (shorts[2] << 16) | (shorts[1] << 8) | shorts[0];
        !            84:   *hi = (shorts[7] << 24) | (shorts[6] << 16) | (shorts[5] << 8) | shorts[4];
        !            85: }
        !            86: 
        !            87: /* Make the integer constant T valid for its type
        !            88:    by setting to 0 or 1 all the bits in the constant
        !            89:    that don't belong in the type.  */
        !            90: 
        !            91: static void
        !            92: force_fit_type (t)
        !            93:      tree t;
        !            94: {
        !            95:   register int prec = TYPE_PRECISION (TREE_TYPE (t));
        !            96: 
        !            97:   if (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE)
        !            98:     prec = BITS_PER_WORD;
        !            99: 
        !           100:   /* First clear all bits that are beyond the type's precision.  */
        !           101: 
        !           102:   if (prec > HOST_BITS_PER_INT)
        !           103:     {
        !           104:       TREE_INT_CST_HIGH (t)
        !           105:        &= ~((-1) << (prec - HOST_BITS_PER_INT));
        !           106:     }
        !           107:   else
        !           108:     {
        !           109:       TREE_INT_CST_HIGH (t) = 0;
        !           110:       if (prec < HOST_BITS_PER_INT)
        !           111:        TREE_INT_CST_LOW (t)
        !           112:          &= ~((-1) << prec);
        !           113:     }
        !           114: 
        !           115:   /* If it's a signed type and value's sign bit is set, extend the sign.  */
        !           116: 
        !           117:   if (! TREE_UNSIGNED (TREE_TYPE (t))
        !           118:       && (prec > HOST_BITS_PER_INT
        !           119:          ? TREE_INT_CST_HIGH (t) & (1 << (prec - HOST_BITS_PER_INT - 1))
        !           120:          : TREE_INT_CST_LOW (t) & (1 << (prec - 1))))
        !           121:     {
        !           122:       /* Value is negative:
        !           123:         set to 1 all the bits that are outside this type's precision.  */
        !           124:       if (prec > HOST_BITS_PER_INT)
        !           125:        {
        !           126:          TREE_INT_CST_HIGH (t)
        !           127:            |= ((-1) << (prec - HOST_BITS_PER_INT));
        !           128:        }
        !           129:       else
        !           130:        {
        !           131:          TREE_INT_CST_HIGH (t) = -1;
        !           132:          if (prec < HOST_BITS_PER_INT)
        !           133:            TREE_INT_CST_LOW (t)
        !           134:              |= ((-1) << prec);
        !           135:        }
        !           136:     }
        !           137: }
        !           138: 
        !           139: /* Add two 64-bit integers with 64-bit result.
        !           140:    Each argument is given as two `int' pieces.
        !           141:    One argument is L1 and H1; the other, L2 and H2.
        !           142:    The value is stored as two `int' pieces in *LV and *HV.
        !           143:    We use the 8-shorts representation internally.  */
        !           144: 
        !           145: static void
        !           146: add_double (l1, h1, l2, h2, lv, hv)
        !           147:      int l1, h1, l2, h2;
        !           148:      int *lv, *hv;
        !           149: {
        !           150:   short arg1[8];
        !           151:   short arg2[8];
        !           152:   register int carry = 0;
        !           153:   register int i;
        !           154: 
        !           155:   encode (arg1, l1, h1);
        !           156:   encode (arg2, l2, h2);
        !           157: 
        !           158:   for (i = 0; i < 8; i++)
        !           159:     {
        !           160:       carry += arg1[i] + arg2[i];
        !           161:       arg1[i] = carry & 0xff;
        !           162:       carry >>= 8;
        !           163:     }
        !           164: 
        !           165:   decode (arg1, lv, hv);
        !           166: }
        !           167: 
        !           168: /* Negate a 64-bit integers with 64-bit result.
        !           169:    The argument is given as two `int' pieces in L1 and H1.
        !           170:    The value is stored as two `int' pieces in *LV and *HV.
        !           171:    We use the 8-shorts representation internally.  */
        !           172: 
        !           173: static void
        !           174: neg_double (l1, h1, lv, hv)
        !           175:      int l1, h1;
        !           176:      int *lv, *hv;
        !           177: {
        !           178:   if (l1 == 0)
        !           179:     {
        !           180:       *lv = 0;
        !           181:       *hv = - h1;
        !           182:     }
        !           183:   else
        !           184:     {
        !           185:       *lv = - l1;
        !           186:       *hv = ~ h1;
        !           187:     }
        !           188: }
        !           189: 
        !           190: /* Multiply two 64-bit integers with 64-bit result.
        !           191:    Each argument is given as two `int' pieces.
        !           192:    One argument is L1 and H1; the other, L2 and H2.
        !           193:    The value is stored as two `int' pieces in *LV and *HV.
        !           194:    We use the 8-shorts representation internally.  */
        !           195: 
        !           196: static void
        !           197: mul_double (l1, h1, l2, h2, lv, hv)
        !           198:      int l1, h1, l2, h2;
        !           199:      int *lv, *hv;
        !           200: {
        !           201:   short arg1[8];
        !           202:   short arg2[8];
        !           203:   short prod[16];
        !           204:   register int carry = 0;
        !           205:   register int i, j, k;
        !           206: 
        !           207:   encode (arg1, l1, h1);
        !           208:   encode (arg2, l2, h2);
        !           209: 
        !           210:   bzero (prod, sizeof prod);
        !           211: 
        !           212:   for (i = 0; i < 8; i++)
        !           213:     for (j = 0; j < 8; j++)
        !           214:       {
        !           215:        k = i + j;
        !           216:        carry = arg1[i] * arg2[j];
        !           217:        while (carry)
        !           218:          {
        !           219:            carry += prod[k];
        !           220:            prod[k] = carry & 0xff;
        !           221:            carry >>= 8;
        !           222:            k++;
        !           223:          }
        !           224:       }
        !           225: 
        !           226:   decode (prod, lv, hv);       /* @@decode ignores prod[8] -> prod[15] */
        !           227: }
        !           228: 
        !           229: /* Shift the 64-bit integer in L1, H1 left by COUNT places
        !           230:    keeping only PREC bits of result.
        !           231:    Shift right if COUNT is negative.
        !           232:    ARITH nonzero specifies arithmetic shifting; otherwise use logical shift.
        !           233:    Store the value as two `int' pieces in *LV and *HV.  */
        !           234: 
        !           235: static void
        !           236: lshift_double (l1, h1, count, prec, lv, hv, arith)
        !           237:      int l1, h1, count, prec;
        !           238:      int *lv, *hv;
        !           239:      int arith;
        !           240: {
        !           241:   short arg1[8];
        !           242:   register int i;
        !           243:   register int carry;
        !           244: 
        !           245:   if (count < 0)
        !           246:     {
        !           247:       rshift_double (l1, h1, - count, prec, lv, hv, arith);
        !           248:       return;
        !           249:     }
        !           250: 
        !           251:   encode (arg1, l1, h1);
        !           252:   if (prec < HOST_BITS_PER_INT)
        !           253:     count &= (1 << prec) - 1;
        !           254: 
        !           255:   while (count > 0)
        !           256:     {
        !           257:       carry = 0;
        !           258:       for (i = 0; i < 8; i++)
        !           259:        {
        !           260:          carry += arg1[i] << 1;
        !           261:          arg1[i] = carry & 0xff;
        !           262:          carry >>= 8;
        !           263:        }
        !           264:       count--;
        !           265:     }
        !           266: 
        !           267:   decode (arg1, lv, hv);
        !           268: }
        !           269: 
        !           270: /* Shift the 64-bit integer in L1, H1 right by COUNT places
        !           271:    keeping only PREC bits of result.  COUNT must be positive.
        !           272:    ARITH nonzero specifies arithmetic shifting; otherwise use logical shift.
        !           273:    Store the value as two `int' pieces in *LV and *HV.  */
        !           274: 
        !           275: static void
        !           276: rshift_double (l1, h1, count, prec, lv, hv, arith)
        !           277:      int l1, h1, count, prec;
        !           278:      int *lv, *hv;
        !           279:      int arith;
        !           280: {
        !           281:   short arg1[8];
        !           282:   register int i;
        !           283:   register int carry;
        !           284: 
        !           285:   encode (arg1, l1, h1);
        !           286:   if (prec < HOST_BITS_PER_INT)
        !           287:     count &= (1 << prec) - 1;
        !           288: 
        !           289:   carry = arith && arg1[7] >> 7;
        !           290:   while (count > 0)
        !           291:     {
        !           292:       for (i = 7; i >= 0; i--)
        !           293:        {
        !           294:          carry <<= 8;
        !           295:          carry += arg1[i];
        !           296:          arg1[i] = (carry >> 1) & 0xff;
        !           297:        }
        !           298:       count--;
        !           299:     }
        !           300: 
        !           301:   decode (arg1, lv, hv);
        !           302: }
        !           303: 
        !           304: /* Rotate the 64-bit integer in L1, H1 left by COUNT places
        !           305:    keeping only PREC bits of result.
        !           306:    Rotate right if COUNT is negative.
        !           307:    Store the value as two `int' pieces in *LV and *HV.  */
        !           308: 
        !           309: static void
        !           310: lrotate_double (l1, h1, count, prec, lv, hv)
        !           311:      int l1, h1, count, prec;
        !           312:      int *lv, *hv;
        !           313: {
        !           314:   short arg1[8];
        !           315:   register int i;
        !           316:   register int carry;
        !           317: 
        !           318:   if (count < 0)
        !           319:     {
        !           320:       rrotate_double (l1, h1, - count, prec, lv, hv);
        !           321:       return;
        !           322:     }
        !           323: 
        !           324:   encode (arg1, l1, h1);
        !           325:   if (prec < HOST_BITS_PER_INT)
        !           326:     count &= (1 << prec) - 1;
        !           327: 
        !           328:   carry = arg1[7] >> 7;
        !           329:   while (count > 0)
        !           330:     {
        !           331:       for (i = 0; i < 8; i++)
        !           332:        {
        !           333:          carry += arg1[i] << 1;
        !           334:          arg1[i] = carry & 0xff;
        !           335:          carry >>= 8;
        !           336:        }
        !           337:       count--;
        !           338:     }
        !           339: 
        !           340:   decode (arg1, lv, hv);
        !           341: }
        !           342: 
        !           343: /* Rotate the 64-bit integer in L1, H1 left by COUNT places
        !           344:    keeping only PREC bits of result.  COUNT must be positive.
        !           345:    Store the value as two `int' pieces in *LV and *HV.  */
        !           346: 
        !           347: static void
        !           348: rrotate_double (l1, h1, count, prec, lv, hv)
        !           349:      int l1, h1, count, prec;
        !           350:      int *lv, *hv;
        !           351: {
        !           352:   short arg1[8];
        !           353:   register int i;
        !           354:   register int carry;
        !           355: 
        !           356:   encode (arg1, l1, h1);
        !           357:   if (prec < HOST_BITS_PER_INT)
        !           358:     count &= (1 << prec) - 1;
        !           359: 
        !           360:   carry = arg1[0] & 1;
        !           361:   while (count > 0)
        !           362:     {
        !           363:       for (i = 7; i >= 0; i--)
        !           364:        {
        !           365:          carry <<= 8;
        !           366:          carry += arg1[i];
        !           367:          arg1[i] = (carry >> 1) & 0xff;
        !           368:        }
        !           369:       count--;
        !           370:     }
        !           371: 
        !           372:   decode (arg1, lv, hv);
        !           373: }
        !           374: 
        !           375: /* Divide 64 bit integer LNUM, HNUM by 64 bit integer LDEN, HDEN
        !           376:    for a quotient (stored in *LQUO, *HQUO) and remainder (in *LREM, *HREM).
        !           377:    CODE is a tree code for a kind of division, one of
        !           378:    TRUNC_DIV_EXPR, FLOOR_DIV_EXPR, CEIL_DIV_EXPR and ROUND_DIV_EXPR.
        !           379:    It controls how the quotient is rounded to a integer.
        !           380:    UNS nonzero says do unsigned division.  */
        !           381: 
        !           382: static void
        !           383: div_and_round_double (code, uns,
        !           384:                      lnum_orig, hnum_orig, lden_orig, hden_orig,
        !           385:                      lquo, hquo, lrem, hrem)
        !           386:      enum tree_code code;
        !           387:      int uns;
        !           388:      int lnum_orig, hnum_orig;         /* num == numerator == dividend */
        !           389:      int lden_orig, hden_orig;         /* den == denominator == divisor */
        !           390:      int *lquo, *hquo, *lrem, *hrem;
        !           391: {
        !           392:   int quo_neg = 0;
        !           393:   short num[9], den[8], quo[8];        /* extra element for scaling.  */
        !           394:   register int i, j, work;
        !           395:   register int carry = 0;
        !           396:   int lnum = lnum_orig, hnum = hnum_orig;
        !           397:   int lden = lden_orig, hden = hden_orig;
        !           398: 
        !           399:   if ((hden == 0) && (lden == 0)) {
        !           400:     *hquo = *lquo = *hrem = *lrem = 0;
        !           401:     error
        !           402:       ("divide by 0 in constant folding - quotient and remainder set to 0.");
        !           403:     return;
        !           404:   }
        !           405: 
        !           406:   /* calculate quotient sign and convert operands to unsigned.  */
        !           407:   if (!uns) 
        !           408:     {
        !           409:       if (hden < 0) 
        !           410:        {
        !           411:          quo_neg = ~ quo_neg;
        !           412:          neg_double (lden, hden, &lden, &hden);
        !           413:        }
        !           414:       if (hnum < 0)
        !           415:        {
        !           416:          quo_neg = ~ quo_neg;
        !           417:          neg_double (lnum, hnum, &lnum, &hnum);
        !           418:        }
        !           419:     }
        !           420: 
        !           421:   if (hnum == 0 && hden == 0)
        !           422:     {                          /* single precision */
        !           423:       *hquo = *hrem = 0;
        !           424:       *lquo = (unsigned) lnum / lden;  /* rounds toward zero since positive args */
        !           425:       goto finish_up;
        !           426:     }
        !           427: 
        !           428:   if (hnum == 0)
        !           429:     {                          /* trivial case: dividend < divisor */
        !           430:       /* hden != 0 already checked.  */
        !           431:       *hquo = *lquo = 0;
        !           432:       *hrem = hnum;
        !           433:       *lrem = lnum;
        !           434:       goto finish_up;
        !           435:     }
        !           436: 
        !           437:   bzero (quo, sizeof quo);
        !           438: 
        !           439:   bzero (num, sizeof num);     /* to zero 9th element */
        !           440:   bzero (den, sizeof den);
        !           441: 
        !           442:   encode (num, lnum, hnum); 
        !           443:   encode (den, lden, hden);
        !           444: 
        !           445:   if (hden == 0)
        !           446:     {                          /* simpler algorithm */
        !           447:       /* hnum != 0 already checked.  */
        !           448:       for (i = 7; i >= 0; i--)
        !           449:        {
        !           450:          work = num[i] + (carry << 8);
        !           451:          quo[i] = work / lden;
        !           452:          carry = work % lden;
        !           453:        }
        !           454:     }
        !           455:   else {                       /* full double precision,
        !           456:                                   with thanks to Don Knuth's
        !           457:                                   "Semi-Numericial Algorithms".  */
        !           458: #define BASE 256
        !           459:     int quo_est, scale, num_hi_sig, den_hi_sig, quo_hi_sig;
        !           460: 
        !           461:     /* Find the highest non-zero divisor digit.  */
        !           462:     for (i = 7; ; i--)
        !           463:       if (den[i] != 0) {
        !           464:        den_hi_sig = i;
        !           465:        break;
        !           466:       }
        !           467:     for (i = 7; ; i--)
        !           468:       if (num[i] != 0) {
        !           469:        num_hi_sig = i;
        !           470:        break;
        !           471:       }
        !           472:     quo_hi_sig = num_hi_sig - den_hi_sig + 1;
        !           473: 
        !           474:     /* Insure that the first digit of the divisor is at least BASE/2.
        !           475:        This is required by the quotient digit estimation algorithm.  */
        !           476: 
        !           477:     scale = BASE / (den[den_hi_sig] + 1);
        !           478:     if (scale > 1) {           /* scale divisor and dividend */
        !           479:       carry = 0;
        !           480:       for (i = 0; i <= 8; i++) {
        !           481:        work = (num[i] * scale) + carry;
        !           482:        num[i] = work & 0xff;
        !           483:        carry = work >> 8;
        !           484:        if (num[i] != 0) num_hi_sig = i;
        !           485:       }
        !           486:       carry = 0;
        !           487:       for (i = 0; i <= 7; i++) {
        !           488:        work = (den[i] * scale) + carry;
        !           489:        den[i] = work & 0xff;
        !           490:        carry = work >> 8;
        !           491:        if (den[i] != 0) den_hi_sig = i;
        !           492:       }
        !           493:     }
        !           494: 
        !           495:     /* Main loop */
        !           496:     for (i = quo_hi_sig; i > 0; i--) {
        !           497:       /* quess the next quotient digit, quo_est, by dividing the first
        !           498:         two remaining dividend digits by the high order quotient digit.
        !           499:         quo_est is never low and is at most 2 high.  */
        !           500: 
        !           501:       int num_hi;              /* index of highest remaining dividend digit */
        !           502: 
        !           503:       num_hi = i + den_hi_sig;
        !           504: 
        !           505:       work = (num[num_hi] * BASE) + (num_hi ? 0 : num[num_hi - 1]);
        !           506:       if (num[num_hi] != den[den_hi_sig]) {
        !           507:        quo_est = work / den[den_hi_sig];
        !           508:       }
        !           509:       else {
        !           510:        quo_est = BASE - 1;
        !           511:       }
        !           512: 
        !           513:       /* refine quo_est so it's usually correct, and at most one high.   */
        !           514:       while ((den[den_hi_sig - 1] * quo_est)
        !           515:             > (((work - (quo_est * den[den_hi_sig])) * BASE)
        !           516:                 + ((num_hi - 1) ? 0 : num[num_hi - 2]))) {
        !           517:        quo_est--;
        !           518:       }
        !           519: 
        !           520:       /* try quo_est as the quotient digit, by multiplying the
        !           521:          divisor by quo_est and subtracting from the remaining dividend.  */
        !           522: 
        !           523:       carry = 0;
        !           524: 
        !           525:       for (j = 0; j <= den_hi_sig; j++) {
        !           526:        int digit;
        !           527: 
        !           528:        work = num[i + j] - (quo_est * den[j]) + carry;
        !           529:        digit = work & 0xff;
        !           530:        carry = work >> 8;
        !           531:        if (digit < 0) {
        !           532:          digit += BASE;
        !           533:          carry--;
        !           534:        }
        !           535:        num[i + j] = digit;
        !           536:       }
        !           537: 
        !           538:       /* if quo_est was high by one, then num[i] went negative and
        !           539:         we need to correct things.  */
        !           540: 
        !           541:       if (num[num_hi] < 0) {
        !           542:        quo_est--;
        !           543:        carry = 0;              /* add divisor back in */
        !           544:        for (j = 0; j <= den_hi_sig; j++) {
        !           545:          work = num[i + j] + den[j] + carry;
        !           546:          if (work > BASE) {
        !           547:            work -= BASE;
        !           548:            carry = 1;
        !           549:          }
        !           550:          else {
        !           551:            carry = 0;
        !           552:          }
        !           553:          num[i + j] = work;
        !           554:        }
        !           555:        num [num_hi] += carry;
        !           556:       }
        !           557: 
        !           558:       /* store the quotient digit.  */
        !           559:       quo[i - 1] = quo_est;
        !           560:     }
        !           561:   }
        !           562: 
        !           563:   decode (quo, lquo, hquo);
        !           564: 
        !           565:  finish_up:
        !           566:   /* if result is negative, make it so.  */
        !           567:   if (quo_neg)
        !           568:     neg_double (*lquo, *hquo, lquo, hquo);
        !           569: 
        !           570:   /* compute trial remainder:  rem = num - (quo * den)  */
        !           571:   mul_double (*lquo, *hquo, lden_orig, hden_orig, lrem, hrem);
        !           572:   neg_double (*lrem, *hrem, lrem, hrem);
        !           573:   add_double (lnum_orig, hnum_orig, *lrem, *hrem, lrem, hrem);
        !           574: 
        !           575:   switch (code)
        !           576:     {
        !           577:     case TRUNC_DIV_EXPR:
        !           578:     case TRUNC_MOD_EXPR:       /* round toward zero */
        !           579:       return;
        !           580: 
        !           581:     case FLOOR_DIV_EXPR:
        !           582:     case FLOOR_MOD_EXPR:       /* round toward negative infinity */
        !           583:       if (quo_neg && (*lrem != 0 || *hrem != 0))   /* ratio < 0 && rem != 0 */
        !           584:        {
        !           585:          /* quo = quo - 1;  */
        !           586:          add_double (*lquo, *hquo, -1, -1, lquo, hquo);
        !           587:        }
        !           588:       else return;
        !           589:       break;
        !           590: 
        !           591:     case CEIL_DIV_EXPR:
        !           592:     case CEIL_MOD_EXPR:                /* round toward positive infinity */
        !           593:       if (!quo_neg && (*lrem != 0 || *hrem != 0))  /* ratio > 0 && rem != 0 */
        !           594:        {
        !           595:          add_double (*lquo, *hquo, 1, 0, lquo, hquo);
        !           596:        }
        !           597:       else return;
        !           598:       break;
        !           599:     
        !           600:     case ROUND_DIV_EXPR:
        !           601:     case ROUND_MOD_EXPR:       /* round to closest integer */
        !           602:       {
        !           603:        int labs_rem = *lrem, habs_rem = *hrem;
        !           604:        int labs_den = lden, habs_den = hden, ltwice, htwice;
        !           605: 
        !           606:        /* get absolute values */
        !           607:        if (*hrem < 0) neg_double(*lrem, *hrem, &labs_rem, &habs_rem);
        !           608:        if (hden < 0) neg_double(lden, hden, &labs_den, &habs_den);
        !           609: 
        !           610:        /* if (2 * abs (lrem) >= abs (lden)) */
        !           611:        mul_double(2, 0, labs_rem, habs_rem, &ltwice, &htwice);
        !           612:        if (((unsigned) habs_den < (unsigned) htwice)
        !           613:            || (((unsigned) habs_den == (unsigned) htwice)
        !           614:                && ((unsigned) labs_den < (unsigned) ltwice)))
        !           615:          {
        !           616:            if (*hquo < 0)
        !           617:              /* quo = quo - 1;  */
        !           618:              add_double (*lquo, *hquo, -1, -1, lquo, hquo);
        !           619:            else
        !           620:              /* quo = quo + 1; */
        !           621:              add_double (*lquo, *hquo, 1, 0, lquo, hquo);
        !           622:          }
        !           623:        else return;
        !           624:       }
        !           625:       break;
        !           626: 
        !           627:     default:
        !           628:       abort ();
        !           629:     }
        !           630: 
        !           631:   /* compute true remainder:  rem = num - (quo * den)  */
        !           632:   mul_double (*lquo, *hquo, lden_orig, hden_orig, lrem, hrem);
        !           633:   neg_double (*lrem, *hrem, lrem, hrem);
        !           634:   add_double (lnum_orig, hnum_orig, *lrem, *hrem, lrem, hrem);
        !           635: }
        !           636: 
        !           637: /* Split a tree IN into a constant and a variable part
        !           638:    that could be combined with CODE to make IN.
        !           639:    CODE must be a commutative arithmetic operation.
        !           640:    Store the constant part into *CONP and the variable in &VARP.
        !           641:    Return 1 if this was done; zero means the tree IN did not decompose
        !           642:    this way.
        !           643: 
        !           644:    If CODE is PLUS_EXPR we also split trees that use MINUS_EXPR.
        !           645:    Therefore, we must tell the caller whether the variable part
        !           646:    was subtracted.  We do this by storing 1 or -1 into *VARSIGNP.
        !           647:    The value stored is the coefficient for the variable term.
        !           648:    The constant term we return should always be added;
        !           649:    we negate it if necessary.  */
        !           650: 
        !           651: static int
        !           652: split_tree (in, code, varp, conp, varsignp)
        !           653:      tree in;
        !           654:      enum tree_code code;
        !           655:      tree *varp, *conp;
        !           656:      int *varsignp;
        !           657: {
        !           658:   register tree outtype = TREE_TYPE (in);
        !           659:   *varp = 0;
        !           660:   *conp = 0;
        !           661: 
        !           662:   /* Strip any conversions that don't change the machine mode.  */
        !           663:   while ((TREE_CODE (in) == NOP_EXPR
        !           664:          || TREE_CODE (in) == CONVERT_EXPR)
        !           665:         && (TYPE_MODE (TREE_TYPE (in))
        !           666:             == TYPE_MODE (TREE_TYPE (TREE_OPERAND (in, 0)))))
        !           667:     in = TREE_OPERAND (in, 0);
        !           668: 
        !           669:   if (TREE_CODE (in) == code
        !           670:       || (TREE_CODE (TREE_TYPE (in)) != REAL_TYPE
        !           671:          /* We can associate addition and subtraction together
        !           672:             (even though the C standard doesn't say so)
        !           673:             for integers because the value is not affected.
        !           674:             For reals, the value might be affected, so we can't.  */
        !           675:          &&
        !           676:          ((code == PLUS_EXPR && TREE_CODE (in) == MINUS_EXPR)
        !           677:           || (code == MINUS_EXPR && TREE_CODE (in) == PLUS_EXPR))))
        !           678:     {
        !           679:       enum tree_code code = TREE_CODE (TREE_OPERAND (in, 0));
        !           680:       if (code == INTEGER_CST || code == REAL_CST)
        !           681:        {
        !           682:          *conp = TREE_OPERAND (in, 0);
        !           683:          *varp = TREE_OPERAND (in, 1);
        !           684:          if (TREE_TYPE (*varp) != outtype)
        !           685:            *varp = convert (outtype, *varp);
        !           686:          *varsignp = (TREE_CODE (in) == MINUS_EXPR) ? -1 : 1;
        !           687:          return 1;
        !           688:        }
        !           689:       if (TREE_LITERAL (TREE_OPERAND (in, 1)))
        !           690:        {
        !           691:          *conp = TREE_OPERAND (in, 1);
        !           692:          *varp = TREE_OPERAND (in, 0);
        !           693:          *varsignp = 1;
        !           694:          if (TREE_TYPE (*varp) != outtype)
        !           695:            *varp = convert (outtype, *varp);
        !           696:          if (TREE_CODE (in) == MINUS_EXPR)
        !           697:            {
        !           698:              /* If operation is subtraction and constant is second,
        !           699:                 must negate it to get an additive constant.
        !           700:                 And this cannot be done unless it is a manifest constant.
        !           701:                 It could also be the address of a static variable.
        !           702:                 We cannot negate that, so give up.  */
        !           703:              if (TREE_CODE (*conp) == INTEGER_CST
        !           704:                  || TREE_CODE (*conp) == REAL_CST)
        !           705:                *conp = combine (MINUS_EXPR, integer_zero_node, *conp);
        !           706:              else
        !           707:                return 0;
        !           708:            }
        !           709:          return 1;
        !           710:        }
        !           711:       if (TREE_LITERAL (TREE_OPERAND (in, 0)))
        !           712:        {
        !           713:          *conp = TREE_OPERAND (in, 0);
        !           714:          *varp = TREE_OPERAND (in, 1);
        !           715:          if (TREE_TYPE (*varp) != outtype)
        !           716:            *varp = convert (outtype, *varp);
        !           717:          *varsignp = (TREE_CODE (in) == MINUS_EXPR) ? -1 : 1;
        !           718:          return 1;
        !           719:        }
        !           720:     }
        !           721:   return 0;
        !           722: }
        !           723: 
        !           724: /* Combine two constants NUM and ARG2 under operation CODE
        !           725:    to produce a new constant.
        !           726:    We assume ARG1 and ARG2 have the same data type,
        !           727:    or at least are the same kind of constant and the same machine mode.  */
        !           728: 
        !           729: tree
        !           730: combine (code, arg1, arg2)
        !           731:      enum tree_code code;
        !           732:      register tree arg1, arg2;
        !           733: {
        !           734:   if (TREE_CODE (arg1) == INTEGER_CST)
        !           735:     {
        !           736:       register int int1l = TREE_INT_CST_LOW (arg1);
        !           737:       register int int1h = TREE_INT_CST_HIGH (arg1);
        !           738:       int int2l = TREE_INT_CST_LOW (arg2);
        !           739:       int int2h = TREE_INT_CST_HIGH (arg2);
        !           740:       int low, hi;
        !           741:       int garbagel, garbageh;
        !           742:       register tree t;
        !           743:       int uns = TREE_UNSIGNED (TREE_TYPE (arg1));
        !           744: 
        !           745:       switch (code)
        !           746:        {
        !           747:        case BIT_IOR_EXPR:
        !           748:          t = build_int_2 (int1l | int2l, int1h | int2h);
        !           749:          break;
        !           750: 
        !           751:        case BIT_XOR_EXPR:
        !           752:          t = build_int_2 (int1l ^ int2l, int1h ^ int2h);
        !           753:          break;
        !           754: 
        !           755:        case BIT_AND_EXPR:
        !           756:          t = build_int_2 (int1l & int2l, int1h & int2h);
        !           757:          break;
        !           758: 
        !           759:        case BIT_ANDTC_EXPR:
        !           760:          t = build_int_2 (int1l & ~int2l, int1h & ~int2h);
        !           761:          break;
        !           762: 
        !           763:        case RSHIFT_EXPR:
        !           764:          int2l = - int2l;
        !           765:        case LSHIFT_EXPR:
        !           766:          lshift_double (int1l, int1h, int2l,
        !           767:                         TYPE_PRECISION (TREE_TYPE (arg1)),
        !           768:                         &low, &hi,
        !           769:                         !uns);
        !           770:          t = build_int_2 (low, hi);
        !           771:          break;
        !           772: 
        !           773:        case RROTATE_EXPR:
        !           774:          int2l = - int2l;
        !           775:        case LROTATE_EXPR:
        !           776:          lrotate_double (int1l, int1h, int2l,
        !           777:                          TYPE_PRECISION (TREE_TYPE (arg1)),
        !           778:                          &low, &hi);
        !           779:          t = build_int_2 (low, hi);
        !           780:          break;
        !           781: 
        !           782:        case PLUS_EXPR:
        !           783:          add_double (int1l, int1h, int2l, int2h, &low, &hi);
        !           784:          t = build_int_2 (low, hi);
        !           785:          break;
        !           786: 
        !           787:        case MINUS_EXPR:
        !           788:          neg_double (int2l, int2h, &int2l, &int2h);
        !           789:          add_double (int1l, int1h, int2l, int2h, &low, &hi);
        !           790:          t = build_int_2 (low, hi);
        !           791:          break;
        !           792: 
        !           793:        case MULT_EXPR:
        !           794:          mul_double (int1l, int1h, int2l, int2h, &low, &hi);
        !           795:          t = build_int_2 (low, hi);
        !           796:          break;
        !           797: 
        !           798:        case TRUNC_DIV_EXPR: case ROUND_DIV_EXPR: 
        !           799:        case FLOOR_DIV_EXPR: case CEIL_DIV_EXPR:
        !           800:          div_and_round_double (code, uns, int1l, int1h, int2l, int2h,
        !           801:                                &low, &hi, &garbagel, &garbageh);
        !           802:          t = build_int_2 (low, hi);
        !           803:          break;
        !           804: 
        !           805:        case TRUNC_MOD_EXPR: case ROUND_MOD_EXPR: 
        !           806:        case FLOOR_MOD_EXPR: case CEIL_MOD_EXPR:
        !           807:          div_and_round_double (code, uns, int1l, int1h, int2l, int2h,
        !           808:                                &garbagel, &garbageh, &low, &hi);
        !           809:          t = build_int_2 (low, hi);
        !           810:          break;
        !           811: 
        !           812:        case MIN_EXPR:
        !           813:        case MAX_EXPR:
        !           814:          if (uns)
        !           815:            {
        !           816:              low = (((unsigned) int1h < (unsigned) int2h)
        !           817:                     || (((unsigned) int1h == (unsigned) int2h)
        !           818:                         && ((unsigned) int1l < (unsigned) int2l)));
        !           819:            }
        !           820:          else
        !           821:            {
        !           822:              low = ((int1h < int2h)
        !           823:                     || ((int1h == int2h)
        !           824:                         && ((unsigned) int1l < (unsigned) int2l)));
        !           825:            }
        !           826:          if (low == (code == MIN_EXPR))
        !           827:            t = build_int_2 (int1l, int1h);
        !           828:          else
        !           829:            t = build_int_2 (int2l, int2h);
        !           830:          break;
        !           831: 
        !           832:        default:
        !           833:          abort ();
        !           834:        }
        !           835:       TREE_TYPE (t) = TREE_TYPE (arg1);
        !           836:       force_fit_type (t);
        !           837:       return t;
        !           838:     }
        !           839:   if (TREE_CODE (arg1) == REAL_CST)
        !           840:     {
        !           841:       register double d1 = TREE_REAL_CST (arg1);
        !           842:       register double d2 = TREE_REAL_CST (arg2);
        !           843:       register tree t;
        !           844: 
        !           845:       switch (code)
        !           846:        {
        !           847:        case PLUS_EXPR:
        !           848:          t = build_real (d1 + d2);
        !           849:          break;
        !           850: 
        !           851:        case MINUS_EXPR:
        !           852:          t = build_real (d1 - d2);
        !           853:          break;
        !           854: 
        !           855:        case MULT_EXPR:
        !           856:          t = build_real (d1 * d2);
        !           857:          break;
        !           858: 
        !           859:        case RDIV_EXPR:
        !           860:          if (d2 == 0)
        !           861:            return 0;
        !           862: 
        !           863:          t = build_real (d1 / d2);
        !           864:          break;
        !           865: 
        !           866:        case MIN_EXPR:
        !           867:          if (d1 < d2)
        !           868:            t = build_real (d1);
        !           869:          else
        !           870:            t = build_real (d2);
        !           871:          break;
        !           872: 
        !           873:        case MAX_EXPR:
        !           874:          if (d1 > d2)
        !           875:            t = build_real (d1);
        !           876:          else
        !           877:            t = build_real (d2);
        !           878:          break;
        !           879: 
        !           880:        default:
        !           881:          abort ();
        !           882:        }
        !           883:       TREE_TYPE (t) = TREE_TYPE (arg1);
        !           884:       return t;
        !           885:     }
        !           886:   if (TREE_CODE (arg1) == COMPLEX_CST)
        !           887:     {
        !           888:       register tree r1 = TREE_REALPART (arg1);
        !           889:       register tree i1 = TREE_IMAGPART (arg1);
        !           890:       register tree r2 = TREE_REALPART (arg2);
        !           891:       register tree i2 = TREE_IMAGPART (arg2);
        !           892:       register tree t;
        !           893: 
        !           894:       switch (code)
        !           895:        {
        !           896:        case PLUS_EXPR:
        !           897:          t = build_complex (combine (PLUS_EXPR, r1, r2),
        !           898:                             combine (PLUS_EXPR, i1, i2));
        !           899:          break;
        !           900: 
        !           901:        case MINUS_EXPR:
        !           902:          t = build_complex (combine (MINUS_EXPR, r1, r2),
        !           903:                             combine (MINUS_EXPR, i1, i2));
        !           904:          break;
        !           905: 
        !           906:        case MULT_EXPR:
        !           907:          t = build_complex (combine (MINUS_EXPR,
        !           908:                                      combine (MULT_EXPR, r1, r2),
        !           909:                                      combine (MULT_EXPR, i1, i2)),
        !           910:                             combine (PLUS_EXPR,
        !           911:                                      combine (MULT_EXPR, r1, i2),
        !           912:                                      combine (MULT_EXPR, i1, r2)));
        !           913:          break;
        !           914: 
        !           915:        case RDIV_EXPR:
        !           916:          {
        !           917:            register tree magsquared
        !           918:              = combine (PLUS_EXPR,
        !           919:                         combine (MULT_EXPR, r2, r2),
        !           920:                         combine (MULT_EXPR, i2, i2));
        !           921:            t = build_complex (combine (RDIV_EXPR,
        !           922:                                        combine (PLUS_EXPR,
        !           923:                                                 combine (MULT_EXPR, r1, r2),
        !           924:                                                 combine (MULT_EXPR, i1, i2)),
        !           925:                                        magsquared),
        !           926:                               combine (RDIV_EXPR,
        !           927:                                        combine (MINUS_EXPR,
        !           928:                                                 combine (MULT_EXPR, i1, r2),
        !           929:                                                 combine (MULT_EXPR, r1, i2)),
        !           930:                                        magsquared));
        !           931:          }
        !           932:          break;
        !           933: 
        !           934:        default:
        !           935:          abort ();
        !           936:        }
        !           937:       TREE_TYPE (t) = TREE_TYPE (arg1);
        !           938:       return t;
        !           939:     }
        !           940:   return 0;
        !           941: }
        !           942: 
        !           943: /* Given T, a tree representing type conversion of a constant,
        !           944:    return a constant tree representing the result of conversion.  */
        !           945: 
        !           946: static tree
        !           947: fold_convert (t)
        !           948:      register tree t;
        !           949: {
        !           950:   register tree arg1 = TREE_OPERAND (t, 0);
        !           951:   register tree type = TREE_TYPE (t);
        !           952: 
        !           953:   if (TREE_CODE (type) == POINTER_TYPE
        !           954:       || TREE_CODE (type) == INTEGER_TYPE
        !           955:       || TREE_CODE (type) == ENUMERAL_TYPE)
        !           956:     {
        !           957:       if (TREE_CODE (arg1) == INTEGER_CST)
        !           958:        {
        !           959:          /* Given an integer constant, make new constant with new type,
        !           960:             appropriately sign-extended or truncated.  */
        !           961:          register int inprec;
        !           962:          register int outprec;
        !           963: 
        !           964:          if (TREE_CODE (TREE_TYPE (arg1)) == POINTER_TYPE)
        !           965:            inprec = BITS_PER_WORD;
        !           966:          else
        !           967:            inprec = TYPE_PRECISION (TREE_TYPE (arg1));
        !           968:          if (TREE_CODE (type) == POINTER_TYPE)
        !           969:            outprec = BITS_PER_WORD;
        !           970:          else
        !           971:            outprec = TYPE_PRECISION (type);
        !           972: 
        !           973:          t = build_int_2 (TREE_INT_CST_LOW (arg1),
        !           974:                           TREE_INT_CST_HIGH (arg1));
        !           975:          TREE_TYPE (t) = type;
        !           976:          force_fit_type (t);
        !           977:        }
        !           978:       else if (TREE_CODE (arg1) == REAL_CST)
        !           979:        t = build_int_2 ((int) TREE_REAL_CST (arg1),
        !           980:                         (int) (TREE_REAL_CST (arg1) / 0x10000 / 0x10000));
        !           981:     }
        !           982:   else if (TREE_CODE (type) == REAL_TYPE)
        !           983:     {
        !           984:       if (TREE_CODE (arg1) == INTEGER_CST)
        !           985:        t = build_real_from_int_cst (arg1);
        !           986:       else if (TREE_CODE (arg1) == REAL_CST)
        !           987:        t = build_real (TREE_REAL_CST (arg1));
        !           988:     }
        !           989:   TREE_TYPE (t) = type;
        !           990:   TREE_LITERAL (t) = 1;
        !           991:   return t;
        !           992: }
        !           993: 
        !           994: /* Return nonzero if two constants (that are not manifest constants)
        !           995:    are necessarily equal.  It detects only the easiest, common case of
        !           996:    equality.  */
        !           997: 
        !           998: static int
        !           999: operand_equal_p (arg0, arg1)
        !          1000:      tree arg0, arg1;
        !          1001: {
        !          1002:   while ((TREE_CODE (arg0) == NOP_EXPR
        !          1003:          || TREE_CODE (arg0) == CONVERT_EXPR)
        !          1004:         && TYPE_MODE (TREE_TYPE (arg0)) == TYPE_MODE (TREE_TYPE (TREE_OPERAND (arg0, 0))))
        !          1005:     arg0 = TREE_OPERAND (arg0, 0);
        !          1006:   while ((TREE_CODE (arg1) == NOP_EXPR
        !          1007:          || TREE_CODE (arg1) == CONVERT_EXPR)
        !          1008:         && TYPE_MODE (TREE_TYPE (arg1)) == TYPE_MODE (TREE_TYPE (TREE_OPERAND (arg1, 0))))
        !          1009:     arg1 = TREE_OPERAND (arg1, 0);
        !          1010: 
        !          1011:   if (TREE_CODE (arg0) == TREE_CODE (arg1)
        !          1012:       && TREE_CODE (arg0) == ADDR_EXPR
        !          1013:       && TREE_OPERAND (arg0, 0) == TREE_OPERAND (arg1, 0))
        !          1014:     return 1;
        !          1015:   return 0;
        !          1016: }
        !          1017: 
        !          1018: /* Perform constant folding and related simplification of EXPR.
        !          1019:    The related simplifications include x*1 => x, x*0 => 0, etc.,
        !          1020:    and application of the associative law.
        !          1021:    NOP_EXPR conversions may be removed freely (as long as we
        !          1022:    are careful not to change the C type of the overall expression)
        !          1023:    We cannot simplify through a CONVERT_EXPR, FIX_EXPR or FLOAT_EXPR,
        !          1024:    but we can constant-fold them if they have constant operands.  */
        !          1025: 
        !          1026: tree
        !          1027: fold (expr) 
        !          1028:      tree expr;
        !          1029: {
        !          1030:   register tree t = expr;
        !          1031:   register tree arg0, arg1;
        !          1032:   register enum tree_code code = TREE_CODE (t);
        !          1033:   register int kind;
        !          1034: 
        !          1035:   /* WINS will be nonzero when the switch is done
        !          1036:      if all operands are constant.
        !          1037: 
        !          1038:      LOSES will be nonzero when the switch is done
        !          1039:      if any operand is volatile.
        !          1040:      This inhibits optimizations such as  (foo () * 0) => 0.
        !          1041:      But identity-element optimizations such as
        !          1042:      (foo () * 1) => (foo ()) can be done even if LOSES is set.  */
        !          1043: 
        !          1044:   int wins = 1;
        !          1045:   int loses = 0;
        !          1046: 
        !          1047:   /* Return right away if already constant.  */
        !          1048:   if (TREE_LITERAL (t))
        !          1049:     {
        !          1050:       if (code == CONST_DECL)
        !          1051:        return DECL_INITIAL (t);
        !          1052:       return t;
        !          1053:     }
        !          1054:   
        !          1055:   kind = *tree_code_type[(int) code];
        !          1056:   if (kind == 'e' || kind == 'r')
        !          1057:     {
        !          1058:       register int len = tree_code_length[(int) code];
        !          1059:       register int i;
        !          1060:       for (i = 0; i < len; i++)
        !          1061:        {
        !          1062:          if (TREE_OPERAND (t, i) == 0)
        !          1063:            continue;           /* Valid for CALL_EXPR, at least.  */
        !          1064:          if (TREE_CODE (TREE_OPERAND (t, i)) != INTEGER_CST
        !          1065:              && TREE_CODE (TREE_OPERAND (t, i)) != REAL_CST)
        !          1066:            /* Note that TREE_LITERAL isn't enough:
        !          1067:               static var addresses are constant but we can't
        !          1068:               do arithmetic on them.  */
        !          1069:            wins = 0;
        !          1070:          if (TREE_VOLATILE (TREE_OPERAND (t, i)))
        !          1071:            loses = 1;
        !          1072:        }
        !          1073:       arg0 = TREE_OPERAND (t, 0);
        !          1074:       if (len > 1)
        !          1075:        arg1 = TREE_OPERAND (t, 1);
        !          1076:     }
        !          1077: 
        !          1078:   /* Now WINS and LOSES are set as described above,
        !          1079:      ARG0 is the first operand of EXPR,
        !          1080:      and ARG1 is the second operand (if it has more than one operand).  */
        !          1081: 
        !          1082:   switch (code)
        !          1083:     {
        !          1084:     case INTEGER_CST:
        !          1085:     case REAL_CST:
        !          1086:     case STRING_CST:
        !          1087:     case COMPLEX_CST:
        !          1088:     case CONSTRUCTOR:
        !          1089:       return t;
        !          1090: 
        !          1091:     case CONST_DECL:
        !          1092:       return fold (DECL_INITIAL (t));
        !          1093: 
        !          1094:     case NOP_EXPR:
        !          1095:     case FLOAT_EXPR:
        !          1096:     case CONVERT_EXPR:
        !          1097:     case FIX_TRUNC_EXPR:
        !          1098:       /* Other kinds of FIX are not handled properly by fold_convert.  */
        !          1099:       if (!wins)
        !          1100:        {
        !          1101:          TREE_LITERAL (t) = TREE_LITERAL (arg0);
        !          1102:          return t;
        !          1103:        }
        !          1104:       return fold_convert (t);
        !          1105: 
        !          1106:     case RANGE_EXPR:
        !          1107:       TREE_LITERAL (t) = wins;
        !          1108:       return t;
        !          1109: 
        !          1110:     case NEGATE_EXPR:
        !          1111:       if (wins)
        !          1112:        {
        !          1113:          if (TREE_CODE (arg0) == INTEGER_CST)
        !          1114:            {
        !          1115:              if (TREE_INT_CST_LOW (arg0) == 0)
        !          1116:                t = build_int_2 (0, - TREE_INT_CST_HIGH (arg0));
        !          1117:              else
        !          1118:                t = build_int_2 (- TREE_INT_CST_LOW (arg0),
        !          1119:                                 ~ TREE_INT_CST_HIGH (arg0));
        !          1120:              force_fit_type (t);
        !          1121:            }
        !          1122:          else if (TREE_CODE (arg0) == REAL_CST)
        !          1123:            t = build_real (- TREE_REAL_CST (arg0));
        !          1124:          TREE_TYPE (t) = TREE_TYPE (expr);
        !          1125:        }
        !          1126:       return t;
        !          1127: 
        !          1128:     case ABS_EXPR:
        !          1129:       if (wins)
        !          1130:        {
        !          1131:          if (TREE_CODE (arg0) == INTEGER_CST)
        !          1132:            {
        !          1133:              if (! TREE_UNSIGNED (TREE_TYPE (expr))
        !          1134:                  || TREE_INT_CST_HIGH (arg0) < 0)
        !          1135:                {
        !          1136:                  if (TREE_INT_CST_LOW (arg0) == 0)
        !          1137:                    t = build_int_2 (0, - TREE_INT_CST_HIGH (arg0));
        !          1138:                  else
        !          1139:                    t = build_int_2 (- TREE_INT_CST_LOW (arg0),
        !          1140:                                     ~ TREE_INT_CST_HIGH (arg0));
        !          1141:                }
        !          1142:            }
        !          1143:          else if (TREE_CODE (arg0) == REAL_CST)
        !          1144:            {
        !          1145:              if (TREE_REAL_CST (arg0) < 0)
        !          1146:                t = build_real (- TREE_REAL_CST (arg0));
        !          1147:            }
        !          1148:          TREE_TYPE (t) = TREE_TYPE (expr);
        !          1149:        }
        !          1150:       return t;
        !          1151: 
        !          1152:     case BIT_NOT_EXPR:
        !          1153:       if (wins)
        !          1154:        {
        !          1155:          if (TREE_CODE (arg0) == INTEGER_CST)
        !          1156:            t = build_int_2 (~ TREE_INT_CST_LOW (arg0),
        !          1157:                             ~ TREE_INT_CST_HIGH (arg0));
        !          1158:          TREE_TYPE (t) = TREE_TYPE (expr);
        !          1159:          force_fit_type (t);
        !          1160:        }
        !          1161:       return t;
        !          1162: 
        !          1163:     case PLUS_EXPR:
        !          1164:       if (integer_zerop (arg0))
        !          1165:        return convert (TREE_TYPE (expr), arg1);
        !          1166:       if (integer_zerop (arg1))
        !          1167:        return convert (TREE_TYPE (expr), arg0);
        !          1168:     associate:
        !          1169:       /* In most languages, can't associate operations on floats
        !          1170:         through parentheses.  Rather than remember where the parentheses
        !          1171:         were, we don't associate floats at all.  It shouldn't matter much.  */
        !          1172:       if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE)
        !          1173:        goto binary;
        !          1174:       /* The varsign == -1 cases happen only for addition and subtraction.
        !          1175:         It says that the arg that was split was really CON minus VAR.
        !          1176:         The rest of the code applies to all associative operations.  */
        !          1177:       if (!wins)
        !          1178:        {
        !          1179:          tree var, con, tem;
        !          1180:          int varsign;
        !          1181:          tree inner_arg;
        !          1182: 
        !          1183:          if (split_tree (arg0, code, &var, &con, &varsign))
        !          1184:            {
        !          1185:              if (varsign == -1)
        !          1186:                {
        !          1187:                  /* EXPR is (CON-VAR) +- ARG1.  */
        !          1188:                  /* If it is + and VAR==ARG1, return just CONST.  */
        !          1189:                  if (code == PLUS_EXPR && operand_equal_p (var, arg1))
        !          1190:                    return con;
        !          1191:                    
        !          1192:                  /* Otherwise return (CON +- ARG1) - VAR.  */
        !          1193:                  TREE_SET_CODE (t, MINUS_EXPR);
        !          1194:                  TREE_OPERAND (t, 1) = var;
        !          1195:                  TREE_OPERAND (t, 0)
        !          1196:                    = fold (build (code, TREE_TYPE (t), con, arg1));
        !          1197:                }
        !          1198:              else
        !          1199:                {
        !          1200:                  /* EXPR is (VAR+CON) +- ARG1.  */
        !          1201:                  /* If it is - and VAR==ARG1, return just CONST.  */
        !          1202:                  if (code == MINUS_EXPR && operand_equal_p (var, arg1))
        !          1203:                    return con;
        !          1204:                    
        !          1205:                  /* Otherwise return VAR +- (ARG1 +- CON).  */
        !          1206:                  TREE_OPERAND (t, 1) = tem
        !          1207:                    = fold (build (code, TREE_TYPE (t), arg1, con));
        !          1208:                  TREE_OPERAND (t, 0) = var;
        !          1209:                  if (integer_zerop (tem)
        !          1210:                      && (code == PLUS_EXPR || code == MINUS_EXPR))
        !          1211:                    return var;
        !          1212:                  /* If we have x +/- (c - d) [c an explicit integer]
        !          1213:                     change it to x -/+ (d - c) since if d is relocatable
        !          1214:                     then the latter can be a single immediate insn
        !          1215:                     and the former cannot.  */
        !          1216:                  if (TREE_CODE (tem) == MINUS_EXPR
        !          1217:                      && TREE_CODE (TREE_OPERAND (tem, 0)) == INTEGER_CST)
        !          1218:                    {
        !          1219:                      tree tem1 = TREE_OPERAND (tem, 1);
        !          1220:                      TREE_OPERAND (tem, 1) = TREE_OPERAND (tem, 0);
        !          1221:                      TREE_OPERAND (tem, 0) = tem1;
        !          1222:                      TREE_SET_CODE (t,
        !          1223:                                     (code == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR));
        !          1224:                    }
        !          1225:                }
        !          1226:              return t;
        !          1227:            }
        !          1228: 
        !          1229:          if (split_tree (arg1, code, &var, &con, &varsign))
        !          1230:            {
        !          1231:              /* EXPR is ARG0 +- (CON +- VAR).  */
        !          1232:              if (varsign == -1)
        !          1233:                TREE_SET_CODE (t,
        !          1234:                               (code == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR));
        !          1235:              if (TREE_CODE (t) == MINUS_EXPR && operand_equal_p (var, arg0))
        !          1236:                return con;
        !          1237:              TREE_OPERAND (t, 0)
        !          1238:                = fold (build (code, TREE_TYPE (t), arg0, con));
        !          1239:              TREE_OPERAND (t, 1) = var;
        !          1240:              if (integer_zerop (TREE_OPERAND (t, 0))
        !          1241:                  && TREE_CODE (t) == PLUS_EXPR)
        !          1242:                return var;
        !          1243:              return t;
        !          1244:            }
        !          1245:        }
        !          1246:     binary:
        !          1247:       {
        !          1248:        register tree t1 = NULL_TREE;
        !          1249:        if (wins)
        !          1250:          t1 = combine (code, arg0, arg1);
        !          1251:        if (t1 != NULL_TREE) return t1;
        !          1252:        return t;
        !          1253:       }
        !          1254: 
        !          1255:     case MINUS_EXPR:
        !          1256:       if (! wins && integer_zerop (arg0))
        !          1257:        return build (NEGATE_EXPR, TREE_TYPE (expr), arg1);
        !          1258:       if (integer_zerop (arg1))
        !          1259:        return convert (TREE_TYPE (expr), arg0);
        !          1260:       /* Fold &x - &x.  This can happen from &x.foo - &x.  */
        !          1261:       if (operand_equal_p (arg0, arg1))
        !          1262:        return convert (TREE_TYPE (t), integer_zero_node);
        !          1263:       goto associate;
        !          1264: 
        !          1265:     case MULT_EXPR:
        !          1266:       if (!loses && integer_zerop (arg0))
        !          1267:        return convert (TREE_TYPE (expr), arg0);
        !          1268:       if (!loses && integer_zerop (arg1))
        !          1269:        return convert (TREE_TYPE (expr), arg1);
        !          1270:       if (integer_onep (arg0))
        !          1271:        return convert (TREE_TYPE (expr), arg1);
        !          1272:       if (integer_onep (arg1))
        !          1273:        return convert (TREE_TYPE (expr), arg0);
        !          1274:       goto associate;
        !          1275: 
        !          1276:     case BIT_IOR_EXPR:
        !          1277:       if (!loses && integer_all_onesp (arg0))
        !          1278:        return convert (TREE_TYPE (expr), arg0);
        !          1279:       if (!loses && integer_all_onesp (arg1))
        !          1280:        return convert (TREE_TYPE (expr), arg1);
        !          1281:     case BIT_XOR_EXPR:
        !          1282:       if (integer_zerop (arg0))
        !          1283:        return convert (TREE_TYPE (expr), arg1);
        !          1284:       if (integer_zerop (arg1))
        !          1285:        return convert (TREE_TYPE (expr), arg0);
        !          1286:       goto associate;
        !          1287: 
        !          1288:     case BIT_AND_EXPR:
        !          1289:       if (integer_all_onesp (arg0))
        !          1290:        return convert (TREE_TYPE (expr), arg1);
        !          1291:       if (integer_all_onesp (arg1))
        !          1292:        return convert (TREE_TYPE (expr), arg0);
        !          1293:       if (!loses && integer_zerop (arg0))
        !          1294:        return convert (TREE_TYPE (expr), arg0);
        !          1295:       if (!loses && integer_zerop (arg1))
        !          1296:        return convert (TREE_TYPE (expr), arg1);
        !          1297:       /* Simplify (int)((unsigned char)x & 0x377) into (int)(unsigned char)x.  */
        !          1298:       if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == NOP_EXPR
        !          1299:          && TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg1, 0))))
        !          1300:        {
        !          1301:          int prec = TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg1, 0)));
        !          1302:          if (prec < BITS_PER_WORD && prec < HOST_BITS_PER_INT
        !          1303:              && (~TREE_INT_CST_LOW (arg0) & ((1 << prec) - 1)) == 0)
        !          1304:            return convert (TREE_TYPE (expr), arg1);
        !          1305:        }
        !          1306:       if (TREE_CODE (arg1) == INTEGER_CST && TREE_CODE (arg0) == NOP_EXPR
        !          1307:          && TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0))))
        !          1308:        {
        !          1309:          int prec = TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)));
        !          1310:          if (prec < BITS_PER_WORD && prec < HOST_BITS_PER_INT
        !          1311:              && (~TREE_INT_CST_LOW (arg1) & ((1 << prec) - 1)) == 0)
        !          1312:            return convert (TREE_TYPE (expr), arg0);
        !          1313:        }
        !          1314:       goto associate;
        !          1315: 
        !          1316:     case BIT_ANDTC_EXPR:
        !          1317:       if (integer_all_onesp (arg0))
        !          1318:        return convert (TREE_TYPE (expr), arg1);
        !          1319:       if (integer_zerop (arg1))
        !          1320:        return convert (TREE_TYPE (expr), arg0);
        !          1321:       if (!loses && integer_zerop (arg0))
        !          1322:        return convert (TREE_TYPE (expr), arg0);
        !          1323:       if (!loses && integer_all_onesp (arg1))
        !          1324:        return combine (code, arg1, arg1);
        !          1325:       goto binary;
        !          1326: 
        !          1327:     case TRUNC_DIV_EXPR:
        !          1328:     case ROUND_DIV_EXPR:
        !          1329:     case FLOOR_DIV_EXPR:
        !          1330:     case CEIL_DIV_EXPR:
        !          1331:     case RDIV_EXPR:
        !          1332:       if (integer_onep (arg1))
        !          1333:        return convert (TREE_TYPE (expr), arg0);
        !          1334:       goto binary;
        !          1335: 
        !          1336:     case CEIL_MOD_EXPR:
        !          1337:     case FLOOR_MOD_EXPR:
        !          1338:     case ROUND_MOD_EXPR:
        !          1339:     case TRUNC_MOD_EXPR:
        !          1340:       if (!loses && integer_onep (arg1))
        !          1341:        return combine (code, arg1, arg1);
        !          1342:       goto binary;
        !          1343: 
        !          1344:     case LSHIFT_EXPR:
        !          1345:     case RSHIFT_EXPR:
        !          1346:     case LROTATE_EXPR:
        !          1347:     case RROTATE_EXPR:
        !          1348:       if (integer_zerop (arg1))
        !          1349:        return convert (TREE_TYPE (expr), arg0);
        !          1350:       goto binary;
        !          1351: 
        !          1352:     case MIN_EXPR: case MAX_EXPR:
        !          1353:       goto associate;
        !          1354: 
        !          1355:     case TRUTH_NOT_EXPR:
        !          1356:       if (wins)
        !          1357:        {
        !          1358:          if (TREE_CODE (arg0) == INTEGER_CST)
        !          1359:            {
        !          1360:              t = build_int_2 ((TREE_INT_CST_LOW (arg0) == 0
        !          1361:                                && TREE_INT_CST_HIGH (arg0) == 0),
        !          1362:                               0);
        !          1363:              TREE_TYPE (t) = integer_type_node;
        !          1364:            }
        !          1365:          if (TREE_CODE (arg0) == REAL_CST)
        !          1366:            {
        !          1367:              t = build_int_2 (TREE_REAL_CST (arg0) == 0, 0);
        !          1368:              TREE_TYPE (t) = integer_type_node;
        !          1369:            }
        !          1370:        }
        !          1371:       return t;
        !          1372: 
        !          1373:     case TRUTH_AND_EXPR:
        !          1374:     case TRUTH_ANDIF_EXPR:
        !          1375:       if (wins)
        !          1376:        {
        !          1377:          if (TREE_CODE (arg0) == INTEGER_CST
        !          1378:              && TREE_CODE (arg1) == INTEGER_CST)
        !          1379:            t = build_int_2 (((TREE_INT_CST_LOW (arg0) || TREE_INT_CST_HIGH (arg0))
        !          1380:                              && (TREE_INT_CST_LOW (arg1) || TREE_INT_CST_HIGH (arg1))),
        !          1381:                             0);
        !          1382:          if (TREE_CODE (arg0) == REAL_CST
        !          1383:              && TREE_CODE (arg1) == REAL_CST)
        !          1384:            t = build_int_2 ((TREE_REAL_CST (arg0) && TREE_REAL_CST (arg1)),
        !          1385:                             0);
        !          1386:          TREE_TYPE (t) = TREE_TYPE (expr);
        !          1387:        }
        !          1388:       return t;
        !          1389: 
        !          1390:     case TRUTH_OR_EXPR:
        !          1391:     case TRUTH_ORIF_EXPR:
        !          1392:       if (wins)
        !          1393:        {
        !          1394:          if (TREE_CODE (arg0) == INTEGER_CST
        !          1395:              && TREE_CODE (arg1) == INTEGER_CST)
        !          1396:            t = build_int_2 (((TREE_INT_CST_LOW (arg0) || TREE_INT_CST_HIGH (arg0))
        !          1397:                              || (TREE_INT_CST_LOW (arg1) || TREE_INT_CST_HIGH (arg1))),
        !          1398:                             0);
        !          1399:          if (TREE_CODE (arg0) == REAL_CST && TREE_CODE (arg1) == REAL_CST)
        !          1400:            t = build_int_2 ((TREE_REAL_CST (arg0) || TREE_REAL_CST (arg1)),
        !          1401:                             0);
        !          1402:          TREE_TYPE (t) = TREE_TYPE (expr);
        !          1403:        }
        !          1404:       return t;
        !          1405: 
        !          1406:     case EQ_EXPR:
        !          1407:     case NE_EXPR:
        !          1408:     case LT_EXPR:
        !          1409:     case GT_EXPR:
        !          1410:     case LE_EXPR:
        !          1411:     case GE_EXPR:
        !          1412:       /* Convert foo++ == CONST into ++foo == CONST + INCR.
        !          1413:         First, see if one arg is constant; find the constant arg
        !          1414:         and the other one.  */
        !          1415:       {
        !          1416:        tree constop = 0, varop;
        !          1417:        tree *constoploc;
        !          1418: 
        !          1419:        if (TREE_LITERAL (arg1))
        !          1420:          constoploc = &TREE_OPERAND (t, 1), constop = arg1, varop = arg0;
        !          1421:        if (TREE_LITERAL (arg0))
        !          1422:          constoploc = &TREE_OPERAND (t, 0), constop = arg0, varop = arg1;
        !          1423: 
        !          1424:        if (constop && TREE_CODE (varop) == POSTINCREMENT_EXPR)
        !          1425:          {
        !          1426:            tree newconst
        !          1427:              = fold (build (PLUS_EXPR, TREE_TYPE (t),
        !          1428:                             constop, TREE_OPERAND (varop, 1)));
        !          1429:            /* This optimization is invalid for ordered comparisons
        !          1430:               if CONST+INCR overflows!
        !          1431:               We can assume that address + integer will not overflow.  */
        !          1432:            if (TREE_CODE (newconst) != INTEGER_CST
        !          1433:                || ! tree_int_cst_lt (newconst, constop)
        !          1434:                || code == EQ_EXPR || code == NE_EXPR)
        !          1435:              {
        !          1436:                TREE_CODE (varop) = PREINCREMENT_EXPR;
        !          1437:                *constoploc = newconst;
        !          1438:                return t;
        !          1439:              }
        !          1440:          }
        !          1441:        else if (constop && TREE_CODE (varop) == POSTDECREMENT_EXPR)
        !          1442:          {
        !          1443:            tree newconst
        !          1444:              = fold (build (MINUS_EXPR, TREE_TYPE (t),
        !          1445:                             constop, TREE_OPERAND (varop, 1)));
        !          1446:            if (TREE_CODE (newconst) != INTEGER_CST
        !          1447:                || tree_int_cst_lt (newconst, constop)
        !          1448:                || code == EQ_EXPR || code == NE_EXPR)
        !          1449:              {
        !          1450:                TREE_CODE (varop) = PREDECREMENT_EXPR;
        !          1451:                *constoploc = newconst;
        !          1452:                return t;
        !          1453:              }
        !          1454:          }
        !          1455:       }
        !          1456: 
        !          1457:       /* An unsigned comparison against 0 can be simplified.  */
        !          1458:       if (integer_zerop (arg0)
        !          1459:          && (TREE_CODE (TREE_TYPE (arg0)) == INTEGER_TYPE
        !          1460:              || TREE_CODE (TREE_TYPE (arg0)) == POINTER_TYPE)
        !          1461:          && TREE_UNSIGNED (TREE_TYPE (arg0)))
        !          1462:        {
        !          1463:          switch (TREE_CODE (t))
        !          1464:            {
        !          1465:            case LT_EXPR:
        !          1466:              TREE_CODE (t) = NE_EXPR;
        !          1467:              break;
        !          1468:            case GE_EXPR:
        !          1469:              TREE_CODE (t) = EQ_EXPR;
        !          1470:              break;
        !          1471:            case LE_EXPR:
        !          1472:              return build (COMPOUND_EXPR, integer_type_node,
        !          1473:                            arg1, integer_one_node);
        !          1474:            case GT_EXPR:
        !          1475:              return build (COMPOUND_EXPR, integer_type_node,
        !          1476:                            arg1, integer_zero_node);
        !          1477:            }
        !          1478:        }
        !          1479: 
        !          1480:       /* An unsigned comparison against 0 can be simplified.  */
        !          1481:       if (integer_zerop (arg1)
        !          1482:          && (TREE_CODE (TREE_TYPE (arg1)) == INTEGER_TYPE
        !          1483:              || TREE_CODE (TREE_TYPE (arg1)) == POINTER_TYPE)
        !          1484:          && TREE_UNSIGNED (TREE_TYPE (arg1)))
        !          1485:        {
        !          1486:          switch (TREE_CODE (t))
        !          1487:            {
        !          1488:            case GT_EXPR:
        !          1489:              TREE_CODE (t) = NE_EXPR;
        !          1490:              break;
        !          1491:            case LE_EXPR:
        !          1492:              TREE_CODE (t) = EQ_EXPR;
        !          1493:              break;
        !          1494:            case GE_EXPR:
        !          1495:              return build (COMPOUND_EXPR, integer_type_node,
        !          1496:                            arg0, integer_one_node);
        !          1497:            case LT_EXPR:
        !          1498:              return build (COMPOUND_EXPR, integer_type_node,
        !          1499:                            arg0, integer_zero_node);
        !          1500:            }
        !          1501:        }
        !          1502: 
        !          1503:       /* To compute GT, swap the arguments and do LT.
        !          1504:         To compute GE, do LT and invert the result.
        !          1505:         To compute LE, swap the arguments, do LT and invert the result.
        !          1506:         To compute NE, do EQ and invert the result.  */
        !          1507:       if (code == LE_EXPR || code == GT_EXPR)
        !          1508:        {
        !          1509:          register tree temp = arg0;
        !          1510:          arg0 = arg1;
        !          1511:          arg1 = temp;
        !          1512:        }
        !          1513: 
        !          1514:       /* Compute a result for LT or EQ if args permit.  */
        !          1515:       if (TREE_CODE (arg0) == INTEGER_CST
        !          1516:          && TREE_CODE (arg1) == INTEGER_CST)
        !          1517:        {
        !          1518:          if (code == EQ_EXPR || code == NE_EXPR)
        !          1519:            t = build_int_2
        !          1520:              (TREE_INT_CST_LOW (arg0) == TREE_INT_CST_LOW (arg1)
        !          1521:               && TREE_INT_CST_HIGH (arg0) == TREE_INT_CST_HIGH (arg1),
        !          1522:               0);
        !          1523:          else
        !          1524:            t = build_int_2 ((TREE_UNSIGNED (TREE_TYPE (arg0))
        !          1525:                              ? INT_CST_LT_UNSIGNED (arg0, arg1)
        !          1526:                              : INT_CST_LT (arg0, arg1)),
        !          1527:                             0);
        !          1528:        }
        !          1529:       else if (TREE_CODE (arg0) == REAL_CST
        !          1530:               && TREE_CODE (arg1) == REAL_CST)
        !          1531:        {
        !          1532:          if (code == EQ_EXPR || code == NE_EXPR)
        !          1533:            t = build_int_2 (TREE_REAL_CST (arg0) == TREE_REAL_CST (arg1), 0);
        !          1534:          else
        !          1535:            t = build_int_2 (TREE_REAL_CST (arg0) < TREE_REAL_CST (arg1), 0);
        !          1536:        }
        !          1537:       else
        !          1538:        return t;
        !          1539: 
        !          1540:       /* If we wanted ...-or-equal, invert the result.  */
        !          1541:       if (code == GE_EXPR || code == LE_EXPR || code == NE_EXPR)
        !          1542:        TREE_INT_CST_LOW (t) ^= 1;
        !          1543:       TREE_TYPE (t) = TREE_TYPE (expr);
        !          1544:       return t;
        !          1545: 
        !          1546:     COND_EXPR:
        !          1547:       if (TREE_LITERAL (arg0))
        !          1548:        return TREE_OPERAND (expr, (integer_zerop (arg0) ? 2 : 1));
        !          1549:       return t;
        !          1550: 
        !          1551:     default:
        !          1552:       return t;
        !          1553:     } /* switch (code) */
        !          1554: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.