> > 2018-07-26 Martin Liska <mli...@suse.cz> > > PR middle-end/83023 > * predict.c (expr_expected_value_1): Handle DECL_IS_MALLOC, > BUILT_IN_REALLOC and DECL_IS_OPERATOR_NEW. > * predict.def (PRED_MALLOC_NONNULL): New predictor.
Patch is OK. I am still somewhat worried that we will run into functions that do return NULL in most times and otherwise they return newly mallocated block. For this reason please simply document the behaviour in extend.texi. For auto-detected malloc attribute I guess we may invent extra flag about probability of NULL return value later if we run into interesting testcases. I think it is a mistake that we don't detect malloc attribute early. It has good chance of making the simplifications in early opts to cascade. I will look into this. Honza > > gcc/testsuite/ChangeLog: > > 2018-07-26 Martin Liska <mli...@suse.cz> > > PR middle-end/83023 > * gcc.dg/predict-16.c: New test. > * g++.dg/predict-1.C: New test. > --- > gcc/predict.c | 12 +++++++++++ > gcc/predict.def | 5 ++++- > gcc/testsuite/g++.dg/predict-1.C | 15 +++++++++++++ > gcc/testsuite/gcc.dg/predict-16.c | 36 +++++++++++++++++++++++++++++++ > 4 files changed, 67 insertions(+), 1 deletion(-) > create mode 100644 gcc/testsuite/g++.dg/predict-1.C > create mode 100644 gcc/testsuite/gcc.dg/predict-16.c > > diff --git a/gcc/predict.c b/gcc/predict.c > index 2ee8274fe61..ef6794edda5 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) || DECL_IS_OPERATOR_NEW (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)) > { > @@ -2420,6 +2428,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 03900bf89b3..bf659704bfc 100644 > --- a/gcc/predict.def > +++ b/gcc/predict.def > @@ -55,6 +55,10 @@ DEF_PREDICTOR (PRED_UNCONDITIONAL, "unconditional jump", > PROB_ALWAYS, > DEF_PREDICTOR (PRED_BUILTIN_UNPREDICTABLE, "__builtin_unpredictable", > PROB_EVEN, > 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. */ > @@ -173,7 +177,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/g++.dg/predict-1.C > b/gcc/testsuite/g++.dg/predict-1.C > new file mode 100644 > index 00000000000..8e2032f33a4 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/predict-1.C > @@ -0,0 +1,15 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fdump-tree-profile_estimate" } */ > + > +#include <new> > + > +int *r; > + > +void test() > +{ > + r = new(std::nothrow) int; > + if (r) > + __builtin_memset (r, 0, sizeof(int)); > +} > + > +/* { dg-final { scan-tree-dump "malloc returned non-NULL heuristics of > edge\[^:\]*: 99.96%" "profile_estimate"} } */ > diff --git a/gcc/testsuite/gcc.dg/predict-16.c > b/gcc/testsuite/gcc.dg/predict-16.c > new file mode 100644 > index 00000000000..e1f331b909a > --- /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%" 5 "profile_estimate"} } */ > -- > 2.18.0 >