diff mbox

[PR81030] Call compute_outgoing_frequencies at expand

Message ID f0d1ec7f-eb4c-c691-f190-e8df941d70b1@mentor.com
State New
Headers show

Commit Message

Tom de Vries July 17, 2017, 11:22 a.m. UTC
Hi,

this patch fixes PR81030, an P1 ICE in expand.


I.

For the test-case from the patch compiled at -O1 we have at .optimized:
...
   _21 = 0;
   _22 = c.5_6 != 0;
   _23 = _21 | _22;
   if (_23 != 0)
     goto <bb 7>; [73.27%] [count: INV]
   else
     goto <bb 6>; [26.73%] [count: INV]
;;    succ:       7 [73.3% (guessed)]  (TRUE_VALUE,EXECUTABLE)
;;                6 [26.7% (guessed)]  (FALSE_VALUE,EXECUTABLE)
...

While expanding this bit, we first swap the operands of the BIT_IOR_EXPR:
...
;; Generating RTL for gimple basic block 4
Swap operands in stmt:
_23 = _21 | _22;
Cost left opnd=0, right opnd=2
...

And then in expand_gimple_cond we substitute the def of _23 and replace 
the BIT_IOR_EXPR with TRUTH_ORIF_EXPR. So we really expand:
...
   if (_22 || _21)
...

In do_jump_1, we encounter the following TRUTH_ORIF_EXPR handling:
...
  case TRUTH_ORIF_EXPR:
  {
    /* Spread the probability evenly between the two conditions. So
       the first condition has half the total probability of being true.
       The second condition has the other half of the total probability,
       so its jump has a probability of half the total, relative to
       the probability we reached it (i.e. the first condition was
       false).  */
    profile_probability op0_prob = profile_probability::uninitialized ();
    profile_probability op1_prob = profile_probability::uninitialized ();
    if (prob.initialized_p ())
      {
        op0_prob = prob.apply_scale (1, 2);
        op1_prob = prob.apply_scale (1, 2) / op0_prob.invert ();
      }
    if (if_true_label == NULL)
      {
        drop_through_label = gen_label_rtx ();
        do_jump (op0, NULL, drop_through_label, op0_prob);
        do_jump (op1, if_false_label, NULL, op1_prob);
      }
    else
      {
        do_jump (op0, NULL, if_true_label, op0_prob);
        do_jump (op1, if_false_label, if_true_label, op1_prob);
      }
    break;
  }
...

This expands into two jumps. The intention is two conditional jumps, but 
since _21 is 0, the second becomes unconditional:
...
;; if (_23 != 0)

(insn 12 11 13 4 (set (reg:CCZ 17 flags)
         (compare:CCZ (mem/c:SI (symbol_ref:DI ("c") [flags 0x2] 
<var_decl 0x7f0983db0f30 c>) [1 cD.1821+0 S4 A32])
             (const_int 0 [0]))) "test2.c":20 -1
      (nil))

(insn 13 12 14 4 (set (reg:QI 95)
         (ne:QI (reg:CCZ 17 flags)
             (const_int 0 [0]))) "test2.c":20 -1
      (nil))

(insn 14 13 15 4 (set (reg:CCZ 17 flags)
         (compare:CCZ (reg:QI 95)
             (const_int 0 [0]))) "test2.c":20 -1
      (nil))

(jump_insn 15 14 18 4 (set (pc)
         (if_then_else (ne (reg:CCZ 17 flags)
                 (const_int 0 [0]))
             (label_ref 0)
             (pc))) "test2.c":20 -1
      (int_list:REG_BR_PROB 3664 (nil)))

(note 18 15 16 10 [bb 10] NOTE_INSN_BASIC_BLOCK)

(jump_insn 16 18 17 10 (set (pc)
         (label_ref 0)) -1
      (nil))

(barrier 17 16 0)
...

The jump_insn 15 now contains a reg-note with the branch probability set 
to 3664.

Eventually, in pass_expand::execute we call 'cleanup_cfg 
(CLEANUP_NO_INSN_DEL)' during which we call checking_verify_flow_info, 
which complains that:
...
test2.c:26:1: error: verify_flow_info: REG_BR_PROB does not match cfg 
3664 7327
  }
  ^
during RTL pass: expand
test2.c:26:1: internal compiler error: verify_flow_info failed
...

In other words, this jump_insn has a branch probability note of 3664, 
but the corresponding edge claims a probability of 7327:
...
(jump_insn 15 14 18 5 (set (pc)
         (if_then_else (ne (reg:CCZ 17 flags)
                 (const_int 0 [0]))
             (label_ref:DI 32)
             (pc))) "test2.c":20 617 {*jcc_1}
      (int_list:REG_BR_PROB 3664 (nil))
  -> 32)
