From 6476a02bc9ec2b98f26d36245feb601caea0b5cb Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Thu, 4 Dec 2008 21:54:09 +0000 Subject: [PATCH] cse.c (lookup_as_function): Delete mode frobbing code. * cse.c (lookup_as_function): Delete mode frobbing code. (fold_rtx_subreg): Re-implement it there for SUBREGs. Co-Authored-By: Gary Funck From-SVN: r142446 --- gcc/ChangeLog | 6 +++++ gcc/cse.c | 33 +++++++++++++----------- gcc/testsuite/ChangeLog | 4 +++ gcc/testsuite/gcc.dg/union-5.c | 46 ++++++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/union-5.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 81ef178612f4..e6db964c29d3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2008-12-04 Eric Botcazou + Gary Funck + + * cse.c (lookup_as_function): Delete mode frobbing code. + (fold_rtx_subreg): Re-implement it there for SUBREGs. + 2008-11-30 Eric Botcazou PR target/38287 diff --git a/gcc/cse.c b/gcc/cse.c index 15a2a7af556c..31ee15c7656c 100644 --- a/gcc/cse.c +++ b/gcc/cse.c @@ -1455,17 +1455,6 @@ lookup_as_function (rtx x, enum rtx_code code) struct table_elt *p = lookup (x, SAFE_HASH (x, VOIDmode), GET_MODE (x)); - /* If we are looking for a CONST_INT, the mode doesn't really matter, as - long as we are narrowing. So if we looked in vain for a mode narrower - than word_mode before, look for word_mode now. */ - if (p == 0 && code == CONST_INT - && GET_MODE_SIZE (GET_MODE (x)) < GET_MODE_SIZE (word_mode)) - { - x = copy_rtx (x); - PUT_MODE (x, word_mode); - p = lookup (x, SAFE_HASH (x, VOIDmode), word_mode); - } - if (p == 0) return 0; @@ -3258,6 +3247,7 @@ static rtx fold_rtx_subreg (rtx x, rtx insn) { enum machine_mode mode = GET_MODE (x); + enum machine_mode imode = GET_MODE (SUBREG_REG (x)); rtx folded_arg0; rtx const_arg0; rtx new; @@ -3267,6 +3257,21 @@ fold_rtx_subreg (rtx x, rtx insn) || (new = lookup_as_function (x, CONST_DOUBLE)) != 0) return new; + /* If we didn't and if doing so makes sense, see if we previously + assigned a constant value to the enclosing word mode SUBREG. */ + if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (word_mode) + && GET_MODE_SIZE (word_mode) < GET_MODE_SIZE (imode)) + { + int byte = SUBREG_BYTE (x) - subreg_lowpart_offset (mode, word_mode); + if (byte >= 0 && (byte % UNITS_PER_WORD) == 0) + { + rtx y = gen_rtx_SUBREG (word_mode, SUBREG_REG (x), byte); + new = lookup_as_function (y, CONST_INT); + if (new) + return gen_lowpart (mode, new); + } + } + /* If this is a paradoxical SUBREG, we have no idea what value the extra bits would have. However, if the operand is equivalent to a SUBREG whose operand is the same as our mode, and all the modes @@ -3275,9 +3280,8 @@ fold_rtx_subreg (rtx x, rtx insn) Similarly if we find an integer constant. */ - if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))) + if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (imode)) { - enum machine_mode imode = GET_MODE (SUBREG_REG (x)); struct table_elt *elt; if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD @@ -3310,8 +3314,7 @@ fold_rtx_subreg (rtx x, rtx insn) if (folded_arg0 != SUBREG_REG (x)) { - new = simplify_subreg (mode, folded_arg0, - GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x)); + new = simplify_subreg (mode, folded_arg0, imode, SUBREG_BYTE (x)); if (new) return new; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 53c1a0ba3583..ec52ece7d1a5 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2008-12-04 Eric Botcazou + + * gcc.dg/union-5.c: New test. + 2008-11-30 Eric Botcazou * g++.dg/opt/reload3.C: New test. diff --git a/gcc/testsuite/gcc.dg/union-5.c b/gcc/testsuite/gcc.dg/union-5.c new file mode 100644 index 000000000000..d0dfaa07e77f --- /dev/null +++ b/gcc/testsuite/gcc.dg/union-5.c @@ -0,0 +1,46 @@ +/* { dg-do run } */ +/* { dg-options "-O -fgcse" } */ + +extern void abort(void); + +typedef unsigned short int uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; + +typedef struct +{ + uint16_t thread; + uint16_t phase; +} s32; + +typedef union +{ + uint32_t i; + s32 s; +} u32; + +typedef union +{ + uint64_t i; + u32 u; +} u64; + +static __attribute__((noinline)) +void foo(int val) +{ + u64 data; + uint32_t thread; + + data.u.i = 0x10000L; + thread = data.u.s.thread; + if (val) + abort (); + if (thread) + abort (); +} + +int main(void) +{ + foo (0); + return 0; +} -- 2.47.2