summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/function.c
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>2002-05-09 21:44:15 +0000
committerobrien <obrien@FreeBSD.org>2002-05-09 21:44:15 +0000
commitb7d19d3348f08e28d0db33ed1d275c605eaf39ca (patch)
treec8d0b59c618288a2d5d5fb376118467ddec8f5ca /contrib/gcc/function.c
parent603733766c669f42cc46cca4dcbceb3aa563b98b (diff)
downloadFreeBSD-src-b7d19d3348f08e28d0db33ed1d275c605eaf39ca.zip
FreeBSD-src-b7d19d3348f08e28d0db33ed1d275c605eaf39ca.tar.gz
Merge rev 1.2 (a.out support) into the GCC 3.1 prerelease.
Diffstat (limited to 'contrib/gcc/function.c')
-rw-r--r--contrib/gcc/function.c438
1 files changed, 280 insertions, 158 deletions
diff --git a/contrib/gcc/function.c b/contrib/gcc/function.c
index 3ca6b0e..9533442 100644
--- a/contrib/gcc/function.c
+++ b/contrib/gcc/function.c
@@ -127,6 +127,9 @@ int current_function_uses_only_leaf_regs;
post-instantiation libcalls. */
int virtuals_instantiated;
+/* Assign unique numbers to labels generated for profiling. */
+static int profile_label_no;
+
/* These variables hold pointers to functions to create and destroy
target specific, per-function data structures. */
void (*init_machine_status) PARAMS ((struct function *));
@@ -243,21 +246,22 @@ static void put_reg_into_stack PARAMS ((struct function *, rtx, tree,
static void schedule_fixup_var_refs PARAMS ((struct function *, rtx, tree,
enum machine_mode,
struct hash_table *));
-static void fixup_var_refs PARAMS ((rtx, enum machine_mode, int,
+static void fixup_var_refs PARAMS ((rtx, enum machine_mode, int, rtx,
struct hash_table *));
static struct fixup_replacement
*find_fixup_replacement PARAMS ((struct fixup_replacement **, rtx));
static void fixup_var_refs_insns PARAMS ((rtx, rtx, enum machine_mode,
- int, int));
+ int, int, rtx));
static void fixup_var_refs_insns_with_hash
PARAMS ((struct hash_table *, rtx,
- enum machine_mode, int));
+ enum machine_mode, int, rtx));
static void fixup_var_refs_insn PARAMS ((rtx, rtx, enum machine_mode,
- int, int));
+ int, int, rtx));
static void fixup_var_refs_1 PARAMS ((rtx, enum machine_mode, rtx *, rtx,
- struct fixup_replacement **));
-static rtx fixup_memory_subreg PARAMS ((rtx, rtx, int));
-static rtx walk_fixup_memory_subreg PARAMS ((rtx, rtx, int));
+ struct fixup_replacement **, rtx));
+static rtx fixup_memory_subreg PARAMS ((rtx, rtx, enum machine_mode, int));
+static rtx walk_fixup_memory_subreg PARAMS ((rtx, rtx, enum machine_mode,
+ int));
static rtx fixup_stack_1 PARAMS ((rtx, rtx));
static void optimize_bit_field PARAMS ((rtx, rtx, rtx *));
static void instantiate_decls PARAMS ((tree, int));
@@ -393,11 +397,29 @@ pop_function_context_from (context)
if (restore_lang_status)
(*restore_lang_status) (p);
- /* Finish doing put_var_into_stack for any of our variables
- which became addressable during the nested function. */
- for (queue = p->fixup_var_refs_queue; queue; queue = queue->next)
- fixup_var_refs (queue->modified, queue->promoted_mode,
- queue->unsignedp, 0);
+ /* Finish doing put_var_into_stack for any of our variables which became
+ addressable during the nested function. If only one entry has to be
+ fixed up, just do that one. Otherwise, first make a list of MEMs that
+ are not to be unshared. */
+ if (p->fixup_var_refs_queue == 0)
+ ;
+ else if (p->fixup_var_refs_queue->next == 0)
+ fixup_var_refs (p->fixup_var_refs_queue->modified,
+ p->fixup_var_refs_queue->promoted_mode,
+ p->fixup_var_refs_queue->unsignedp,
+ p->fixup_var_refs_queue->modified, 0);
+ else
+ {
+ rtx list = 0;
+
+ for (queue = p->fixup_var_refs_queue; queue; queue = queue->next)
+ list = gen_rtx_EXPR_LIST (VOIDmode, queue->modified, list);
+
+ for (queue = p->fixup_var_refs_queue; queue; queue = queue->next)
+ fixup_var_refs (queue->modified, queue->promoted_mode,
+ queue->unsignedp, list, 0);
+
+ }
p->fixup_var_refs_queue = 0;
@@ -830,7 +852,10 @@ assign_stack_temp (mode, size, keep)
return assign_stack_temp_for_type (mode, size, keep, NULL_TREE);
}
-/* Assign a temporary of given TYPE.
+/* Assign a temporary.
+ If TYPE_OR_DECL is a decl, then we are doing it on behalf of the decl
+ and so that should be used in error messages. In either case, we
+ allocate of the given type.
KEEP is as for assign_stack_temp.
MEMORY_REQUIRED is 1 if the result must be addressable stack memory;
it is 0 if a register is OK.
@@ -838,15 +863,26 @@ assign_stack_temp (mode, size, keep)
to wider modes. */
rtx
-assign_temp (type, keep, memory_required, dont_promote)
- tree type;
+assign_temp (type_or_decl, keep, memory_required, dont_promote)
+ tree type_or_decl;
int keep;
int memory_required;
int dont_promote ATTRIBUTE_UNUSED;
{
- enum machine_mode mode = TYPE_MODE (type);
+ tree type, decl;
+ enum machine_mode mode;
#ifndef PROMOTE_FOR_CALL_ONLY
- int unsignedp = TREE_UNSIGNED (type);
+ int unsignedp;
+#endif
+
+ if (DECL_P (type_or_decl))
+ decl = type_or_decl, type = TREE_TYPE (decl);
+ else
+ decl = NULL, type = type_or_decl;
+
+ mode = TYPE_MODE (type);
+#ifndef PROMOTE_FOR_CALL_ONLY
+ unsignedp = TREE_UNSIGNED (type);
#endif
if (mode == BLKmode || memory_required)
@@ -868,6 +904,17 @@ assign_temp (type, keep, memory_required, dont_promote)
&& host_integerp (TYPE_ARRAY_MAX_SIZE (type), 1))
size = tree_low_cst (TYPE_ARRAY_MAX_SIZE (type), 1);
+ /* The size of the temporary may be too large to fit into an integer. */
+ /* ??? Not sure this should happen except for user silliness, so limit
+ this to things that aren't compiler-generated temporaries. The
+ rest of the time we'll abort in assign_stack_temp_for_type. */
+ if (decl && size == -1
+ && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST)
+ {
+ error_with_decl (decl, "size of variable `%s' is too large");
+ size = 1;
+ }
+
tmp = assign_stack_temp_for_type (mode, size, keep, type);
return tmp;
}
@@ -1529,15 +1576,16 @@ schedule_fixup_var_refs (function, reg, type, promoted_mode, ht)
}
else
/* Variable is local; fix it up now. */
- fixup_var_refs (reg, promoted_mode, unsigned_p, ht);
+ fixup_var_refs (reg, promoted_mode, unsigned_p, reg, ht);
}
static void
-fixup_var_refs (var, promoted_mode, unsignedp, ht)
+fixup_var_refs (var, promoted_mode, unsignedp, may_share, ht)
rtx var;
enum machine_mode promoted_mode;
int unsignedp;
struct hash_table *ht;
+ rtx may_share;
{
tree pending;
rtx first_insn = get_insns ();
@@ -1549,19 +1597,20 @@ fixup_var_refs (var, promoted_mode, unsignedp, ht)
{
if (stack != 0)
abort ();
- fixup_var_refs_insns_with_hash (ht, var, promoted_mode, unsignedp);
+ fixup_var_refs_insns_with_hash (ht, var, promoted_mode, unsignedp,
+ may_share);
return;
}
fixup_var_refs_insns (first_insn, var, promoted_mode, unsignedp,
- stack == 0);
+ stack == 0, may_share);
/* Scan all pending sequences too. */
for (; stack; stack = stack->next)
{
push_to_full_sequence (stack->first, stack->last);
fixup_var_refs_insns (stack->first, var, promoted_mode, unsignedp,
- stack->next != 0);
+ stack->next != 0, may_share);
/* Update remembered end of sequence
in case we added an insn at the end. */
stack->last = get_last_insn ();
@@ -1575,7 +1624,8 @@ fixup_var_refs (var, promoted_mode, unsignedp, ht)
if (seq != const0_rtx && seq != 0)
{
push_to_sequence (seq);
- fixup_var_refs_insns (seq, var, promoted_mode, unsignedp, 0);
+ fixup_var_refs_insns (seq, var, promoted_mode, unsignedp, 0,
+ may_share);
end_sequence ();
}
}
@@ -1608,17 +1658,19 @@ find_fixup_replacement (replacements, x)
return p;
}
-/* Scan the insn-chain starting with INSN for refs to VAR
- and fix them up. TOPLEVEL is nonzero if this chain is the
- main chain of insns for the current function. */
+/* Scan the insn-chain starting with INSN for refs to VAR and fix them
+ up. TOPLEVEL is nonzero if this chain is the main chain of insns
+ for the current function. MAY_SHARE is either a MEM that is not
+ to be unshared or a list of them. */
static void
-fixup_var_refs_insns (insn, var, promoted_mode, unsignedp, toplevel)
+fixup_var_refs_insns (insn, var, promoted_mode, unsignedp, toplevel, may_share)
rtx insn;
rtx var;
enum machine_mode promoted_mode;
int unsignedp;
int toplevel;
+ rtx may_share;
{
while (insn)
{
@@ -1643,7 +1695,8 @@ fixup_var_refs_insns (insn, var, promoted_mode, unsignedp, toplevel)
if (seq)
{
push_to_sequence (seq);
- fixup_var_refs_insns (seq, var, promoted_mode, unsignedp, 0);
+ fixup_var_refs_insns (seq, var, promoted_mode, unsignedp, 0,
+ may_share);
XEXP (PATTERN (insn), i) = get_insns ();
end_sequence ();
}
@@ -1651,7 +1704,8 @@ fixup_var_refs_insns (insn, var, promoted_mode, unsignedp, toplevel)
}
else if (INSN_P (insn))
- fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, toplevel);
+ fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, toplevel,
+ may_share);
insn = next;
}
@@ -1665,25 +1719,22 @@ fixup_var_refs_insns (insn, var, promoted_mode, unsignedp, toplevel)
(inside the CALL_PLACEHOLDER). */
static void
-fixup_var_refs_insns_with_hash (ht, var, promoted_mode, unsignedp)
+fixup_var_refs_insns_with_hash (ht, var, promoted_mode, unsignedp, may_share)
struct hash_table *ht;
rtx var;
enum machine_mode promoted_mode;
int unsignedp;
+ rtx may_share;
{
- struct insns_for_mem_entry *ime = (struct insns_for_mem_entry *)
- hash_lookup (ht, var, /*create=*/0, /*copy=*/0);
- rtx insn_list = ime->insns;
-
- while (insn_list)
- {
- rtx insn = XEXP (insn_list, 0);
-
- if (INSN_P (insn))
- fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, 1);
-
- insn_list = XEXP (insn_list, 1);
- }
+ struct insns_for_mem_entry *ime
+ = (struct insns_for_mem_entry *) hash_lookup (ht, var,
+ /*create=*/0, /*copy=*/0);
+ rtx insn_list;
+
+ for (insn_list = ime->insns; insn_list != 0; insn_list = XEXP (insn_list, 1))
+ if (INSN_P (XEXP (insn_list, 0)))
+ fixup_var_refs_insn (XEXP (insn_list, 0), var, promoted_mode,
+ unsignedp, 1, may_share);
}
@@ -1694,12 +1745,13 @@ fixup_var_refs_insns_with_hash (ht, var, promoted_mode, unsignedp)
function. */
static void
-fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, toplevel)
+fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, toplevel, no_share)
rtx insn;
rtx var;
enum machine_mode promoted_mode;
int unsignedp;
int toplevel;
+ rtx no_share;
{
rtx call_dest = 0;
rtx set, prev, prev_set;
@@ -1804,7 +1856,7 @@ fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, toplevel)
it here. */
fixup_var_refs_1 (var, promoted_mode, &PATTERN (insn), insn,
- &replacements);
+ &replacements, no_share);
/* If this is last_parm_insn, and any instructions were output
after it to fix it up, then we must set last_parm_insn to
@@ -1824,7 +1876,8 @@ fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, toplevel)
/* OLD might be a (subreg (mem)). */
if (GET_CODE (replacements->old) == SUBREG)
replacements->old
- = fixup_memory_subreg (replacements->old, insn, 0);
+ = fixup_memory_subreg (replacements->old, insn,
+ promoted_mode, 0);
else
replacements->old
= fixup_stack_1 (replacements->old, insn);
@@ -1864,7 +1917,8 @@ fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, toplevel)
{
if (GET_CODE (note) != INSN_LIST)
XEXP (note, 0)
- = walk_fixup_memory_subreg (XEXP (note, 0), insn, 1);
+ = walk_fixup_memory_subreg (XEXP (note, 0), insn,
+ promoted_mode, 1);
note = XEXP (note, 1);
}
}
@@ -1881,12 +1935,13 @@ fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, toplevel)
or the SUBREG, as appropriate, to the pseudo. */
static void
-fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
+fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share)
rtx var;
enum machine_mode promoted_mode;
rtx *loc;
rtx insn;
struct fixup_replacement **replacements;
+ rtx no_share;
{
int i;
rtx x = *loc;
@@ -1983,7 +2038,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
{
replacement = find_fixup_replacement (replacements, x);
if (replacement->new == 0)
- replacement->new = copy_most_rtx (x, var);
+ replacement->new = copy_most_rtx (x, no_share);
*loc = x = replacement->new;
code = GET_CODE (x);
@@ -1998,6 +2053,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
case SYMBOL_REF:
case LABEL_REF:
case CONST_DOUBLE:
+ case CONST_VECTOR:
return;
case SIGN_EXTRACT:
@@ -2033,7 +2089,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
return;
}
else
- tem = fixup_memory_subreg (tem, insn, 0);
+ tem = fixup_memory_subreg (tem, insn, promoted_mode, 0);
}
else
tem = fixup_stack_1 (tem, insn);
@@ -2119,7 +2175,8 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
if (SUBREG_PROMOTED_VAR_P (x))
{
*loc = var;
- fixup_var_refs_1 (var, GET_MODE (var), loc, insn, replacements);
+ fixup_var_refs_1 (var, GET_MODE (var), loc, insn, replacements,
+ no_share);
return;
}
@@ -2147,7 +2204,8 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
return;
}
- replacement->new = *loc = fixup_memory_subreg (x, insn, 0);
+ replacement->new = *loc = fixup_memory_subreg (x, insn,
+ promoted_mode, 0);
INSN_CODE (insn) = -1;
if (! flag_force_mem && recog_memoized (insn) >= 0)
@@ -2225,11 +2283,11 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
/* Since this case will return, ensure we fixup all the
operands here. */
fixup_var_refs_1 (var, promoted_mode, &XEXP (outerdest, 1),
- insn, replacements);
+ insn, replacements, no_share);
fixup_var_refs_1 (var, promoted_mode, &XEXP (outerdest, 2),
- insn, replacements);
+ insn, replacements, no_share);
fixup_var_refs_1 (var, promoted_mode, &SET_SRC (x),
- insn, replacements);
+ insn, replacements, no_share);
tem = XEXP (outerdest, 0);
@@ -2238,7 +2296,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
This was legitimate when the MEM was a REG. */
if (GET_CODE (tem) == SUBREG
&& SUBREG_REG (tem) == var)
- tem = fixup_memory_subreg (tem, insn, 0);
+ tem = fixup_memory_subreg (tem, insn, promoted_mode, 0);
else
tem = fixup_stack_1 (tem, insn);
@@ -2322,15 +2380,30 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
{
rtx pat, last;
- replacement = find_fixup_replacement (replacements, SET_SRC (x));
- if (replacement->new)
- SET_SRC (x) = replacement->new;
- else if (GET_CODE (SET_SRC (x)) == SUBREG)
- SET_SRC (x) = replacement->new
- = fixup_memory_subreg (SET_SRC (x), insn, 0);
+ if (GET_CODE (SET_SRC (x)) == SUBREG
+ && (GET_MODE_SIZE (GET_MODE (SET_SRC (x)))
+ > GET_MODE_SIZE (GET_MODE (var))))
+ {
+ /* This (subreg VAR) is now a paradoxical subreg. We need
+ to replace VAR instead of the subreg. */
+ replacement = find_fixup_replacement (replacements, var);
+ if (replacement->new == NULL_RTX)
+ replacement->new = gen_reg_rtx (GET_MODE (var));
+ SUBREG_REG (SET_SRC (x)) = replacement->new;
+ }
else
- SET_SRC (x) = replacement->new
- = fixup_stack_1 (SET_SRC (x), insn);
+ {
+ replacement = find_fixup_replacement (replacements, SET_SRC (x));
+ if (replacement->new)
+ SET_SRC (x) = replacement->new;
+ else if (GET_CODE (SET_SRC (x)) == SUBREG)
+ SET_SRC (x) = replacement->new
+ = fixup_memory_subreg (SET_SRC (x), insn, promoted_mode,
+ 0);
+ else
+ SET_SRC (x) = replacement->new
+ = fixup_stack_1 (SET_SRC (x), insn);
+ }
if (recog_memoized (insn) >= 0)
return;
@@ -2379,7 +2452,8 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
rtx pat, last;
if (GET_CODE (SET_DEST (x)) == SUBREG)
- SET_DEST (x) = fixup_memory_subreg (SET_DEST (x), insn, 0);
+ SET_DEST (x) = fixup_memory_subreg (SET_DEST (x), insn,
+ promoted_mode, 0);
else
SET_DEST (x) = fixup_stack_1 (SET_DEST (x), insn);
@@ -2424,6 +2498,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
{
rtx temp;
rtx fixeddest = SET_DEST (x);
+ enum machine_mode temp_mode;
/* STRICT_LOW_PART can be discarded, around a MEM. */
if (GET_CODE (fixeddest) == STRICT_LOW_PART)
@@ -2431,13 +2506,17 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
/* Convert (SUBREG (MEM)) to a MEM in a changed mode. */
if (GET_CODE (fixeddest) == SUBREG)
{
- fixeddest = fixup_memory_subreg (fixeddest, insn, 0);
- promoted_mode = GET_MODE (fixeddest);
+ fixeddest = fixup_memory_subreg (fixeddest, insn,
+ promoted_mode, 0);
+ temp_mode = GET_MODE (fixeddest);
}
else
- fixeddest = fixup_stack_1 (fixeddest, insn);
+ {
+ fixeddest = fixup_stack_1 (fixeddest, insn);
+ temp_mode = promoted_mode;
+ }
- temp = gen_reg_rtx (promoted_mode);
+ temp = gen_reg_rtx (temp_mode);
emit_insn_after (gen_move_insn (fixeddest,
gen_lowpart (GET_MODE (fixeddest),
@@ -2458,47 +2537,59 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
- fixup_var_refs_1 (var, promoted_mode, &XEXP (x, i), insn, replacements);
+ fixup_var_refs_1 (var, promoted_mode, &XEXP (x, i), insn, replacements,
+ no_share);
else if (fmt[i] == 'E')
{
int j;
for (j = 0; j < XVECLEN (x, i); j++)
fixup_var_refs_1 (var, promoted_mode, &XVECEXP (x, i, j),
- insn, replacements);
+ insn, replacements, no_share);
}
}
}
-/* Given X, an rtx of the form (SUBREG:m1 (MEM:m2 addr)),
- return an rtx (MEM:m1 newaddr) which is equivalent.
- If any insns must be emitted to compute NEWADDR, put them before INSN.
+/* Previously, X had the form (SUBREG:m1 (REG:PROMOTED_MODE ...)).
+ The REG was placed on the stack, so X now has the form (SUBREG:m1
+ (MEM:m2 ...)).
+
+ Return an rtx (MEM:m1 newaddr) which is equivalent. If any insns
+ must be emitted to compute NEWADDR, put them before INSN.
UNCRITICAL nonzero means accept paradoxical subregs.
This is used for subregs found inside REG_NOTES. */
static rtx
-fixup_memory_subreg (x, insn, uncritical)
+fixup_memory_subreg (x, insn, promoted_mode, uncritical)
rtx x;
rtx insn;
+ enum machine_mode promoted_mode;
int uncritical;
{
- int offset = SUBREG_BYTE (x);
- rtx addr = XEXP (SUBREG_REG (x), 0);
+ int offset;
+ rtx mem = SUBREG_REG (x);
+ rtx addr = XEXP (mem, 0);
enum machine_mode mode = GET_MODE (x);
rtx result;
/* Paradoxical SUBREGs are usually invalid during RTL generation. */
- if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))
- && ! uncritical)
+ if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (mem)) && ! uncritical)
abort ();
+ offset = SUBREG_BYTE (x);
+ if (BYTES_BIG_ENDIAN)
+ /* If the PROMOTED_MODE is wider than the mode of the MEM, adjust
+ the offset so that it points to the right location within the
+ MEM. */
+ offset -= (GET_MODE_SIZE (promoted_mode) - GET_MODE_SIZE (GET_MODE (mem)));
+
if (!flag_force_addr
&& memory_address_p (mode, plus_constant (addr, offset)))
/* Shortcut if no insns need be emitted. */
- return adjust_address (SUBREG_REG (x), mode, offset);
+ return adjust_address (mem, mode, offset);
start_sequence ();
- result = adjust_address (SUBREG_REG (x), mode, offset);
+ result = adjust_address (mem, mode, offset);
emit_insn_before (gen_sequence (), insn);
end_sequence ();
return result;
@@ -2509,14 +2600,14 @@ fixup_memory_subreg (x, insn, uncritical)
If X itself is a (SUBREG (MEM ...) ...), return the replacement expression.
Otherwise return X, with its contents possibly altered.
- If any insns must be emitted to compute NEWADDR, put them before INSN.
-
- UNCRITICAL is as in fixup_memory_subreg. */
+ INSN, PROMOTED_MODE and UNCRITICAL are as for
+ fixup_memory_subreg. */
static rtx
-walk_fixup_memory_subreg (x, insn, uncritical)
+walk_fixup_memory_subreg (x, insn, promoted_mode, uncritical)
rtx x;
rtx insn;
+ enum machine_mode promoted_mode;
int uncritical;
{
enum rtx_code code;
@@ -2529,7 +2620,7 @@ walk_fixup_memory_subreg (x, insn, uncritical)
code = GET_CODE (x);
if (code == SUBREG && GET_CODE (SUBREG_REG (x)) == MEM)
- return fixup_memory_subreg (x, insn, uncritical);
+ return fixup_memory_subreg (x, insn, promoted_mode, uncritical);
/* Nothing special about this RTX; fix its operands. */
@@ -2537,13 +2628,15 @@ walk_fixup_memory_subreg (x, insn, uncritical)
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
- XEXP (x, i) = walk_fixup_memory_subreg (XEXP (x, i), insn, uncritical);
+ XEXP (x, i) = walk_fixup_memory_subreg (XEXP (x, i), insn,
+ promoted_mode, uncritical);
else if (fmt[i] == 'E')
{
int j;
for (j = 0; j < XVECLEN (x, i); j++)
XVECEXP (x, i, j)
- = walk_fixup_memory_subreg (XVECEXP (x, i, j), insn, uncritical);
+ = walk_fixup_memory_subreg (XVECEXP (x, i, j), insn,
+ promoted_mode, uncritical);
}
}
return x;
@@ -2872,10 +2965,10 @@ gen_mem_addressof (reg, decl)
SET_DECL_RTL (decl, reg);
if (TREE_USED (decl) || (DECL_P (decl) && DECL_INITIAL (decl) != 0))
- fixup_var_refs (reg, GET_MODE (reg), TREE_UNSIGNED (type), 0);
+ fixup_var_refs (reg, GET_MODE (reg), TREE_UNSIGNED (type), reg, 0);
}
else
- fixup_var_refs (reg, GET_MODE (reg), 0, 0);
+ fixup_var_refs (reg, GET_MODE (reg), 0, reg, 0);
return reg;
}
@@ -3726,6 +3819,7 @@ instantiate_virtual_regs_1 (loc, object, extra_insns)
{
case CONST_INT:
case CONST_DOUBLE:
+ case CONST_VECTOR:
case CONST:
case SYMBOL_REF:
case CODE_LABEL:
@@ -4753,13 +4847,15 @@ assign_parms (fndecl)
/* If we were passed a pointer but the actual value
can safely live in a register, put it in one. */
if (passed_pointer && TYPE_MODE (TREE_TYPE (parm)) != BLKmode
- && ! ((! optimize
- && ! DECL_REGISTER (parm))
- || TREE_SIDE_EFFECTS (parm)
- /* If -ffloat-store specified, don't put explicit
- float variables into registers. */
- || (flag_float_store
- && TREE_CODE (TREE_TYPE (parm)) == REAL_TYPE)))
+ /* If by-reference argument was promoted, demote it. */
+ && (TYPE_MODE (TREE_TYPE (parm)) != GET_MODE (DECL_RTL (parm))
+ || ! ((! optimize
+ && ! DECL_REGISTER (parm))
+ || TREE_SIDE_EFFECTS (parm)
+ /* If -ffloat-store specified, don't put explicit
+ float variables into registers. */
+ || (flag_float_store
+ && TREE_CODE (TREE_TYPE (parm)) == REAL_TYPE))))
{
/* We can't use nominal_mode, because it will have been set to
Pmode above. We must use the actual mode of the parm. */
@@ -5079,6 +5175,35 @@ assign_parms (fndecl)
current_function_return_rtx
= (DECL_RTL_SET_P (DECL_RESULT (fndecl))
? DECL_RTL (DECL_RESULT (fndecl)) : NULL_RTX);
+
+ /* If scalar return value was computed in a pseudo-reg, or was a named
+ return value that got dumped to the stack, copy that to the hard
+ return register. */
+ if (DECL_RTL_SET_P (DECL_RESULT (fndecl)))
+ {
+ tree decl_result = DECL_RESULT (fndecl);
+ rtx decl_rtl = DECL_RTL (decl_result);
+
+ if (REG_P (decl_rtl)
+ ? REGNO (decl_rtl) >= FIRST_PSEUDO_REGISTER
+ : DECL_REGISTER (decl_result))
+ {
+ rtx real_decl_rtl;
+
+#ifdef FUNCTION_OUTGOING_VALUE
+ real_decl_rtl = FUNCTION_OUTGOING_VALUE (TREE_TYPE (decl_result),
+ fndecl);
+#else
+ real_decl_rtl = FUNCTION_VALUE (TREE_TYPE (decl_result),
+ fndecl);
+#endif
+ REG_FUNCTION_VALUE_P (real_decl_rtl) = 1;
+ /* The delay slot scheduler assumes that current_function_return_rtx
+ holds the hard register containing the return value, not a
+ temporary pseudo. */
+ current_function_return_rtx = real_decl_rtl;
+ }
+ }
}
/* Indicate whether REGNO is an incoming argument to the current function
@@ -6583,10 +6708,13 @@ expand_function_start (subr, parms_have_cleanups)
Pmode);
}
-#ifdef PROFILE_HOOK
if (current_function_profile)
- PROFILE_HOOK (profile_label_no);
+ {
+ current_function_profile_label_no = profile_label_no++;
+#ifdef PROFILE_HOOK
+ PROFILE_HOOK (current_function_profile_label_no);
#endif
+ }
/* After the display initializations is where the tail-recursion label
should go, if we end up needing one. Ensure we have a NOTE here
@@ -6899,23 +7027,18 @@ expand_function_end (filename, line, end_bindings)
? REGNO (decl_rtl) >= FIRST_PSEUDO_REGISTER
: DECL_REGISTER (decl_result))
{
- rtx real_decl_rtl;
+ rtx real_decl_rtl = current_function_return_rtx;
-#ifdef FUNCTION_OUTGOING_VALUE
- real_decl_rtl = FUNCTION_OUTGOING_VALUE (TREE_TYPE (decl_result),
- current_function_decl);
-#else
- real_decl_rtl = FUNCTION_VALUE (TREE_TYPE (decl_result),
- current_function_decl);
-#endif
- REG_FUNCTION_VALUE_P (real_decl_rtl) = 1;
+ /* This should be set in assign_parms. */
+ if (! REG_FUNCTION_VALUE_P (real_decl_rtl))
+ abort ();
/* If this is a BLKmode structure being returned in registers,
then use the mode computed in expand_return. Note that if
decl_rtl is memory, then its mode may have been changed,
but that current_function_return_rtx has not. */
if (GET_MODE (real_decl_rtl) == BLKmode)
- PUT_MODE (real_decl_rtl, GET_MODE (current_function_return_rtx));
+ PUT_MODE (real_decl_rtl, GET_MODE (decl_rtl));
/* If a named return value dumped decl_return to memory, then
we may need to re-do the PROMOTE_MODE signed/unsigned
@@ -6936,11 +7059,6 @@ expand_function_end (filename, line, end_bindings)
int_size_in_bytes (TREE_TYPE (decl_result)));
else
emit_move_insn (real_decl_rtl, decl_rtl);
-
- /* The delay slot scheduler assumes that current_function_return_rtx
- holds the hard register containing the return value, not a
- temporary pseudo. */
- current_function_return_rtx = real_decl_rtl;
}
}
@@ -7763,86 +7881,90 @@ reposition_prologue_and_epilogue_notes (f)
rtx f ATTRIBUTE_UNUSED;
{
#if defined (HAVE_prologue) || defined (HAVE_epilogue)
+ rtx insn, last, note;
int len;
if ((len = VARRAY_SIZE (prologue)) > 0)
{
- rtx insn, note = 0;
+ last = 0, note = 0;
/* Scan from the beginning until we reach the last prologue insn.
We apparently can't depend on basic_block_{head,end} after
reorg has run. */
- for (insn = f; len && insn; insn = NEXT_INSN (insn))
+ for (insn = f; insn; insn = NEXT_INSN (insn))
{
if (GET_CODE (insn) == NOTE)
{
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_PROLOGUE_END)
note = insn;
}
- else if ((len -= contains (insn, prologue)) == 0)
+ else if (contains (insn, prologue))
{
- rtx next;
- /* Find the prologue-end note if we haven't already, and
- move it to just after the last prologue insn. */
- if (note == 0)
- {
- for (note = insn; (note = NEXT_INSN (note));)
- if (GET_CODE (note) == NOTE
- && NOTE_LINE_NUMBER (note) == NOTE_INSN_PROLOGUE_END)
- break;
- }
+ last = insn;
+ if (--len == 0)
+ break;
+ }
+ }
+
+ if (last)
+ {
+ rtx next;
- next = NEXT_INSN (note);
+ /* Find the prologue-end note if we haven't already, and
+ move it to just after the last prologue insn. */
+ if (note == 0)
+ {
+ for (note = last; (note = NEXT_INSN (note));)
+ if (GET_CODE (note) == NOTE
+ && NOTE_LINE_NUMBER (note) == NOTE_INSN_PROLOGUE_END)
+ break;
+ }
- /* Whether or not we can depend on BLOCK_HEAD,
- attempt to keep it up-to-date. */
- if (BLOCK_HEAD (0) == note)
- BLOCK_HEAD (0) = next;
+ next = NEXT_INSN (note);
- remove_insn (note);
- /* Avoid placing note between CODE_LABEL and BASIC_BLOCK note. */
- if (GET_CODE (insn) == CODE_LABEL)
- insn = NEXT_INSN (insn);
- add_insn_after (note, insn);
- }
+ /* Avoid placing note between CODE_LABEL and BASIC_BLOCK note. */
+ if (GET_CODE (last) == CODE_LABEL)
+ last = NEXT_INSN (last);
+ reorder_insns (note, note, last);
}
}
if ((len = VARRAY_SIZE (epilogue)) > 0)
{
- rtx insn, note = 0;
+ last = 0, note = 0;
/* Scan from the end until we reach the first epilogue insn.
We apparently can't depend on basic_block_{head,end} after
reorg has run. */
- for (insn = get_last_insn (); len && insn; insn = PREV_INSN (insn))
+ for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
{
if (GET_CODE (insn) == NOTE)
{
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EPILOGUE_BEG)
note = insn;
}
- else if ((len -= contains (insn, epilogue)) == 0)
+ else if (contains (insn, epilogue))
{
- /* Find the epilogue-begin note if we haven't already, and
- move it to just before the first epilogue insn. */
- if (note == 0)
- {
- for (note = insn; (note = PREV_INSN (note));)
- if (GET_CODE (note) == NOTE
- && NOTE_LINE_NUMBER (note) == NOTE_INSN_EPILOGUE_BEG)
- break;
- }
-
- /* Whether or not we can depend on BLOCK_HEAD,
- attempt to keep it up-to-date. */
- if (n_basic_blocks
- && BLOCK_HEAD (n_basic_blocks-1) == insn)
- BLOCK_HEAD (n_basic_blocks-1) = note;
+ last = insn;
+ if (--len == 0)
+ break;
+ }
+ }
- remove_insn (note);
- add_insn_before (note, insn);
+ if (last)
+ {
+ /* Find the epilogue-begin note if we haven't already, and
+ move it to just before the first epilogue insn. */
+ if (note == 0)
+ {
+ for (note = insn; (note = PREV_INSN (note));)
+ if (GET_CODE (note) == NOTE
+ && NOTE_LINE_NUMBER (note) == NOTE_INSN_EPILOGUE_BEG)
+ break;
}
+
+ if (PREV_INSN (last) != note)
+ reorder_insns (note, note, PREV_INSN (last));
}
}
#endif /* HAVE_prologue or HAVE_epilogue */
OpenPOWER on IntegriCloud