summaryrefslogtreecommitdiff
path: root/gcc/lower-subreg.c
diff options
context:
space:
mode:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2007-02-03 23:24:05 +0000
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2007-02-03 23:24:05 +0000
commit67c3f5800258cc7f24b26b3a62e43eb30eee6df4 (patch)
treedb3f29175ce934413da3dd780817932fff7c451e /gcc/lower-subreg.c
parentee7100c7eda59dc44e6b0949274813d029228619 (diff)
downloadgcc-67c3f5800258cc7f24b26b3a62e43eb30eee6df4.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@121553 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/lower-subreg.c')
-rw-r--r--gcc/lower-subreg.c71
1 files changed, 49 insertions, 22 deletions
diff --git a/gcc/lower-subreg.c b/gcc/lower-subreg.c
index 104a1d98a48..62bfea0a100 100644
--- a/gcc/lower-subreg.c
+++ b/gcc/lower-subreg.c
@@ -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 *data)
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 *data)
}
}
}
+ 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)