re PR target/45074 (GCC Segmentation fault - negating global register variables)
authorRichard Sandiford <rdsandiford@googlemail.com>
Wed, 1 Jun 2011 19:49:53 +0000 (19:49 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Wed, 1 Jun 2011 19:49:53 +0000 (19:49 +0000)
gcc/
PR target/45074
* optabs.h (valid_multiword_target_p): Declare.
* expmed.c (extract_bit_field_1): Check valid_multiword_target_p when
doing multi-word operations.
* optabs.c (expand_binop): Likewise.
(expand_doubleword_bswap): Likewise.
(expand_absneg_bit): Likewise.
(expand_unop): Likewise.
(expand_copysign_bit): Likewise.
(multiword_target_p): New function.

gcc/testsuite/
PR target/45074
* gcc.target/mips/pr45074.c: New test.

From-SVN: r174541

gcc/ChangeLog
gcc/expmed.c
gcc/optabs.c
gcc/optabs.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/mips/pr45074.c [new file with mode: 0644]

index 658174b3606625fbcc72941a59463ead396b995f..85b68a744b0843c72346ba73dc26d410870cff5e 100644 (file)
@@ -1,3 +1,16 @@
+2011-06-01  Richard Sandiford  <rdsandiford@googlemail.com>
+
+       PR target/45074
+       * optabs.h (valid_multiword_target_p): Declare.
+       * expmed.c (extract_bit_field_1): Check valid_multiword_target_p when
+       doing multi-word operations.
+       * optabs.c (expand_binop): Likewise.
+       (expand_doubleword_bswap): Likewise.
+       (expand_absneg_bit): Likewise.
+       (expand_unop): Likewise.
+       (expand_copysign_bit): Likewise.
+       (multiword_target_p): New function.
+
 2011-06-01  Richard Sandiford  <rdsandiford@googlemail.com>
 
        PR rtl-optimization/48830
index 5527c1e711282fb0aef5c92e8bc8d63311eeae40..314fac79c284c679c43765ee1f00f33654a5381a 100644 (file)
@@ -1341,7 +1341,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
       unsigned int nwords = (bitsize + (BITS_PER_WORD - 1)) / BITS_PER_WORD;
       unsigned int i;
 
-      if (target == 0 || !REG_P (target))
+      if (target == 0 || !REG_P (target) || !valid_multiword_target_p (target))
        target = gen_reg_rtx (mode);
 
       /* Indicate for flow that the entire target reg is being set.  */
index 1473b0f13aff1caf0f2bf607af270c557eb54ae9..224fb11b59b1210170b86a6fc5cb34c0df59c712 100644 (file)
@@ -1537,7 +1537,10 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
 
       /* If TARGET is the same as one of the operands, the REG_EQUAL note
         won't be accurate, so use a new target.  */
-      if (target == 0 || target == op0 || target == op1)
+      if (target == 0
+         || target == op0
+         || target == op1
+         || !valid_multiword_target_p (target))
        target = gen_reg_rtx (mode);
 
       start_sequence ();
@@ -1605,7 +1608,10 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
 
          /* If TARGET is the same as one of the operands, the REG_EQUAL note
             won't be accurate, so use a new target.  */
-         if (target == 0 || target == op0 || target == op1)
+         if (target == 0
+             || target == op0
+             || target == op1
+             || !valid_multiword_target_p (target))
            target = gen_reg_rtx (mode);
 
          start_sequence ();
@@ -1659,7 +1665,11 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
         opportunities, and second because if target and op0 happen to be MEMs
         designating the same location, we would risk clobbering it too early
         in the code sequence we generate below.  */
-      if (target == 0 || target == op0 || target == op1 || ! REG_P (target))
+      if (target == 0
+         || target == op0
+         || target == op1
+         || !REG_P (target)
+         || !valid_multiword_target_p (target))
        target = gen_reg_rtx (mode);
 
       start_sequence ();
@@ -1779,7 +1789,7 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
 
       xtarget = gen_reg_rtx (mode);
 
-      if (target == 0 || !REG_P (target))
+      if (target == 0 || !REG_P (target) || !valid_multiword_target_p (target))
        target = xtarget;
 
       /* Indicate for flow that the entire target reg is being set.  */
@@ -2481,7 +2491,7 @@ expand_doubleword_bswap (enum machine_mode mode, rtx op, rtx target)
   t0 = expand_unop (word_mode, bswap_optab,
                    operand_subword_force (op, 1, mode), NULL_RTX, true);
 
-  if (target == 0)
+  if (target == 0 || !valid_multiword_target_p (target))
     target = gen_reg_rtx (mode);
   if (REG_P (target))
     emit_clobber (target);
@@ -2724,7 +2734,9 @@ expand_absneg_bit (enum rtx_code code, enum machine_mode mode,
   if (code == ABS)
     mask = double_int_not (mask);
 
-  if (target == 0 || target == op0)
+  if (target == 0
+      || target == op0
+      || (nwords > 1 && !valid_multiword_target_p (target)))
     target = gen_reg_rtx (mode);
 
   if (nwords > 1)
@@ -2915,7 +2927,7 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
       int i;
       rtx insns;
 
-      if (target == 0 || target == op0)
+      if (target == 0 || target == op0 || !valid_multiword_target_p (target))
        target = gen_reg_rtx (mode);
 
       start_sequence ();
@@ -3386,7 +3398,10 @@ expand_copysign_bit (enum machine_mode mode, rtx op0, rtx op1, rtx target,
 
   mask = double_int_setbit (double_int_zero, bitpos);
 
-  if (target == 0 || target == op0 || target == op1)
+  if (target == 0
+      || target == op0
+      || target == op1
+      || (nwords > 1 && !valid_multiword_target_p (target)))
     target = gen_reg_rtx (mode);
 
   if (nwords > 1)
@@ -7034,6 +7049,23 @@ insn_operand_matches (enum insn_code icode, unsigned int opno, rtx operand)
              (operand, insn_data[(int) icode].operand[opno].mode)));
 }
 \f
