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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@121553
138bc75d-0d04-0410-961f-
82ee72b054a4
+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.
+
2007-02-03 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
* pa.md (addvdi3, addvsi3, subvdi3, subvsi3, negvdi2, negvsi2): New
2007-02-03 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
* pa.md (addvdi3, addvsi3, subvdi3, subvsi3, negvdi2, negvsi2): New
copy from reg M to reg N. */
static VEC(bitmap,heap) *reg_copy_graph;
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. */
/* 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. */
x = SET_DEST (set);
if (x != recog_data.operand[0] && x != recog_data.operand[1])
return NULL_RTX;
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;
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
return NULL_RTX;
/* We try to decompose in integer modes, to avoid generating
- else if (GET_CODE (x) == REG)
+ 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 whether X can not be decomposed into subwords. */
+/* Return whether X can be decomposed into subwords. */
-cannot_decompose_p (rtx x)
{
if (REG_P (x))
{
unsigned int regno = REGNO (x);
if (HARD_REGISTER_NUM_P (regno))
{
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));
- return bitmap_bit_p (non_decomposable_context, regno);
+ return !bitmap_bit_p (non_decomposable_context, regno);
}
/* Decompose the registers used in a simple move SET within INSN. If
}
/* Decompose the registers used in a simple move SET within INSN. If
/* If SRC is a register which we can't decompose, or has side
effects, we need to move via a temporary register. */
/* 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)
{
|| side_effects_p (src)
|| GET_CODE (src) == ASM_OPERANDS)
{
dest_mode = orig_mode;
pushing = push_operand (dest, dest_mode);
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)
|| (side_effects_p (dest) && !pushing)
|| (!SCALAR_INT_MODE_P (dest_mode)
&& !resolve_reg_p (dest)