Studying note of GCC-3.4.6 source (10 cont4)

1.6.3.1.1.2.      Get the result

In the rest of int_const_binop, the operation result which now are saved in low and hi, will be combined into a tree object with corresponding fields set. Below notrunc if nonzero, indicates don’t trucate to fit the type; overflow records if overflow occurs in the procedure, and no_overflow if nonzero, indicates the operation won’t lead to overflow.

 

int_const_binop (continue)

 

1331   /* If this is for a sizetype, can be represented as one (signed)

1332     HOST_WIDE_INT word, and doesn't overflow, use size_int since it caches

1333     constants.  */

1334   if (is_sizetype

1335       && ((hi == 0 && (HOST_WIDE_INT) low >= 0)

1336            || (hi == -1 && (HOST_WIDE_INT) low < 0))

1337       && overflow == 0 && ! TREE_OVERFLOW (arg1) && ! TREE_OVERFLOW (arg2))

1338     return size_int_type_wide (low, type);

1339   else

1340   {

1341     t = build_int_2 (low, hi);

1342     TREE_TYPE (t) = TREE_TYPE (arg1);

1343   }

1344

1345   TREE_OVERFLOW (t)

1346     = ((notrunc

1347        ? (!uns || is_sizetype) && overflow

1348         : (force_fit_type (t, (!uns || is_sizetype) && overflow)

1349        && ! no_overflow))

1350        | TREE_OVERFLOW (arg1)

1351        | TREE_OVERFLOW (arg2));

1352

1353   /* If we're doing a size calculation, unsigned arithmetic does overflow.

1354     So check if force_fit_type truncated the value.  */

1355   if (is_sizetype

1356       && ! TREE_OVERFLOW (t)

1357       && (TREE_INT_CST_HIGH (t) != hi

1358           || TREE_INT_CST_LOW (t) != low))

1359     TREE_OVERFLOW (t) = 1;

1360

1361   TREE_CONSTANT_OVERFLOW (t) = (TREE_OVERFLOW (t)

1362                            | TREE_CONSTANT_OVERFLOW (arg1)

1363                            | TREE_CONSTANT_OVERFLOW (arg2));

1364   return t;

1365 }

 

Above at line 1338, if the expression is of type of size_t, and the result can fit in single HOST_WIDE_INT, and no overflow in the procedure, it invokes size_int_type_wide to cache the result within the hashtable size_htab (in the function, it will invoke force_fit_type to trucate the result and record overflow if happen). Since the precision of size_t is 32 on our assuming target, other situation always denotes overflow. But it is possible that the overflow hasn’t been recorded, line 1355 checks for this negligence.

1.6.3.1.2.            Determine size of element & array

After getting the length of the array, in following, it will determine the size of element. At line 1645 below, TYPE_PACKED returns nonzero if that objects of this type should be laid out in as compact a way as possible. And at line 1657, integer_one_node refers to the global unique tree object of constant 1.

At line 1669, the size of array is expressed by number of bits, while at line 1680, the size is expressed in unit (usually, bytes).

 

layout_type (continue)

 

1643         /* Special handling for arrays of bits (for Chill).  */

1644         element_size = TYPE_SIZE (element);

1645         if (TYPE_PACKED (type) && INTEGRAL_TYPE_P (element)

1646            && (integer_zerop (TYPE_MAX_VALUE (element))

1647                || integer_onep (TYPE_MAX_VALUE (element)))

1648            && host_integerp (TYPE_MIN_VALUE (element), 1))

1649         {

1650           HOST_WIDE_INT maxvalue

1651              = tree_low_cst (TYPE_MAX_VALUE (element), 1);

1652           HOST_WIDE_INT minvalue

1653              = tree_low_cst (TYPE_MIN_VALUE (element), 1);

1654

1655           if (maxvalue - minvalue == 1

1656              && (maxvalue == 1 || maxvalue == 0))

1657             element_size = integer_one_node;

1658         }

1659

1660         /* If neither bound is a constant and sizetype is signed, make

1661           sure the size is never negative. We should really do this

1662           if *either* bound is non-constant, but this is the best

1663           compromise between C and Ada.  */

1664         if (! TREE_UNSIGNED (sizetype)

1665            && TREE_CODE (TYPE_MIN_VALUE (index)) != INTEGER_CST

1666            && TREE_CODE (TYPE_MAX_VALUE (index)) != INTEGER_CST)

1667           length = size_binop (MAX_EXPR, length, size_zero_node);

1668

