summaryrefslogtreecommitdiffstats
path: root/gnu/usr.bin/cc/cc_int/integrate.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/usr.bin/cc/cc_int/integrate.c')
-rw-r--r--gnu/usr.bin/cc/cc_int/integrate.c62
1 files changed, 45 insertions, 17 deletions
diff --git a/gnu/usr.bin/cc/cc_int/integrate.c b/gnu/usr.bin/cc/cc_int/integrate.c
index 63b150d..2355508 100644
--- a/gnu/usr.bin/cc/cc_int/integrate.c
+++ b/gnu/usr.bin/cc/cc_int/integrate.c
@@ -134,10 +134,15 @@ function_cannot_inline_p (fndecl)
if (int_size_in_bytes (TREE_TYPE (TREE_TYPE (fndecl))) < 0)
return "function with varying-size return value cannot be inline";
- /* Cannot inline a function with a varying size argument. */
+ /* Cannot inline a function with a varying size argument or one that
+ receives a transparent union. */
for (parms = DECL_ARGUMENTS (fndecl); parms; parms = TREE_CHAIN (parms))
- if (int_size_in_bytes (TREE_TYPE (parms)) < 0)
- return "function with varying-size parameter cannot be inline";
+ {
+ if (int_size_in_bytes (TREE_TYPE (parms)) < 0)
+ return "function with varying-size parameter cannot be inline";
+ else if (TYPE_TRANSPARENT_UNION (TREE_TYPE (parms)))
+ return "function with transparent unit parameter cannot be inline";
+ }
if (!DECL_INLINE (fndecl) && get_max_uid () > max_insns)
{
@@ -1235,6 +1240,7 @@ expand_inline_function (fndecl, parms, target, ignore, type, structure_value_add
tree arg = convert (TREE_TYPE (formal), TREE_VALUE (actual));
/* Mode of the variable used within the function. */
enum machine_mode mode = TYPE_MODE (TREE_TYPE (formal));
+ int invisiref = 0;
/* Make sure this formal has some correspondence in the users code
* before emitting any line notes for it. */
@@ -1263,6 +1269,7 @@ expand_inline_function (fndecl, parms, target, ignore, type, structure_value_add
store_expr (arg, stack_slot, 0);
arg_vals[i] = XEXP (stack_slot, 0);
+ invisiref = 1;
}
else if (GET_CODE (loc) != MEM)
{
@@ -1288,8 +1295,11 @@ expand_inline_function (fndecl, parms, target, ignore, type, structure_value_add
be two different pseudos, and `safe_from_p' will make all
sorts of smart assumptions about their not conflicting.
But if ARG_VALS[I] overlaps TARGET, these assumptions are
- wrong, so put ARG_VALS[I] into a fresh register. */
+ wrong, so put ARG_VALS[I] into a fresh register.
+ Don't worry about invisible references, since their stack
+ temps will never overlap the target. */
|| (target != 0
+ && ! invisiref
&& (GET_CODE (arg_vals[i]) == REG
|| GET_CODE (arg_vals[i]) == SUBREG
|| GET_CODE (arg_vals[i]) == MEM)
@@ -1640,7 +1650,7 @@ expand_inline_function (fndecl, parms, target, ignore, type, structure_value_add
for (insn = insns; insn; insn = NEXT_INSN (insn))
{
- rtx copy, pattern;
+ rtx copy, pattern, set;
map->orig_asm_operands_vector = 0;
@@ -1648,6 +1658,7 @@ expand_inline_function (fndecl, parms, target, ignore, type, structure_value_add
{
case INSN:
pattern = PATTERN (insn);
+ set = single_set (insn);
copy = 0;
if (GET_CODE (pattern) == USE
&& GET_CODE (XEXP (pattern, 0)) == REG
@@ -1659,33 +1670,47 @@ expand_inline_function (fndecl, parms, target, ignore, type, structure_value_add
/* Ignore setting a function value that we don't want to use. */
if (map->inline_target == 0
- && GET_CODE (pattern) == SET
- && GET_CODE (SET_DEST (pattern)) == REG
- && REG_FUNCTION_VALUE_P (SET_DEST (pattern)))
+ && set != 0
+ && GET_CODE (SET_DEST (set)) == REG
+ && REG_FUNCTION_VALUE_P (SET_DEST (set)))
{
- if (volatile_refs_p (SET_SRC (pattern)))
+ if (volatile_refs_p (SET_SRC (set)))
{
+ rtx new_set;
+
/* If we must not delete the source,
load it into a new temporary. */
copy = emit_insn (copy_rtx_and_substitute (pattern, map));
- SET_DEST (PATTERN (copy))
- = gen_reg_rtx (GET_MODE (SET_DEST (PATTERN (copy))));
+
+ new_set = single_set (copy);
+ if (new_set == 0)
+ abort ();
+
+ SET_DEST (new_set)
+ = gen_reg_rtx (GET_MODE (SET_DEST (new_set)));
}
else
break;
}
+
+ /* If this is setting the static chain rtx, omit it. */
+ else if (static_chain_value != 0
+ && set != 0
+ && GET_CODE (SET_DEST (set)) == REG
+ && rtx_equal_p (SET_DEST (set),
+ static_chain_incoming_rtx))
+ break;
+
/* If this is setting the static chain pseudo, set it from
the value we want to give it instead. */
else if (static_chain_value != 0
- && GET_CODE (pattern) == SET
- && rtx_equal_p (SET_SRC (pattern),
+ && set != 0
+ && rtx_equal_p (SET_SRC (set),
static_chain_incoming_rtx))
{
- rtx newdest = copy_rtx_and_substitute (SET_DEST (pattern), map);
-
- copy = emit_insn (gen_rtx (SET, VOIDmode, newdest,
- static_chain_value));
+ rtx newdest = copy_rtx_and_substitute (SET_DEST (set), map);
+ copy = emit_move_insn (newdest, static_chain_value);
static_chain_value = 0;
}
else
@@ -2585,6 +2610,9 @@ subst_constants (loc, insn, map)
/* If storing a recognizable value save it for later recording. */
if ((map->num_sets < MAX_RECOG_OPERANDS)
&& (CONSTANT_P (src)
+ || (GET_CODE (src) == REG
+ && REGNO (src) >= FIRST_VIRTUAL_REGISTER
+ && REGNO (src) <= LAST_VIRTUAL_REGISTER)
|| (GET_CODE (src) == PLUS
&& GET_CODE (XEXP (src, 0)) == REG
&& REGNO (XEXP (src, 0)) >= FIRST_VIRTUAL_REGISTER
OpenPOWER on IntegriCloud