This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Add malloc predictor (PR middle-end/83023).


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 <mliska@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  <mliska@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  <mliska@suse.cz>

        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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]