break;
 
        case R_PPC64_GOT16_DS:
-         if ((h ? h->elf.type : ELF_ST_TYPE (sym->st_info)) == STT_GNU_IFUNC)
+         if ((h ? h->elf.type : ELF_ST_TYPE (sym->st_info)) == STT_GNU_IFUNC
+             || !htab->do_toc_opt)
            break;
          from = TOCstart + htab->sec_info[input_section->id].toc_off;
          if (relocation + addend - from + 0x8000 < 0x10000
 
        case R_PPC64_GOT16_LO_DS:
        case R_PPC64_GOT16_HA:
-         if ((h ? h->elf.type : ELF_ST_TYPE (sym->st_info)) == STT_GNU_IFUNC)
+         if ((h ? h->elf.type : ELF_ST_TYPE (sym->st_info)) == STT_GNU_IFUNC
+             || !htab->do_toc_opt)
            break;
          from = TOCstart + htab->sec_info[input_section->id].toc_off;
          if (relocation + addend - from + 0x80008000ULL < 0x100000000ULL
          break;
 
        case R_PPC64_GOT_PCREL34:
-         if ((h ? h->elf.type : ELF_ST_TYPE (sym->st_info)) == STT_GNU_IFUNC)
+         if ((h ? h->elf.type : ELF_ST_TYPE (sym->st_info)) == STT_GNU_IFUNC
+             || !htab->do_toc_opt)
            break;
          from = (rel->r_offset
                  + input_section->output_section->vma
                  + input_section->output_offset);
-         if (relocation - from + (1ULL << 33) < 1ULL << 34
-             && SYMBOL_REFERENCES_LOCAL (info, &h->elf))
-           {
-             offset = rel->r_offset;
-             pinsn = bfd_get_32 (input_bfd, contents + offset);
-             pinsn <<= 32;
-             pinsn |= bfd_get_32 (input_bfd, contents + offset + 4);
-             if ((pinsn & ((-1ULL << 50) | (63ULL << 26)))
-                  == ((1ULL << 58) | (1ULL << 52) | (57ULL << 26) /* pld */))
-               {
-                 /* Replace with paddi.  */
-                 pinsn += (2ULL << 56) + (14ULL << 26) - (57ULL << 26);
-                 r_type = R_PPC64_PCREL34;
-                 rel->r_info = ELF64_R_INFO (r_symndx, r_type);
-                 bfd_put_32 (input_bfd, pinsn >> 32, contents + offset);
-                 bfd_put_32 (input_bfd, pinsn, contents + offset + 4);
-                 goto pcrelopt;
-               }
-           }
-         break;
+         if (!(relocation - from + (1ULL << 33) < 1ULL << 34
+               && SYMBOL_REFERENCES_LOCAL (info, &h->elf)))
+           break;
+
+         offset = rel->r_offset;
+         pinsn = bfd_get_32 (input_bfd, contents + offset);
+         pinsn <<= 32;
+         pinsn |= bfd_get_32 (input_bfd, contents + offset + 4);
+         if ((pinsn & ((-1ULL << 50) | (63ULL << 26)))
+             != ((1ULL << 58) | (1ULL << 52) | (57ULL << 26) /* pld */))
+           break;
+
+         /* Replace with paddi.  */
+         pinsn += (2ULL << 56) + (14ULL << 26) - (57ULL << 26);
+         r_type = R_PPC64_PCREL34;
+         rel->r_info = ELF64_R_INFO (r_symndx, r_type);
+         bfd_put_32 (input_bfd, pinsn >> 32, contents + offset);
+         bfd_put_32 (input_bfd, pinsn, contents + offset + 4);
+         /* Fall through.  */
 
        case R_PPC64_PCREL34:
-         if (SYMBOL_REFERENCES_LOCAL (info, &h->elf))
+         if (!htab->params->no_pcrel_opt
+             && rel + 1 < relend
+             && rel[1].r_offset == rel->r_offset
+             && rel[1].r_info == ELF64_R_INFO (0, R_PPC64_PCREL_OPT)
+             && SYMBOL_REFERENCES_LOCAL (info, &h->elf))
            {
              offset = rel->r_offset;
              pinsn = bfd_get_32 (input_bfd, contents + offset);
                   == ((1ULL << 58) | (2ULL << 56) | (1ULL << 52)
                       | (14ULL << 26) /* paddi */))
                {
-               pcrelopt:
-                 if (rel + 1 < relend
-                     && rel[1].r_offset == offset
-                     && rel[1].r_info == ELF64_R_INFO (0, R_PPC64_PCREL_OPT))
+                 bfd_vma off2 = rel[1].r_addend;
+                 if (off2 == 0)
+                   /* zero means next insn.  */
+                   off2 = 8;
+                 off2 += offset;
+                 if (off2 + 4 <= input_section->size)
                    {
-                     bfd_vma off2 = rel[1].r_addend;
-                     if (off2 == 0)
-                       /* zero means next insn.  */
-                       off2 = 8;
-                     off2 += offset;
-                     if (off2 + 4 <= input_section->size)
+                     uint64_t pinsn2;
+                     bfd_signed_vma addend_off;
+                     pinsn2 = bfd_get_32 (input_bfd, contents + off2);
+                     pinsn2 <<= 32;
+                     if ((pinsn2 & (63ULL << 58)) == 1ULL << 58)
                        {
-                         uint64_t pinsn2;
-                         bfd_signed_vma addend_off;
-                         pinsn2 = bfd_get_32 (input_bfd, contents + off2);
-                         pinsn2 <<= 32;
+                         if (off2 + 8 > input_section->size)
+                           break;
+                         pinsn2 |= bfd_get_32 (input_bfd,
+                                               contents + off2 + 4);
+                       }
+                     if (xlate_pcrel_opt (&pinsn, &pinsn2, &addend_off))
+                       {
+                         addend += addend_off;
+                         rel->r_addend = addend;
+                         bfd_put_32 (input_bfd, pinsn >> 32,
+                                     contents + offset);
+                         bfd_put_32 (input_bfd, pinsn,
+                                     contents + offset + 4);
+                         bfd_put_32 (input_bfd, pinsn2 >> 32,
+                                     contents + off2);
                          if ((pinsn2 & (63ULL << 58)) == 1ULL << 58)
-                           {
-                             if (off2 + 8 > input_section->size)
-                               break;
-                             pinsn2 |= bfd_get_32 (input_bfd,
-                                                   contents + off2 + 4);
-                           }
-                         if (xlate_pcrel_opt (&pinsn, &pinsn2, &addend_off))
-                           {
-                             addend += addend_off;
-                             rel->r_addend = addend;
-                             bfd_put_32 (input_bfd, pinsn >> 32,
-                                         contents + offset);
-                             bfd_put_32 (input_bfd, pinsn,
-                                         contents + offset + 4);
-                             bfd_put_32 (input_bfd, pinsn2 >> 32,
-                                         contents + off2);
-                             if ((pinsn2 & (63ULL << 58)) == 1ULL << 58)
-                               bfd_put_32 (input_bfd, pinsn2,
-                                           contents + off2 + 4);
-                           }
+                           bfd_put_32 (input_bfd, pinsn2,
+                                       contents + off2 + 4);
                        }
                    }
                }
 
                                          &ppc_layout_sections_again,
                                          1, -1, -1, 0,
                                          ${DEFAULT_PLT_STATIC_CHAIN-0}, -1, 5,
-                                         -1, -1, 0, -1, -1, 0};
+                                         -1, -1, 0, 0, -1, -1, 0};
 
 /* Fake input file for stubs.  */
 static lang_input_statement_type *stub_file;
   OPTION_NO_PLT_LOCALENTRY,
   OPTION_POWER10_STUBS,
   OPTION_NO_POWER10_STUBS,
