public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* PR target/45074: Check targets of multi-word operations
@ 2011-04-17 18:39 Richard Sandiford
  0 siblings, 0 replies; only message in thread
From: Richard Sandiford @ 2011-04-17 18:39 UTC (permalink / raw)
  To: gcc-patches

PR45074 is a case where expand_absneg_bit needs to decompose a
multi-word negation operation into separate word_mode operations.
The target of the operation is a global FP register variable.

For various reasons, CANNOT_CHANGE_MODE_CLASS forbids changes
from DFmode to SImode for FP registers, so a direct subreg is
not allowed.  This in turn causes:

	  rtx targ_piece = operand_subword (target, i, 1, mode);

to return null, and we segfault on:

	      if (temp != targ_piece)
		emit_move_insn (targ_piece, temp);

This patch adds a multiword_target_p function that tests whether
a given target is suitable for this kind of word_mode decomposition.
I grepped for uses of operand_subword (as opposed to operand_subword_force),
and several use the same:

     if (target == 0 || some_other_stuff)
       target = gen_reg_rtx (mode);

     for (i = 0; i < nwords; i++)
       {
	 rtx targ_piece = operand_subword (target, i, 1, mode);
         ...
       }

idiom.  The patch handles those in the same way.

Tested on mips64-linux-gnu.  OK to install?

Richard


gcc/
	PR target/45074
	* optabs.h (multiword_target_p): Declare.
	* expmed.c (extract_bit_field_1): Check 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.

Index: gcc/optabs.h
===================================================================
--- gcc/optabs.h	2011-04-17 12:07:46.000000000 +0100
+++ gcc/optabs.h	2011-04-17 12:08:50.000000000 +0100
@@ -1054,6 +1054,8 @@ create_integer_operand (struct expand_op
   create_expand_operand (op, EXPAND_INTEGER, GEN_INT (intval), VOIDmode, false);
 }
 
+extern bool multiword_target_p (rtx);
+
 extern bool maybe_legitimize_operands (enum insn_code icode,
 				       unsigned int opno, unsigned int nops,
 				       struct expand_operand *ops);
Index: gcc/expmed.c
===================================================================
--- gcc/expmed.c	2011-04-17 12:07:46.000000000 +0100
+++ gcc/expmed.c	2011-04-17 12:08:50.000000000 +0100
@@ -1342,7 +1342,7 @@ extract_bit_field_1 (rtx str_rtx, unsign
       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) || !multiword_target_p (target))
 	target = gen_reg_rtx (mode);
 
       /* Indicate for flow that the entire target reg is being set.  */
Index: gcc/optabs.c
===================================================================
--- gcc/optabs.c	2011-04-17 12:07:46.000000000 +0100
+++ gcc/optabs.c	2011-04-17 18:11:58.000000000 +0100
@@ -1605,7 +1605,10 @@ expand_binop (enum machine_mode mode, op
 
 	  /* 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
+	      || !multiword_target_p (target))
 	    target = gen_reg_rtx (mode);
 
 	  start_sequence ();
@@ -1659,7 +1662,11 @@ expand_binop (enum machine_mode mode, op
 	 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)
+	  || !multiword_target_p (target))
 	target = gen_reg_rtx (mode);
 
       start_sequence ();
@@ -2481,7 +2488,7 @@ expand_doubleword_bswap (enum machine_mo
   t0 = expand_unop (word_mode, bswap_optab,
 		    operand_subword_force (op, 1, mode), NULL_RTX, true);
 
-  if (target == 0)
+  if (target == 0 || !multiword_target_p (target))
     target = gen_reg_rtx (mode);
   if (REG_P (target))
     emit_clobber (target);
@@ -2724,7 +2731,9 @@ expand_absneg_bit (enum rtx_code code, e
   if (code == ABS)
     mask = double_int_not (mask);
 
-  if (target == 0 || target == op0)
+  if (target == 0
+      || target == op0
+      || (nwords > 1 && !multiword_target_p (target)))
     target = gen_reg_rtx (mode);
 
   if (nwords > 1)
@@ -2915,7 +2924,7 @@ expand_unop (enum machine_mode mode, opt
       int i;
       rtx insns;
 
-      if (target == 0 || target == op0)
+      if (target == 0 || target == op0 || !multiword_target_p (target))
 	target = gen_reg_rtx (mode);
 
       start_sequence ();
@@ -3386,7 +3395,10 @@ expand_copysign_bit (enum machine_mode m
 
   mask = double_int_setbit (double_int_zero, bitpos);
 
-  if (target == 0 || target == op0 || target == op1)
+  if (target == 0
+      || target == op0
+      || target == op1
+      || (nwords > 1 && !multiword_target_p (target)))
     target = gen_reg_rtx (mode);
 
   if (nwords > 1)
@@ -7001,6 +7013,23 @@ insn_operand_matches (enum insn_code ico
 	      (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
+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: gcc/testsuite/gcc.target/mips/pr45074.c
===================================================================
--- /dev/null	2011-04-17 10:56:28.045573347 +0100
+++ gcc/testsuite/gcc.target/mips/pr45074.c	2011-04-17 12:08:50.000000000 +0100
@@ -0,0 +1,8 @@
+/* { dg-options "-mhard-float -mgp32 -O" } */
+register double g __asm__("$f20");
+
+NOMIPS16 void
+test (double a)
+{
+  g = -a;
+}

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2011-04-17 17:26 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-04-17 18:39 PR target/45074: Check targets of multi-word operations Richard Sandiford

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).