+/* TARGET is a target of a multiword operation that we are going to
+   implement as a series of word-mode operations.  Return true if
+   TARGET is suitable for this purpose.  */
+
+bool
+valid_multiword_target_p (rtx target)
+{
+  enum machine_mode mode;
+  int i;
+
+  mode = GET_MODE (target);
+  for (i = 0; i < GET_MODE_SIZE (mode); i += UNITS_PER_WORD)
+    if (!validate_subreg (word_mode, mode, target, i))
+      return false;
+  return true;
+}
+
 /* Like maybe_legitimize_operand, but do not change the code of the
    current rtx value.  */
 
index db6e65e89758c75d9fedf7fd9af22d3b0447cf8c..62bc14e484034f33983753c0ce1b7490e554f104 100644 (file)
@@ -1059,6 +1059,8 @@ create_integer_operand (struct expand_operand *op, HOST_WIDE_INT intval)
   create_expand_operand (op, EXPAND_INTEGER, GEN_INT (intval), VOIDmode, false);
 }
 
+extern bool valid_multiword_target_p (rtx);
+
 extern bool maybe_legitimize_operands (enum insn_code icode,
                                       unsigned int opno, unsigned int nops,
                                       struct expand_operand *ops);
index 219534488663b021576f544a264ac670054f2998..7e90e17f08400526d0f903fa74e9badc5c2f0dc8 100644 (file)
@@ -1,3 +1,8 @@
+2011-06-01  Richard Sandiford  <rdsandiford@googlemail.com>
+
+       PR target/45074
+       * gcc.target/mips/pr45074.c: New test.
+
 2011-06-01  Eric Botcazou  <ebotcazou@adacore.com>
            Hans-Peter Nilsson  <hp@axis.com>
 
diff --git a/gcc/testsuite/gcc.target/mips/pr45074.c b/gcc/testsuite/gcc.target/mips/pr45074.c
new file mode 100644 (file)
index 0000000..ba578c8
--- /dev/null
@@ -0,0 +1,8 @@
+/* { dg-options "-mhard-float -mgp32 -O" } */
+register double g __asm__("$f20");
+
+NOMIPS16 void
+test (double a)
+{
+  g = -a;
+}