This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [wide-int] Small wide_int_to_tree optimisation
- From: Richard Biener <richard dot guenther at gmail dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>, Kenneth Zadeck <zadeck at naturalbridge dot com>, Mike Stump <mikestump at comcast dot net>, Richard Sandiford <rdsandiford at googlemail dot com>
- Date: Thu, 28 Nov 2013 15:22:05 +0100
- Subject: Re: [wide-int] Small wide_int_to_tree optimisation
- Authentication-results: sourceware.org; auth=none
- References: <87d2lkrasi dot fsf at sandifor-thinkpad dot stglab dot manchester dot uk dot ibm dot com>
On Thu, Nov 28, 2013 at 1:05 PM, Richard Sandiford
<rdsandiford@googlemail.com> wrote:
> This patch convers some gcc_asserts to gcc_checking_asserts.
> I think the first two in particular should be checking-only,
> since we ignore the bits above the target precision anyway.
>
> Also we have:
>
> /* This is a little hokie, but if the prec is smaller than
> what is necessary to hold INTEGER_SHARE_LIMIT, then the
> obvious test will not get the correct answer. */
> if (prec < HOST_BITS_PER_WIDE_INT)
> {
> if (cst.to_uhwi () < (unsigned HOST_WIDE_INT) INTEGER_SHARE_LIMIT)
> ix = cst.to_uhwi ();
> }
> else if (wi::ltu_p (cst, INTEGER_SHARE_LIMIT))
> ix = cst.to_uhwi ();
>
> But this case only occurs for single-HWI integers. We later check
> for that and extract the HWI value, so it seems simpler to postpone
> the index check until then.
>
> Tested on x86_64-linux-gnu. OK to install?
Ok.
Thanks,
Richard.
> Thanks,
> Richard
>
>
> Index: gcc/tree.c
> ===================================================================
> *** gcc/tree.c 2013-11-28 11:27:32.043124135 +0000
> --- gcc/tree.c 2013-11-28 11:45:39.957427563 +0000
> *************** wide_int_to_tree (tree type, const wide_
> *** 1205,1295 ****
> if (l > 1)
> {
> if (pcst.elt (l - 1) == 0)
> ! gcc_assert (pcst.elt (l - 2) < 0);
> if (pcst.elt (l - 1) == (HOST_WIDE_INT) -1)
> ! gcc_assert (pcst.elt (l - 2) >= 0);
> }
>
> wide_int cst = wide_int::from (pcst, prec, sgn);
> unsigned int ext_len = get_int_cst_ext_nunits (type, cst);
>
> ! switch (TREE_CODE (type))
> {
> ! case NULLPTR_TYPE:
> ! gcc_assert (cst == 0);
> ! /* Fallthru. */
> !
> ! case POINTER_TYPE:
> ! case REFERENCE_TYPE:
> ! case POINTER_BOUNDS_TYPE:
> ! /* Cache NULL pointer and zero bounds. */
> ! if (cst == 0)
> ! {
> ! limit = 1;
> ! ix = 0;
> ! }
> ! break;
>
> ! case BOOLEAN_TYPE:
> ! /* Cache false or true. */
> ! limit = 2;
> ! if (wi::leu_p (cst, 1))
> ! ix = cst.to_uhwi ();
> ! break;
> !
> ! case INTEGER_TYPE:
> ! case OFFSET_TYPE:
> ! if (TYPE_SIGN (type) == UNSIGNED)
> {
> ! /* Cache 0..N */
> ! limit = INTEGER_SHARE_LIMIT;
> !
> ! /* This is a little hokie, but if the prec is smaller than
> ! what is necessary to hold INTEGER_SHARE_LIMIT, then the
> ! obvious test will not get the correct answer. */
> ! if (prec < HOST_BITS_PER_WIDE_INT)
> {
> ! if (cst.to_uhwi () < (unsigned HOST_WIDE_INT) INTEGER_SHARE_LIMIT)
> ! ix = cst.to_uhwi ();
> }
> ! else if (wi::ltu_p (cst, INTEGER_SHARE_LIMIT))
> ! ix = cst.to_uhwi ();
> ! }
> ! else
> ! {
> ! /* Cache -1..N */
> ! limit = INTEGER_SHARE_LIMIT + 1;
>
> ! if (cst == -1)
> ! ix = 0;
> ! else if (!wi::neg_p (cst))
> {
> ! if (prec < HOST_BITS_PER_WIDE_INT)
> ! {
> ! if (cst.to_shwi () < INTEGER_SHARE_LIMIT)
> ! ix = cst.to_shwi () + 1;
> ! }
> ! else if (wi::lts_p (cst, INTEGER_SHARE_LIMIT))
> ! ix = cst.to_shwi () + 1;
> }
> ! }
> ! break;
>
> ! case ENUMERAL_TYPE:
> ! break;
>
> ! default:
> ! gcc_unreachable ();
> ! }
>
> - if (ext_len == 1)
> - {
> - /* We just need to store a single HOST_WIDE_INT. */
> - HOST_WIDE_INT hwi;
> - if (TYPE_UNSIGNED (type))
> - hwi = cst.to_uhwi ();
> - else
> - hwi = cst.to_shwi ();
> if (ix >= 0)
> {
> /* Look for it in the type's vector of small shared ints. */
> --- 1205,1276 ----
> if (l > 1)
> {
> if (pcst.elt (l - 1) == 0)
> ! gcc_checking_assert (pcst.elt (l - 2) < 0);
> if (pcst.elt (l - 1) == (HOST_WIDE_INT) -1)
> ! gcc_checking_assert (pcst.elt (l - 2) >= 0);
> }
>
> wide_int cst = wide_int::from (pcst, prec, sgn);
> unsigned int ext_len = get_int_cst_ext_nunits (type, cst);
>
> ! if (ext_len == 1)
> {
> ! /* We just need to store a single HOST_WIDE_INT. */
> ! HOST_WIDE_INT hwi;
> ! if (TYPE_UNSIGNED (type))
> ! hwi = cst.to_uhwi ();
> ! else
> ! hwi = cst.to_shwi ();
>
> ! switch (TREE_CODE (type))
> {
> ! case NULLPTR_TYPE:
> ! gcc_assert (hwi == 0);
> ! /* Fallthru. */
> !
> ! case POINTER_TYPE:
> ! case REFERENCE_TYPE:
> ! case POINTER_BOUNDS_TYPE:
> ! /* Cache NULL pointer and zero bounds. */
> ! if (hwi == 0)
> {
> ! limit = 1;
> ! ix = 0;
> }
> ! break;
>
> ! case BOOLEAN_TYPE:
> ! /* Cache false or true. */
> ! limit = 2;
> ! if (hwi < 2)
> ! ix = hwi;
> ! break;
> !
> ! case INTEGER_TYPE:
> ! case OFFSET_TYPE:
> ! if (TYPE_SIGN (type) == UNSIGNED)
> {
> ! /* Cache [0, N). */
> ! limit = INTEGER_SHARE_LIMIT;
> ! if (IN_RANGE (hwi, 0, INTEGER_SHARE_LIMIT - 1))
> ! ix = hwi;
> }
> ! else
> ! {
> ! /* Cache [-1, N). */
> ! limit = INTEGER_SHARE_LIMIT + 1;
> ! if (IN_RANGE (hwi, -1, INTEGER_SHARE_LIMIT - 1))
> ! ix = hwi + 1;
> ! }
> ! break;
>
> ! case ENUMERAL_TYPE:
> ! break;
>
> ! default:
> ! gcc_unreachable ();
> ! }
>
> if (ix >= 0)
> {
> /* Look for it in the type's vector of small shared ints. */
> *************** wide_int_to_tree (tree type, const wide_
> *** 1302,1311 ****
> t = TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix);
> if (t)
> /* Make sure no one is clobbering the shared constant. */
> ! gcc_assert (TREE_TYPE (t) == type
> ! && TREE_INT_CST_NUNITS (t) == 1
> ! && TREE_INT_CST_EXT_NUNITS (t) == 1
> ! && TREE_INT_CST_ELT (t, 0) == hwi);
> else
> {
> /* Create a new shared int. */
> --- 1283,1292 ----
> t = TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix);
> if (t)
> /* Make sure no one is clobbering the shared constant. */
> ! gcc_checking_assert (TREE_TYPE (t) == type
> ! && TREE_INT_CST_NUNITS (t) == 1
> ! && TREE_INT_CST_EXT_NUNITS (t) == 1
> ! && TREE_INT_CST_ELT (t, 0) == hwi);
> else
> {
> /* Create a new shared int. */