[prev in list] [next in list] [prev in thread] [next in thread]
List: gcc-patches
Subject: Re: Tree inlining for the C front end (part 3 of 3)
From: Alexandre Oliva <aoliva () redhat ! com>
Date: 2001-09-29 22:29:33
[Download RAW message or body]
On Sep 25, 2001, Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at> wrote:
> On 24 Sep 2001, Alexandre Oliva wrote:
>> And finally, this patch enables tree inlining in the C front end.
>> [...]
>> Here's patch #3/3. Bootstrapped and tested on athlon-pc-linux-gnu,
>> along with patches #1 and #2. Ok to install?
> I firmly believe this should *NOT* be installed before it has passed
> serious compile-time and run-time (=code quality) performance bench-
> marking.
> We really, really, really should avoid having a huge regression in
> these respects as we had for the C++ frontend in GCC 3.0 and 3.0.1.
> The absolutely minimal set of tests required IMNSHO are timings for a
> compiler bootstrap (with and without this inliner), SPEC results, and
> at least another application benchmark (build time and run-time).
Ok, so I went ahead and verified that my patches had indeed disabled
-finline-functions, which I fixed with the patch below. While I was
at it, I improved memory usage by only saving trees of inlinable
functions, which reduced the gap between bootstrap with and without my
patch. I have also fixed all regressions in the testsuite, going back
to the same passes and failures as without my patches.
Here are today's numbers for bootstrap times of the entire GCC tree
(i.e., all languages, libraries included), with `make -j8 bootstrap',
starting from a just-configured build tree.
Bootstrap with none of my patches and standard BOOT_CFLAGS:
real 41m29.371s
user 36m29.430s
sys 4m7.420s
Bootstrap with patches 1 and 2 only, standard BOOT_CFLAGS:
real 41m32.907s
user 36m30.400s
sys 4m11.080s
Bootstrap with all 4 patches and standard BOOT_CFLAGS:
real 42m2.477s
user 37m2.970s
sys 4m7.510s
Bootstrap with patches 1 and 2 only and BOOT_CFLAGS='-O3 -g'.
real 43m48.287s
user 38m50.090s
sys 4m7.500s
Bootstrap with all 4 patches and BOOT_CFLAGS='-O3 -g'
real 44m30.794s
user 39m25.950s
sys 4m13.910s
That's a 1.3% increase in bootstrap time (all libraries, all
languages) for standard BOOT_CFLAGS, and 1.6% for a -O3 bootstrap.
Much better, eh? :-)
Here are some SPEC95 cint results, averaged over 3 runs, first with
patches 1 and 2 only (i.e., no tree inlining in C, just infrastructure
changes), then with all of 4 patches:
Base Base Base Peak Peak Peak
Benchmarks Ref Time Run Time Ratio Ref Time Run Time Ratio
------------ -------- -------- -------- -------- -------- --------
099.go 4600 87.7 52.4 4600 88.2 52.1
124.m88ksim 1900 37.2 51.1 1900 41.2 46.1
126.gcc 1700 33.9 50.1 1700 34.0 50.0
129.compress 1800 72.7 24.8 1800 72.4 24.9
130.li 1900 38.5 49.3 1900 36.4 52.2
132.ijpeg 2400 55.5 43.2 2400 56.9 42.2
134.perl 1900 29.0 65.6 1900 28.9 65.8
147.vortex 2700 67.2 40.2 2700 65.4 41.3
SPECint_base95 (Geom. Mean) 45.6
SPECint95 (Geom. Mean) 45.3
------------ -------- -------- -------- -------- -------- --------
099.go 4600 87.8 52.4 4600 88.5 52.0
124.m88ksim 1900 37.2 51.1 1900 41.1 46.2
126.gcc 1700 33.9 50.1 1700 34.1 49.9
129.compress 1800 72.9 24.7 1800 73.3 24.5
130.li 1900 38.3 49.6 1900 36.4 52.2
132.ijpeg 2400 55.5 43.2 2400 56.9 42.2
134.perl 1900 28.9 65.9 1900 28.9 65.8
147.vortex 2700 67.4 40.0 2700 65.2 41.4
SPECint_base95 (Geom. Mean) 45.6
SPECint95 (Geom. Mean) 45.3
No significant differences in performance, as expected, and a
hopefully acceptable increase in build time.
Some notes:
- I have mixed feelings about disabling inlining of functions that
call __builtin_return_address() (see the #if 0 block in
inline_forbidden_p(). It seems to me that we shouldn't be messing
up with such functions. In particular, if some functions in
gcc.c-torture/execute/20010122-1.c are reordered, they end up
inlined and produce incorrect results. The patch below doesn't
address this issue, though; it just uses a mechanism other than
calling alloca() to prevent inlining of a function in those
functions that would be currently inlined while they shouldn't.
- Some changes in tree-inline.c were necessary to cope with
differences between C++ and C. For example, C functions without
prototypes may be called with excess or missing arguments; I've
arranged for trailing parameters to be declared uninitialized, and
for trailing arguments to be evaluated and discarded. Also, type
promotion of return types is different in C and in C++; the type of
the DECL_RESULT of a C function is the promoted type, but the inline
site expects the actual return type, so I introduced a conversion if
types don't match. Also, I found out varargs_function_p() is not
enough to detect C functions with variable number of arguments, so I
moved the function back to the C++ front-end, and moved its test
into the language-specific section of the inlinability test. While
I was at it, I introduced the test for
function_attribute_inlinable_p() in the C++ inlinability tests too.
I wonder if I should move some more tests from the C version too,
such as the test for calls to setjmp(), va_start, return_address,
non-local gotos, etc. I also plan on integrating the move of
varags_function_p() back into the C++ front-end into some previous
patch for purposes of installing them; perhaps some other changes
may also be put in together. Of course, I'll test whatever patch I
check in individually.
- save_for_inline() is still called, so that we can defer the output
of functions and still choose not to emit them when not necessary,
but I have arranged for it to not do much in case we know we won't
inline the function. In particular, I've arranged for it to not
mess up with TREE_READONLY of parameters, which broke
gcc.dg/980709-1.c because the declaration of addr was marked as
readonly, despite my efforts to get the code to recognize the
(mem(addressof(reg))) as (reg) when marking the parameter as
updated. The reg was, for some reason, beyond the max_parm_reg, and
I couldn't figure out how to fix max_parm_reg. I decided I was just
beating a dead horse, and there was no reason to try to keep the RTL
inliner working, so I just went ahead and disabled that piece of
code.
- The change in cse.c fixes the problem of cse moving the only use of
a LABEL, stored in a register, without moving the REG_LABEL along
with it, causing the compiler to enter an endless loop. It turned
out that the problem was that the label was already deleted, and we
don't want REG_LABEL for deleted labels, but check_for_label_ref
still demanded them; such a demand would never be fulfilled, though.
This new patch was bootstrapped and regression tested on
athlon-pc-linux-gnu, along with the 3 previously-posted patches. Are
they ok to install?
[Attachment #3 (text/x-patch)]
Index: gcc/ChangeLog
from Alexandre Oliva <aoliva@redhat.com>
* Makefile.in (c-lang.o): Depend on insn-config.h and integrate.h.
* c-decl.c (c_expand_body): Determine whether a function is
inlinable upfront, and don't keep DECL_SAVED_TREE otherwise.
* c-lang.c: Include insn-config.h and integrate.h.
(c_post_options): Don't inline trees when instrumenting functions.
(inline_forbidden_p): New function.
(c_cannot_inline_tree_fn): Likewise.
(c_init): Set lang_cannot_inline_tree_fn.
* c-typeck.c (decl_constant_value): Revert previous change.
* tree-inline.c (initialize_inlined_parameters): Handle calls
with fewer arguments than declared parameters, and fewer
parameters than passed arguments. Don't assume value is a
DECL.
(declare_return_variable): Convert return value back to the
original type, if it was promoted.
(tree_inlinable_function_p): New function.
(inlinable_function_p): Don't look at DECL_INLINE if we're
inlining all functions. Make it work with a NULL id.
Re-check DECL_UNINLINABLE after language-specific checks.
(varargs_function_p): Move back to cp/tree.c.
* tree-inline.h (tree_inlinable_function_p): Declare it.
(varargs_function_p): Removed declaration.
* integrate.h (function_attribute_inlinable_p): Declare it.
* integrate.c (function_attribute_inlinable_p): Export it.
(save_for_inline): Don't bother to prepare argvec when not
inlining.
* cse.c (check_for_label_ref): Don't check deleted labels.
Index: gcc/cp/ChangeLog
from Alexandre Oliva <aoliva@redhat.com>
* cp/tree.c (varargs_function_p): Move back from ../tree-inline.c.
(cp_cannot_inline_tree_fn): Test varargs_function_p and
function_attribute_inlinable_p.
Index: gcc/testsuite/ChangeLog
from Alexandre Oliva <aoliva@redhat.com>
* gcc.c-torture/execute/20010122-1.c: Don't assume alloca() is
enough to avoid inlining.
--- gcc/Makefile.in 2001/09/27 17:06:26
+++ gcc/Makefile.in 2001/09/29 17:57:27
@@ -1175 +1175 @@
- $(RTL_H) $(EXPR_H) tree-inline.h
+ $(RTL_H) $(EXPR_H) tree-inline.h insn-config.h integrate.h
--- gcc/c-decl.c 2001/09/27 17:06:28
+++ gcc/c-decl.c 2001/09/29 17:57:27
@@ -6691,0 +6692,2 @@
+ int uninlinable = 1;
+
@@ -6698 +6700,9 @@
- optimize_inline_calls (fndecl);
+ {
+ /* First, cache whether the current function is inlinable. Some
+ predicates depend on cfun and current_function_decl to
+ function completely. */
+ uninlinable = ! tree_inlinable_function_p (fndecl);
+
+ /* Then, inline any functions called in it. */
+ optimize_inline_calls (fndecl);
+ }
@@ -6739 +6749 @@
- if (! flag_inline_trees)
+ if (uninlinable)
@@ -6744 +6753,0 @@
-
--- gcc/c-lang.c 2001/09/27 17:06:29
+++ gcc/c-lang.c 2001/09/29 17:57:27
@@ -38,0 +39,2 @@
+#include "insn-config.h"
+#include "integrate.h"
@@ -45,0 +48 @@
+static int c_cannot_inline_tree_fn PARAMS ((tree *));
@@ -60,2 +63,3 @@
- /* Adjust various flags based on command-line settings. */
- if (!flag_no_inline)
+ /* Use tree inlining if possible. Function instrumentation is only
+ done in the RTL level, so we disable tree inlining. */
+ if (! flag_instrument_function_entry_exit)
@@ -63,7 +67,10 @@
- flag_inline_trees = 1;
- flag_no_inline = 1;
- }
- if (flag_inline_functions)
- {
- flag_inline_trees = 2;
- flag_inline_functions = 0;
+ if (!flag_no_inline)
+ {
+ flag_inline_trees = 1;
+ flag_no_inline = 1;
+ }
+ if (flag_inline_functions)
+ {
+ flag_inline_trees = 2;
+ flag_inline_functions = 0;
+ }
@@ -108,0 +116 @@
+ lang_cannot_inline_tree_fn = &c_cannot_inline_tree_fn;
@@ -335,0 +344,141 @@
+}
+
+static tree inline_forbidden_p PARAMS ((tree *, int *, void *));
+
+static tree
+inline_forbidden_p (nodep, walk_subtrees, fn)
+ tree *nodep;
+ int *walk_subtrees ATTRIBUTE_UNUSED;
+ void *fn;
+{
+ tree node = *nodep;
+ tree t;
+
+ switch (TREE_CODE (node))
+ {
+ case CALL_EXPR:
+ t = get_callee_fndecl (node);
+
+ if (! t)
+ break;
+
+ /* We cannot inline functions that call setjmp. */
+ if (setjmp_call_p (t))
+ return node;
+
+ switch (DECL_FUNCTION_CODE (t))
+ {
+ /* We cannot inline functions that take a variable number of
+ arguments. */
+ case BUILT_IN_VARARGS_START:
+ case BUILT_IN_STDARG_START:
+#if 0
+ /* Functions that need information about the address of the
+ caller can't (shouldn't?) be inlined. */
+ case BUILT_IN_RETURN_ADDRESS:
+#endif
+ return node;
+
+ default:
+ break;
+ }
+
+ break;
+
+ case DECL_STMT:
+ /* We cannot inline functions that contain other functions. */
+ if (TREE_CODE (TREE_OPERAND (node, 0)) == FUNCTION_DECL
+ && DECL_INITIAL (TREE_OPERAND (node, 0)))
+ return node;
+ break;
+
+ case GOTO_STMT:
+ case GOTO_EXPR:
+ t = TREE_OPERAND (node, 0);
+
+ /* We will not inline a function which uses computed goto. The
+ addresses of its local labels, which may be tucked into
+ global storage, are of course not constant across
+ instantiations, which causes unexpected behaviour. */
+ if (TREE_CODE (t) != LABEL_DECL)
+ return node;
+
+ /* We cannot inline a nested function that jumps to a nonlocal
+ label. */
+ if (TREE_CODE (t) == LABEL_DECL
+ && DECL_CONTEXT (t) && DECL_CONTEXT (t) != fn)
+ return node;
+
+ break;
+
+ default:
+ break;
+ }
+
+ return NULL_TREE;
+}
+
+static int
+c_cannot_inline_tree_fn (fnp)
+ tree *fnp;
+{
+ tree fn = *fnp;
+ tree t;
+
+ if (! function_attribute_inlinable_p (fn))
+ {
+ DECL_UNINLINABLE (fn) = 1;
+ return 1;
+ }
+
+ /* If a function has pending sizes, we must not defer its
+ compilation, and we can't inline it as a tree. */
+ if (fn == current_function_decl)
+ {
+ t = get_pending_sizes ();
+ put_pending_sizes (t);
+
+ if (t)
+ {
+ DECL_UNINLINABLE (fn) = 1;
+ return 1;
+ }
+ }
+
+ if (DECL_CONTEXT (fn))
+ {
+ /* If a nested function has pending sizes, we may have already
+ saved them. */
+ if (DECL_LANG_SPECIFIC (fn)->pending_sizes)
+ {
+ DECL_UNINLINABLE (fn) = 1;
+ return 1;
+ }
+ }
+ else
+ {
+ /* We rely on the fact that this function is called upfront,
+ just before we start expanding a function. If FN is active
+ (i.e., it's the current_function_decl or a parent thereof),
+ we have to walk FN's saved tree. Otherwise, we can safely
+ assume we have done it before and, if we didn't mark it as
+ uninlinable (in which case we wouldn't have been called), it
+ is inlinable. Unfortunately, this strategy doesn't work for
+ nested functions, because they're only expanded as part of
+ their enclosing functions, so the inlinability test comes in
+ late. */
+ t = current_function_decl;
+
+ while (t && t != fn)
+ t = DECL_CONTEXT (t);
+ if (! t)
+ return 0;
+ }
+
+ if (walk_tree (&DECL_SAVED_TREE (fn), inline_forbidden_p, fn, NULL))
+ {
+ DECL_UNINLINABLE (fn) = 1;
+ return 1;
+ }
+
+ return 0;
--- gcc/c-typeck.c 2001/09/27 17:06:30
+++ gcc/c-typeck.c 2001/09/26 21:02:16 1.139
@@ -807,7 +807,7 @@
in a place where a variable is invalid. */
current_function_decl != 0
&& ! TREE_THIS_VOLATILE (decl)
+ && TREE_READONLY (decl)
- && TREE_READONLY_DECL_P (decl)
&& DECL_INITIAL (decl) != 0
&& TREE_CODE (DECL_INITIAL (decl)) != ERROR_MARK
/* This is invalid if initial value is not constant.
--- gcc/tree-inline.c Thu Sep 27 10:06:31 2001
+++ gcc/tree-inline.c Sat Sep 29 10:57:29 2001
@@ -486 +486,2 @@
- for (p = parms, a = args; p; a = TREE_CHAIN (a), p = TREE_CHAIN (p))
+ for (p = parms, a = args; p;
+ a = a ? TREE_CHAIN (a) : a, p = TREE_CHAIN (p))
@@ -493 +494,2 @@
- value = TREE_VALUE (a);
+ value = a ? TREE_VALUE (a) : NULL_TREE;
+
@@ -499 +501 @@
- && !TREE_SIDE_EFFECTS (value))
+ && value && !TREE_SIDE_EFFECTS (value))
@@ -502 +504 @@
- value = fold (decl_constant_value (value));
+ value = fold (DECL_P (value) ? decl_constant_value (value) : value);
@@ -569,0 +572,17 @@
+ /* Evaluate trailing arguments. */
+ for (; a; a = TREE_CHAIN (a))
+ {
+ tree init_stmt;
+ tree value;
+
+ /* Find the initializer. */
+ value = a ? TREE_VALUE (a) : NULL_TREE;
+
+ if (! value || ! TREE_SIDE_EFFECTS (value))
+ continue;
+
+ init_stmt = build_stmt (EXPR_STMT, value);
+ TREE_CHAIN (init_stmt) = init_stmts;
+ init_stmts = init_stmt;
+ }
+
@@ -609,3 +628,9 @@
- /* Build the USE_STMT. */
- *use_stmt = build_stmt (EXPR_STMT, var);
-
+ /* Build the USE_STMT. If the return type of the function was
+ promoted, convert it back to the expected type. */
+ if (TREE_TYPE (var) == TREE_TYPE (TREE_TYPE (fn)))
+ *use_stmt = build_stmt (EXPR_STMT, var);
+ else
+ *use_stmt = build_stmt (EXPR_STMT,
+ build1 (NOP_EXPR, TREE_TYPE (TREE_TYPE (fn)),
+ var));
+
@@ -622 +647,12 @@
-/* Returns non-zero if FN is a function that can be inlined. */
+/* Returns non-zero if a function can be inlined as a tree. */
+
+int
+tree_inlinable_function_p (fn)
+ tree fn;
+{
+ return inlinable_function_p (fn, NULL);
+}
+
+/* Returns non-zero if FN is a function that can be inlined into the
+ inlining context ID_. If ID_ is NULL, check whether the function
+ can be inlined at all. */
@@ -640,5 +676 @@
- if (!flag_inline_trees)
- ;
- /* If the function was not declared `inline', then we don't inline
- it. */
- else if (!DECL_INLINE (fn))
+ if (! flag_inline_trees)
@@ -646,2 +678,3 @@
- /* We can't inline varargs functions. */
- else if (varargs_function_p (fn))
+ /* If we're not inlining all functions and the function was not
+ declared `inline', we don't inline it. */
+ else if (flag_inline_trees < 2 && ! DECL_INLINE (fn))
@@ -663 +696 @@
- DECL_UNINLINABLE (fn) = !inlinable;
+ DECL_UNINLINABLE (fn) = ! inlinable;
@@ -670 +703 @@
- && ((DECL_NUM_STMTS (fn) + id->inlined_stmts) * INSNS_PER_STMT
+ && ((DECL_NUM_STMTS (fn) + (id ? id->inlined_stmts : 0)) * INSNS_PER_STMT
@@ -680 +713 @@
- if (!DECL_SAVED_TREE (fn))
+ if (! DECL_SAVED_TREE (fn))
@@ -682,0 +716,4 @@
+ /* Check again, language hooks may have modified it. */
+ if (! inlinable || DECL_UNINLINABLE (fn))
+ return 0;
+
@@ -685 +722 @@
- if (inlinable)
+ if (id)
@@ -693 +730 @@
- if (inlinable && DECL_INLINED_FNS (fn))
+ if (DECL_INLINED_FNS (fn))
@@ -1308,13 +1344,0 @@
-}
-
-/* Does FUNCTION use a variable-length argument list? */
-
-int
-varargs_function_p (function)
- tree function;
-{
- tree parm = TYPE_ARG_TYPES (TREE_TYPE (function));
- for (; parm; parm = TREE_CHAIN (parm))
- if (TREE_VALUE (parm) == void_type_node)
- return 0;
- return 1;
--- gcc/tree-inline.h Thu Sep 27 10:06:31 2001
+++ gcc/tree-inline.h Sat Sep 29 10:57:29 2001
@@ -27,0 +28 @@
+int tree_inlinable_function_p PARAMS ((tree));
@@ -33 +33,0 @@
-int varargs_function_p PARAMS ((tree));
--- gcc/cp/tree.c 2001/09/27 17:06:39
+++ gcc/cp/tree.c 2001/09/29 17:57:31
@@ -1797,0 +1798,13 @@
+/* Does FUNCTION use a variable-length argument list? */
+
+int
+varargs_function_p (function)
+ tree function;
+{
+ tree parm = TYPE_ARG_TYPES (TREE_TYPE (function));
+ for (; parm; parm = TREE_CHAIN (parm))
+ if (TREE_VALUE (parm) == void_type_node)
+ return 0;
+ return 1;
+}
+
@@ -2122,0 +2136,2 @@
+ tree fn = *fnp;
+
@@ -2125,2 +2140,14 @@
- if (DECL_TEMPLATE_INFO (*fnp)
- && TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (*fnp)))
+ if (DECL_TEMPLATE_INFO (fn)
+ && TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (fn)))
+ {
+ *fnp = fn = instantiate_decl (fn, /*defer_ok=*/0);
+ return TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (fn));
+ }
+
+ if (varargs_function_p (fn))
+ {
+ DECL_UNINLINABLE (fn) = 1;
+ return 1;
+ }
+
+ if (! function_attribute_inlinable_p (fn))
@@ -2128,2 +2155,2 @@
- *fnp = instantiate_decl (*fnp, /*defer_ok=*/0);
- return TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (*fnp));
+ DECL_UNINLINABLE (fn) = 1;
+ return 1;
--- gcc/testsuite/gcc.c-torture/execute/20010122-1.c 2001/04/11 20:31:15 1.2
+++ gcc/testsuite/gcc.c-torture/execute/20010122-1.c 2001/09/29 17:57:31
@@ -78,15 +78,14 @@ void *test6a (char * p)
void *(*func1[6])(void) = { test1, test2, test3, test4, test5, test6 };
-char * call_func1 (int i)
+char * call_func1_ (int i)
{
- char * save = (char*) alloca (4);
-
save_ret1[i] = func1[i] ();
-
- return save;
}
+/* We dont' want call_func1_ to be inlined, so call it through a
+ pointer. */
+void (*call_func1)(int) = call_func1_;
static void *ret_addr;
void *save_ret2[6];
@@ -164,15 +163,15 @@ char * dummy (void)
void (*func2[6])(void) = { test7, test8, test9, test10, test11, test12 };
-char * call_func2 (int i)
+void call_func2_ (int i)
{
- char * save = (char*) alloca (4);
-
func2[i] ();
save_ret2[i] = ret_addr;
-
- return save;
}
+
+/* We dont' want call_func2_ to be inlined, so call it through a
+ pointer. */
+void (*call_func2)(int) = call_func2_;
int main (void)
{
--- gcc/integrate.h 2001/09/21 00:45:30 1.21
+++ gcc/integrate.h 2001/09/29 17:57:29
@@ -152,6 +152,11 @@ extern union tree_node *copy_decl_for_in
union tree_node *,
union tree_node *));
+/* Check whether there's any attribute in a function declaration that
+ makes the function uninlinable. Returns false if it finds any,
+ true otherwise. */
+extern bool function_attribute_inlinable_p PARAMS ((union tree_node *));
+
extern void try_constants PARAMS ((rtx, struct inline_remap *));
/* Return the label indicated. */
--- gcc/integrate.c 2001/09/21 15:16:31 1.165
+++ gcc/integrate.c 2001/09/29 17:57:29
@@ -77,8 +77,6 @@ typedef struct initial_value_struct {
initial_value_pair *entries;
} initial_value_struct;
-static bool function_attribute_inlinable_p PARAMS ((tree));
-
static void setup_initial_hard_reg_value_integration PARAMS ((struct function *, \
struct inline_remap *));
static rtvec initialize_for_inline PARAMS ((tree));
@@ -129,7 +127,7 @@ get_label_from_map (map, i)
/* Return false if the function FNDECL cannot be inlined on account of its
attributes, true otherwise. */
-static bool
+bool
function_attribute_inlinable_p (fndecl)
tree fndecl;
{
@@ -442,8 +440,8 @@ save_for_inline (fndecl)
Also set up ARG_VECTOR, which holds the unmodified DECL_RTX values
for the parms, prior to elimination of virtual registers.
These values are needed for substituting parms properly. */
-
- parmdecl_map = (tree *) xmalloc (max_parm_reg * sizeof (tree));
+ if (! flag_no_inline)
+ parmdecl_map = (tree *) xmalloc (max_parm_reg * sizeof (tree));
/* Make and emit a return-label if we have not already done so. */
@@ -453,7 +451,10 @@ save_for_inline (fndecl)
emit_label (return_label);
}
- argvec = initialize_for_inline (fndecl);
+ if (! flag_no_inline)
+ argvec = initialize_for_inline (fndecl);
+ else
+ argvec = NULL;
/* Delete basic block notes created by early run of find_basic_block.
The notes would be later used by find_basic_blocks to reuse the memory
@@ -470,27 +471,31 @@ save_for_inline (fndecl)
if (GET_CODE (insn) != NOTE)
abort ();
- /* Get the insn which signals the end of parameter setup code. */
- first_nonparm_insn = get_first_nonparm_insn ();
+ if (! flag_no_inline)
+ {
+ /* Get the insn which signals the end of parameter setup code. */
+ first_nonparm_insn = get_first_nonparm_insn ();
- /* Now just scan the chain of insns to see what happens to our
- PARM_DECLs. If a PARM_DECL is used but never modified, we
- can substitute its rtl directly when expanding inline (and
- perform constant folding when its incoming value is constant).
- Otherwise, we have to copy its value into a new register and track
- the new register's life. */
- in_nonparm_insns = 0;
- save_parm_insns (insn, first_nonparm_insn);
-
- cfun->inl_max_label_num = max_label_num ();
- cfun->inl_last_parm_insn = cfun->x_last_parm_insn;
- cfun->original_arg_vector = argvec;
+ /* Now just scan the chain of insns to see what happens to our
+ PARM_DECLs. If a PARM_DECL is used but never modified, we
+ can substitute its rtl directly when expanding inline (and
+ perform constant folding when its incoming value is
+ constant). Otherwise, we have to copy its value into a new
+ register and track the new register's life. */
+ in_nonparm_insns = 0;
+ save_parm_insns (insn, first_nonparm_insn);
+
+ cfun->inl_max_label_num = max_label_num ();
+ cfun->inl_last_parm_insn = cfun->x_last_parm_insn;
+ cfun->original_arg_vector = argvec;
+ }
cfun->original_decl_initial = DECL_INITIAL (fndecl);
cfun->no_debugging_symbols = (write_symbols == NO_DEBUG);
DECL_SAVED_INSNS (fndecl) = cfun;
/* Clean up. */
- free (parmdecl_map);
+ if (! flag_no_inline)
+ free (parmdecl_map);
}
/* Scan the chain of insns to see what happens to our PARM_DECLs. If a
--- gcc/cse.c 2001/09/28 13:01:40 1.205
+++ gcc/cse.c 2001/09/29 17:57:28
@@ -7376,6 +7376,7 @@ check_for_label_ref (rtl, data)
LABEL_REF for a CODE_LABEL that isn't in the insn chain, don't do this
since no REG_LABEL will be added. */
return (GET_CODE (*rtl) == LABEL_REF
+ && LABEL_P (XEXP (*rtl, 0))
&& INSN_UID (XEXP (*rtl, 0)) != 0
&& ! find_reg_note (insn, REG_LABEL, XEXP (*rtl, 0)));
}
--
Alexandre Oliva Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer aoliva@{cygnus.com, redhat.com}
CS PhD student at IC-Unicamp oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist *Please* write to mailing lists, not to me
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic