gas: xtensa: limit size of auto litpools
authorMax Filippov <jcmvbkbc@gmail.com>
Thu, 8 Feb 2018 18:28:52 +0000 (10:28 -0800)
committerMax Filippov <jcmvbkbc@gmail.com>
Tue, 20 Feb 2018 19:49:48 +0000 (11:49 -0800)
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  <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/ChangeLog
gas/config/tc-xtensa.c
gas/testsuite/gas/xtensa/all.exp
gas/testsuite/gas/xtensa/auto-litpools-2.d [new file with mode: 0644]
gas/testsuite/gas/xtensa/auto-litpools-2.s [new file with mode: 0644]
gas/testsuite/gas/xtensa/auto-litpools.d
gas/testsuite/gas/xtensa/auto-litpools.s

index 19fb02f7dee8345b0c52de7841bf199b165b4175..3ce69953544e6e486342ddd6008225d7bcc6e2ad 100644 (file)
@@ -1,3 +1,26 @@
+2018-02-20  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.
+
 2018-02-20  Thomas Preud'homme  <thomas.preudhomme@arm.com>
 
        * doc/c-arm.texi (.arch_extension): Mention extensions it accepts are
index b522447b51313967a8e549ba21870cbb8ec7a497..4db7ef57e8f13660d23b108af4b016ebb16be9a3 100644 (file)
@@ -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;
index c0dd8a5fa025c3528852e58fab07bfad4abc4be3..650a93223d46851eb906b5158acc49e270e16b94 100644 (file)
@@ -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 (file)
index 0000000..d153c2b
--- /dev/null
@@ -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 (file)
index 0000000..30b1383
--- /dev/null
@@ -0,0 +1,9 @@
+       .text
+       .global _start
+_start:
+       j       1f
+       .rep    33000
+       movi    a2, 0xf03df03d
+       .endr
+1:
+       ret
index fc6f5cbbc308e65c8954a0112ce5ca7ae6e41fce..8eadd1f08cf6116242d5b0915462221354370733 100644 (file)
@@ -6,7 +6,7 @@
 #...
 .*8:.*l32r.a2, 4 .*
 #...
-.*3e43b:.*j.3e444 .*
+.*3f029:.*j.3f030 .*
 #...
-.*40754:.*l32r.a2, 3e440 .*
+.*40752:.*l32r.a2, 3f02c .*
 #...
index 9a5b26ba16c9f4b3168165a318d8231dcb3be0c6..aa4241533027ae569d402fb7a496dc0fed3d0891 100644 (file)
@@ -1,7 +1,7 @@
        .text
        .align  4
        .literal        .L0, 0x12345
-       .literal        .L1, 0x12345
+       .literal        .L1, 0x78f078f0
 
 f:
        l32r    a2, .L0