Hi,

builtin_expect should be a NOP in size_estimation. Indeed, the call
stmt itself is 0 weight in size and time. But it may introduce
an extra relation expr which has non-zero size/time. The end result
is: for w/ and w/o builtin_expect, we have different size/time estimation
for early inlining.

This patch fixes this problem.

-Rong
2013-09-26  Rong Xu  <x...@google.com>

        * ipa-inline-analysis.c (estimate_function_body_sizes): fix
        the size estimation for builtin_expect.

Index: ipa-inline-analysis.c
===================================================================
--- ipa-inline-analysis.c       (revision 202638)
+++ ipa-inline-analysis.c       (working copy)
@@ -2266,6 +2266,8 @@ estimate_function_body_sizes (struct cgraph_node *
   /* Estimate static overhead for function prologue/epilogue and alignment. */
   int overhead = PARAM_VALUE (PARAM_INLINE_FUNCTION_OVERHEAD_SIZE);
   int size = overhead;
+  gimple fix_expect_builtin;
+
   /* Benefits are scaled by probability of elimination that is in range
      <0,2>.  */
   basic_block bb;
@@ -2359,14 +2361,73 @@ estimate_function_body_sizes (struct cgraph_node *
            }
        }
 
+      fix_expect_builtin = NULL;
       for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
        {
          gimple stmt = gsi_stmt (bsi);
+         if (gimple_call_builtin_p (stmt, BUILT_IN_EXPECT))
+            {
+              tree var = gimple_call_lhs (stmt);
+              tree arg = gimple_call_arg (stmt, 0);
+              use_operand_p use_p;
+              gimple use_stmt;
+              bool match = false;
+              bool done = false;
+              gcc_assert (var && arg);
+              gcc_assert (TREE_CODE (var) == SSA_NAME);
+
+              while (TREE_CODE (arg) == SSA_NAME)
+                {
+                  gimple stmt_tmp = SSA_NAME_DEF_STMT (arg);
+                  switch (gimple_assign_rhs_code (stmt_tmp))
+                    {
+                      case LT_EXPR:
+                      case LE_EXPR:
+                      case GT_EXPR:
+                      case GE_EXPR:
+                      case EQ_EXPR:
+                      case NE_EXPR:
+                        match = true;
+                        done = true;
+                        break;
+                      case NOP_EXPR:
+                        break;
+                      default:
+                        done = true;
+                        break;
+                    }
+                  if (done)
+                    break;
+                  arg = gimple_assign_rhs1 (stmt_tmp);
+                }
+
+              if (match && single_imm_use (var, &use_p, &use_stmt))
+                {
+                  if (gimple_code (use_stmt) == GIMPLE_COND)
+                    {
+                      fix_expect_builtin = use_stmt;
+                    }
+                }
+
+              /* we should see one builtin_expert call in one bb.  */
+              break;
+            }
+        }
+
+      for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
+       {
+         gimple stmt = gsi_stmt (bsi);
          int this_size = estimate_num_insns (stmt, &eni_size_weights);
          int this_time = estimate_num_insns (stmt, &eni_time_weights);
          int prob;
          struct predicate will_be_nonconstant;
 
+         if (stmt == fix_expect_builtin)
+            {
+              this_size--;
+              this_time--;
+            }
+
          if (dump_file && (dump_flags & TDF_DETAILS))
            {
              fprintf (dump_file, "  ");

Reply via email to