[PATCH v3 3/3] RISCV: Add --defer-deletion flag

Patrick O'Neill patrick@rivosinc.com
Fri May 27 21:20:05 GMT 2022


Previously the linker failed to relax only the backwards case (where a
relaxation enables another relaxation that has already been checked).
With patches 1-4, the behavior has been changed to fail in both the
forward and backwards case. It's possible that this will lead to worse
performance, so the --no-defer-deletion flag allows you to use the
non-linear immediate deletion method.
By default, the linear deletion method is enabled as this is expected to
be more performant.

2022-05-27 Patrick O'Neill <patrick@rivosinc.com>

	* elfnn-riscv.c: Pass flag to deletion function to immediately
	  delete bytes (or not).
	* bfdlink.h: Add delete_immediately flag.
	* ld/ld.texi: Document the new --defer-deletion flag.
	* ld/ldlex.h: Add DEFER_DELETION and NO_DEFER_DELETION options.
	* ld/lexsup.c: Parse --defer-deletion and --no-defer-deletion
	  flags.

Signed-off-by: Patrick O'Neill <patrick@rivosinc.com>
---
I think that there may be a better way to phrase the --defer-deletion
flag. I'm also unsure if this is the correct way of expressing
a target-specific linker flag.
---
v2 Changelog:
- This is a new patch.
---
v3 Changelog:
- Rebase with changes to elfnn-riscv.c from patch 2/3.
---
 bfd/elfnn-riscv.c | 12 ++++++++----
 include/bfdlink.h |  4 ++++
 ld/ld.texi        | 10 ++++++++++
 ld/ldlex.h        |  2 ++
 ld/lexsup.c       | 10 ++++++++++
 5 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c
index 4b6ea179442..0a750773d47 100644
--- a/bfd/elfnn-riscv.c
+++ b/bfd/elfnn-riscv.c
@@ -4324,7 +4324,8 @@ _bfd_riscv_relax_call (bfd *abfd, asection *sec, asection *sym_sec,
   /* Delete unnecessary JALR.  */
   *again = true;
   return riscv_relax_delete_bytes (abfd, sec, rel->r_offset + len, 8 - len,
-				   rel + 1, link_info, pcgp_relocs, true);
+				   rel + 1, link_info, pcgp_relocs,
+				   !link_info->immediate_deletion);
 }
 
 /* Traverse all output sections and return the max alignment.  */
@@ -4417,7 +4418,8 @@ _bfd_riscv_relax_lui (bfd *abfd,
 	  /* We can delete the unnecessary LUI and reuse the reloc.  */
 	  *again = true;
 	  return riscv_relax_delete_bytes (abfd, sec, rel->r_offset, 4, rel,
-					   link_info, pcgp_relocs, true);
+					   link_info, pcgp_relocs,
+					   !link_info->immediate_deletion);
 
 	default:
 	  abort ();
@@ -4450,7 +4452,8 @@ _bfd_riscv_relax_lui (bfd *abfd,
 
       *again = true;
       return riscv_relax_delete_bytes (abfd, sec, rel->r_offset + 2, 2, rel + 1,
-				       link_info, pcgp_relocs, true);
+				       link_info, pcgp_relocs,
+				       !link_info->immediate_deletion);
     }
 
   return true;
@@ -4492,7 +4495,8 @@ _bfd_riscv_relax_tls_le (bfd *abfd,
       rel->r_info = ELFNN_R_INFO (0, R_RISCV_NONE);
       *again = true;
       return riscv_relax_delete_bytes (abfd, sec, rel->r_offset, 4, rel,
-				       link_info, pcgp_relocs, true);
+				       link_info, pcgp_relocs,
+				       !link_info->immediate_deletion);
 
     default:
       abort ();
diff --git a/include/bfdlink.h b/include/bfdlink.h
index 09a3ec01685..f6c87fbe911 100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -587,6 +587,10 @@ struct bfd_link_info
        args_type structure in ldmain.c:main.  */
   signed int disable_target_specific_optimizations;
 
+  /* Enable or disable deferred deletion of linker relaxations.
+     This option is enabled my default.  */
+  unsigned int immediate_deletion: 1;
+
   /* Function callbacks.  */
   const struct bfd_link_callbacks *callbacks;
 
diff --git a/ld/ld.texi b/ld/ld.texi
index eabbec8faa9..c536eed4162 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -2186,6 +2186,16 @@ This option is ignored for Linux compatibility.
 @item -Qy
 This option is ignored for SVR4 compatibility.
 
+@cindex defer relaxation deletion
+@kindex --defer-relaxation-deletions
+@kindex --no-defer-relaxation-deletions
+@item --defer-relaxation-deletions
+@itemx --no-defer-relaxation-deletions
+Enable (or don't enable) linear time linker relaxations by deferring byte
+deletion. This assumes the pathologial case is rare. If the pathological case
+is common, disabling linear linking will improve performance.
+Default to linear time linker relaxation.
+
 @kindex --relax
 @cindex synthesizing linker
 @cindex relaxing addressing modes
diff --git a/ld/ldlex.h b/ld/ldlex.h
index 57ade1f754b..ce9f5d5aafe 100644
--- a/ld/ldlex.h
+++ b/ld/ldlex.h
@@ -54,6 +54,8 @@ enum option_values
   OPTION_OFORMAT,
   OPTION_RELAX,
   OPTION_NO_RELAX,
+  OPTION_DEFER_DELETION,
+  OPTION_NO_DEFER_DELETION,
   OPTION_NO_SYMBOLIC,
   OPTION_RETAIN_SYMBOLS_FILE,
   OPTION_RPATH,
diff --git a/ld/lexsup.c b/ld/lexsup.c
index 9225f71b3ce..1a0d9a31fef 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -442,6 +442,10 @@ static const struct ld_option ld_options[] =
     '\0', NULL, N_("Reduce code size by using target specific optimizations"), TWO_DASHES },
   { {"no-relax", no_argument, NULL, OPTION_NO_RELAX},
     '\0', NULL, N_("Do not use relaxation techniques to reduce code size"), TWO_DASHES },
+  { {"defer-deletion", no_argument, NULL, OPTION_DEFER_DELETION},
+    '\0', NULL, N_("Defer deletions caused by linker relaxation"), TWO_DASHES },
+  { {"no-defer-deletion", no_argument, NULL, OPTION_NO_DEFER_DELETION},
+    '\0', NULL, N_("Do not defer deletions caused by linker relaxation"), TWO_DASHES },
   { {"retain-symbols-file", required_argument, NULL,
      OPTION_RETAIN_SYMBOLS_FILE},
     '\0', N_("FILE"), N_("Keep only symbols listed in FILE"), TWO_DASHES },
@@ -935,6 +939,12 @@ parse_args (unsigned argc, char **argv)
 	case OPTION_NO_WARN_RWX_SEGMENTS:
 	  link_info.no_warn_rwx_segments = 1;
 	  break;
+	case OPTION_DEFER_DELETION:
+	  link_info.immediate_deletion = false;
+	  break;
+	case OPTION_NO_DEFER_DELETION:
+	  link_info.immediate_deletion = true;
+	  break;
 	case 'e':
 	  lang_add_entry (optarg, true);
 	  break;
-- 
2.25.1



More information about the Binutils mailing list