On 08/07/2018 01:51 PM, Jan Hubicka wrote:
>>
>> 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.

Thanks.

> 
> 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 documented that and installed patch as r263355.

Martin

> 
> 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
>>
> 

Reply via email to