aboutsummaryrefslogtreecommitdiff
path: root/gcc/function.c
diff options
context:
space:
mode:
authorVladimir Makarov <vmakarov@tofu.to.cygnus.com>1999-05-05 13:30:51 +0000
committerVladimir Makarov <vmakarov@gcc.gnu.org>1999-05-05 13:30:51 +0000
commit8b04083becc6a7703c24f9802cd943da33de2a4a (patch)
tree13754bae153a54ceb8907f647de03fe66ccfbb4c /gcc/function.c
parent24dc3000ddb70742725cec46ee03b3cf9679c453 (diff)
function.c (purge_addressof_replacements): Rename into purge_bitfield_addressof_replacements.
Wed May 5 16:26:13 1999 Vladimir Makarov <vmakarov@tofu.to.cygnus.com> * function.c (purge_addressof_replacements): Rename into purge_bitfield_addressof_replacements. (purge_addressof_replacements): New variable. (purge_addressof_1): Add code for changing addressof in notes for field values which are extracted by usage MEM with narrower mode. (purge_addressof): Initialize purge_bitfield_addressof_replacements. From-SVN: r26784
Diffstat (limited to 'gcc/function.c')
-rw-r--r--gcc/function.c125
1 files changed, 76 insertions, 49 deletions
diff --git a/gcc/function.c b/gcc/function.c
index e6fb7866378..0937844d812 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -3031,6 +3031,14 @@ put_addressof_into_stack (r, ht)
/* List of replacements made below in purge_addressof_1 when creating
bitfield insertions. */
+static rtx purge_bitfield_addressof_replacements;
+
+/* List of replacements made below in purge_addressof_1 for patterns
+ (MEM (ADDRESSOF (REG ...))). The key of the list entry is the
+ corresponding (ADDRESSOF (REG ...)) and value is a substitution for
+ the all pattern. List PURGE_BITFIELD_ADDRESSOF_REPLACEMENTS is not
+ enough in complex cases, e.g. when some field values can be
+ extracted by usage MEM with narrower mode. */
static rtx purge_addressof_replacements;
/* Helper function for purge_addressof. See if the rtx expression at *LOC
@@ -3110,51 +3118,54 @@ purge_addressof_1 (loc, insn, force, store, ht)
was replaced by. */
rtx tem;
- for (tem = purge_addressof_replacements; tem != NULL_RTX;
+ for (tem = purge_bitfield_addressof_replacements;
+ tem != NULL_RTX;
tem = XEXP (XEXP (tem, 1), 1))
- {
- rtx y = XEXP (tem, 0);
- if (GET_CODE (y) == MEM
- && rtx_equal_p (XEXP (x, 0), XEXP (y, 0)))
- {
- /* It can happen that the note may speak of things in
- a wider (or just different) mode than the code did.
- This is especially true of REG_RETVAL. */
+ if (rtx_equal_p (x, XEXP (tem, 0)))
+ {
+ *loc = XEXP (XEXP (tem, 1), 0);
+ return;
+ }
- rtx z = XEXP (XEXP (tem, 1), 0);
- if (GET_MODE (x) != GET_MODE (y))
- {
- if (GET_CODE (z) == SUBREG && SUBREG_WORD (z) == 0)
- z = SUBREG_REG (z);
-
- /* ??? If we'd gotten into any of the really complex
- cases below, I'm not sure we can do a proper
- replacement. Might we be able to delete the
- note in some cases? */
- if (GET_MODE_SIZE (GET_MODE (x))
- < GET_MODE_SIZE (GET_MODE (y)))
- abort ();
-
- if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD
- && (GET_MODE_SIZE (GET_MODE (x))
- > GET_MODE_SIZE (GET_MODE (z))))
- {
- /* This can occur as a result in invalid
- pointer casts, e.g. float f; ...
- *(long long int *)&f.
- ??? We could emit a warning here, but
- without a line number that wouldn't be
- very helpful. */
- z = gen_rtx_SUBREG (GET_MODE (x), z, 0);
- }
- else
- z = gen_lowpart (GET_MODE (x), z);
- }
+ /* See comment for purge_addressof_replacements. */
+ for (tem = purge_addressof_replacements;
+ tem != NULL_RTX;
+ tem = XEXP (XEXP (tem, 1), 1))
+ if (rtx_equal_p (XEXP (x, 0), XEXP (tem, 0)))
+ {
+ rtx z = XEXP (XEXP (tem, 1), 0);
- *loc = z;
- return;
- }
- }
+ if (GET_MODE (x) == GET_MODE (z)
+ || (GET_CODE (XEXP (XEXP (tem, 1), 0)) != REG
+ && GET_CODE (XEXP (XEXP (tem, 1), 0)) != SUBREG))
+ abort ();
+
+ /* It can happen that the note may speak of things
+ in a wider (or just different) mode than the
+ code did. This is especially true of
+ REG_RETVAL. */
+
+ if (GET_CODE (z) == SUBREG && SUBREG_WORD (z) == 0)
+ z = SUBREG_REG (z);
+
+ if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD
+ && (GET_MODE_SIZE (GET_MODE (x))
+ > GET_MODE_SIZE (GET_MODE (z))))
+ {
+ /* This can occur as a result in invalid
+ pointer casts, e.g. float f; ...
+ *(long long int *)&f.
+ ??? We could emit a warning here, but
+ without a line number that wouldn't be
+ very helpful. */
+ z = gen_rtx_SUBREG (GET_MODE (x), z, 0);
+ }
+ else
+ z = gen_lowpart (GET_MODE (x), z);
+
+ *loc = z;
+ return;
+ }
/* There should always be such a replacement. */
abort ();
@@ -3242,10 +3253,11 @@ purge_addressof_1 (loc, insn, force, store, ht)
/* Remember the replacement so that the same one can be done
on the REG_NOTES. */
- purge_addressof_replacements
+ purge_bitfield_addressof_replacements
= gen_rtx_EXPR_LIST (VOIDmode, x,
- gen_rtx_EXPR_LIST (VOIDmode, val,
- purge_addressof_replacements));
+ gen_rtx_EXPR_LIST
+ (VOIDmode, val,
+ purge_bitfield_addressof_replacements));
/* We replaced with a reg -- all done. */
return;
@@ -3255,10 +3267,24 @@ purge_addressof_1 (loc, insn, force, store, ht)
{
/* Remember the replacement so that the same one can be done
on the REG_NOTES. */
- purge_addressof_replacements
- = gen_rtx_EXPR_LIST (VOIDmode, x,
- gen_rtx_EXPR_LIST (VOIDmode, sub,
- purge_addressof_replacements));
+ if (GET_CODE (sub) == REG || GET_CODE (sub) == SUBREG)
+ {
+ rtx tem;
+
+ for (tem = purge_addressof_replacements;
+ tem != NULL_RTX;
+ tem = XEXP (XEXP (tem, 1), 1))
+ if (rtx_equal_p (XEXP (x, 0), XEXP (tem, 0)))
+ {
+ XEXP (XEXP (tem, 1), 0) = sub;
+ return;
+ }
+ purge_addressof_replacements
+ = gen_rtx (EXPR_LIST, VOIDmode, XEXP (x, 0),
+ gen_rtx_EXPR_LIST (VOIDmode, sub,
+ purge_addressof_replacements));
+ return;
+ }
goto restart;
}
give_up:;
@@ -3440,6 +3466,7 @@ purge_addressof (insns)
/* Clean up. */
hash_table_free (&ht);
+ purge_bitfield_addressof_replacements = 0;
purge_addressof_replacements = 0;
}