The cirros image was rebuilt against the 3.13.0-83 kernel, drivers e1000e, igbvf...
[packages/trusty/cirros-testvm.git] / cirros-testvm / src-cirros / buildroot-2015.05 / package / binutils / 2.25 / 907-xtensa-optimize-removed_by_actions.patch
diff --git a/cirros-testvm/src-cirros/buildroot-2015.05/package/binutils/2.25/907-xtensa-optimize-removed_by_actions.patch b/cirros-testvm/src-cirros/buildroot-2015.05/package/binutils/2.25/907-xtensa-optimize-removed_by_actions.patch
new file mode 100644 (file)
index 0000000..9df8065
--- /dev/null
@@ -0,0 +1,356 @@
+From 3e3f60207399ab29dd55af109e5ae9facc7d8e83 Mon Sep 17 00:00:00 2001
+From: Max Filippov <jcmvbkbc@gmail.com>
+Date: Sat, 28 Mar 2015 08:46:28 +0300
+Subject: [PATCH 2/4] xtensa: optimize removed_by_actions
+
+The function removed_by_actions iterates through text actions to
+calculate an offset applied by text actions to a given VMA. Although it
+has a parameter p_start_action that allows for incremental offset
+calculation, in many places it's used with p_start_action explicitly set
+to the first action. After the first relaxation pass when the list of
+text actions is finalized, an array of offsets sorted by VMA may be used
+to speed up this function.
+
+Original profile:
+
+% time    self  children    called     name
+-----------------------------------------
+          0.35    0.00   33872/4808961     relax_section_symbols
+          3.32    0.00  326022/4808961     relax_property_section
+         12.83    0.00 1259379/4808961     offset_with_removed_text
+         32.50    0.00 3189688/4808961     translate_reloc
+  71.5   49.00    0.00 4808961         removed_by_actions
+-----------------------------------------
+
+Same data, after optimization:
+
+% time    self  children    called     name
+-----------------------------------------
+          0.00    0.00   33872/4808537     relax_section_symbols
+          0.01    0.00  326022/4808537     relax_property_section
+          0.05    0.00 1258955/4808537     offset_with_removed_text_map
+          0.13    0.00 3189688/4808537     translate_reloc
+   1.0    0.20    0.00 4808537         removed_by_actions_map
+          0.00    0.00     120/120         map_removal_by_action
+-----------------------------------------
+
+2015-04-01  Max Filippov  <jcmvbkbc@gmail.com>
+bfd/
+       * elf32-xtensa.c (removal_by_action_entry_struct,
+       removal_by_action_map_struct): new structures.
+       (removal_by_action_entry, removal_by_action_map): new typedefs.
+       (text_action_list_struct): add new field: map.
+       (map_removal_by_action, removed_by_actions_map,
+       offset_with_removed_text_map): new functions.
+       (relax_section): replace offset_with_removed_text with
+       offset_with_removed_text_map.
+       (translate_reloc, relax_property_section, relax_section_symbols):
+       replace removed_by_actions with removed_by_actions_map.
+
+Backported from: 071aa5c98a31c966f5fbfc573fcee61350fd1936
+Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
+---
+ bfd/elf32-xtensa.c | 181 +++++++++++++++++++++++++++++++++++++++++++++--------
+ 1 file changed, 156 insertions(+), 25 deletions(-)
+
+diff --git a/bfd/elf32-xtensa.c b/bfd/elf32-xtensa.c
+index 872370b..21b2871 100644
+--- a/bfd/elf32-xtensa.c
++++ b/bfd/elf32-xtensa.c
+@@ -5420,11 +5420,28 @@ struct text_action_struct
+   text_action *next;
+ };
++struct removal_by_action_entry_struct
++{
++  bfd_vma offset;
++  int removed;
++  int eq_removed;
++  int eq_removed_before_fill;
++};
++typedef struct removal_by_action_entry_struct removal_by_action_entry;
++
++struct removal_by_action_map_struct
++{
++  unsigned n_entries;
++  removal_by_action_entry *entry;
++};
++typedef struct removal_by_action_map_struct removal_by_action_map;
++
+ /* List of all of the actions taken on a text section.  */
+ struct text_action_list_struct
+ {
+   text_action *head;
++  removal_by_action_map map;
+ };
+@@ -5636,6 +5653,101 @@ action_list_count (text_action_list *action_list)
+   return count;
+ }
++static void
++map_removal_by_action (text_action_list *action_list)
++{
++  text_action *r;
++  int removed = 0;
++  removal_by_action_map map;
++  bfd_boolean eq_complete;
++
++  map.n_entries = 0;
++  map.entry = bfd_malloc (action_list_count (action_list) *
++                        sizeof (removal_by_action_entry));
++  eq_complete = FALSE;
++
++  for (r = action_list->head; r;)
++    {
++      removal_by_action_entry *ientry = map.entry + map.n_entries;
++
++      if (map.n_entries && (ientry - 1)->offset == r->offset)
++      {
++        --ientry;
++      }
++      else
++      {
++        ++map.n_entries;
++        eq_complete = FALSE;
++        ientry->offset = r->offset;
++        ientry->eq_removed_before_fill = removed;
++      }
++
++      if (!eq_complete)
++      {
++        if (r->action != ta_fill || r->removed_bytes >= 0)
++          {
++            ientry->eq_removed = removed;
++            eq_complete = TRUE;
++          }
++        else
++          ientry->eq_removed = removed + r->removed_bytes;
++      }
++
++      removed += r->removed_bytes;
++      ientry->removed = removed;
++      r = r->next;
++    }
++  action_list->map = map;
++}
++
++static int
++removed_by_actions_map (text_action_list *action_list, bfd_vma offset,
++                      bfd_boolean before_fill)
++{
++  unsigned a, b;
++
++  if (!action_list->map.entry)
++    map_removal_by_action (action_list);
++
++  if (!action_list->map.n_entries)
++    return 0;
++
++  a = 0;
++  b = action_list->map.n_entries;
++
++  while (b - a > 1)
++    {
++      unsigned c = (a + b) / 2;
++
++      if (action_list->map.entry[c].offset <= offset)
++      a = c;
++      else
++      b = c;
++    }
++
++  if (action_list->map.entry[a].offset < offset)
++    {
++      return action_list->map.entry[a].removed;
++    }
++  else if (action_list->map.entry[a].offset == offset)
++    {
++      return before_fill ?
++      action_list->map.entry[a].eq_removed_before_fill :
++      action_list->map.entry[a].eq_removed;
++    }
++  else
++    {
++      return 0;
++    }
++}
++
++static bfd_vma
++offset_with_removed_text_map (text_action_list *action_list, bfd_vma offset)
++{
++  int removed = removed_by_actions_map (action_list, offset, FALSE);
++  return offset - removed;
++}
++
+ /* The find_insn_action routine will only find non-fill actions.  */
+@@ -5909,6 +6021,9 @@ init_xtensa_relax_info (asection *sec)
+   relax_info->action_list.head = NULL;
++  relax_info->action_list.map.n_entries = 0;
++  relax_info->action_list.map.entry = NULL;
++
+   relax_info->fix_list = NULL;
+   relax_info->fix_array = NULL;
+   relax_info->fix_array_count = 0;
+@@ -9218,7 +9333,7 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info)
+                 if (elf_hash_table (link_info)->dynamic_sections_created)
+                   shrink_dynamic_reloc_sections (link_info, abfd, sec, irel);
+                 irel->r_info = ELF32_R_INFO (0, R_XTENSA_NONE);
+-                irel->r_offset = offset_with_removed_text
++                irel->r_offset = offset_with_removed_text_map
+                   (&relax_info->action_list, irel->r_offset);
+                 continue;
+               }
+@@ -9255,7 +9370,7 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info)
+                   }
+               }
+-            source_offset = offset_with_removed_text
++            source_offset = offset_with_removed_text_map
+               (&relax_info->action_list, irel->r_offset);
+             irel->r_offset = source_offset;
+           }
+@@ -9352,7 +9467,7 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info)
+                     break;
+                   }
+-                new_end_offset = offset_with_removed_text
++                new_end_offset = offset_with_removed_text_map
+                   (&target_relax_info->action_list,
+                    r_rel.target_offset + diff_value);
+                 diff_value = new_end_offset - new_reloc.target_offset;
+@@ -9750,7 +9865,6 @@ translate_reloc (const r_reloc *orig_rel, r_reloc *new_rel, asection *sec)
+   xtensa_relax_info *relax_info;
+   removed_literal *removed;
+   bfd_vma target_offset, base_offset;
+-  text_action *act;
+   *new_rel = *orig_rel;
+@@ -9803,19 +9917,26 @@ translate_reloc (const r_reloc *orig_rel, r_reloc *new_rel, asection *sec)
+      offset.  */
+   base_offset = r_reloc_get_target_offset (new_rel) - new_rel->rela.r_addend;
+-  act = relax_info->action_list.head;
+   if (base_offset <= target_offset)
+     {
+-      int base_removed = removed_by_actions (&act, base_offset, FALSE);
+-      int addend_removed = removed_by_actions (&act, target_offset, FALSE);
++      int base_removed = removed_by_actions_map (&relax_info->action_list,
++                                               base_offset, FALSE);
++      int addend_removed = removed_by_actions_map (&relax_info->action_list,
++                                                 target_offset, FALSE) -
++      base_removed;
++
+       new_rel->target_offset = target_offset - base_removed - addend_removed;
+       new_rel->rela.r_addend -= addend_removed;
+     }
+   else
+     {
+       /* Handle a negative addend.  The base offset comes first.  */
+-      int tgt_removed = removed_by_actions (&act, target_offset, FALSE);
+-      int addend_removed = removed_by_actions (&act, base_offset, FALSE);
++      int tgt_removed = removed_by_actions_map (&relax_info->action_list,
++                                              target_offset, FALSE);
++      int addend_removed = removed_by_actions_map (&relax_info->action_list,
++                                                 base_offset, FALSE) -
++      tgt_removed;
++
+       new_rel->target_offset = target_offset - tgt_removed;
+       new_rel->rela.r_addend += addend_removed;
+     }
+@@ -10138,9 +10259,10 @@ relax_property_section (bfd *abfd,
+             bfd_vma old_offset = val.r_rel.target_offset;
+             bfd_vma new_offset;
+             long old_size, new_size;
+-            text_action *act = target_relax_info->action_list.head;
+-            new_offset = old_offset -
+-              removed_by_actions (&act, old_offset, FALSE);
++            int removed_by_old_offset =
++              removed_by_actions_map (&target_relax_info->action_list,
++                                      old_offset, FALSE);
++            new_offset = old_offset - removed_by_old_offset;
+             /* Assert that we are not out of bounds.  */
+             old_size = bfd_get_32 (abfd, size_p);
+@@ -10164,9 +10286,10 @@ relax_property_section (bfd *abfd,
+                     /* Recompute the new_offset, but this time don't
+                        include any fill inserted by relaxation.  */
+-                    act = target_relax_info->action_list.head;
+-                    new_offset = old_offset -
+-                      removed_by_actions (&act, old_offset, TRUE);
++                    removed_by_old_offset =
++                      removed_by_actions_map (&target_relax_info->action_list,
++                                              old_offset, TRUE);
++                    new_offset = old_offset - removed_by_old_offset;
+                     /* If it is not unreachable and we have not yet
+                        seen an unreachable at this address, place it
+@@ -10182,8 +10305,12 @@ relax_property_section (bfd *abfd,
+                   }
+               }
+             else
+-              new_size -=
+-                  removed_by_actions (&act, old_offset + old_size, TRUE);
++              {
++                int removed_by_old_offset_size =
++                  removed_by_actions_map (&target_relax_info->action_list,
++                                          old_offset + old_size, TRUE);
++                new_size -= removed_by_old_offset_size - removed_by_old_offset;
++              }
+             if (new_size != old_size)
+               {
+@@ -10441,14 +10568,16 @@ relax_section_symbols (bfd *abfd, asection *sec)
+       if (isym->st_shndx == sec_shndx)
+       {
+-        text_action *act = relax_info->action_list.head;
+         bfd_vma orig_addr = isym->st_value;
++        int removed = removed_by_actions_map (&relax_info->action_list,
++                                              orig_addr, FALSE);
+-        isym->st_value -= removed_by_actions (&act, orig_addr, FALSE);
+-
++        isym->st_value -= removed;
+         if (ELF32_ST_TYPE (isym->st_info) == STT_FUNC)
+           isym->st_size -=
+-            removed_by_actions (&act, orig_addr + isym->st_size, FALSE);
++            removed_by_actions_map (&relax_info->action_list,
++                                    orig_addr + isym->st_size, FALSE) -
++            removed;
+       }
+     }
+@@ -10466,15 +10595,17 @@ relax_section_symbols (bfd *abfd, asection *sec)
+          || sym_hash->root.type == bfd_link_hash_defweak)
+         && sym_hash->root.u.def.section == sec)
+       {
+-        text_action *act = relax_info->action_list.head;
+         bfd_vma orig_addr = sym_hash->root.u.def.value;
++        int removed = removed_by_actions_map (&relax_info->action_list,
++                                              orig_addr, FALSE);
+-        sym_hash->root.u.def.value -=
+-          removed_by_actions (&act, orig_addr, FALSE);
++        sym_hash->root.u.def.value -= removed;
+         if (sym_hash->type == STT_FUNC)
+           sym_hash->size -=
+-            removed_by_actions (&act, orig_addr + sym_hash->size, FALSE);
++            removed_by_actions_map (&relax_info->action_list,
++                                    orig_addr + sym_hash->size, FALSE) -
++            removed;
+       }
+     }
+-- 
+1.8.1.4
+