This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: [PATCH] gas: xtensa: limit size of auto litpools
- From: Max Filippov <jcmvbkbc at gmail dot com>
- To: binutils at sourceware dot org
- Cc: Sterling Augustine <augustine dot sterling at gmail dot com>, linux-xtensa at linux-xtensa dot org, Max Filippov <jcmvbkbc at gmail dot com>
- Date: Tue, 20 Feb 2018 11:15:36 -0800
- Subject: Re: [PATCH] gas: xtensa: limit size of auto litpools
- Authentication-results: sourceware.org; auth=none
- References: <1518394719-6457-1-git-send-email-jcmvbkbc@gmail.com>
On Sun, Feb 11, 2018 at 4:18 PM, Max Filippov <jcmvbkbc@gmail.com> wrote:
> 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.
Ping?
> gas/
> 2018-02-08 Max Filippov <jcmvbkbc@gmail.com>
>
> * 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.
> ---
> gas/config/tc-xtensa.c | 119 +++++++++++++++++++----------
> gas/testsuite/gas/xtensa/all.exp | 1 +
> gas/testsuite/gas/xtensa/auto-litpools-2.d | 6 ++
> gas/testsuite/gas/xtensa/auto-litpools-2.s | 9 +++
> gas/testsuite/gas/xtensa/auto-litpools.d | 4 +-
> gas/testsuite/gas/xtensa/auto-litpools.s | 2 +-
> 6 files changed, 96 insertions(+), 45 deletions(-)
> create mode 100644 gas/testsuite/gas/xtensa/auto-litpools-2.d
> create mode 100644 gas/testsuite/gas/xtensa/auto-litpools-2.s
>
> diff --git a/gas/config/tc-xtensa.c b/gas/config/tc-xtensa.c
> index 1dbb73aa55c7..74a55019bdd9 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;
> }
> @@ -11187,6 +11199,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)
> {
> @@ -11244,49 +11316,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 c0dd8a5fa025..650a93223d46 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 000000000000..d153c2bdac95
> --- /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 000000000000..30b1383d009c
> --- /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 fc6f5cbbc308..8eadd1f08cf6 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 9a5b26ba16c9..aa4241533027 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
> --
> 2.1.4
>
--
Thanks.
-- Max