909-xtensa-replace-action-list-with-splay-tree.patch 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826
  1. From e5409aedd3ee2192855018a564650ffb75c26e60 Mon Sep 17 00:00:00 2001
  2. From: Max Filippov <jcmvbkbc@gmail.com>
  3. Date: Sun, 5 Apr 2015 17:04:22 +0300
  4. Subject: [PATCH 4/4] xtensa: replace action list with splay tree
  5. text_action_add uses linear list search to order text actions list by
  6. action VMA. The list is used at the first relaxation pass, when it's not
  7. fixed yet.
  8. Replace the list with splay tree from libiberty.
  9. Original profile:
  10. % time self children called name
  11. -----------------------------------------
  12. 0.00 0.00 14/158225 compute_text_actions
  13. 3.62 0.00 25211/158225 remove_dead_literal
  14. 8.42 0.00 58645/158225 coalesce_shared_literal
  15. 10.68 0.00 74355/158225 text_action_add_proposed
  16. 38.8 22.73 0.00 158225 text_action_add
  17. 0.00 0.00 144527/293246 bfd_zmalloc
  18. -----------------------------------------
  19. Same data, after optimization:
  20. % time self children called name
  21. -----------------------------------------
  22. 0.00 0.00 14/158225 compute_text_actions
  23. 0.00 0.00 25211/158225 remove_dead_literal
  24. 0.00 0.01 58645/158225 coalesce_shared_literal
  25. 0.00 0.01 74355/158225 text_action_add_proposed
  26. 0.1 0.00 0.02 158225 text_action_add
  27. 0.01 0.00 144527/144527 splay_tree_insert
  28. 0.00 0.00 144527/195130 splay_tree_lookup
  29. 0.00 0.00 144527/293246 bfd_zmalloc
  30. -----------------------------------------
  31. 2015-04-03 Max Filippov <jcmvbkbc@gmail.com>
  32. bfd/
  33. * elf32-xtensa.c (splay-tree.h): include header.
  34. (text_action_struct): drop next pointer.
  35. (text_action_list_struct): drop head pointer, add count and
  36. tree fields.
  37. (find_fill_action): instead of linear search in text_action_list
  38. search in the tree.
  39. (text_action_compare, action_first, action_next): new functions.
  40. (text_action_add, text_action_add_literal): instead of linear
  41. search and insertion insert new node into the tree.
  42. (removed_by_actions): pass additional parameter: action_list,
  43. use it to traverse the tree.
  44. (offset_with_removed_text): pass additional action_list parameter
  45. to removed_by_actions.
  46. (map_action_fn_context): new typedef.
  47. (map_action_fn_context_struct): new structure.
  48. (map_action_fn): new function.
  49. (map_removal_by_action): use splay_tree_foreach to build map.
  50. (find_insn_action): replace linear search in text_action_list
  51. with series of splay_tree_lookups.
  52. (print_action, print_action_list_fn): new functions.
  53. (print_action_list): use splay_tree_foreach.
  54. (init_xtensa_relax_info): drop action_list.head initialization.
  55. Initialize the tree.
  56. (compute_text_actions): use non-zero action_list_count instead of
  57. non-NULL action list.
  58. (xlate_map_context): new typedef.
  59. (xlate_map_context_struct): new structure.
  60. (xlate_map_fn): new function.
  61. (build_xlate_map): use splay_tree_foreach to build map.
  62. (action_remove_bytes_fn): new function.
  63. (relax_section): use zero action_list_count instead of NULL
  64. action list. Use splay_tree_foreach to count final section size.
  65. Drop unused variable 'removed'.
  66. Backported from: 4c2af04fe8b4452bf51d2debf1bb467fafcd0f08
  67. Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
  68. ---
  69. bfd/elf32-xtensa.c | 488 +++++++++++++++++++++++++++++++----------------------
  70. 1 file changed, 282 insertions(+), 206 deletions(-)
  71. diff --git a/bfd/elf32-xtensa.c b/bfd/elf32-xtensa.c
  72. index 51733ad..53af1c6 100644
  73. --- a/bfd/elf32-xtensa.c
  74. +++ b/bfd/elf32-xtensa.c
  75. @@ -28,6 +28,7 @@
  76. #include "libbfd.h"
  77. #include "elf-bfd.h"
  78. #include "elf/xtensa.h"
  79. +#include "splay-tree.h"
  80. #include "xtensa-isa.h"
  81. #include "xtensa-config.h"
  82. @@ -5416,8 +5417,6 @@ struct text_action_struct
  83. bfd_vma virtual_offset; /* Zero except for adding literals. */
  84. int removed_bytes;
  85. literal_value value; /* Only valid when adding literals. */
  86. -
  87. - text_action *next;
  88. };
  89. struct removal_by_action_entry_struct
  90. @@ -5440,7 +5439,8 @@ typedef struct removal_by_action_map_struct removal_by_action_map;
  91. /* List of all of the actions taken on a text section. */
  92. struct text_action_list_struct
  93. {
  94. - text_action *head;
  95. + unsigned count;
  96. + splay_tree tree;
  97. removal_by_action_map map;
  98. };
  99. @@ -5448,20 +5448,18 @@ struct text_action_list_struct
  100. static text_action *
  101. find_fill_action (text_action_list *l, asection *sec, bfd_vma offset)
  102. {
  103. - text_action **m_p;
  104. + text_action a;
  105. /* It is not necessary to fill at the end of a section. */
  106. if (sec->size == offset)
  107. return NULL;
  108. - for (m_p = &l->head; *m_p && (*m_p)->offset <= offset; m_p = &(*m_p)->next)
  109. - {
  110. - text_action *t = *m_p;
  111. - /* When the action is another fill at the same address,
  112. - just increase the size. */
  113. - if (t->offset == offset && t->action == ta_fill)
  114. - return t;
  115. - }
  116. + a.offset = offset;
  117. + a.action = ta_fill;
  118. +
  119. + splay_tree_node node = splay_tree_lookup (l->tree, (splay_tree_key)&a);
  120. + if (node)
  121. + return (text_action *)node->value;
  122. return NULL;
  123. }
  124. @@ -5509,6 +5507,49 @@ adjust_fill_action (text_action *ta, int fill_diff)
  125. }
  126. +static int
  127. +text_action_compare (splay_tree_key a, splay_tree_key b)
  128. +{
  129. + text_action *pa = (text_action *)a;
  130. + text_action *pb = (text_action *)b;
  131. + static const int action_priority[] =
  132. + {
  133. + [ta_fill] = 0,
  134. + [ta_none] = 1,
  135. + [ta_convert_longcall] = 2,
  136. + [ta_narrow_insn] = 3,
  137. + [ta_remove_insn] = 4,
  138. + [ta_remove_longcall] = 5,
  139. + [ta_remove_literal] = 6,
  140. + [ta_widen_insn] = 7,
  141. + [ta_add_literal] = 8,
  142. + };
  143. +
  144. + if (pa->offset == pb->offset)
  145. + {
  146. + if (pa->action == pb->action)
  147. + return 0;
  148. + return action_priority[pa->action] - action_priority[pb->action];
  149. + }
  150. + else
  151. + return pa->offset < pb->offset ? -1 : 1;
  152. +}
  153. +
  154. +static text_action *
  155. +action_first (text_action_list *action_list)
  156. +{
  157. + splay_tree_node node = splay_tree_min (action_list->tree);
  158. + return node ? (text_action *)node->value : NULL;
  159. +}
  160. +
  161. +static text_action *
  162. +action_next (text_action_list *action_list, text_action *action)
  163. +{
  164. + splay_tree_node node = splay_tree_successor (action_list->tree,
  165. + (splay_tree_key)action);
  166. + return node ? (text_action *)node->value : NULL;
  167. +}
  168. +
  169. /* Add a modification action to the text. For the case of adding or
  170. removing space, modify any current fill and assume that
  171. "unreachable_space" bytes can be freely contracted. Note that a
  172. @@ -5521,8 +5562,8 @@ text_action_add (text_action_list *l,
  173. bfd_vma offset,
  174. int removed)
  175. {
  176. - text_action **m_p;
  177. text_action *ta;
  178. + text_action a;
  179. /* It is not necessary to fill at the end of a section. */
  180. if (action == ta_fill && sec->size == offset)
  181. @@ -5532,34 +5573,30 @@ text_action_add (text_action_list *l,
  182. if (action == ta_fill && removed == 0)
  183. return;
  184. - for (m_p = &l->head; *m_p && (*m_p)->offset <= offset; m_p = &(*m_p)->next)
  185. + a.action = action;
  186. + a.offset = offset;
  187. +
  188. + if (action == ta_fill)
  189. {
  190. - text_action *t = *m_p;
  191. + splay_tree_node node = splay_tree_lookup (l->tree, (splay_tree_key)&a);
  192. - if (action == ta_fill)
  193. + if (node)
  194. {
  195. - /* When the action is another fill at the same address,
  196. - just increase the size. */
  197. - if (t->offset == offset && t->action == ta_fill)
  198. - {
  199. - t->removed_bytes += removed;
  200. - return;
  201. - }
  202. - /* Fills need to happen before widens so that we don't
  203. - insert fill bytes into the instruction stream. */
  204. - if (t->offset == offset && t->action == ta_widen_insn)
  205. - break;
  206. + ta = (text_action *)node->value;
  207. + ta->removed_bytes += removed;
  208. + return;
  209. }
  210. }
  211. + else
  212. + BFD_ASSERT (splay_tree_lookup (l->tree, (splay_tree_key)&a) == NULL);
  213. - /* Create a new record and fill it up. */
  214. ta = (text_action *) bfd_zmalloc (sizeof (text_action));
  215. ta->action = action;
  216. ta->sec = sec;
  217. ta->offset = offset;
  218. ta->removed_bytes = removed;
  219. - ta->next = (*m_p);
  220. - *m_p = ta;
  221. + splay_tree_insert (l->tree, (splay_tree_key)ta, (splay_tree_value)ta);
  222. + ++l->count;
  223. }
  224. @@ -5570,7 +5607,6 @@ text_action_add_literal (text_action_list *l,
  225. const literal_value *value,
  226. int removed)
  227. {
  228. - text_action **m_p;
  229. text_action *ta;
  230. asection *sec = r_reloc_get_section (loc);
  231. bfd_vma offset = loc->target_offset;
  232. @@ -5578,14 +5614,6 @@ text_action_add_literal (text_action_list *l,
  233. BFD_ASSERT (action == ta_add_literal);
  234. - for (m_p = &l->head; *m_p != NULL; m_p = &(*m_p)->next)
  235. - {
  236. - if ((*m_p)->offset > offset
  237. - && ((*m_p)->offset != offset
  238. - || (*m_p)->virtual_offset > virtual_offset))
  239. - break;
  240. - }
  241. -
  242. /* Create a new record and fill it up. */
  243. ta = (text_action *) bfd_zmalloc (sizeof (text_action));
  244. ta->action = action;
  245. @@ -5594,8 +5622,10 @@ text_action_add_literal (text_action_list *l,
  246. ta->virtual_offset = virtual_offset;
  247. ta->value = *value;
  248. ta->removed_bytes = removed;
  249. - ta->next = (*m_p);
  250. - *m_p = ta;
  251. +
  252. + BFD_ASSERT (splay_tree_lookup (l->tree, (splay_tree_key)ta) == NULL);
  253. + splay_tree_insert (l->tree, (splay_tree_key)ta, (splay_tree_value)ta);
  254. + ++l->count;
  255. }
  256. @@ -5606,7 +5636,8 @@ text_action_add_literal (text_action_list *l,
  257. so that each search may begin where the previous one left off. */
  258. static int
  259. -removed_by_actions (text_action **p_start_action,
  260. +removed_by_actions (text_action_list *action_list,
  261. + text_action **p_start_action,
  262. bfd_vma offset,
  263. bfd_boolean before_fill)
  264. {
  265. @@ -5614,6 +5645,13 @@ removed_by_actions (text_action **p_start_action,
  266. int removed = 0;
  267. r = *p_start_action;
  268. + if (r)
  269. + {
  270. + splay_tree_node node = splay_tree_lookup (action_list->tree,
  271. + (splay_tree_key)r);
  272. + BFD_ASSERT (node != NULL && r == (text_action *)node->value);
  273. + }
  274. +
  275. while (r)
  276. {
  277. if (r->offset > offset)
  278. @@ -5625,7 +5663,7 @@ removed_by_actions (text_action **p_start_action,
  279. removed += r->removed_bytes;
  280. - r = r->next;
  281. + r = action_next (action_list, r);
  282. }
  283. *p_start_action = r;
  284. @@ -5636,68 +5674,74 @@ removed_by_actions (text_action **p_start_action,
  285. static bfd_vma
  286. offset_with_removed_text (text_action_list *action_list, bfd_vma offset)
  287. {
  288. - text_action *r = action_list->head;
  289. - return offset - removed_by_actions (&r, offset, FALSE);
  290. + text_action *r = action_first (action_list);
  291. +
  292. + return offset - removed_by_actions (action_list, &r, offset, FALSE);
  293. }
  294. static unsigned
  295. action_list_count (text_action_list *action_list)
  296. {
  297. - text_action *r = action_list->head;
  298. - unsigned count = 0;
  299. - for (r = action_list->head; r != NULL; r = r->next)
  300. - {
  301. - count++;
  302. - }
  303. - return count;
  304. + return action_list->count;
  305. }
  306. -static void
  307. -map_removal_by_action (text_action_list *action_list)
  308. +typedef struct map_action_fn_context_struct map_action_fn_context;
  309. +struct map_action_fn_context_struct
  310. {
  311. - text_action *r;
  312. - int removed = 0;
  313. + int removed;
  314. removal_by_action_map map;
  315. bfd_boolean eq_complete;
  316. +};
  317. - map.n_entries = 0;
  318. - map.entry = bfd_malloc (action_list_count (action_list) *
  319. - sizeof (removal_by_action_entry));
  320. - eq_complete = FALSE;
  321. +static int
  322. +map_action_fn (splay_tree_node node, void *p)
  323. +{
  324. + map_action_fn_context *ctx = p;
  325. + text_action *r = (text_action *)node->value;
  326. + removal_by_action_entry *ientry = ctx->map.entry + ctx->map.n_entries;
  327. - for (r = action_list->head; r;)
  328. + if (ctx->map.n_entries && (ientry - 1)->offset == r->offset)
  329. {
  330. - removal_by_action_entry *ientry = map.entry + map.n_entries;
  331. + --ientry;
  332. + }
  333. + else
  334. + {
  335. + ++ctx->map.n_entries;
  336. + ctx->eq_complete = FALSE;
  337. + ientry->offset = r->offset;
  338. + ientry->eq_removed_before_fill = ctx->removed;
  339. + }
  340. - if (map.n_entries && (ientry - 1)->offset == r->offset)
  341. + if (!ctx->eq_complete)
  342. + {
  343. + if (r->action != ta_fill || r->removed_bytes >= 0)
  344. {
  345. - --ientry;
  346. + ientry->eq_removed = ctx->removed;
  347. + ctx->eq_complete = TRUE;
  348. }
  349. else
  350. - {
  351. - ++map.n_entries;
  352. - eq_complete = FALSE;
  353. - ientry->offset = r->offset;
  354. - ientry->eq_removed_before_fill = removed;
  355. - }
  356. + ientry->eq_removed = ctx->removed + r->removed_bytes;
  357. + }
  358. - if (!eq_complete)
  359. - {
  360. - if (r->action != ta_fill || r->removed_bytes >= 0)
  361. - {
  362. - ientry->eq_removed = removed;
  363. - eq_complete = TRUE;
  364. - }
  365. - else
  366. - ientry->eq_removed = removed + r->removed_bytes;
  367. - }
  368. + ctx->removed += r->removed_bytes;
  369. + ientry->removed = ctx->removed;
  370. + return 0;
  371. +}
  372. - removed += r->removed_bytes;
  373. - ientry->removed = removed;
  374. - r = r->next;
  375. - }
  376. - action_list->map = map;
  377. +static void
  378. +map_removal_by_action (text_action_list *action_list)
  379. +{
  380. + map_action_fn_context ctx;
  381. +
  382. + ctx.removed = 0;
  383. + ctx.map.n_entries = 0;
  384. + ctx.map.entry = bfd_malloc (action_list_count (action_list) *
  385. + sizeof (removal_by_action_entry));
  386. + ctx.eq_complete = FALSE;
  387. +
  388. + splay_tree_foreach (action_list->tree, map_action_fn, &ctx);
  389. + action_list->map = ctx.map;
  390. }
  391. static int
  392. @@ -5754,28 +5798,26 @@ offset_with_removed_text_map (text_action_list *action_list, bfd_vma offset)
  393. static text_action *
  394. find_insn_action (text_action_list *action_list, bfd_vma offset)
  395. {
  396. - text_action *t;
  397. - for (t = action_list->head; t; t = t->next)
  398. + static const text_action_t action[] =
  399. {
  400. - if (t->offset == offset)
  401. - {
  402. - switch (t->action)
  403. - {
  404. - case ta_none:
  405. - case ta_fill:
  406. - break;
  407. - case ta_remove_insn:
  408. - case ta_remove_longcall:
  409. - case ta_convert_longcall:
  410. - case ta_narrow_insn:
  411. - case ta_widen_insn:
  412. - return t;
  413. - case ta_remove_literal:
  414. - case ta_add_literal:
  415. - BFD_ASSERT (0);
  416. - break;
  417. - }
  418. - }
  419. + ta_convert_longcall,
  420. + ta_remove_longcall,
  421. + ta_widen_insn,
  422. + ta_narrow_insn,
  423. + ta_remove_insn,
  424. + };
  425. + text_action a;
  426. + unsigned i;
  427. +
  428. + a.offset = offset;
  429. + for (i = 0; i < sizeof (action) / sizeof (*action); ++i)
  430. + {
  431. + splay_tree_node node;
  432. +
  433. + a.action = action[i];
  434. + node = splay_tree_lookup (action_list->tree, (splay_tree_key)&a);
  435. + if (node)
  436. + return (text_action *)node->value;
  437. }
  438. return NULL;
  439. }
  440. @@ -5784,40 +5826,50 @@ find_insn_action (text_action_list *action_list, bfd_vma offset)
  441. #if DEBUG
  442. static void
  443. -print_action_list (FILE *fp, text_action_list *action_list)
  444. +print_action (FILE *fp, text_action *r)
  445. +{
  446. + const char *t = "unknown";
  447. + switch (r->action)
  448. + {
  449. + case ta_remove_insn:
  450. + t = "remove_insn"; break;
  451. + case ta_remove_longcall:
  452. + t = "remove_longcall"; break;
  453. + case ta_convert_longcall:
  454. + t = "convert_longcall"; break;
  455. + case ta_narrow_insn:
  456. + t = "narrow_insn"; break;
  457. + case ta_widen_insn:
  458. + t = "widen_insn"; break;
  459. + case ta_fill:
  460. + t = "fill"; break;
  461. + case ta_none:
  462. + t = "none"; break;
  463. + case ta_remove_literal:
  464. + t = "remove_literal"; break;
  465. + case ta_add_literal:
  466. + t = "add_literal"; break;
  467. + }
  468. +
  469. + fprintf (fp, "%s: %s[0x%lx] \"%s\" %d\n",
  470. + r->sec->owner->filename,
  471. + r->sec->name, (unsigned long) r->offset, t, r->removed_bytes);
  472. +}
  473. +
  474. +static int
  475. +print_action_list_fn (splay_tree_node node, void *p)
  476. {
  477. - text_action *r;
  478. + text_action *r = (text_action *)node->value;
  479. - fprintf (fp, "Text Action\n");
  480. - for (r = action_list->head; r != NULL; r = r->next)
  481. - {
  482. - const char *t = "unknown";
  483. - switch (r->action)
  484. - {
  485. - case ta_remove_insn:
  486. - t = "remove_insn"; break;
  487. - case ta_remove_longcall:
  488. - t = "remove_longcall"; break;
  489. - case ta_convert_longcall:
  490. - t = "convert_longcall"; break;
  491. - case ta_narrow_insn:
  492. - t = "narrow_insn"; break;
  493. - case ta_widen_insn:
  494. - t = "widen_insn"; break;
  495. - case ta_fill:
  496. - t = "fill"; break;
  497. - case ta_none:
  498. - t = "none"; break;
  499. - case ta_remove_literal:
  500. - t = "remove_literal"; break;
  501. - case ta_add_literal:
  502. - t = "add_literal"; break;
  503. - }
  504. + print_action (p, r);
  505. + return 0;
  506. +}
  507. - fprintf (fp, "%s: %s[0x%lx] \"%s\" %d\n",
  508. - r->sec->owner->filename,
  509. - r->sec->name, (unsigned long) r->offset, t, r->removed_bytes);
  510. - }
  511. +static void
  512. +print_action_list (FILE *fp, text_action_list *action_list)
  513. +{
  514. + fprintf (fp, "Text Action\n");
  515. + splay_tree_foreach (action_list->tree, print_action_list_fn, fp);
  516. }
  517. #endif /* DEBUG */
  518. @@ -6071,8 +6123,8 @@ init_xtensa_relax_info (asection *sec)
  519. relax_info->removed_list.head = NULL;
  520. relax_info->removed_list.tail = NULL;
  521. - relax_info->action_list.head = NULL;
  522. -
  523. + relax_info->action_list.tree = splay_tree_new (text_action_compare,
  524. + NULL, NULL);
  525. relax_info->action_list.map.n_entries = 0;
  526. relax_info->action_list.map.entry = NULL;
  527. @@ -7762,7 +7814,7 @@ compute_text_actions (bfd *abfd,
  528. free_reloc_range_list (&relevant_relocs);
  529. #if DEBUG
  530. - if (relax_info->action_list.head)
  531. + if (action_list_count (&relax_info->action_list))
  532. print_action_list (stderr, &relax_info->action_list);
  533. #endif
  534. @@ -8263,6 +8315,54 @@ xlate_offset_with_removed_text (const xlate_map_t *map,
  535. return e->new_address - e->orig_address + offset;
  536. }
  537. +typedef struct xlate_map_context_struct xlate_map_context;
  538. +struct xlate_map_context_struct
  539. +{
  540. + xlate_map_t *map;
  541. + xlate_map_entry_t *current_entry;
  542. + int removed;
  543. +};
  544. +
  545. +static int
  546. +xlate_map_fn (splay_tree_node node, void *p)
  547. +{
  548. + text_action *r = (text_action *)node->value;
  549. + xlate_map_context *ctx = p;
  550. + unsigned orig_size = 0;
  551. +
  552. + switch (r->action)
  553. + {
  554. + case ta_none:
  555. + case ta_remove_insn:
  556. + case ta_convert_longcall:
  557. + case ta_remove_literal:
  558. + case ta_add_literal:
  559. + break;
  560. + case ta_remove_longcall:
  561. + orig_size = 6;
  562. + break;
  563. + case ta_narrow_insn:
  564. + orig_size = 3;
  565. + break;
  566. + case ta_widen_insn:
  567. + orig_size = 2;
  568. + break;
  569. + case ta_fill:
  570. + break;
  571. + }
  572. + ctx->current_entry->size =
  573. + r->offset + orig_size - ctx->current_entry->orig_address;
  574. + if (ctx->current_entry->size != 0)
  575. + {
  576. + ctx->current_entry++;
  577. + ctx->map->entry_count++;
  578. + }
  579. + ctx->current_entry->orig_address = r->offset + orig_size;
  580. + ctx->removed += r->removed_bytes;
  581. + ctx->current_entry->new_address = r->offset + orig_size - ctx->removed;
  582. + ctx->current_entry->size = 0;
  583. + return 0;
  584. +}
  585. /* Build a binary searchable offset translation map from a section's
  586. action list. */
  587. @@ -8270,75 +8370,40 @@ xlate_offset_with_removed_text (const xlate_map_t *map,
  588. static xlate_map_t *
  589. build_xlate_map (asection *sec, xtensa_relax_info *relax_info)
  590. {
  591. - xlate_map_t *map = (xlate_map_t *) bfd_malloc (sizeof (xlate_map_t));
  592. text_action_list *action_list = &relax_info->action_list;
  593. unsigned num_actions = 0;
  594. - text_action *r;
  595. - int removed;
  596. - xlate_map_entry_t *current_entry;
  597. + xlate_map_context ctx;
  598. - if (map == NULL)
  599. + ctx.map = (xlate_map_t *) bfd_malloc (sizeof (xlate_map_t));
  600. +
  601. + if (ctx.map == NULL)
  602. return NULL;
  603. num_actions = action_list_count (action_list);
  604. - map->entry = (xlate_map_entry_t *)
  605. + ctx.map->entry = (xlate_map_entry_t *)
  606. bfd_malloc (sizeof (xlate_map_entry_t) * (num_actions + 1));
  607. - if (map->entry == NULL)
  608. + if (ctx.map->entry == NULL)
  609. {
  610. - free (map);
  611. + free (ctx.map);
  612. return NULL;
  613. }
  614. - map->entry_count = 0;
  615. + ctx.map->entry_count = 0;
  616. - removed = 0;
  617. - current_entry = &map->entry[0];
  618. + ctx.removed = 0;
  619. + ctx.current_entry = &ctx.map->entry[0];
  620. - current_entry->orig_address = 0;
  621. - current_entry->new_address = 0;
  622. - current_entry->size = 0;
  623. + ctx.current_entry->orig_address = 0;
  624. + ctx.current_entry->new_address = 0;
  625. + ctx.current_entry->size = 0;
  626. - for (r = action_list->head; r != NULL; r = r->next)
  627. - {
  628. - unsigned orig_size = 0;
  629. - switch (r->action)
  630. - {
  631. - case ta_none:
  632. - case ta_remove_insn:
  633. - case ta_convert_longcall:
  634. - case ta_remove_literal:
  635. - case ta_add_literal:
  636. - break;
  637. - case ta_remove_longcall:
  638. - orig_size = 6;
  639. - break;
  640. - case ta_narrow_insn:
  641. - orig_size = 3;
  642. - break;
  643. - case ta_widen_insn:
  644. - orig_size = 2;
  645. - break;
  646. - case ta_fill:
  647. - break;
  648. - }
  649. - current_entry->size =
  650. - r->offset + orig_size - current_entry->orig_address;
  651. - if (current_entry->size != 0)
  652. - {
  653. - current_entry++;
  654. - map->entry_count++;
  655. - }
  656. - current_entry->orig_address = r->offset + orig_size;
  657. - removed += r->removed_bytes;
  658. - current_entry->new_address = r->offset + orig_size - removed;
  659. - current_entry->size = 0;
  660. - }
  661. + splay_tree_foreach (action_list->tree, xlate_map_fn, &ctx);
  662. - current_entry->size = (bfd_get_section_limit (sec->owner, sec)
  663. - - current_entry->orig_address);
  664. - if (current_entry->size != 0)
  665. - map->entry_count++;
  666. + ctx.current_entry->size = (bfd_get_section_limit (sec->owner, sec)
  667. + - ctx.current_entry->orig_address);
  668. + if (ctx.current_entry->size != 0)
  669. + ctx.map->entry_count++;
  670. - return map;
  671. + return ctx.map;
  672. }
  673. @@ -9302,6 +9367,16 @@ move_shared_literal (asection *sec,
  674. /* Second relaxation pass. */
  675. +static int
  676. +action_remove_bytes_fn (splay_tree_node node, void *p)
  677. +{
  678. + bfd_size_type *final_size = p;
  679. + text_action *action = (text_action *)node->value;
  680. +
  681. + *final_size -= action->removed_bytes;
  682. + return 0;
  683. +}
  684. +
  685. /* Modify all of the relocations to point to the right spot, and if this
  686. is a relaxable section, delete the unwanted literals and fix the
  687. section size. */
  688. @@ -9334,7 +9409,7 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info)
  689. internal_relocs = retrieve_internal_relocs (abfd, sec,
  690. link_info->keep_memory);
  691. - if (!internal_relocs && !relax_info->action_list.head)
  692. + if (!internal_relocs && !action_list_count (&relax_info->action_list))
  693. return TRUE;
  694. contents = retrieve_contents (abfd, sec, link_info->keep_memory);
  695. @@ -9412,6 +9487,12 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info)
  696. }
  697. /* Update the action so that the code that moves
  698. the contents will do the right thing. */
  699. + /* ta_remove_longcall and ta_remove_insn actions are
  700. + grouped together in the tree as well as
  701. + ta_convert_longcall and ta_none, so that changes below
  702. + can be done w/o removing and reinserting action into
  703. + the tree. */
  704. +
  705. if (action->action == ta_remove_longcall)
  706. action->action = ta_remove_insn;
  707. else
  708. @@ -9584,13 +9665,12 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info)
  709. if ((relax_info->is_relaxable_literal_section
  710. || relax_info->is_relaxable_asm_section)
  711. - && relax_info->action_list.head)
  712. + && action_list_count (&relax_info->action_list))
  713. {
  714. /* Walk through the planned actions and build up a table
  715. of move, copy and fill records. Use the move, copy and
  716. fill records to perform the actions once. */
  717. - int removed = 0;
  718. bfd_size_type final_size, copy_size, orig_insn_size;
  719. bfd_byte *scratch = NULL;
  720. bfd_byte *dup_contents = NULL;
  721. @@ -9601,15 +9681,12 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info)
  722. bfd_vma orig_dot_vo = 0; /* Virtual offset from orig_dot. */
  723. bfd_vma dup_dot = 0;
  724. - text_action *action = relax_info->action_list.head;
  725. + text_action *action;
  726. final_size = sec->size;
  727. - for (action = relax_info->action_list.head; action;
  728. - action = action->next)
  729. - {
  730. - final_size -= action->removed_bytes;
  731. - }
  732. + splay_tree_foreach (relax_info->action_list.tree,
  733. + action_remove_bytes_fn, &final_size);
  734. scratch = (bfd_byte *) bfd_zmalloc (final_size);
  735. dup_contents = (bfd_byte *) bfd_zmalloc (final_size);
  736. @@ -9618,8 +9695,8 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info)
  737. print_action_list (stderr, &relax_info->action_list);
  738. #endif
  739. - for (action = relax_info->action_list.head; action;
  740. - action = action->next)
  741. + for (action = action_first (&relax_info->action_list); action;
  742. + action = action_next (&relax_info->action_list, action))
  743. {
  744. virtual_action = FALSE;
  745. if (action->offset > orig_dot)
  746. @@ -9748,7 +9825,6 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info)
  747. break;
  748. }
  749. - removed += action->removed_bytes;
  750. BFD_ASSERT (dup_dot <= final_size);
  751. BFD_ASSERT (orig_dot <= orig_size);
  752. }
  753. --
  754. 1.8.1.4