This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix up invalid SUBREGs created by simplify_gen_subreg in dse.c (PR target/37382)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Richard Sandiford <rdsandiford at googlemail dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Wed, 10 Sep 2008 04:19:15 -0400
- Subject: [PATCH] Fix up invalid SUBREGs created by simplify_gen_subreg in dse.c (PR target/37382)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
extract_low_bits and simplify_gen_subreg can create invalid SUBREGs, e.g.
when passed a SYMBOL_REF as an operand (dse.c handles all CONSTANT_Ps that
way). In the shift == 0 replace_read fixes it up in copy_to_mode_reg,
but in the shift != 0 case new_lhs is emit_move_insn into new_reg and
nothing calls force_operand on it, which has code to fix this up:
if (code == SUBREG
&& !REG_P (SUBREG_REG (value))
&& !MEM_P (SUBREG_REG (value)))
{
value
= simplify_gen_subreg (GET_MODE (value),
force_reg (GET_MODE (SUBREG_REG (value)),
force_operand (SUBREG_REG (value),
NULL_RTX)),
GET_MODE (SUBREG_REG (value)),
SUBREG_BYTE (value));
code = GET_CODE (value);
}
The following patch fixes it up by calling force_operand if needed
(we already have a pseudo, so I didn't want to call copy_to_mode_reg
and then copy it into another pseudo). Another alternative would
be not to call simplify_gen_subreg in find_shift_sequence and
extract_low_bits, but simplify_subreg and if that fails,
if the operand isn't REG_P or MEM_P first force_operand it and
only afterwards call simplify_gen_subreg. The disadvantage is
that this can emit insns even if the subreg isn't valid, and in
extract_low_bits case I think the callers don't expect any insns
to be emitted right away. So I think just calling force_operand to fix it
up is far easier.
Ok for trunk?
2008-09-10 Jakub Jelinek <jakub@redhat.com>
PR target/37382
* dse.c (find_shift_sequence): If new_lhs isn't general_operand,
call force_operand on it.
* gcc.c-torture/compile/pr37382.c: New test.
--- gcc/dse.c.jj 2008-09-05 12:56:32.000000000 +0200
+++ gcc/dse.c 2008-09-10 09:50:47.000000000 +0200
@@ -1500,7 +1500,10 @@ find_shift_sequence (int access_size,
take the value from the store and put it into the
shift pseudo, then shift it, then generate another
move to put in into the target of the read. */
- emit_move_insn (new_reg, new_lhs);
+ if (! general_operand (new_lhs, VOIDmode))
+ new_lhs = force_operand (new_lhs, new_reg);
+ if (new_lhs != new_reg)
+ emit_move_insn (new_reg, new_lhs);
emit_insn (shift_seq);
read_reg = extract_low_bits (read_mode, new_mode, new_reg);
break;
--- gcc/testsuite/gcc.c-torture/compile/pr37382.c.jj 2008-09-10 09:54:13.000000000 +0200
+++ gcc/testsuite/gcc.c-torture/compile/pr37382.c 2008-09-10 09:58:02.000000000 +0200
@@ -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);
+}
Jakub