From: Max Filippov Date: Thu, 8 Feb 2018 18:28:52 +0000 (-0800) Subject: gas: xtensa: limit size of auto litpools X-Git-Url: http://git.efficios.com/?a=commitdiff_plain;h=cd665a945eccba1406696c65ac7eebb12a355446;p=deliverable%2Fbinutils-gdb.git gas: xtensa: limit size of auto litpools Literal movement code may grow auto litpool so big that it won't be possible to jump around it. Limit the size of auto litpools by 1/2 of the jump range. gas/ 2018-02-20 Max Filippov * config/tc-xtensa.c (struct litpool_frag): Add new field literal_count. (MAX_AUTO_POOL_LITERALS, MAX_EXPLICIT_POOL_LITERALS) (MAX_POOL_LITERALS): New macro definitions. (auto_litpool_limit): Initialize to 0. (md_parse_option): Set auto_litpool_limit in the presence of --auto-litpools option. (xtensa_maybe_create_literal_pool_frag): Zero-initialize literal_count field. (xg_find_litpool): New function. Make sure that found literal pool size is within the limit. (xtensa_move_literals): Extract literal pool search code into the new function. * testsuite/gas/xtensa/all.exp: Add auto-litpools-2 test. * testsuite/gas/xtensa/auto-litpools-2.d: New file. * testsuite/gas/xtensa/auto-litpools-2.s: New file. * testsuite/gas/xtensa/auto-litpools.d: Fix up changed addresses. * testsuite/gas/xtensa/auto-litpools.s: Change literal value so that objdump doesn't get out of sync. --- diff --git a/gas/ChangeLog b/gas/ChangeLog index 19fb02f7de..3ce6995354 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,26 @@ +2018-02-20 Max Filippov + + * config/tc-xtensa.c (struct litpool_frag): Add new field + literal_count. + (MAX_AUTO_POOL_LITERALS, MAX_EXPLICIT_POOL_LITERALS) + (MAX_POOL_LITERALS): New macro definitions. + (auto_litpool_limit): Initialize to 0. + (md_parse_option): Set auto_litpool_limit in the presence of + --auto-litpools option. + (xtensa_maybe_create_literal_pool_frag): Zero-initialize + literal_count field. + (xg_find_litpool): New function. Make sure that found literal + pool size is within the limit. + (xtensa_move_literals): Extract literal pool search code into + the new function. + * testsuite/gas/xtensa/all.exp: Add auto-litpools-2 test. + * testsuite/gas/xtensa/auto-litpools-2.d: New file. + * testsuite/gas/xtensa/auto-litpools-2.s: New file. + * testsuite/gas/xtensa/auto-litpools.d: Fix up changed + addresses. + * testsuite/gas/xtensa/auto-litpools.s: Change literal value so + that objdump doesn't get out of sync. + 2018-02-20 Thomas Preud'homme * doc/c-arm.texi (.arch_extension): Mention extensions it accepts are diff --git a/gas/config/tc-xtensa.c b/gas/config/tc-xtensa.c index b522447b51..4db7ef57e8 100644 --- a/gas/config/tc-xtensa.c +++ b/gas/config/tc-xtensa.c @@ -438,6 +438,7 @@ struct litpool_frag addressT addr; short priority; /* 1, 2, or 3 -- 1 is highest */ short original_priority; + int literal_count; }; /* Map a segment to its litpool_frag list. */ @@ -451,6 +452,14 @@ struct litpool_seg static struct litpool_seg litpool_seg_list; +/* Limit maximal size of auto litpool by half of the j range. */ +#define MAX_AUTO_POOL_LITERALS 16384 + +/* Limit maximal size of explicit literal pool by l32r range. */ +#define MAX_EXPLICIT_POOL_LITERALS 65536 + +#define MAX_POOL_LITERALS \ + (auto_litpools ? MAX_AUTO_POOL_LITERALS : MAX_EXPLICIT_POOL_LITERALS) /* Directive functions. */ @@ -488,7 +497,7 @@ static int init_trampoline_frag (fragS *); static fixS *xg_append_jump (fragS *fragP, symbolS *sym, offsetT offset); static void xtensa_maybe_create_literal_pool_frag (bfd_boolean, bfd_boolean); static bfd_boolean auto_litpools = FALSE; -static int auto_litpool_limit = 10000; +static int auto_litpool_limit = 0; /* Alignment Functions. */ @@ -984,6 +993,8 @@ md_parse_option (int c, const char *arg) case option_auto_litpools: auto_litpools = TRUE; use_literal_section = FALSE; + if (auto_litpool_limit <= 0) + auto_litpool_limit = MAX_AUTO_POOL_LITERALS / 2; return 1; case option_no_auto_litpools: @@ -7912,6 +7923,7 @@ xtensa_maybe_create_literal_pool_frag (bfd_boolean create, lpf->fragP = fragP; lpf->priority = (needed) ? (only_if_needed) ? 3 : 2 : 1; lpf->original_priority = lpf->priority; + lpf->literal_count = 0; lps->frag_count = 0; } @@ -11188,6 +11200,66 @@ xg_promote_candidate_litpool (struct litpool_seg *lps, /* Rest is done in xtensa_relax_frag. */ } +static struct litpool_frag *xg_find_litpool (struct litpool_seg *lps, + struct litpool_frag *lpf, + addressT addr) +{ + struct litpool_frag *lp = lpf->prev; + + gas_assert (lp->fragP); + + while (lp->fragP->fr_subtype == RELAX_LITERAL_POOL_CANDIDATE_BEGIN) + { + lp = lp->prev; + if (lp->fragP == NULL) + { + /* End of list; have to bite the bullet. + Take the nearest. */ + lp = lpf->prev; + break; + } + /* Does it (conservatively) reach? */ + if (addr - lp->addr <= 128 * 1024) + { + if (lp->fragP->fr_subtype == RELAX_LITERAL_POOL_BEGIN && + lp->literal_count < MAX_POOL_LITERALS) + { + /* Found a good one. */ + break; + } + else if (lp->prev->fragP && + addr - lp->prev->addr > 128 * 1024 && + lp->prev->literal_count < MAX_POOL_LITERALS) + { + /* This is still a "candidate" but the next one + will be too far away, so revert to the nearest + one, convert it and add the jump around. */ + lp = lpf->prev; + break; + } + } + } + + if (lp->literal_count >= MAX_POOL_LITERALS) + { + lp = lpf->prev; + while (lp && lp->fragP && lp->literal_count >= MAX_POOL_LITERALS) + { + lp = lp->prev; + } + gas_assert (lp); + } + + gas_assert (lp && lp->fragP && lp->literal_count < MAX_POOL_LITERALS); + ++lp->literal_count; + + /* Convert candidate and add the jump around. */ + if (lp->fragP->fr_subtype == RELAX_LITERAL_POOL_CANDIDATE_BEGIN) + xg_promote_candidate_litpool (lps, lp); + + return lp; +} + static void xtensa_move_literals (void) { @@ -11245,49 +11317,12 @@ xtensa_move_literals (void) preferring non-"candidate" positions to avoid the jump-around. */ fragS *litfrag = fragP->tc_frag_data.literal_frags[slot]; - struct litpool_frag *lp = lpf->prev; - if (!lp->fragP) - { - break; - } - while (lp->fragP->fr_subtype == - RELAX_LITERAL_POOL_CANDIDATE_BEGIN) - { - lp = lp->prev; - if (lp->fragP == NULL) - { - /* End of list; have to bite the bullet. - Take the nearest. */ - lp = lpf->prev; - break; - } - /* Does it (conservatively) reach? */ - if (addr - lp->addr <= 128 * 1024) - { - if (lp->fragP->fr_subtype == RELAX_LITERAL_POOL_BEGIN) - { - /* Found a good one. */ - break; - } - else if (lp->prev->fragP && - addr - lp->prev->addr > 128 * 1024) - { - /* This is still a "candidate" but the next one - will be too far away, so revert to the nearest - one, convert it and add the jump around. */ - lp = lpf->prev; - break; - } - } - } - /* Convert candidate and add the jump around. */ - if (lp->fragP->fr_subtype == - RELAX_LITERAL_POOL_CANDIDATE_BEGIN) - xg_promote_candidate_litpool (lps, lp); - - if (! litfrag->tc_frag_data.literal_frag) + if (!litfrag->tc_frag_data.literal_frag) { + struct litpool_frag *lp; + + lp = xg_find_litpool (lps, lpf, addr); /* Take earliest use of this literal to avoid forward refs. */ litfrag->tc_frag_data.literal_frag = lp->fragP; diff --git a/gas/testsuite/gas/xtensa/all.exp b/gas/testsuite/gas/xtensa/all.exp index c0dd8a5fa0..650a93223d 100644 --- a/gas/testsuite/gas/xtensa/all.exp +++ b/gas/testsuite/gas/xtensa/all.exp @@ -102,6 +102,7 @@ if [istarget xtensa*-*-*] then { run_list_test "trampoline-2" run_dump_test "first_frag_align" run_dump_test "auto-litpools" + run_dump_test "auto-litpools-2" run_dump_test "auto-litpools-first1" run_dump_test "auto-litpools-first2" run_dump_test "loc" diff --git a/gas/testsuite/gas/xtensa/auto-litpools-2.d b/gas/testsuite/gas/xtensa/auto-litpools-2.d new file mode 100644 index 0000000000..d153c2bdac --- /dev/null +++ b/gas/testsuite/gas/xtensa/auto-litpools-2.d @@ -0,0 +1,6 @@ +#as: --auto-litpools +#objdump: -d +#name: auto litpool size limitation + +.*: +file format .*xtensa.* +#... diff --git a/gas/testsuite/gas/xtensa/auto-litpools-2.s b/gas/testsuite/gas/xtensa/auto-litpools-2.s new file mode 100644 index 0000000000..30b1383d00 --- /dev/null +++ b/gas/testsuite/gas/xtensa/auto-litpools-2.s @@ -0,0 +1,9 @@ + .text + .global _start +_start: + j 1f + .rep 33000 + movi a2, 0xf03df03d + .endr +1: + ret diff --git a/gas/testsuite/gas/xtensa/auto-litpools.d b/gas/testsuite/gas/xtensa/auto-litpools.d index fc6f5cbbc3..8eadd1f08c 100644 --- a/gas/testsuite/gas/xtensa/auto-litpools.d +++ b/gas/testsuite/gas/xtensa/auto-litpools.d @@ -6,7 +6,7 @@ #... .*8:.*l32r.a2, 4 .* #... -.*3e43b:.*j.3e444 .* +.*3f029:.*j.3f030 .* #... -.*40754:.*l32r.a2, 3e440 .* +.*40752:.*l32r.a2, 3f02c .* #... diff --git a/gas/testsuite/gas/xtensa/auto-litpools.s b/gas/testsuite/gas/xtensa/auto-litpools.s index 9a5b26ba16..aa42415330 100644 --- a/gas/testsuite/gas/xtensa/auto-litpools.s +++ b/gas/testsuite/gas/xtensa/auto-litpools.s @@ -1,7 +1,7 @@ .text .align 4 .literal .L0, 0x12345 - .literal .L1, 0x12345 + .literal .L1, 0x78f078f0 f: l32r a2, .L0