aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-02-07 23:00:04 +0100
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-02-09 23:56:01 +0100
commitffb24e18c9b83e5878ee9ca4513deb5de235e15c (patch)
treec657944ad6a0b204bac6592f3127315d6470419f
parentb369f9225bfcf59361c986c8b7fbbacb420cb936 (diff)
downloadsparse-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.c16
-rw-r--r--expand.c19
-rw-r--r--inline.c5
-rw-r--r--validation/expand/builtin_constant_inline0.c1
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: