On Fri, Jan 27, 2012 at 5:56 PM, Peter Bergner <berg...@vnet.ibm.com> wrote:
> This patch fixes PR16458 by using the type expression attached to a reg
> rtx to detect its signedness and generating unsigned compares when
> appropriate.  However, we continue to use signed compares for the
> special case of when we compare an unsigned reg against the constant 0.
> This is because signed and unsigned compares give the same results
> for equality and "(unsigned)x > 0)" is equivalent to "x != 0".
> Using a signed compare in this special case allows us to continue to
> generate record form instructions (ie, instructions that implicitly
> set cr0).
>
> I'll note that for the moment, I have XFAILed pr16458-4.c, since this
> test case isn't working yet, but it is due to a problem in expand not
> attaching any type expression information on *index's reg rtx like it
> does for *a and *b in pr16458-2.c.  We're tracking that down for 4.8.
>
> This has passed bootstrap and regtesting with no regressions.
> Ok for mainline?

This does not sound suitable for stage4.  rs6000_unsigned_reg_p
looks suspiciously non-rs6000 specific, and if we really can rely
on the way it is implemented should find its way to general RTL
helper routines.  The question is - do we ever coalesce signed
and unsigned variables to the same pseudo?

IIRC avr people recently have come across the same idea.

Richard.

