From 85e741ff3c8703d82911379473280ab5cc23627e Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Thu, 14 Apr 2016 13:20:03 -0400
Subject: [PATCH 086/117] FIXME: fix creation of basic blocks

---
 gcc/rtl/rtl-frontend.c | 50 +++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 39 insertions(+), 11 deletions(-)

diff --git a/gcc/rtl/rtl-frontend.c b/gcc/rtl/rtl-frontend.c
index 1400fa3..6180f62 100644
--- a/gcc/rtl/rtl-frontend.c
+++ b/gcc/rtl/rtl-frontend.c
@@ -50,6 +50,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "context.h"
 #include "pass_manager.h"
 #include "toplev.h"
+#include "bitmap.h"
 
 /* Language-dependent contents of a type.  */
 
@@ -307,9 +308,13 @@ class fixup_expr : public fixup
 class function_reader : public rtx_reader
 {
  public:
-  function_reader (line_maps *set) : rtx_reader (set), m_max_bb_idx (-1),
+  function_reader (line_maps *set) : rtx_reader (set),
     m_first_insn (NULL)
-  {}
+  {
+    bitmap_initialize (&m_bb_indices, NULL);
+    bitmap_set_bit (&m_bb_indices, ENTRY_BLOCK);
+    bitmap_set_bit (&m_bb_indices, EXIT_BLOCK);
+  }
 
   ~function_reader ();
   void handle_unknown_directive (file_location, const char *);
@@ -347,7 +352,7 @@ class function_reader : public rtx_reader
   struct uid_hash : int_hash <int, -1, -2> {};
   hash_map<uid_hash, rtx_insn *> m_insns_by_uid;
   auto_vec<fixup *> m_fixups;
-  int m_max_bb_idx;
+  bitmap_head m_bb_indices;
   rtx_insn *m_first_insn;
   deferred_locations m_deferred_locations;
   auto_vec<tree> m_fake_scope;
@@ -530,8 +535,7 @@ void
 function_reader::add_fixup_bb (file_location loc, rtx insn, int operand_idx,
 			       int bb_idx)
 {
-  if (m_max_bb_idx < bb_idx)
-    m_max_bb_idx = bb_idx;
+  bitmap_set_bit (&m_bb_indices, bb_idx);
   m_fixups.safe_push (new fixup_bb (loc, insn, operand_idx, bb_idx));
 }
 
@@ -599,7 +603,7 @@ function_reader::create_function ()
   //struct function *fn = ; // DECL_STRUCT_FUNCTION (node->decl);
   //push_cfun (fn);
 
-  /* Create cfg.  */
+  /* Create bare-bones cfg.  This creates the entry and exit blocks.  */
 #if 1
   init_empty_tree_cfg_for_function (cfun);
 #else
@@ -610,21 +614,45 @@ function_reader::create_function ()
 
      We can't call create_basic_block and use the regular RTL block-creation
      hooks, since this creates NOTE_INSN_BASIC_BLOCK instances.  We don't
-     want to do that; we want to use the notes we were provided with. */
-  size_t new_size = m_max_bb_idx + 1;
+     want to do that; we want to use the notes we were provided with.
+
+     The term "index" has two meanings for basic blocks in a CFG:
+     (a) the "index" field within struct basic_block_def.
+     (b) the index of a basic_block within the cfg's x_basic_block_info
+     vector, as accessed via BASIC_BLOCK_FOR_FN.
+
+     These can get out-of-sync when basic blocks are optimized away.
+     They get back in sync by "compact_blocks".
+     We make the assumption that the CFG has been compacted, and
+     so we reconstruct cfun->cfg->x_basic_block_info->m_vecdata with NULL
+     values in it for any missing basic blocks, so that (a) == (b) for
+     all of the blocks we create.  The doubly-linked list of basic
+     blocks (next_bb/prev_bb) skip over these "holes".  */
+
+  /* Ensure that the vector of basic_block pointers is big enough.  */
+  unsigned highest_bb_idx = bitmap_last_set_bit (&m_bb_indices);
+  size_t new_size = highest_bb_idx + 1;
   if (basic_block_info_for_fn (cfun)->length () < new_size)
     vec_safe_grow_cleared (basic_block_info_for_fn (cfun), new_size);
 
+  /* Populate the vector.  */
+  unsigned bb_idx;
+  bitmap_iterator bi;
   basic_block after = ENTRY_BLOCK_PTR_FOR_FN (cfun);
   gcc_assert (after);
-  while (n_basic_blocks_for_fn (cfun) < new_size)
+  EXECUTE_IF_SET_IN_BITMAP (&m_bb_indices, 0, bb_idx, bi)
     {
+      /* The entry and exit blocks were already created above.  */
+      if (bb_idx == ENTRY_BLOCK || bb_idx == EXIT_BLOCK)
+	continue;
       basic_block bb = alloc_block ();
       init_rtl_bb_info (bb);
-      bb->index = n_basic_blocks_for_fn (cfun)++;
+      bb->index = bb_idx;
       bb->flags = BB_NEW | BB_RTL;
       link_block (bb, after);
-      SET_BASIC_BLOCK_FOR_FN (cfun, bb->index, bb);
+
+      n_basic_blocks_for_fn (cfun)++;
+      SET_BASIC_BLOCK_FOR_FN (cfun, bb_idx, bb);
       //df_bb_refs_record (bb->index, false);
       //update_bb_for_insn (bb);
       BB_SET_PARTITION (bb, BB_UNPARTITIONED);
-- 
1.8.5.3

