This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix up invalid SUBREGs created by simplify_gen_subreg in dse.c (PR target/37382)


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]