diff mbox series

Extend ipa-fnsummary to skip __builtin_expect

Message ID ZJ3uUW7I2HcSq8Ml@kam.mff.cuni.cz
State New
Headers show
Series Extend ipa-fnsummary to skip __builtin_expect | expand

Commit Message

Jan Hubicka June 29, 2023, 8:49 p.m. UTC
Compute ipa-predicates for conditionals involving __builtin_expect_p

std::vector allocator looks as follows:

__attribute__((nodiscard))
struct pair * std::__new_allocator<std::pair<unsigned int, unsigned int> >::allocate (struct __new_allocator * const this, size_type __n, const void * D.27753)
{
  bool _1;
  long int _2;
  long int _3;
  long unsigned int _5;
  struct pair * _9;

  <bb 2> [local count: 1073741824]:
  _1 = __n_7(D) > 1152921504606846975;
  _2 = (long int) _1;
  _3 = __builtin_expect (_2, 0);
  if (_3 != 0)
    goto <bb 3>; [10.00%]
  else
    goto <bb 6>; [90.00%]

  <bb 3> [local count: 107374184]:
  if (__n_7(D) > 2305843009213693951)
    goto <bb 4>; [50.00%]
  else
    goto <bb 5>; [50.00%]

  <bb 4> [local count: 53687092]:
  std::__throw_bad_array_new_length ();

  <bb 5> [local count: 53687092]:
  std::__throw_bad_alloc ();

  <bb 6> [local count: 966367641]:
  _5 = __n_7(D) * 8;
  _9 = operator new (_5);
  return _9;
}


So there is check for allocated block size being greater than max_size which is
wrapper in __builtin_expect.  This makes ipa-fnsummary to give up analyzing
predicates and it will miss the fact that the two different calls to __throw
will be optimized out if __n is larady smaller than 1152921504606846975 which
it is after _M_check_len.

This patch extends ipa-fnsummary to understand functions that return their
parameter.

We still do not get the value range propagated sicne _M_check_len is not
inlined early and ipa-prop misses return functions, but we get closer :)

Bootstrapped/regtested x86_64-linux, comitted.


gcc/ChangeLog:

	PR tree-optimization/109849
	* ipa-fnsummary.cc (decompose_param_expr): Skip
	functions returning its parameter.
	(set_cond_stmt_execution_predicate): Return early
	if predicate was constructed.

gcc/testsuite/ChangeLog:

	PR tree-optimization/109849
	* gcc.dg/ipa/pr109849.c: New test.
diff mbox series

Patch

diff --git a/gcc/ipa-fnsummary.cc b/gcc/ipa-fnsummary.cc
index 78cbb60d056..a09f6305c63 100644
--- a/gcc/ipa-fnsummary.cc
+++ b/gcc/ipa-fnsummary.cc
@@ -1516,6 +1516,19 @@  decompose_param_expr (struct ipa_func_body_info *fbi,
 
       if (TREE_CODE (expr) != SSA_NAME || SSA_NAME_IS_DEFAULT_DEF (expr))
 	break;
+      stmt = SSA_NAME_DEF_STMT (expr);
+
+      if (gcall *call = dyn_cast <gcall *> (stmt))
+	{
+	  int flags = gimple_call_return_flags (call);
+	  if (!(flags & ERF_RETURNS_ARG))
+	    goto fail;
+	  int arg = flags & ERF_RETURN_ARG_MASK;
+	  if (arg >= (int)gimple_call_num_args (call))
+	    goto fail;
+	  expr = gimple_call_arg (stmt, arg);
+	  continue;
+	}
 
       if (!is_gimple_assign (stmt = SSA_NAME_DEF_STMT (expr)))
 	break;
@@ -1664,6 +1677,7 @@  set_cond_stmt_execution_predicate (struct ipa_func_body_info *fbi,
 	    }
 	}
       vec_free (param_ops);
+      return;
     }
 
   if (TREE_CODE (op) != SSA_NAME)
diff --git a/gcc/testsuite/gcc.dg/ipa/pr109849.c b/gcc/testsuite/gcc.dg/ipa/pr109849.c
new file mode 100644
index 00000000000..09b62f90d70
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/pr109849.c
@@ -0,0 +1,27 @@ 
+/* { dg-do compile } */
+/* { dg-options "-Os -fdump-ipa-inline-details" } */
+void bad (void);
+void
+test(int a)
+{
+	if (__builtin_expect (a>3, 0))
+	{
+		bad ();
+		bad ();
+		bad ();
+		bad ();
+		bad ();
+		bad ();
+		bad ();
+		bad ();
+	}
+}
+void
+foo (int a)
+{
+	if (a>0)
+		__builtin_unreachable ();
+	test (a);
+}
+/* { dg-final { scan-ipa-dump "Inlined 2 calls" "inline"  } } */
+/* { dg-final { scan-ipa-dump "Inlining test" "inline"  } } */