This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Fix build_range_check on 1 .. signed_max ranges (PR middle-end/37882)
- From: "Richard Guenther" <richard dot guenther at gmail dot com>
- To: "Jakub Jelinek" <jakub at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Wed, 22 Oct 2008 12:41:40 +0200
- Subject: Re: [PATCH] Fix build_range_check on 1 .. signed_max ranges (PR middle-end/37882)
- References: <20081022102907.GA14706@tyan-ft48-01.lab.bos.redhat.com>
On Wed, Oct 22, 2008 at 12:29 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> Hi!
>
> signed_type_for may return a type with bigger precision than the precision
> of the passed type, e.g. type_for_size langhook's comment says:
> /* Given PRECISION and UNSIGNEDP, return a suitable type-tree for an
> integer type with at least that precision. */
> In the
> /* Optimize (c>=1) && (c<=127) into (signed char)c > 0. */
> optimization, precision at least as wide as c's isn't good enough,
> we need exactly the same precision.
> The following patch fixes it. We could call build_nonstandard_integer_type
> unconditionally, but that would in the common case where precision is sane
> unnecessarily create a new type and as fold is used also in the FEs, I think
> it is better to use the standard types if possible.
>
> Ok for trunk/4.3 if bootstrap/regtest passes?
Ok. In future (4.5) we may want to "optimize" {un,}signed_type_for to always
return an integer type of the requested precision and keep a cache on its own
(after all we don't want a langhook here for LTO reasons).
Thanks,
Richard.
> 2008-10-22 Jakub Jelinek <jakub@redhat.com>
>
> PR middle-end/37882
> * fold-const.c (build_range_type): For 1 .. signed_max
> range call build_nonstandard_inter_type if signed_type_for
> returned a type with bigger precision.
>
> * gcc.c-torture/execute/pr37882.c: New test.
>
> --- gcc/fold-const.c.jj 2008-10-20 12:36:10.000000000 +0200
> +++ gcc/fold-const.c 2008-10-22 12:11:13.000000000 +0200
> @@ -4503,7 +4503,12 @@ build_range_check (tree type, tree exp,
> {
> if (TYPE_UNSIGNED (etype))
> {
> - etype = signed_type_for (etype);
> + tree signed_etype = signed_type_for (etype);
> + if (TYPE_PRECISION (signed_etype) != TYPE_PRECISION (etype))
> + etype
> + = build_nonstandard_integer_type (TYPE_PRECISION (etype), 0);
> + else
> + etype = signed_etype;
> exp = fold_convert (etype, exp);
> }
> return fold_build2 (GT_EXPR, type, exp,
> --- gcc/testsuite/gcc.c-torture/execute/pr37882.c.jj 2008-10-22 12:14:42.000000000 +0200
> +++ gcc/testsuite/gcc.c-torture/execute/pr37882.c 2008-10-22 12:14:25.000000000 +0200
> @@ -0,0 +1,16 @@
> +/* PR middle-end/37882 */
> +
> +struct S
> +{
> + int a : 21;
> + unsigned char b : 3;
> +} s;
> +
> +int
> +main ()
> +{
> + s.b = 4;
> + if (s.b > 0 && s.b < 4)
> + __builtin_abort ();
> + return 0;
> +}
>
> Jakub
>