diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f45615709b2..79193e7be44 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2012-04-11 Peter Bergner + Michael Matz + + PR target/16458 + * rtlanal.c (unsigned_reg_p): New function. + Update copyright notice dates. + * rtl.h (unsigned_reg_p): Prototype it. + Update copyright notice dates. + * config/rs6000/rs6000.c (rs6000_generate_compare): Use it. + Update comment. + * expr.c (expand_expr_real_1): Set register attributes. + * stmt.c (expand_case): Likewise. + 2012-04-11 Oleg Endo PR target/50751 diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index fa882de429b..d053931d85b 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -15561,14 +15561,11 @@ rs6000_generate_compare (rtx cmp, enum machine_mode mode) || 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)) + && unsigned_reg_p (op0) + && (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; diff --git a/gcc/expr.c b/gcc/expr.c index 548a407d55e..14709bfcd08 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -9015,8 +9015,13 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, && stmt_is_replaceable_p (SSA_NAME_DEF_STMT (exp))) g = SSA_NAME_DEF_STMT (exp); if (g) - return expand_expr_real (gimple_assign_rhs_to_tree (g), target, tmode, - modifier, NULL); + { + rtx r = expand_expr_real (gimple_assign_rhs_to_tree (g), target, + tmode, modifier, NULL); + if (REG_P (r) && !REG_EXPR (r)) + set_reg_attrs_for_decl_rtl (SSA_NAME_VAR (exp), r); + return r; + } ssa_name = exp; decl_rtl = get_rtx_for_ssa_name (ssa_name); diff --git a/gcc/rtl.h b/gcc/rtl.h index 915ef136538..4d5d6d88990 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -1,6 +1,6 @@ /* Register Transfer Language (RTL) definitions for GCC Copyright (C) 1987, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 + 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. This file is part of GCC. @@ -1909,6 +1909,7 @@ extern HOST_WIDE_INT get_integer_term (const_rtx); extern rtx get_related_value (const_rtx); extern bool offset_within_block_p (const_rtx, HOST_WIDE_INT); extern void split_const (rtx, rtx *, rtx *); +extern bool unsigned_reg_p (rtx); extern int reg_mentioned_p (const_rtx, const_rtx); extern int count_occurrences (const_rtx, const_rtx, int); extern int reg_referenced_p (const_rtx, const_rtx); diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c index 7c4a49bef09..858264b7a03 100644 --- a/gcc/rtlanal.c +++ b/gcc/rtlanal.c @@ -1,7 +1,7 @@ /* Analyze RTL for GNU compiler. Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, - 2011 Free Software Foundation, Inc. + 2011, 2012 Free Software Foundation, Inc. This file is part of GCC. @@ -635,6 +635,25 @@ count_occurrences (const_rtx x, const_rtx find, int count_dest) return count; } + +/* Return TRUE if OP is a register or subreg of a register that + holds an unsigned quantity. Otherwise, return FALSE. */ + +bool +unsigned_reg_p (rtx op) +{ + if (REG_P (op) + && REG_EXPR (op) + && TYPE_UNSIGNED (TREE_TYPE (REG_EXPR (op)))) + return true; + + if (GET_CODE (op) == SUBREG + && SUBREG_PROMOTED_UNSIGNED_P (op)) + return true; + + return false; +} + /* Nonzero if register REG appears somewhere within IN. Also works if REG is not a register; in this case it checks diff --git a/gcc/stmt.c b/gcc/stmt.c index 0589bfd1bb8..7aabdc2caa6 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -2285,7 +2285,11 @@ expand_case (gimple stmt) do_pending_stack_adjust (); if (MEM_P (index)) - index = copy_to_reg (index); + { + index = copy_to_reg (index); + if (TREE_CODE (index_expr) == SSA_NAME) + set_reg_attrs_for_decl_rtl (SSA_NAME_VAR (index_expr), index); + } /* We generate a binary decision tree to select the appropriate target code. This is done as follows: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5c16617adfb..fac0cb0c8bd 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2012-04-11 Peter Bergner + + 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. + 2012-04-11 Eric Botcazou * gcc.dg/builtin-bswap-1.c: Test __builtin_bswap16 & __builtin_bswap64. diff --git a/gcc/testsuite/gcc.target/powerpc/pr16458-1.c b/gcc/testsuite/gcc.target/powerpc/pr16458-1.c new file mode 100644 index 00000000000..45b8c75c069 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr16458-1.c @@ -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; +} diff --git a/gcc/testsuite/gcc.target/powerpc/pr16458-2.c b/gcc/testsuite/gcc.target/powerpc/pr16458-2.c new file mode 100644 index 00000000000..95e97de5560 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr16458-2.c @@ -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; +} diff --git a/gcc/testsuite/gcc.target/powerpc/pr16458-3.c b/gcc/testsuite/gcc.target/powerpc/pr16458-3.c new file mode 100644 index 00000000000..740d61dcc74 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr16458-3.c @@ -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 = 1, + 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; +} diff --git a/gcc/testsuite/gcc.target/powerpc/pr16458-4.c b/gcc/testsuite/gcc.target/powerpc/pr16458-4.c new file mode 100644 index 00000000000..8db43e82384 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr16458-4.c @@ -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" } } */ +/* { 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 = 1, + 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; +}