/* Procedure integration for GCC.
- Copyright (C) 1988, 1991, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GCC.
tree last = tree_last (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
/* For functions marked as inline increase the maximum size to
- MAX_INLINE_INSNS (-finline-limit-<n>). For regular functions
- use the limit given by INTEGRATE_THRESHOLD. */
+ MAX_INLINE_INSNS_RTL (--param max-inline-insn-rtl=<n>). For
+ regular functions use the limit given by INTEGRATE_THRESHOLD.
+ Note that the RTL inliner is not used by the languages that use
+ the tree inliner (C, C++). */
int max_insns = (DECL_INLINE (fndecl))
- ? (MAX_INLINE_INSNS
+ ? (MAX_INLINE_INSNS_RTL
+ 8 * list_length (DECL_ARGUMENTS (fndecl)))
: INTEGRATE_THRESHOLD (fndecl);
DECL_ABSTRACT_ORIGIN (copy) = DECL_ORIGIN (decl);
/* The new variable/label has no RTL, yet. */
- SET_DECL_RTL (copy, NULL_RTX);
+ if (!TREE_STATIC (copy) && !DECL_EXTERNAL (copy))
+ SET_DECL_RTL (copy, NULL_RTX);
/* These args would always appear unused, if not for this. */
TREE_USED (copy) = 1;
;
else if (DECL_CONTEXT (decl) != from_fn)
/* Things that weren't in the scope of the function we're inlining
- from aren't in the scope we're inlining too, either. */
+ from aren't in the scope we're inlining to, either. */
;
else if (TREE_STATIC (decl))
- /* Function-scoped static variables should say in the original
+ /* Function-scoped static variables should stay in the original
function. */
;
else
return (rtx) (size_t) -1;
}
+ /* If there is a TARGET which is a readonly BLKmode MEM and DECL_RESULT
+ is also a mem, we are going to lose the readonly on the stores, so don't
+ inline. */
+ if (target != 0 && GET_CODE (target) == MEM && GET_MODE (target) == BLKmode
+ && RTX_UNCHANGING_P (target) && DECL_RTL_SET_P (DECL_RESULT (fndecl))
+ && GET_CODE (DECL_RTL (DECL_RESULT (fndecl))) == MEM)
+ return (rtx) (size_t) -1;
+
/* Extra arguments are valid, but will be ignored below, so we must
evaluate them here for side-effects. */
for (; actual; actual = TREE_CHAIN (actual))
else
arg_vals[i] = 0;
+ /* If the formal type was const but the actual was not, we might
+ end up here with an rtx wrongly tagged unchanging in the caller's
+ context. Fix that. */
+ if (arg_vals[i] != 0
+ && (GET_CODE (arg_vals[i]) == REG || GET_CODE (arg_vals[i]) == MEM)
+ && ! TREE_READONLY (TREE_VALUE (actual)))
+ RTX_UNCHANGING_P (arg_vals[i]) = 0;
+
if (arg_vals[i] != 0
&& (! TREE_READONLY (formal)
/* If the parameter is not read-only, copy our argument through
if (inl_f->needs_context)
static_chain_value = lookup_static_chain (fndecl);
+ /* If the inlined function calls __builtin_constant_p, then we'll
+ need to call purge_builtin_constant_p on this function. */
+ if (inl_f->calls_constant_p)
+ current_function_calls_constant_p = 1;
+
if (GET_CODE (parm_insns) == NOTE
&& NOTE_LINE_NUMBER (parm_insns) > 0)
{
- rtx note = emit_note (NOTE_SOURCE_FILE (parm_insns),
- NOTE_LINE_NUMBER (parm_insns));
+ rtx note = emit_line_note (NOTE_SOURCE_FILE (parm_insns),
+ NOTE_LINE_NUMBER (parm_insns));
if (note)
RTX_INTEGRATED_P (note) = 1;
}
&& ! (GET_CODE (XEXP (loc, 0)) == REG
&& REGNO (XEXP (loc, 0)) > LAST_VIRTUAL_REGISTER))
{
- rtx note = emit_note (DECL_SOURCE_FILE (formal),
- DECL_SOURCE_LINE (formal));
+ rtx note = emit_line_note (DECL_SOURCE_FILE (formal),
+ DECL_SOURCE_LINE (formal));
if (note)
RTX_INTEGRATED_P (note) = 1;
This line number note is still needed for debugging though, so we can't
delete it. */
if (flag_test_coverage)
- emit_note (0, NOTE_INSN_REPEATED_LINE_NUMBER);
+ emit_note (NULL, NOTE_INSN_REPEATED_LINE_NUMBER);
- emit_line_note (input_filename, lineno);
+ emit_line_note (input_filename, input_line);
/* If the function returns a BLKmode object in a register, copy it
out of the temp register into a BLKmode memory object. */
#else
try_constants (copy, map);
#endif
- INSN_SCOPE (copy) = INSN_SCOPE (insn);
+ INSN_LOCATOR (copy) = INSN_LOCATOR (insn);
break;
case JUMP_INSN:
cc0_insn = 0;
#endif
try_constants (copy, map);
- INSN_SCOPE (copy) = INSN_SCOPE (insn);
+ INSN_LOCATOR (copy) = INSN_LOCATOR (insn);
/* If this used to be a conditional jump insn but whose branch
direction is now know, we must do something special. */
SIBLING_CALL_P (copy) = SIBLING_CALL_P (insn);
CONST_OR_PURE_CALL_P (copy) = CONST_OR_PURE_CALL_P (insn);
- INSN_SCOPE (copy) = INSN_SCOPE (insn);
+ INSN_LOCATOR (copy) = INSN_LOCATOR (insn);
/* Because the USAGE information potentially contains objects other
than hard registers, we need to copy it. */
NOTE_INSN_DELETED notes aren't useful. */
- if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END
+ if (NOTE_LINE_NUMBER (insn) > 0)
+ copy = emit_line_note (NOTE_SOURCE_FILE (insn),
+ NOTE_LINE_NUMBER (insn));
+ else if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_BEG
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED)
{
- copy = emit_note (NOTE_SOURCE_FILE (insn),
- NOTE_LINE_NUMBER (insn));
- if (copy
- && (NOTE_LINE_NUMBER (copy) == NOTE_INSN_BLOCK_BEG
- || NOTE_LINE_NUMBER (copy) == NOTE_INSN_BLOCK_END)
+ copy = emit_note (NULL, NOTE_LINE_NUMBER (insn));
+ NOTE_DATA (copy) = NOTE_DATA (insn);
+ if ((NOTE_LINE_NUMBER (copy) == NOTE_INSN_BLOCK_BEG
+ || NOTE_LINE_NUMBER (copy) == NOTE_INSN_BLOCK_END)
&& NOTE_BLOCK (insn))
{
tree *mapped_block_p;
else
NOTE_BLOCK (copy) = *mapped_block_p;
}
- else if (copy
- && NOTE_LINE_NUMBER (copy) == NOTE_INSN_EXPECTED_VALUE)
+ else if (NOTE_LINE_NUMBER (copy) == NOTE_INSN_EXPECTED_VALUE)
NOTE_EXPECTED_VALUE (copy)
= copy_rtx_and_substitute (NOTE_EXPECTED_VALUE (insn),
map, 0);
subst_constants (&r, NULL_RTX, map, 1);
SET_DECL_RTL (d, r);
- if (GET_CODE (r) == REG)
- REGNO_DECL (REGNO (r)) = d;
- else if (GET_CODE (r) == CONCAT)
- {
- REGNO_DECL (REGNO (XEXP (r, 0))) = d;
- REGNO_DECL (REGNO (XEXP (r, 1))) = d;
- }
-
apply_change_group ();
}
copy_rtx_and_substitute (constant, map, for_lhs)),
0);
}
+ else if (TREE_CONSTANT_POOL_ADDRESS_P (orig) && inlining)
+ notice_rtl_inlining_of_deferred_constant ();
return orig;
apply_change_group ();
subst_constants (&PATTERN (insn), insn, map, 0);
apply_change_group ();
+
+ /* Enforce consistency between the addresses in the regular insn flow
+ and the ones in CALL_INSN_FUNCTION_USAGE lists, if any. */
+ if (GET_CODE (insn) == CALL_INSN && CALL_INSN_FUNCTION_USAGE (insn))
+ {
+ subst_constants (&CALL_INSN_FUNCTION_USAGE (insn), insn, map, 1);
+ apply_change_group ();
+ }
/* Show we don't know the value of anything stored or clobbered. */
note_stores (PATTERN (insn), mark_stores, NULL);
{
src = SET_SRC (x);
if (GET_MODE_CLASS (GET_MODE (src)) == MODE_CC
-#ifdef HAVE_cc0
- || dest == cc0_rtx
-#endif
- )
+ || CC0_P (dest))
{
compare_mode = GET_MODE (XEXP (src, 0));
if (compare_mode == VOIDmode)
|| REGNO (XEXP (src, 0)) == VIRTUAL_STACK_VARS_REGNUM)
&& CONSTANT_P (XEXP (src, 1)))
|| GET_CODE (src) == COMPARE
-#ifdef HAVE_cc0
- || dest == cc0_rtx
-#endif
+ || CC0_P (dest)
|| (dest == pc_rtx
&& (src == pc_rtx || GET_CODE (src) == RETURN
|| GET_CODE (src) == LABEL_REF))))
if (compare_mode != VOIDmode
&& GET_CODE (src) == COMPARE
&& (GET_MODE_CLASS (GET_MODE (src)) == MODE_CC
-#ifdef HAVE_cc0
- || dest == cc0_rtx
-#endif
- )
+ || CC0_P (dest))
&& GET_MODE (XEXP (src, 0)) == VOIDmode
&& GET_MODE (XEXP (src, 1)) == VOIDmode)
{
debug_hooks = &do_nothing_debug_hooks;
}
+ /* Make sure warnings emitted by the optimizers (e.g. control reaches
+ end of non-void function) is not wildly incorrect. */
+ input_location = DECL_SOURCE_LOCATION (fndecl);
+
/* Compile this function all the way down to assembly code. As a
side effect this destroys the saved RTL representation, but
that's okay, because we don't need to inline this anymore. */