+  OPTION_NO_PCREL_OPT,
   OPTION_STUBSYMS,
   OPTION_NO_STUBSYMS,
   OPTION_SAVRES,
   { "plt-localentry", optional_argument, NULL, OPTION_PLT_LOCALENTRY },
   { "no-plt-localentry", no_argument, NULL, OPTION_NO_PLT_LOCALENTRY },
   { "power10-stubs", optional_argument, NULL, OPTION_POWER10_STUBS },
+  { "no-pcrel-optimize", no_argument, NULL, OPTION_NO_PCREL_OPT },
   { "no-power10-stubs", no_argument, NULL, OPTION_NO_POWER10_STUBS },
   { "emit-stub-syms", no_argument, NULL, OPTION_STUBSYMS },
   { "no-emit-stub-syms", no_argument, NULL, OPTION_NO_STUBSYMS },
   --power10-stubs [=auto]     Use Power10 PLT call stubs (default auto)\n"
                   ));
   fprintf (file, _("\
+  --no-pcrel-optimize         Don'\''t perform R_PPC64_PCREL_OPT optimization\n"
+                  ));
+  fprintf (file, _("\
   --no-power10-stubs          Don'\''t use Power10 PLT call stubs\n"
                   ));
   fprintf (file, _("\
       params.power10_stubs = 0;
       break;
 
+    case OPTION_NO_PCREL_OPT:
+      params.no_pcrel_opt = 1;
+      break;
+
     case OPTION_STUBSYMS:
       params.emit_stub_syms = 1;
       break;
       params.no_multi_toc = 1;
       no_toc_sort = 1;
       params.plt_static_chain = 1;
+      params.no_pcrel_opt = 1;
       return FALSE;
 '