1669         TYPE_SIZE (type) = size_binop (MULT_EXPR, element_size,

1670                                    convert (bitsizetype, length));

1671

1672         /* If we know the size of the element, calculate the total

1673           size directly, rather than do some division thing below.

1674           This optimization helps Fortran assumed-size arrays

1675           (where the size of the array is determined at runtime)

1676           substantially.

1677           Note that we can't do this in the case where the size of

1678           the elements is one bit since TYPE_SIZE_UNIT cannot be

1679           set correctly in that case.  */

1680         if (TYPE_SIZE_UNIT (element) != 0 && ! integer_onep (element_size))

1681           TYPE_SIZE_UNIT (type)

1682              = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (element), length);

1683       }

1684

1685       /* Now round the alignment and size,

1686         using machine-dependent criteria if any.  */

1687

1688 #ifdef ROUND_TYPE_ALIGN

1689      TYPE_ALIGN (type)

1690         = ROUND_TYPE_ALIGN (type, TYPE_ALIGN (element), BITS_PER_UNIT);

1691 #else

1692      TYPE_ALIGN (type) = MAX (TYPE_ALIGN (element), BITS_PER_UNIT);

1693 #endif

1694      TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (element);

1695      TYPE_MODE (type) = BLKmode;

1696      if (TYPE_SIZE (type) != 0

1697 #ifdef MEMBER_TYPE_FORCES_BLK

1698         && ! MEMBER_TYPE_FORCES_BLK (type, VOIDmode)

1699 #endif

1700         /* BLKmode elements force BLKmode aggregate;

1701           else extract/store fields may lose.  */

1702         && (TYPE_MODE (TREE_TYPE (type)) != BLKmode

1703             || TYPE_NO_FORCE_BLK (TREE_TYPE (type))))

1704      {

1705        /* One-element arrays get the component type's mode.  */

1706        if (simple_cst_equal (TYPE_SIZE (type),

1707                          TYPE_SIZE (TREE_TYPE (type))))

1708          TYPE_MODE (type) = TYPE_MODE (TREE_TYPE (type));

1709        else

1710          TYPE_MODE (type)

1711              = mode_for_size_tree (TYPE_SIZE (type), MODE_INT, 1);

1712

1713        if (TYPE_MODE (type) != BLKmode

1714           && STRICT_ALIGNMENT && TYPE_ALIGN (type) < BIGGEST_ALIGNMENT

1715           && TYPE_ALIGN (type) < GET_MODE_ALIGNMENT (TYPE_MODE (type))

1716           && TYPE_MODE (type) != BLKmode)

1717        {

1718          TYPE_NO_FORCE_BLK (type) = 1;

1719          TYPE_MODE (type) = BLKmode;

1720        }

1721      }

1722      break;

1723    }

 

Macro ROUND_TYPE_ALIGN is not defined under Linux/x86. At line 1692, BITS_PER_UNIT for linux is 8 (means byte), see that array at least must be aligned at boundary of byte (it is not a problem for C/C++, in which the size of element is times of byte). And at line 1694, TYPE_USER_ALIGN will return nonzero if align attribute is used in the declaration.

Further, at line 1697, MEMBER_TYPE_FORCES_BLK is not defined. TREE_TYPE of the node of the array returns the type of element for array, at line 1703, TYPE_NO_FORCE_BLK returns nonzero if the element, has type of RECORD_TYPE, UNION_TYPE or QUAL_UNION_TYPE, and has BLKmode only because it lacks the alignment requirement for its size. In such case or element is not of BLKmode, mode_for_size_tree will try to see if any suitable mode other than BLKmode can be found.

 

230  enum machine_mode

231  mode_for_size_tree (tree size, enum mode_class class, int limit)              in stor-layout.c

232  {

233    if (TREE_CODE (size) != INTEGER_CST

234       || TREE_OVERFLOW (size)

235       /* What we really want to say here is that the size can fit in a

236         host integer, but we know there's no way we'd find a mode for

237         this many bits, so there's no point in doing the precise test.  */

238       || compare_tree_int (size, 1000) > 0)

239      return BLKmode;

240    else

241      return mode_for_size (tree_low_cst (size, 1), class, limit);

242  }

 

See that for type having variable size or having extra large size ( > 1000), it will be assigned BLKmode. And mode_for_size at line 241 will also set BLKmode if no other mode is fitting.

Note that at line 1714, STRICT_ALIGNMENT if nonzero, means move instructions will actually fail to work when given unaligned data. And condition at line 1715 checks if the data is somewhat packed form.

1.7. Detail about save_expr

