现在的位置: 首页 > 综合 > 正文

Studying note of GCC-3.4.6 source (10 cont3)

2013年04月12日 ⁄ 综合 ⁄ 共 4741字 ⁄ 字号 评论关闭

1.6.1.1.1.1.4.              Addition and minus

Then for other operation, back in int_const_binop.

 

int_const_binop (continue)

 

1239     case PLUS_EXPR:

1240       overflow = add_double (int1l, int1h, int2l, int2h, &low, &hi);

1241       break;

1242

1243     case MINUS_EXPR:

1244       neg_double (int2l, int2h, &low, &hi);

1245       add_double (int1l, int1h, low, hi, &low, &hi);

1246       overflow = OVERFLOW_SUM_SIGN (hi, int2h, int1h);

1247       break;

1248

1249     case MULT_EXPR:

1250       overflow = mul_double (int1l, int1h, int2l, int2h, &low, &hi);

1251       break;

1252

1253     case TRUNC_DIV_EXPR:

1254     case FLOOR_DIV_EXPR: case CEIL_DIV_EXPR:

1255     case EXACT_DIV_EXPR:

1256       /* This is a shortcut for a common special case.  */

1257       if (int2h == 0 && (HOST_WIDE_INT) int2l > 0

1258          && ! TREE_CONSTANT_OVERFLOW (arg1)

1259          && ! TREE_CONSTANT_OVERFLOW (arg2)

1260          && int1h == 0 && (HOST_WIDE_INT) int1l >= 0)

1261       {

1262         if (code == CEIL_DIV_EXPR)

1263           int1l += int2l - 1;

1264

1265         low = int1l / int2l, hi = 0;

1266         break;

1267       }

1268

1269       /* ... fall through ...  */

 

add_double accepts two operands, in its parameters, l1 a006Ed h1 are the low and high part of the first operand, so are l2 and h2 for second operand.

 

261  int

262  add_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,              in fold-const.c

263             unsigned HOST_WIDE_INT l2, HOST_WIDE_INT h2,

264             unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv)

265  {

266    unsigned HOST_WIDE_INT l;

267    HOST_WIDE_INT h;

268 

269    l = l1 + l2;

270    h = h1 + h2 + (l < l1);

271 

272    *lv = l;

273    *hv = h;

274    return OVERFLOW_SUM_SIGN (h1, h2, h);

275  }

 

Above, if the sum of the low parts is smaller, it means carrier is produced for the sum, takes it into the high part at line 270. For high part, such case means overflow. Overflow occurs if A and B have the same sign, but A and SUM differ in sign. Below macro detects overflow by this way.

 

136  #define OVERFLOW_SUM_SIGN(a, b, sum) ((~((a) ^ (b)) & ((a) ^ (sum))) < 0)

 

neg_double is alittle tricky, it is because of the 2 complement reprensentation.

 

282  int

283  neg_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,      in fold-const.c

284             unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv)

285  {

286    if (l1 == 0)

287    {

288      *lv = 0;

289      *hv = - h1;

290      return (*hv & h1) < 0;

291    }

292    else

293    {

294      *lv = -l1;

295      *hv = ~h1;

296      return 0;

297    }

298  }

1.6.1.1.1.1.5.              Multiplication

While to implement effective and correct multiplication, it must carefully to deal with the problem of overflow as multiplication may double the size of operands.

 

307  int

308  mul_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,      in fold-const.c

309             unsigned HOST_WIDE_INT l2, HOST_WIDE_INT h2,

310             unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv)

311  {

312    HOST_WIDE_INT arg1[4];

313    HOST_WIDE_INT arg2[4];

314    HOST_WIDE_INT prod[4 * 2];

315    unsigned HOST_WIDE_INT carry;

316    int i, j, k;

317    unsigned HOST_WIDE_INT toplow, neglow;

318    HOST_WIDE_INT tophigh, neghigh;

319 

320    encode (arg1, l1, h1);

321    encode (arg2, l2, h2);

322 

323    memset (prod, 0, sizeof prod);

324 

325    for (i = 0; i < 4; i++)

326    {

327      carry = 0;

328      for (j = 0; j < 4; j++)

329      {

330        k = i + j;

331        /* This product is <= 0xFFFE0001, the sum <= 0xFFFF0000.  */

332        carry += arg1[i] * arg2[j];

333        /* Since prod[p] < 0xFFFF, this sum <= 0xFFFFFFFF.  */

334        carry += prod[k];

335        prod[k] = LOWPART (carry);

336        carry = HIGHPART (carry);

337      }

338      prod[i + 4] = carry;

339    }

340 

341    decode (prod, lv, hv); /* This ignores prod[4] through prod[4*2-1] */

342 

343    /* Check for overflow by calculating the top half of the answer in full;

344      it should agree with the low half's sign bit.  */

345    decode (prod + 4, &toplow, &tophigh);

346    if (h1 < 0)

347    {

348      neg_double (l2, h2, &neglow, &neghigh);

349      add_double (neglow, neghigh, toplow, tophigh, &toplow, &tophigh);

350    }

351    if (h2 < 0)

352    {

353      neg_double (l1, h1, &neglow, &neghigh);

354      add_double (neglow, neghigh, toplow, tophigh, &toplow, &tophigh);

355    }

356    return (*hv < 0 ? ~(toplow & tophigh) : toplow | tophigh) != 0;

357  }

 

To handle the problem of overflow, encode at line 320 and 321 will put the operands into the buffer of double size.

 

153  static void                                                                                           in fold-const.c

154  encode (HOST_WIDE_INT *words, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi)

155  {

156    words[0] = LOWPART (low);

157    words[1] = HIGHPART (low);

158    words[2] = LOWPART (hi);

159    words[3] = HIGHPART (hi);

160  }

 

To see the operation in FOR loop at line 325 clearly, using following example to demonstrate the procedure. Assuming multiplication (decimal integer of size 2, and the result will be temperarily saved in buffer of size 4):

 

65 (then h1 = 6, l1 = 5)

              X     23 (then h2 = 2, l2 = 3) 

l1 * l2 (15)

              +     carry (0)

              +     prod[0+0] (0)     

carry (1) ß 15 à prod[0+0] (5)  (end of l1 * l2)

h1 * l2 (18)

+    carry (1)

              +    prod[1+0] (0)     

carry (1) ß19 à prod[1+0] (9)   (end of h1 * l2, prod[0+2] = carry = 1)

              l1 * h2 (10)

       +     carry (0)

       +     prod[0+1] (9)     

carry (1) ß 19 à prod[0+1] (8)  (end of l1 * h2)

              h1 * h2 (12)

       +     carry (1)<

抱歉!评论已关闭.