From ffb24e18c9b83e5878ee9ca4513deb5de235e15c Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Fri, 7 Feb 2020 23:00:04 +0100 Subject: 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 Originally-by: Linus Torvalds Signed-off-by: Luc Van Oostenryck --- evaluate.c | 16 ---------------- expand.c | 19 +++++++++++++++++++ inline.c | 5 ----- validation/expand/builtin_constant_inline0.c | 1 - 4 files changed, 19 insertions(+), 22 deletions(-) diff --git a/evaluate.c b/evaluate.c index f1a266be..b7bb1f52 100644 --- a/evaluate.c +++ b/evaluate.c @@ -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; } diff --git a/expand.c b/expand.c index 36612c86..e7559878 100644 --- a/expand.c +++ b/expand.c @@ -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); diff --git a/inline.c b/inline.c index 6f73a305..a9597280 100644 --- a/inline.c +++ b/inline.c @@ -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: -- cgit 1.2.3-korg