PATCH COMMITTED: More lower-subreg.c patches

Ian Lance Taylor iant@google.com
Sat Feb 3 23:27:00 GMT 2007


Anatoly Sokolov and Andrew Pinski pointed out a couple of other cases
which the new lower-subreg did not handle.

1) Pointers with a mode larger than word_mode (e.g., AVR).

2) Decomposable values passed in hard registers where the hard
   register does not permit a subreg of mode word_mode (e.g., vector
   register parameters where the vector value is decomposed by other
   instructions).

This patch fixes those cases.  Bootstrapped and tested on
i686-pc-linux-gnu.  Committed.

Ian


2007-02-03  Ian Lance Taylor  <iant@google.com>

	* lower-subreg.c (simple_move_operand): New static function,
	broken out of simple_move.  Reject LABEL_REF, SYMBOL_REF, and HIGH
	operands.
	(simple_move): Call simple_move_operand.
	(find_decomposable_subregs): Add special handling of MEMs.
	(can_decompose_p): Rename from cannot_decompose_p.  Reverse
	meaning of return value.  If we see a hard register, test whether
	it can store a word_mode value.  Change all callers.


Index: lower-subreg.c
===================================================================
--- lower-subreg.c	(revision 121552)
+++ lower-subreg.c	(working copy)
@@ -66,6 +66,31 @@ static bitmap non_decomposable_context;
    copy from reg M to reg N.  */
 static VEC(bitmap,heap) *reg_copy_graph;
 
+/* Return whether X is a simple object which we can take a word_mode
+   subreg of.  */
+
+static bool
+simple_move_operand (rtx x)
+{
+  if (GET_CODE (x) == SUBREG)
+    x = SUBREG_REG (x);
+
+  if (!OBJECT_P (x))
+    return false;
+
+  if (GET_CODE (x) == LABEL_REF
+      || GET_CODE (x) == SYMBOL_REF
+      || GET_CODE (x) == HIGH)
+    return false;
+
+  if (MEM_P (x)
+      && (MEM_VOLATILE_P (x)
+	  || mode_dependent_address_p (XEXP (x, 0))))
+    return false;
+
+  return true;
+}
+
 /* If INSN is a single set between two objects, return the single set.
    Such an insn can always be decomposed.  INSN should have been
    passed to recog and extract_insn before this is called.  */
@@ -87,25 +112,16 @@ simple_move (rtx insn)
   x = SET_DEST (set);
   if (x != recog_data.operand[0] && x != recog_data.operand[1])
     return NULL_RTX;
-  if (GET_CODE (x) == SUBREG)
-    x = SUBREG_REG (x);
-  if (!OBJECT_P (x))
-    return NULL_RTX;
-  if (MEM_P (x)
-      && (MEM_VOLATILE_P (x)
-	  || mode_dependent_address_p (XEXP (x, 0))))
+  if (!simple_move_operand (x))
     return NULL_RTX;
 
   x = SET_SRC (set);
   if (x != recog_data.operand[0] && x != recog_data.operand[1])
     return NULL_RTX;
-  if (GET_CODE (x) == SUBREG)
-    x = SUBREG_REG (x);
-  if (!OBJECT_P (x) && GET_CODE (x) != ASM_OPERANDS)
-    return NULL_RTX;
-  if (MEM_P (x)
-      && (MEM_VOLATILE_P (x)
-	  || mode_dependent_address_p (XEXP (x, 0))))
+  /* For the src we can handle ASM_OPERANDS, and it is beneficial for
+     things like x86 rdtsc which returns a DImode value.  */
+  if (GET_CODE (x) != ASM_OPERANDS
+      && !simple_move_operand (x))
     return NULL_RTX;
 
   /* We try to decompose in integer modes, to avoid generating
@@ -259,7 +275,7 @@ find_decomposable_subregs (rtx *px, void
 	  return -1;
 	}
     }
-  else if (GET_CODE (x) == REG)
+  else if (REG_P (x))
     {
       unsigned int regno;
 
@@ -299,6 +315,16 @@ find_decomposable_subregs (rtx *px, void
 	    }
 	}
     }
+  else if (MEM_P (x))
+    {
+      enum classify_move_insn cmi_mem = NOT_SIMPLE_MOVE;
+
+      /* Any registers used in a MEM do not participate in a
+	 SIMPLE_MOVE or SIMPLE_PSEUDO_REG_MOVE.  Do our own recursion
+	 here, and return -1 to block the parent's recursion.  */
+      for_each_rtx (&XEXP (x, 0), find_decomposable_subregs, &cmi_mem);
+      return -1;
+    }
 
   return 0;
 }
@@ -585,22 +611,23 @@ resolve_reg_notes (rtx insn)
     }
 }
 
-/* Return whether X can not be decomposed into subwords.  */
+/* Return whether X can be decomposed into subwords.  */
 
 static bool
-cannot_decompose_p (rtx x)
+can_decompose_p (rtx x)
 {
   if (REG_P (x))
     {
       unsigned int regno = REGNO (x);
 
       if (HARD_REGISTER_NUM_P (regno))
-	return !validate_subreg (word_mode, GET_MODE (x), x, UNITS_PER_WORD);
+	return (validate_subreg (word_mode, GET_MODE (x), x, UNITS_PER_WORD)
+		&& HARD_REGNO_MODE_OK (regno, word_mode));
       else
-	return bitmap_bit_p (non_decomposable_context, regno);
+	return !bitmap_bit_p (non_decomposable_context, regno);
     }
 
-  return false;
+  return true;
 }
 
 /* Decompose the registers used in a simple move SET within INSN.  If
@@ -681,7 +708,7 @@ resolve_simple_move (rtx set, rtx insn)
   /* If SRC is a register which we can't decompose, or has side
      effects, we need to move via a temporary register.  */
 
-  if (cannot_decompose_p (src)
+  if (!can_decompose_p (src)
       || side_effects_p (src)
       || GET_CODE (src) == ASM_OPERANDS)
     {
@@ -701,7 +728,7 @@ resolve_simple_move (rtx set, rtx insn)
 
   dest_mode = orig_mode;
   pushing = push_operand (dest, dest_mode);
-  if (cannot_decompose_p (dest)
+  if (!can_decompose_p (dest)
       || (side_effects_p (dest) && !pushing)
       || (!SCALAR_INT_MODE_P (dest_mode)
 	  && !resolve_reg_p (dest)



More information about the Gcc-patches mailing list