On 07/26/2018 05:00 PM, Marc Glisse wrote:
> On Thu, 26 Jul 2018, Martin Liška wrote:
>
>> Following patch implements new predictors that annotates malloc-like
>> functions.
>> These almost every time return a non-null value.
>
> Out of curiosity (the __builtin_expect there doesn't hurt and we don't need
> to remove it), does it make __builtin_expect unnecessary in the
> implementation of operator new (libstdc++-v3/libsupc++/new_op.cc)? It looks
> like
>
> while (__builtin_expect ((p = malloc (sz)) == 0, false))
> {
> new_handler handler = std::get_new_handler ();
> if (! handler)
> _GLIBCXX_THROW_OR_ABORT(bad_alloc());
> handler ();
> }
>
> where being in a loop may trigger opposite heuristics.
>
Thanks Marc for the pointer, it actually showed one problem with newly added
predictor.
So first, current trunk does:
Predictions for bb 5
first match heuristics: 10.00%
combined heuristics: 10.00%
__builtin_expect heuristics of edge 5->6: 10.00%
call heuristics of edge 5->6 (ignored): 33.00%
loop exit heuristics of edge 5->9 (ignored): 5.50%
removal of the __builtin_expect wrongly selected a different first march
predictor:
Predictions for bb 5
first match heuristics: 94.50%
combined heuristics: 94.50%
pointer (on trees) heuristics of edge 5->6 (ignored): 30.00%
malloc returned non-NULL heuristics of edge 5->6 (ignored): 0.04%
call heuristics of edge 5->6 (ignored): 33.00%
loop exit heuristics of edge 5->9: 5.50%
I fixed that by moving PRED_MALLOC_NONNULL up in the list, now it's fine:
1 edges in bb 4 predicted to even probabilities
Predictions for bb 5
first match heuristics: 0.04%
combined heuristics: 0.04%
pointer (on trees) heuristics of edge 5->6 (ignored): 30.00%
malloc returned non-NULL heuristics of edge 5->6: 0.04%
call heuristics of edge 5->6 (ignored): 33.00%
loop exit heuristics of edge 5->9 (ignored): 5.50%
So answer is yes, the builtin can be then removed.
Martin
>From ba2aa6cb7367f529ad96ece92e25cd0366a28735 Mon Sep 17 00:00:00 2001
From: marxin <[email protected]>
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 <[email protected]>
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 <[email protected]>
PR middle-end/83023
* gcc.dg/predict-16.c: New test.
---
gcc/predict.c | 8 ++++++++
gcc/predict.def | 5 ++++-
gcc/testsuite/gcc.dg/predict-16.c | 31 +++++++++++++++++++++++++++++++
3 files changed, 43 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..a7b2223c697 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))
{
diff --git a/gcc/predict.def b/gcc/predict.def
index 4ed97ed165c..426c17f26fd 100644
--- a/gcc/predict.def
+++ b/gcc/predict.def
@@ -88,6 +88,10 @@ DEF_PREDICTOR (PRED_NORETURN, "noreturn call", PROB_VERY_LIKELY,
DEF_PREDICTOR (PRED_COLD_FUNCTION, "cold function call", PROB_VERY_LIKELY,
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)
+
/* Edge causing loop to terminate is probably not taken. */
DEF_PREDICTOR (PRED_LOOP_EXIT, "loop exit", HITRATE (89),
PRED_FLAG_FIRST_MATCH)
@@ -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..3a3e943bb79
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/predict-16.c
@@ -0,0 +1,31 @@
+/* { 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 *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);
+}
+
+/* { dg-final { scan-tree-dump-times "malloc returned non-NULL heuristics of edge\[^:\]*: 99.96%" 4 "profile_estimate"} } */
--
2.18.0