save_expr wraps expression into a node of SAVE_EXPR. Do this to any expression which may be used in more than one place, but must be evaluated only once (for example: ++j += k; will be expanded to ++j = ++j + k; by the compiler, but ++j has side-effect, evaluates it twice will cause different result. Thus the compiler must compress other evaluations except those required by original semantics).

Normally, expand_expr would reevaluate the expression each time. Calling save_expr produces something that is evaluated and recorded the first time expand_expr is called on it. Subsequent calls to expand_expr just reuse the recorded value.

The call to expand_expr that generates code that actually computes the value is the first call at compile time. Subsequent calls at compile time generate code to use the saved value. This produces correct result provided that at run time control always flows through the instruction made by the first expand_expr before reaching the other places where the save_expr was evaluated. The caller of save_expr, must make sure this is so.

Constants, and certain read-only nodes, are returned with no SAVE_EXPR because that is safe. Expressions containing placeholders are not touched.

 

1340 tree

1341 save_expr (tree expr)                                                                                       in tree.c

1342 {

1343   tree t = fold (expr);

1344   tree inner;

1345

1346   /* If the tree evaluates to a constant, then we don't want to hide that

1347     fact (i.e. this allows further folding, and direct checks for constants).

1348     However, a read-only object that has side effects cannot be bypassed.

1349     Since it is no problem to reevaluate literals, we just return the

1350     literal node.  */

1351   inner = skip_simple_arithmetic (t);

1352   if (TREE_CONSTANT (inner)

1353       || (TREE_READONLY (inner) && ! TREE_SIDE_EFFECTS (inner))

1354       || TREE_CODE (inner) == SAVE_EXPR

1355       || TREE_CODE (inner) == ERROR_MARK)

1356     return t;

1357

1358   /* If INNER contains a PLACEHOLDER_EXPR, we must evaluate it each time, since

1359     it means that the size or offset of some field of an object depends on

1360     the value within another field.

1361

1362     Note that it must not be the case that T contains both a PLACEHOLDER_EXPR

1363     and some variable since it would then need to be both evaluated once and

1364     evaluated more than once. Front-ends must assure this case cannot

1365     happen by surrounding any such subexpressions in their own SAVE_EXPR

1366     and forcing evaluation at the proper time.  */

1367   if (contains_placeholder_p (inner))

1368     return t;

1369

1370   t = build (SAVE_EXPR, TREE_TYPE (expr), t, current_function_decl, NULL_TREE);

1371

1372   /* This expression might be placed ahead of a jump to ensure that the

1373     value was computed on both sides of the jump. So make sure it isn't

1374     eliminated as dead.  */

1375   TREE_SIDE_EFFECTS (t) = 1;

1376   TREE_READONLY (t) = 1;

1377   return t;

1378 }

 

At line 1351 above, skip_simple_arithmetic extracts the necessary part of the expression for wrapping inside SAVE_EXPR. It can reduce the number of expression to be wrapped, and speed up the compilation.

 

1383 tree

1384 skip_simple_arithmetic (tree expr)                                                                     in tree.c

1385 {

1386   tree inner;

1387

1388   /* We don't care about whether this can be used as an lvalue in this

1389     context.  */

1390   while (TREE_CODE (expr) == NON_LVALUE_EXPR)

1391     expr = TREE_OPERAND (expr, 0);

1392

1393   /* If we have simple operations applied to a SAVE_EXPR or to a SAVE_EXPR and

1394     a constant, it will be more efficient to not make another SAVE_EXPR since

1395     it will allow better simplification and GCSE will be able to merge the

1396     computations if they actually occur.  */

1397   inner = expr;

1398   while (1)

1399   {

1400     if (TREE_CODE_CLASS (TREE_CODE (inner)) == '1')

1401       inner = TREE_OPERAND (inner, 0);

1402     else if (TREE_CODE_CLASS (TREE_CODE (inner)) == '2')

1403     {

1404       if (TREE_CONSTANT (TREE_OPERAND (inner, 1)))

1405         inner = TREE_OPERAND (inner, 0);

1406       else if (TREE_CONSTANT (TREE_OPERAND (inner, 0)))

1407         inner = TREE_OPERAND (inner, 1);

1408       else

1409         break;

1410     }

1411     else

1412       break;

1413   }

1414

1415   return inner;

1416 }

 

Obviously, only nodes known without side-effect can be ignored. The function steps down the subtree till no node can be ignored anymore. Note that opreator “++” and “—” are binary operator, they contain implicit operand “1”.

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值