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