diff --git a/bfd/merge.c b/bfd/merge.c
index 25798e15cb5..8b35af7e854 100644
--- a/bfd/merge.c
+++ b/bfd/merge.c
@@ -469,6 +469,38 @@ sec_merge_init (unsigned int entsize, bool strings)
   return table;
 }
 
+/* Choose the size increment for the offset maps.  A large value means
+   that we will not have to call bfd_realloc() as many times, if we are
+   dealing with large input sections, and hence the link will be faster.
+   But a large value can also waste a lot of memory if we are dealing
+   with a big number of small input sections.  Which is a problem if we
+   are linking in an environment with a restricted amount of memory.
+   
+   FIXME: The values below are a bit arbitrary.  It would be better to
+   create a tuneable parameter that could be set by the user.  */
+#define MAP_DELTA_SMALL  1024
+#define MAP_DELTA_NORM   2048
+#define MAP_DELTA_LARGE  8192
+
+/* In order to avoid the possibility of using map_delta before it
+   has been set to a value selected by choose_map_delta() we initialise
+   it to a semi-reasonable value.  */
+#define MAP_DELTA_UNSET  4096
+static unsigned int map_delta = MAP_DELTA_UNSET;
+
+static unsigned int
+choose_map_delta (struct bfd_link_info *info)
+{
+  if (info->reduce_memory_overheads)
+    return MAP_DELTA_SMALL;
+
+  /* FIXME: The optimize flag is not really the right flag to test here.  */
+  if (info->optimize)
+    return MAP_DELTA_LARGE;
+
+  return MAP_DELTA_NORM;
+}
+
 /* Append the tuple of input-offset O corresponding
    to hash table ENTRY into SECINFO, such that we later may lookup the
    entry just by O.  */
@@ -478,10 +510,12 @@ append_offsetmap (struct sec_merge_sec_info *secinfo,
 		  mapofs_type o,
 		  struct sec_merge_hash_entry *entry)
 {
-  if ((secinfo->noffsetmap & 2047) == 0)
+  // BFD_ASSERT (map_delta != MAP_DELTA_UNSET);
+  // BFD_ASSERT (map_delta != 0);
+  if ((secinfo->noffsetmap & (map_delta - 1)) == 0)
     {
       bfd_size_type amt;
-      amt = (secinfo->noffsetmap + 2048);
+      amt = (secinfo->noffsetmap + map_delta);
       secinfo->map_ofs = bfd_realloc (secinfo->map_ofs,
 				      amt * sizeof(secinfo->map_ofs[0]));
       if (!secinfo->map_ofs)
@@ -784,7 +818,8 @@ record_section (struct sec_merge_info *sinfo,
   free (contents);
   contents = NULL;
 
-  /* We allocate the ofsmap arrays in blocks of 2048 elements.
+  /* We allocate the ofsmap arrays in blocks of map_delta elements.
+     (See choose_map_delta() above).
      In case we have very many small input files/sections,
      this might waste large amounts of memory, so reallocate these
      arrays here to their true size.  */
@@ -1066,6 +1101,9 @@ bfd_merge_sections (bfd *obfd, struct bfd_link_info *info)
   if (!obfd->xvec->merge_sections)
     return true;
 
+  if (map_delta == MAP_DELTA_UNSET)
+    map_delta = choose_map_delta (info);
+
   for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
     if ((ibfd->flags & DYNAMIC) == 0)
       for (sec = ibfd->sections; sec != NULL; sec = sec->next)