;;    succ:       10 [73.3% (guessed)]
;;                6 [26.7% (guessed)]  (FALLTHRU)
...


II.

The ICE was introduced with r248945, by adding this bit to 
find_many_sub_basic_blocks:
...
           }
+       else
+         /* If nothing changed, there is no need to create new BBs.  */
+         if (EDGE_COUNT (bb->succs) == n_succs[bb->index])
+           continue;

         compute_outgoing_frequencies (bb);
        }
...
Commenting out this bit makes the compilation succeed.


III.

The bit added in find_many_sub_basic_blocks makes sense to me.

It just seems to me that we have been relying on 
find_many_sub_basic_blocks to call compute_outgoing_frequencies for all 
basic blocks during expand. This patch restores that situation, and 
fixes the ICE.

Bootstrapped and reg-tested on x86_64.

OK for trunk?

Thanks,
- Tom
diff mbox

Patch

Call compute_outgoing_frequencies at expand

2017-07-17  Tom de Vries  <tom@codesourcery.com>

	PR middle-end/81030
	* cfgbuild.c (find_many_sub_basic_blocks): Add and handle update_freq
	parameter.
	* cfgbuild.h (find_many_sub_basic_blocks): Add update_freq parameter.
	* cfgexpand.c (pass_expand::execute): Call find_many_sub_basic_blocks
	with update_freq == true.

	* gcc.dg/pr81030.c: New test.

---
 gcc/cfgbuild.c                 |  4 ++--
 gcc/cfgbuild.h                 |  3 ++-
 gcc/cfgexpand.c                |  2 +-
 gcc/testsuite/gcc.dg/pr81030.c | 29 +++++++++++++++++++++++++++++
 4 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/gcc/cfgbuild.c b/gcc/cfgbuild.c
index 56a2cb9..78036fe 100644
--- a/gcc/cfgbuild.c
+++ b/gcc/cfgbuild.c
@@ -594,7 +594,7 @@  compute_outgoing_frequencies (basic_block b)
    and create edges.  */
 
 void
-find_many_sub_basic_blocks (sbitmap blocks)
+find_many_sub_basic_blocks (sbitmap blocks, bool update_freq)
 {
   basic_block bb, min, max;
   bool found = false;
@@ -677,7 +677,7 @@  find_many_sub_basic_blocks (sbitmap blocks)
 	  }
 	else
 	  /* If nothing changed, there is no need to create new BBs.  */
-	  if (EDGE_COUNT (bb->succs) == n_succs[bb->index])
+	  if (!update_freq && EDGE_COUNT (bb->succs) == n_succs[bb->index])
 	    continue;
 
 	compute_outgoing_frequencies (bb);
diff --git a/gcc/cfgbuild.h b/gcc/cfgbuild.h
index afda5ac..0c58590 100644
--- a/gcc/cfgbuild.h
+++ b/gcc/cfgbuild.h
@@ -23,6 +23,7 @@  along with GCC; see the file COPYING3.  If not see
 extern bool inside_basic_block_p (const rtx_insn *);
 extern bool control_flow_insn_p (const rtx_insn *);
 extern void rtl_make_eh_edge (sbitmap, basic_block, rtx);
-extern void find_many_sub_basic_blocks (sbitmap);
+extern void find_many_sub_basic_blocks (sbitmap block,
+					bool update_freq = false);
 
 #endif /* GCC_CFGBUILD_H */
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 3e1d24d..e030a86 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -6464,7 +6464,7 @@  pass_expand::execute (function *fun)
 
   auto_sbitmap blocks (last_basic_block_for_fn (fun));
   bitmap_ones (blocks);
-  find_many_sub_basic_blocks (blocks);
+  find_many_sub_basic_blocks (blocks, true);
   purge_all_dead_edges ();
 
   expand_stack_alignment ();
diff --git a/gcc/testsuite/gcc.dg/pr81030.c b/gcc/testsuite/gcc.dg/pr81030.c
new file mode 100644
index 0000000..23da6e5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr81030.c
@@ -0,0 +1,29 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+void __assert_fail (const char *, const char *, unsigned int, const char *);
+
+int a, b, c, d, e, f, h;
+unsigned char g;
+
+int main ()
+{
+  int i, *j = &b;
+  if (a)
+    {
+      if (h)
+	{
+	  int **k = &j;
+	  d = 0;
+	  *k = &e;
+	}
+      else
+	for (b = 0; b > -28; b = g)
+	  ;
+      c || !j ? : __assert_fail ("c || !j", "small.c", 20, "main");
+      if (f)
+	for (i = 0; i < 1; i++)
+	  ;
+    }
+  return 0;
+}