> Peter
>
> gcc/
>        PR target/16458
>        * config/rs6000/rs6000.c (rs6000_unsigned_reg_p): New function.
>        (rs6000_generate_compare): Use it.
>
> gcc/testsuite/
>        PR target/16458
>        * gcc.target/powerpc/pr16458-1.c: New test.
>        * gcc.target/powerpc/pr16458-2.c: Likewise.
>        * gcc.target/powerpc/pr16458-3.c: Likewise.
>        * gcc.target/powerpc/pr16458-4.c: Likewise.
>
> Index: gcc/config/rs6000/rs6000.c
> ===================================================================
> --- gcc/config/rs6000/rs6000.c  (revision 183628)
> +++ gcc/config/rs6000/rs6000.c  (working copy)
> @@ -15588,6 +15588,22 @@ rs6000_reverse_condition (enum machine_m
>     return reverse_condition (code);
>  }
>
> +static bool
> +rs6000_unsigned_reg_p (rtx op)
> +{
> +  enum rtx_code code = GET_CODE (op);
> +
> +  if (code == REG
> +      && REG_EXPR (op)
> +      && TYPE_UNSIGNED (TREE_TYPE (REG_EXPR (op))))
> +    return true;
> +
> +  if (code == SUBREG && SUBREG_PROMOTED_UNSIGNED_P (op))
> +    return true;
> +
> +  return false;
> +}
> +
>  /* Generate a compare for CODE.  Return a brand-new rtx that
>    represents the result of the compare.  */
>
> @@ -15606,14 +15622,11 @@ rs6000_generate_compare (rtx cmp, enum m
>           || code == GEU || code == LEU)
>     comp_mode = CCUNSmode;
>   else if ((code == EQ || code == NE)
> -          && GET_CODE (op0) == SUBREG
> -          && GET_CODE (op1) == SUBREG
> -          && SUBREG_PROMOTED_UNSIGNED_P (op0)
> -          && SUBREG_PROMOTED_UNSIGNED_P (op1))
> +          && rs6000_unsigned_reg_p (op0)
> +          && (rs6000_unsigned_reg_p (op1)
> +              || (CONST_INT_P (op1) && INTVAL (op1) != 0)))
>     /* These are unsigned values, perhaps there will be a later
> -       ordering compare that can be shared with this one.
> -       Unfortunately we cannot detect the signedness of the operands
> -       for non-subregs.  */
> +       ordering compare that can be shared with this one.  */
>     comp_mode = CCUNSmode;
>   else
>     comp_mode = CCmode;
> Index: gcc/testsuite/gcc.target/powerpc/pr16458-1.c
> ===================================================================
> --- gcc/testsuite/gcc.target/powerpc/pr16458-1.c        (revision 0)
> +++ gcc/testsuite/gcc.target/powerpc/pr16458-1.c        (revision 0)
> @@ -0,0 +1,18 @@
> +/* Test cse'ing of unsigned compares.  */
> +/* { dg-do compile } */
> +/* { dg-options "-O2" } */
> +
> +/* { dg-final { scan-assembler-not "cmpw" } } */
> +/* { dg-final { scan-assembler-times "cmplw" 1 } } */
> +
> +unsigned int a, b;
> +
> +int
> +foo (void)
> +{
> +  if (a == b) return 1;
> +  if (a > b)  return 2;
> +  if (a < b)  return 3;
> +  if (a != b) return 4;
> +  return 0;
> +}
> Index: gcc/testsuite/gcc.target/powerpc/pr16458-2.c
> ===================================================================
> --- gcc/testsuite/gcc.target/powerpc/pr16458-2.c        (revision 0)
> +++ gcc/testsuite/gcc.target/powerpc/pr16458-2.c        (revision 0)
> @@ -0,0 +1,18 @@
> +/* Test cse'ing of unsigned compares.  */
> +/* { dg-do compile } */
> +/* { dg-options "-O2" } */
> +
> +/* { dg-final { scan-assembler-not "cmpw" } } */
> +/* { dg-final { scan-assembler-times "cmplw" 1 } } */
> +
> +unsigned int *a, *b;
> +
> +int
> +foo (void)
> +{
> +  if (*a == *b) return 1;
> +  if (*a > *b)  return 2;
> +  if (*a < *b)  return 3;
> +  if (*a != *b) return 4;
> +  return 0;
> +}
> Index: gcc/testsuite/gcc.target/powerpc/pr16458-3.c
> ===================================================================
> --- gcc/testsuite/gcc.target/powerpc/pr16458-3.c        (revision 0)
> +++ gcc/testsuite/gcc.target/powerpc/pr16458-3.c        (revision 0)
> @@ -0,0 +1,41 @@
> +/* Test cse'ing of unsigned compares.  */
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fno-jump-tables" } */
> +
> +/* { dg-final { scan-assembler-not "cmpwi" } } */
> +/* { dg-final { scan-assembler-times "cmplwi" 5 } } */
> +
> +extern int case0 (void);
> +extern int case1 (void);
> +extern int case2 (void);
> +extern int case3 (void);
> +extern int case4 (void);
> +
> +enum CASE_VALUES
> +{
> +  CASE0 = 0,
> +  CASE1,
> +  CASE2,
> +  CASE3,
> +  CASE4
> +};
> +
> +int
> +foo (enum CASE_VALUES index)
> +{
> +  switch (index)
> +    {
> +    case CASE0:
> +      return case0 ();
> +    case CASE1:
> +      return case1 ();
> +    case CASE2:
> +      return case2 ();
> +    case CASE3:
> +      return case3 ();
> +    case CASE4:
> +      return case4 ();
> +    }
> +
> +  return 0;
> +}
> Index: gcc/testsuite/gcc.target/powerpc/pr16458-4.c
> ===================================================================
> --- gcc/testsuite/gcc.target/powerpc/pr16458-4.c        (revision 0)
> +++ gcc/testsuite/gcc.target/powerpc/pr16458-4.c        (revision 0)
> @@ -0,0 +1,44 @@
> +/* Test cse'ing of unsigned compares.  */
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fno-jump-tables" } */
> +
> +/* The following tests fail due to an issue in expand not
> +   attaching an type expression information on *index's reg rtx.  */
> +
> +/* { dg-final { scan-assembler-not "cmpwi" { xfail *-*-* } } } */
> +/* { dg-final { scan-assembler-times "cmplwi" 5 { xfail *-*-* } } } */
> +
> +extern int case0 (void);
> +extern int case1 (void);
> +extern int case2 (void);
> +extern int case3 (void);
> +extern int case4 (void);
> +
> +enum CASE_VALUES
> +{
> +  CASE0 = 0,
> +  CASE1,
> +  CASE2,
> +  CASE3,
> +  CASE4
> +};
> +
> +int
> +foo (enum CASE_VALUES *index)
> +{
> +  switch (*index)
> +    {
> +    case CASE0:
> +      return case0 ();
> +    case CASE1:
> +      return case1 ();
> +    case CASE2:
> +      return case2 ();
> +    case CASE3:
> +      return case3 ();
> +    case CASE4:
> +      return case4 ();
> +    }
> +
> +  return 0;
> +}
>
>

Reply via email to