On 07/31/2018 11:25 AM, Jan Hubicka wrote: >> Hi. >> >> Following patch implements new predictors that annotates malloc-like >> functions. >> These almost every time return a non-null value. >> >> Patch can bootstrap on ppc64le-redhat-linux and survives regression tests. >> >> Ready to be installed? >> Martin >> >> gcc/ChangeLog: >> >> 2018-07-26 Martin Liska <mli...@suse.cz> >> >> PR middle-end/83023 >> * predict.c (expr_expected_value_1): Handle DECL_IS_MALLOC >> declarations. >> * predict.def (PRED_MALLOC_NONNULL): New predictor. >> >> gcc/testsuite/ChangeLog: >> >> 2018-07-26 Martin Liska <mli...@suse.cz> >> >> PR middle-end/83023 >> * gcc.dg/predict-16.c: New test. > > These are two conceptually different things - wether you return new memory > and whether the return value is commonly non-null. While it goes together > for majority of malloc function I wonder if this is safe WRT the auto-detected > malloc attributes. I do not know how common is code that returns new memory > only under some conditions?
You are right that malloc attribute does not guarantee that non-null is returned in most cases. But I would say in most cases it's the case. I'm sending updated version of the patch where I added BUILT_IN_REALLOC, which doesn't have malloc attribute, but return non-null in most cases. May I install that? Martin > > Honza >
>From 8ead58710e5676032183627bffc139382b34c609 Mon Sep 17 00:00:00 2001 From: marxin <mli...@suse.cz> Date: Thu, 26 Jul 2018 15:25:00 +0200 Subject: [PATCH] Add malloc predictor (PR middle-end/83023). gcc/ChangeLog: 2018-07-26 Martin Liska <mli...@suse.cz> PR middle-end/83023 * predict.c (expr_expected_value_1): Handle DECL_IS_MALLOC declarations. * predict.def (PRED_MALLOC_NONNULL): New predictor. gcc/testsuite/ChangeLog: 2018-07-26 Martin Liska <mli...@suse.cz> PR middle-end/83023 * gcc.dg/predict-16.c: New test. --- gcc/predict.c | 12 +++++++++++ gcc/predict.def | 5 ++++- gcc/testsuite/gcc.dg/predict-16.c | 36 +++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/predict-16.c diff --git a/gcc/predict.c b/gcc/predict.c index a6769eda1c7..69909d2dee1 100644 --- a/gcc/predict.c +++ b/gcc/predict.c @@ -2380,6 +2380,14 @@ expr_expected_value_1 (tree type, tree op0, enum tree_code code, } return NULL; } + + if (DECL_IS_MALLOC (decl)) + { + if (predictor) + *predictor = PRED_MALLOC_NONNULL; + return boolean_true_node; + } + if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL) switch (DECL_FUNCTION_CODE (decl)) { @@ -2414,6 +2422,10 @@ expr_expected_value_1 (tree type, tree op0, enum tree_code code, if (predictor) *predictor = PRED_COMPARE_AND_SWAP; return boolean_true_node; + case BUILT_IN_REALLOC: + if (predictor) + *predictor = PRED_MALLOC_NONNULL; + return boolean_true_node; default: break; } diff --git a/gcc/predict.def b/gcc/predict.def index 4ed97ed165c..76e6590cc96 100644 --- a/gcc/predict.def +++ b/gcc/predict.def @@ -51,6 +51,10 @@ DEF_PREDICTOR (PRED_NO_PREDICTION, "no prediction", PROB_ALWAYS, 0) DEF_PREDICTOR (PRED_UNCONDITIONAL, "unconditional jump", PROB_ALWAYS, PRED_FLAG_FIRST_MATCH) +/* Return value of malloc function is almost always non-null. */ +DEF_PREDICTOR (PRED_MALLOC_NONNULL, "malloc returned non-NULL", \ + PROB_VERY_LIKELY, PRED_FLAG_FIRST_MATCH) + /* Use number of loop iterations determined by # of iterations analysis to set probability. We don't want to use Dempster-Shaffer theory here, as the predictions is exact. */ @@ -169,7 +173,6 @@ DEF_PREDICTOR (PRED_HOT_LABEL, "hot label", HITRATE (85), 0) DEF_PREDICTOR (PRED_COLD_LABEL, "cold label", PROB_VERY_LIKELY, PRED_FLAG_FIRST_MATCH) - /* The following predictors are used in Fortran. */ /* Branch leading to an integer overflow are extremely unlikely. */ diff --git a/gcc/testsuite/gcc.dg/predict-16.c b/gcc/testsuite/gcc.dg/predict-16.c new file mode 100644 index 00000000000..b71ad6c706d --- /dev/null +++ b/gcc/testsuite/gcc.dg/predict-16.c @@ -0,0 +1,36 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-profile_estimate" } */ + +#include <stdlib.h> +#include <string.h> + +void *r; +void *r2; +void *r3; +void *r4; +void *r5; + +void *m (size_t s, int c) +{ + r = malloc (s); + if (r) + memset (r, 0, s); + + r2 = calloc (s, 0); + if (r2) + memset (r2, 0, s); + + r3 = __builtin_malloc (s); + if (r3) + memset (r3, 0, s); + + r4 = __builtin_calloc (s, 0); + if (r4) + memset (r4, 0, s); + + r5 = __builtin_realloc (r4, s); + if (r5) + memset (r4, 0, s); +} + +/* { dg-final { scan-tree-dump-times "malloc returned non-NULL heuristics of edge\[^:\]*: 99.96%" 4 "profile_estimate"} } */ -- 2.18.0