Optimise away eh_frame advance_loc 0
authorAlan Modra <amodra@gmail.com>
Sat, 26 Oct 2019 08:08:26 +0000 (18:38 +1030)
committerAlan Modra <amodra@gmail.com>
Sat, 26 Oct 2019 09:49:28 +0000 (20:19 +1030)
These can be generated when multiple cfi directives are emitted for an
instruction and the insn frag is closed off between directives, as
happens when listings are enabled.  No doubt the advance_loc of zero
could be avoided by backtracking over frags in dw2gencfi.c before
calling cfi_add_advance_loc, but that seems like more work than
cleaning up afterwards as this patch does.

Noticed when looking at the testcase in PR25125.

PR 25125
* dw2gencfi.c (output_cfi_insn): Don't output DW_CFA_advance_loc+0.
* ehopt.c (eh_frame_estimate_size_before_relax): Return -1 for
an advance_loc of zero.
(eh_frame_relax_frag): Translate fr_subtype of 7 to size -1.
(eh_frame_convert_frag): Handle fr_subtype of 7.  Abort on
unexpected fr_subtype.

gas/ChangeLog
gas/dw2gencfi.c
gas/ehopt.c

index 8b78037430555b011d1fef184bae380076a6145c..f900c26af450900e6c5d8361084f6064927c40d1 100644 (file)
@@ -1,3 +1,13 @@
+2019-10-26  Alan Modra  <amodra@gmail.com>
+
+       PR 25125
+       * dw2gencfi.c (output_cfi_insn): Don't output DW_CFA_advance_loc+0.
+       * ehopt.c (eh_frame_estimate_size_before_relax): Return -1 for
+       an advance_loc of zero.
+       (eh_frame_relax_frag): Translate fr_subtype of 7 to size -1.
+       (eh_frame_convert_frag): Handle fr_subtype of 7.  Abort on
+       unexpected fr_subtype.
+
 2019-10-25  Alan Modra  <amodra@gmail.com>
 
        PR gas/25125
index 388123fd2410f64546df069cf1cf0bb424fd3a8d..b01e4c4a9eda2e09008bd1683c851408258c21df 100644 (file)
@@ -1598,7 +1598,9 @@ output_cfi_insn (struct cfi_insn_data *insn)
            addressT delta = S_GET_VALUE (to) - S_GET_VALUE (from);
            addressT scaled = delta / DWARF2_LINE_MIN_INSN_LENGTH;
 
-           if (scaled <= 0x3F)
+           if (scaled == 0)
+             ;
+           else if (scaled <= 0x3F)
              out_one (DW_CFA_advance_loc + scaled);
            else if (scaled <= 0xFF)
              {
index 207e7994059140bf9377f329b75c4b2bf1f8f73a..bf65602f533558f070d772e5e4364da6431787b8 100644 (file)
@@ -482,7 +482,9 @@ eh_frame_estimate_size_before_relax (fragS *frag)
 
   gas_assert (ca > 0);
   diff /= ca;
-  if (diff < 0x40)
+  if (diff == 0)
+    ret = -1;
+  else if (diff < 0x40)
     ret = 0;
   else if (diff < 0x100)
     ret = 1;
@@ -491,7 +493,7 @@ eh_frame_estimate_size_before_relax (fragS *frag)
   else
     ret = 4;
 
-  frag->fr_subtype = (frag->fr_subtype & ~7) | ret;
+  frag->fr_subtype = (frag->fr_subtype & ~7) | (ret & 7);
 
   return ret;
 }
@@ -506,6 +508,8 @@ eh_frame_relax_frag (fragS *frag)
   int oldsize, newsize;
 
   oldsize = frag->fr_subtype & 7;
+  if (oldsize == 7)
+    oldsize = -1;
   newsize = eh_frame_estimate_size_before_relax (frag);
   return newsize - oldsize;
 }
@@ -548,9 +552,17 @@ eh_frame_convert_frag (fragS *frag)
       md_number_to_chars (frag->fr_literal + frag->fr_fix, diff, 2);
       break;
 
-    default:
+    case 4:
       md_number_to_chars (frag->fr_literal + frag->fr_fix, diff, 4);
       break;
+
+    case 7:
+      gas_assert (diff == 0);
+      frag->fr_fix -= 8;
+      break;
+
+    default:
+      abort ();
     }
 
   frag->fr_fix += frag->fr_subtype & 7;