diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-09-11 07:33:23 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-09-11 07:33:23 +0000 |
commit | 171557e8ce0106d9cc0321be218b42bbaaefeec0 (patch) | |
tree | 654aa05676a650f4bfb708a7c200e82d0a1e39c8 /gcc | |
parent | 96efe7138202a220c3f6168a4e7f3fc9f4e93a83 (diff) | |
download | gcc-171557e8ce0106d9cc0321be218b42bbaaefeec0.tar.gz |
PR target/37382
* expmed.c (extract_low_bits): Avoid creating invalid subregs.
* dse.c (find_shift_sequence): Use extract_low_bits instead of
simplify_gen_subreg.
* gcc.c-torture/compile/pr37382.c: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@140265 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/dse.c | 12 | ||||
-rw-r--r-- | gcc/expmed.c | 18 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/compile/pr37382.c | 16 |
5 files changed, 50 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3be4d03bdd8..5cf27d019e6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2008-09-11 Jakub Jelinek <jakub@redhat.com> + + PR target/37382 + * expmed.c (extract_low_bits): Avoid creating invalid subregs. + * dse.c (find_shift_sequence): Use extract_low_bits instead of + simplify_gen_subreg. + 2008-09-11 Ira Rosen <irar@il.ibm.com> * tree-vect-transform.c (vectorizable_store): Use the rhs vector type diff --git a/gcc/dse.c b/gcc/dse.c index 7283bbe67e4..0a3ebb40ffa 100644 --- a/gcc/dse.c +++ b/gcc/dse.c @@ -1445,7 +1445,7 @@ find_shift_sequence (int access_size, new_mode = GET_MODE_WIDER_MODE (new_mode)) { rtx target, new_reg, shift_seq, insn, new_lhs; - int cost, offset; + int cost; /* Try a wider mode if truncating the store mode to NEW_MODE requires a real instruction. */ @@ -1459,11 +1459,6 @@ find_shift_sequence (int access_size, if (!CONSTANT_P (store_info->rhs) && !MODES_TIEABLE_P (new_mode, store_mode)) continue; - offset = subreg_lowpart_offset (new_mode, store_mode); - new_lhs = simplify_gen_subreg (new_mode, copy_rtx (store_info->rhs), - store_mode, offset); - if (new_lhs == NULL_RTX) - continue; new_reg = gen_reg_rtx (new_mode); @@ -1496,6 +1491,11 @@ find_shift_sequence (int access_size, if (cost > COSTS_N_INSNS (1)) continue; + new_lhs = extract_low_bits (new_mode, store_mode, + copy_rtx (store_info->rhs)); + if (new_lhs == NULL_RTX) + continue; + /* We found an acceptable shift. Generate a move to take the value from the store and put it into the shift pseudo, then shift it, then generate another diff --git a/gcc/expmed.c b/gcc/expmed.c index 0daf7fa31f0..6099c4b6839 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -1991,8 +1991,22 @@ extract_low_bits (enum machine_mode mode, enum machine_mode src_mode, rtx src) return src; if (CONSTANT_P (src)) - return simplify_gen_subreg (mode, src, src_mode, - subreg_lowpart_offset (mode, src_mode)); + { + /* simplify_gen_subreg can't be used here, as if simplify_subreg + fails, it will happily create (subreg (symbol_ref)) or similar + invalid SUBREGs. */ + unsigned int byte = subreg_lowpart_offset (mode, src_mode); + rtx ret = simplify_subreg (mode, src, src_mode, byte); + if (ret) + return ret; + + if (GET_MODE (src) == VOIDmode + || !validate_subreg (mode, src_mode, src, byte)) + return NULL_RTX; + + src = force_reg (GET_MODE (src), src); + return gen_rtx_SUBREG (mode, src, byte); + } if (GET_MODE_CLASS (mode) == MODE_CC || GET_MODE_CLASS (src_mode) == MODE_CC) return NULL_RTX; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b42b5dfc2ed..1d3dc0a09d3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2008-09-11 Jakub Jelinek <jakub@redhat.com> + + PR target/37382 + * gcc.c-torture/compile/pr37382.c: New test. + 2008-09-11 Daniel Kraft <d@domob.eu> PR fortran/36214 diff --git a/gcc/testsuite/gcc.c-torture/compile/pr37382.c b/gcc/testsuite/gcc.c-torture/compile/pr37382.c new file mode 100644 index 00000000000..47525bcf956 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr37382.c @@ -0,0 +1,16 @@ +/* PR target/37382 */ + +void baz (char *); +int c; + +void +bar (void) +{ + char a[2]; + int *ip = &c; + char *p = a, *q = (char *) &ip; + const char *r = q + 2; + for (; q != r; p++, q++) + *p = *q; + baz (a); +} |