diff options
author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2020-02-07 23:00:04 +0100 |
---|---|---|
committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2020-02-09 23:56:01 +0100 |
commit | ffb24e18c9b83e5878ee9ca4513deb5de235e15c (patch) | |
tree | c657944ad6a0b204bac6592f3127315d6470419f | |
parent | b369f9225bfcf59361c986c8b7fbbacb420cb936 (diff) | |
download | sparse-ffb24e18c9b83e5878ee9ca4513deb5de235e15c.tar.gz |
do the tree inlining during expansion phase
Currently, the tree inlining is done very early, during the
evaluation phase. This means that the inlining is done even
if the corresponding call belong to a sub-expression that
will be discarded during the expansion phase.
Usually this is not a problem but in some pathological
cases it can lead to a huge waste of memory and CPU time.
So, move this inline expansion to ... the expansion phase.
Also, re-expand the resulting expression since constant
arguments may create new opportunities for simplification.
Note: the motivation for thsi is a pathological case in the
kernel where a combination of max_t() + const_ilog2() +
roundup_pow_of_two() + cpumask_weight() + __const_hweight*()
caused Sparse to use 2.3Gb of memory. With this patch
the memory consumption is down to 247Mb.
Link: https://marc.info/?l=linux-sparse&m=158098958501220
Link: https://lore.kernel.org/netdev/CAHk-=whvS9x5NKtOqcUgJeTY7dfdAHc
Reported-by: Randy Dunlap <rdunlap@infradead.org>
Originally-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r-- | evaluate.c | 16 | ||||
-rw-r--r-- | expand.c | 19 | ||||
-rw-r--r-- | inline.c | 5 | ||||
-rw-r--r-- | validation/expand/builtin_constant_inline0.c | 1 |
4 files changed, 19 insertions, 22 deletions
@@ -3107,22 +3107,6 @@ static int evaluate_symbol_call(struct expression *expr) if (ctype->op && ctype->op->evaluate) return ctype->op->evaluate(expr); - if (ctype->ctype.modifiers & MOD_INLINE) { - int ret; - struct symbol *curr = current_fn; - - if (ctype->definition) - ctype = ctype->definition; - - current_fn = ctype->ctype.base_type; - - ret = inline_function(expr, ctype); - - /* restore the old function */ - current_fn = curr; - return ret; - } - return 0; } @@ -910,6 +910,25 @@ static int expand_symbol_call(struct expression *expr, int cost) if (fn->type != EXPR_PREOP) return SIDE_EFFECTS; + if (ctype->ctype.modifiers & MOD_INLINE) { + struct symbol *def; + + def = ctype->definition ? ctype->definition : ctype; + if (inline_function(expr, def)) { + struct symbol *fn = def->ctype.base_type; + struct symbol *curr = current_fn; + + current_fn = fn; + evaluate_statement(expr->statement); + current_fn = curr; + + fn->expanding = 1; + cost = expand_expression(expr); + fn->expanding = 0; + return cost; + } + } + if (ctype->op && ctype->op->expand) return ctype->op->expand(expr, cost); @@ -519,8 +519,6 @@ int inline_function(struct expression *expr, struct symbol *sym) if (fn->expanding) return 0; - fn->expanding = 1; - name_list = fn->arguments; expr->type = EXPR_STATEMENT; @@ -558,9 +556,6 @@ int inline_function(struct expression *expr, struct symbol *sym) unset_replace_list(fn_symbol_list); - evaluate_statement(stmt); - - fn->expanding = 0; return 1; } diff --git a/validation/expand/builtin_constant_inline0.c b/validation/expand/builtin_constant_inline0.c index 9e775d5e..a0057f20 100644 --- a/validation/expand/builtin_constant_inline0.c +++ b/validation/expand/builtin_constant_inline0.c @@ -11,7 +11,6 @@ int foo(void) /* * check-name: builtin_constant_inline0 * check-command: test-linearize -Wno-decl $file - * check-known-to-fail * * check-output-start foo: |