PR90689, ICE in extract_insn on ppc64le
[platform/upstream/gcc.git] / gcc / config / rs6000 / rs6000.c
index 9842981..95cf9d6 100644 (file)
@@ -2511,13 +2511,7 @@ rs6000_debug_reg_global (void)
           "wd reg_class = %s\n"
           "we reg_class = %s\n"
           "wf reg_class = %s\n"
-          "wg reg_class = %s\n"
-          "wh reg_class = %s\n"
           "wi reg_class = %s\n"
-          "wj reg_class = %s\n"
-          "wk reg_class = %s\n"
-          "wl reg_class = %s\n"
-          "wm reg_class = %s\n"
           "wp reg_class = %s\n"
           "wq reg_class = %s\n"
           "wr reg_class = %s\n"
@@ -2526,7 +2520,6 @@ rs6000_debug_reg_global (void)
           "wv reg_class = %s\n"
           "ww reg_class = %s\n"
           "wx reg_class = %s\n"
-          "wz reg_class = %s\n"
           "wA reg_class = %s\n"
           "\n",
           reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_d]],
@@ -2536,13 +2529,7 @@ rs6000_debug_reg_global (void)
           reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wd]],
           reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_we]],
           reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wf]],
-          reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wg]],
-          reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wh]],
           reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wi]],
-          reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wj]],
-          reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wk]],
-          reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wl]],
-          reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wm]],
           reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wp]],
           reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wq]],
           reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wr]],
@@ -2551,7 +2538,6 @@ rs6000_debug_reg_global (void)
           reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wv]],
           reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_ww]],
           reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wx]],
-          reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wz]],
           reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wA]]);
 
   nl = "\n";
@@ -3162,21 +3148,14 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
        wc - Reserved to represent individual CR bits (used in LLVM).
        wd - Preferred register class for V2DFmode.
        wf - Preferred register class for V4SFmode.
-       wg - Float register for power6x move insns.
-       wh - FP register for direct move instructions.
        wi - FP or VSX register to hold 64-bit integers for VSX insns.
-       wj - FP or VSX register to hold 64-bit integers for direct moves.
-       wk - FP or VSX register to hold 64-bit doubles for direct moves.
-       wl - Float register if we can do 32-bit signed int loads.
-       wm - VSX register for ISA 2.07 direct move operations.
        wn - always NO_REGS.
        wr - GPR if 64-bit mode is permitted.
        ws - Register class to do ISA 2.06 DF operations.
        wt - VSX register for TImode in VSX registers.
        wv - Altivec register for ISA 2.06 VSX DF/DI load/stores.
        ww - Register class to do SF conversions in with VSX operations.
-       wx - Float register if we can do 32-bit int stores.
-       wz - Float register if we can do 32-bit unsigned int loads.  */
+       wx - Float register if we can do 32-bit int stores.  */
 
   if (TARGET_HARD_FLOAT)
     {
@@ -3200,22 +3179,6 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
   if (TARGET_ALTIVEC)
     rs6000_constraints[RS6000_CONSTRAINT_v] = ALTIVEC_REGS;
 
-  if (TARGET_MFPGPR)                                           /* DFmode  */
-    rs6000_constraints[RS6000_CONSTRAINT_wg] = FLOAT_REGS;
-
-  if (TARGET_LFIWAX)
-    rs6000_constraints[RS6000_CONSTRAINT_wl] = FLOAT_REGS;     /* DImode  */
-
-  if (TARGET_DIRECT_MOVE)
-    {
-      rs6000_constraints[RS6000_CONSTRAINT_wh] = FLOAT_REGS;
-      rs6000_constraints[RS6000_CONSTRAINT_wj]                 /* DImode  */
-       = rs6000_constraints[RS6000_CONSTRAINT_wi];
-      rs6000_constraints[RS6000_CONSTRAINT_wk]                 /* DFmode  */
-       = rs6000_constraints[RS6000_CONSTRAINT_ws];
-      rs6000_constraints[RS6000_CONSTRAINT_wm] = VSX_REGS;
-    }
-
   if (TARGET_POWERPC64)
     {
       rs6000_constraints[RS6000_CONSTRAINT_wr] = GENERAL_REGS;
@@ -3230,9 +3193,6 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
   if (TARGET_STFIWX)
     rs6000_constraints[RS6000_CONSTRAINT_wx] = FLOAT_REGS;     /* DImode  */
 
-  if (TARGET_LFIWZX)
-    rs6000_constraints[RS6000_CONSTRAINT_wz] = FLOAT_REGS;     /* DImode  */
-
   if (TARGET_FLOAT128_TYPE)
     {
       rs6000_constraints[RS6000_CONSTRAINT_wq] = VSX_REGS;     /* KFmode  */
@@ -4330,6 +4290,24 @@ rs6000_option_override_internal (bool global_init_p)
       rs6000_isa_flags &= ~OPTION_MASK_FLOAT128_HW;
     }
 
+  /* -mpcrel requires prefixed load/store addressing.  */
+  if (TARGET_PCREL && !TARGET_PREFIXED_ADDR)
+    {
+      if ((rs6000_isa_flags_explicit & OPTION_MASK_PCREL) != 0)
+       error ("%qs requires %qs", "-mpcrel", "-mprefixed-addr");
+
+      rs6000_isa_flags &= ~OPTION_MASK_PCREL;
+    }
+
+  /* -mprefixed-addr (and hence -mpcrel) requires -mcpu=future.  */
+  if (TARGET_PREFIXED_ADDR && !TARGET_FUTURE)
+    {
+      if ((rs6000_isa_flags_explicit & OPTION_MASK_PCREL) != 0)
+       error ("%qs requires %qs", "-mprefixed-addr", "-mcpu=future");
+
+      rs6000_isa_flags &= ~(OPTION_MASK_PCREL | OPTION_MASK_PREFIXED_ADDR);
+    }
+
   /* Print the options after updating the defaults.  */
   if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET)
     rs6000_print_isa_options (stderr, 0, "after defaults", rs6000_isa_flags);
@@ -4470,6 +4448,7 @@ rs6000_option_override_internal (bool global_init_p)
                        && rs6000_tune != PROCESSOR_POWER7
                        && rs6000_tune != PROCESSOR_POWER8
                        && rs6000_tune != PROCESSOR_POWER9
+                       && rs6000_tune != PROCESSOR_FUTURE
                        && rs6000_tune != PROCESSOR_PPCA2
                        && rs6000_tune != PROCESSOR_CELL
                        && rs6000_tune != PROCESSOR_PPC476);
@@ -4483,6 +4462,7 @@ rs6000_option_override_internal (bool global_init_p)
                                 || rs6000_tune == PROCESSOR_POWER7
                                 || rs6000_tune == PROCESSOR_POWER8
                                 || rs6000_tune == PROCESSOR_POWER9
+                                || rs6000_tune == PROCESSOR_FUTURE
                                 || rs6000_tune == PROCESSOR_PPCE500MC
                                 || rs6000_tune == PROCESSOR_PPCE500MC64
                                 || rs6000_tune == PROCESSOR_PPCE5500
@@ -4783,6 +4763,7 @@ rs6000_option_override_internal (bool global_init_p)
        break;
 
       case PROCESSOR_POWER9:
+      case PROCESSOR_FUTURE:
        rs6000_cost = &power9_cost;
        break;
 
@@ -5666,6 +5647,39 @@ rs6000_builtin_md_vectorized_function (tree fndecl, tree type_out,
 /* Default CPU string for rs6000*_file_start functions.  */
 static const char *rs6000_default_cpu;
 
+#ifdef USING_ELFOS_H
+static const char *rs6000_machine;
+
+static const char *
+rs6000_machine_from_flags (void)
+{
+  if ((rs6000_isa_flags & (ISA_FUTURE_MASKS_SERVER & ~ISA_3_0_MASKS_SERVER))
+      != 0)
+    return "future";
+  if ((rs6000_isa_flags & (ISA_3_0_MASKS_SERVER & ~ISA_2_7_MASKS_SERVER)) != 0)
+    return "power9";
+  if ((rs6000_isa_flags & (ISA_2_7_MASKS_SERVER & ~ISA_2_6_MASKS_SERVER)) != 0)
+    return "power8";
+  if ((rs6000_isa_flags & (ISA_2_6_MASKS_SERVER & ~ISA_2_5_MASKS_SERVER)) != 0)
+    return "power7";
+  if ((rs6000_isa_flags & (ISA_2_5_MASKS_SERVER & ~ISA_2_4_MASKS)) != 0)
+    return "power6";
+  if ((rs6000_isa_flags & (ISA_2_4_MASKS & ~ISA_2_1_MASKS)) != 0)
+    return "power5";
+  if ((rs6000_isa_flags & ISA_2_1_MASKS) != 0)
+    return "power4";
+  if ((rs6000_isa_flags & OPTION_MASK_POWERPC64) != 0)
+    return "ppc64";
+  return "ppc";
+}
+
+static void
+emit_asm_machine (void)
+{
+  fprintf (asm_out_file, "\t.machine %s\n", rs6000_machine);
+}
+#endif
+
 /* Do anything needed at the start of the asm file.  */
 
 static void
@@ -5731,27 +5745,10 @@ rs6000_file_start (void)
     }
 
 #ifdef USING_ELFOS_H
+  rs6000_machine = rs6000_machine_from_flags ();
   if (!(rs6000_default_cpu && rs6000_default_cpu[0])
       && !global_options_set.x_rs6000_cpu_index)
-    {
-      fputs ("\t.machine ", asm_out_file);
-      if ((rs6000_isa_flags & OPTION_MASK_MODULO) != 0)
-       fputs ("power9\n", asm_out_file);
-      else if ((rs6000_isa_flags & OPTION_MASK_DIRECT_MOVE) != 0)
-       fputs ("power8\n", asm_out_file);
-      else if ((rs6000_isa_flags & OPTION_MASK_POPCNTD) != 0)
-       fputs ("power7\n", asm_out_file);
-      else if ((rs6000_isa_flags & OPTION_MASK_CMPB) != 0)
-       fputs ("power6\n", asm_out_file);
-      else if ((rs6000_isa_flags & OPTION_MASK_POPCNTB) != 0)
-       fputs ("power5\n", asm_out_file);
-      else if ((rs6000_isa_flags & OPTION_MASK_MFCRF) != 0)
-       fputs ("power4\n", asm_out_file);
-      else if ((rs6000_isa_flags & OPTION_MASK_POWERPC64) != 0)
-       fputs ("ppc64\n", asm_out_file);
-      else
-       fputs ("ppc\n", asm_out_file);
-    }
+    emit_asm_machine ();
 #endif
 
   if (DEFAULT_ABI == ABI_ELFv2)
@@ -7476,30 +7473,22 @@ gpr_or_gpr_p (rtx op0, rtx op1)
 bool
 direct_move_p (rtx op0, rtx op1)
 {
-  int regno0, regno1;
-
   if (!REG_P (op0) || !REG_P (op1))
     return false;
 
-  if (!TARGET_DIRECT_MOVE && !TARGET_MFPGPR)
+  if (!TARGET_DIRECT_MOVE)
     return false;
 
-  regno0 = REGNO (op0);
-  regno1 = REGNO (op1);
+  int regno0 = REGNO (op0);
+  int regno1 = REGNO (op1);
   if (!HARD_REGISTER_NUM_P (regno0) || !HARD_REGISTER_NUM_P (regno1))
     return false;
 
-  if (INT_REGNO_P (regno0))
-    return (TARGET_DIRECT_MOVE) ? VSX_REGNO_P (regno1) : FP_REGNO_P (regno1);
-
-  else if (INT_REGNO_P (regno1))
-    {
-      if (TARGET_MFPGPR && FP_REGNO_P (regno0))
-       return true;
+  if (INT_REGNO_P (regno0) && VSX_REGNO_P (regno1))
+    return true;
 
-      else if (TARGET_DIRECT_MOVE && VSX_REGNO_P (regno0))
-       return true;
-    }
+  if (VSX_REGNO_P (regno0) && INT_REGNO_P (regno1))
+    return true;
 
   return false;
 }
@@ -9130,6 +9119,7 @@ rs6000_reassociation_width (unsigned int opc ATTRIBUTE_UNUSED,
     {
     case PROCESSOR_POWER8:
     case PROCESSOR_POWER9:
+    case PROCESSOR_FUTURE:
       if (DECIMAL_FLOAT_MODE_P (mode))
        return 1;
       if (VECTOR_MODE_P (mode))
@@ -19081,12 +19071,6 @@ rs6000_secondary_reload_simple_move (enum rs6000_reg_type to_type,
        return true;
     }
 
-  /* Power6+: MFTGPR or MFFGPR.  */
-  else if (TARGET_MFPGPR && TARGET_POWERPC64 && size == 8
-      && ((to_type == GPR_REG_TYPE && from_type == FPR_REG_TYPE)
-         || (to_type == FPR_REG_TYPE && from_type == GPR_REG_TYPE)))
-    return true;
-
   /* Move to/from SPR.  */
   else if ((size == 4 || (TARGET_POWERPC64 && size == 8))
           && ((to_type == GPR_REG_TYPE && from_type == SPR_REG_TYPE)
@@ -21081,6 +21065,30 @@ print_operand_address (FILE *file, rtx x)
 {
   if (REG_P (x))
     fprintf (file, "0(%s)", reg_names[ REGNO (x) ]);
+
+  /* Is it a pc-relative address?  */
+  else if (pcrel_address (x, Pmode))
+    {
+      HOST_WIDE_INT offset;
+
+      if (GET_CODE (x) == CONST)
+       x = XEXP (x, 0);
+
+      if (GET_CODE (x) == PLUS)
+       {
+         offset = INTVAL (XEXP (x, 1));
+         x = XEXP (x, 0);
+       }
+      else
+       offset = 0;
+
+      output_addr_const (file, x);
+
+      if (offset)
+       fprintf (file, "%+" PRId64, offset);
+
+      fputs ("@pcrel", file);
+    }
   else if (SYMBOL_REF_P (x) || GET_CODE (x) == CONST
           || GET_CODE (x) == LABEL_REF)
     {
@@ -21272,8 +21280,10 @@ rs6000_call_template_1 (rtx *operands, unsigned int funop, bool sibcall)
           (DEFAULT_ABI == ABI_V4 && TARGET_SECURE_PLT && flag_pic == 2
            ? "+32768" : ""));
 
-  static char str[32];  /* 2 spare */
-  if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
+  static char str[32];  /* 1 spare */
+  if (rs6000_pcrel_p (cfun))
+    sprintf (str, "b%s %s@notoc%s", sibcall ? "" : "l", z, arg);
+  else if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
     sprintf (str, "b%s %s%s%s", sibcall ? "" : "l", z, arg,
             sibcall ? "" : "\n\tnop");
   else if (DEFAULT_ABI == ABI_V4)
@@ -21338,6 +21348,16 @@ rs6000_indirect_call_template_1 (rtx *operands, unsigned int funop,
   /* Currently, funop is either 0 or 1.  The maximum string is always
      a !speculate 64-bit __tls_get_addr call.
 
+     ABI_ELFv2, pcrel:
+     . 27      .reloc .,R_PPC64_TLSGD,%2\n\t
+     . 35      .reloc .,R_PPC64_PLTSEQ_NOTOC,%z1\n\t
+     .  9      crset 2\n\t
+     . 27      .reloc .,R_PPC64_TLSGD,%2\n\t
+     . 36      .reloc .,R_PPC64_PLTCALL_NOTOC,%z1\n\t
+     .  8      beq%T1l-
+     .---
+     .142
+
      ABI_AIX:
      .  9      ld 2,%3\n\t
      . 27      .reloc .,R_PPC64_TLSGD,%2\n\t
@@ -21403,23 +21423,31 @@ rs6000_indirect_call_template_1 (rtx *operands, unsigned int funop,
            gcc_unreachable ();
        }
 
+      const char *notoc = rs6000_pcrel_p (cfun) ? "_NOTOC" : "";
       const char *addend = (DEFAULT_ABI == ABI_V4 && TARGET_SECURE_PLT
                            && flag_pic == 2 ? "+32768" : "");
       if (!speculate)
        {
          s += sprintf (s,
-                       "%s.reloc .,R_PPC%s_PLTSEQ,%%z%u%s\n\t",
-                       tls, rel64, funop, addend);
+                       "%s.reloc .,R_PPC%s_PLTSEQ%s,%%z%u%s\n\t",
+                       tls, rel64, notoc, funop, addend);
          s += sprintf (s, "crset 2\n\t");
        }
       s += sprintf (s,
-                   "%s.reloc .,R_PPC%s_PLTCALL,%%z%u%s\n\t",
-                   tls, rel64, funop, addend);
+                   "%s.reloc .,R_PPC%s_PLTCALL%s,%%z%u%s\n\t",
+                   tls, rel64, notoc, funop, addend);
     }
   else if (!speculate)
     s += sprintf (s, "crset 2\n\t");
 
-  if (DEFAULT_ABI == ABI_AIX)
+  if (rs6000_pcrel_p (cfun))
+    {
+      if (speculate)
+       sprintf (s, "b%%T%ul", funop);
+      else
+       sprintf (s, "beq%%T%ul-", funop);
+    }
+  else if (DEFAULT_ABI == ABI_AIX)
     {
       if (speculate)
        sprintf (s,
@@ -21472,64 +21500,72 @@ rs6000_indirect_sibcall_template (rtx *operands, unsigned int funop)
 }
 
 #if HAVE_AS_PLTSEQ
-/* Output indirect call insns.
-   WHICH is 0 for tocsave, 1 for plt16_ha, 2 for plt16_lo, 3 for mtctr.  */
+/* Output indirect call insns.  WHICH identifies the type of sequence.  */
 const char *
 rs6000_pltseq_template (rtx *operands, int which)
 {
   const char *rel64 = TARGET_64BIT ? "64" : "";
-  char tls[28];
+  char tls[30];
   tls[0] = 0;
   if (TARGET_TLS_MARKERS && GET_CODE (operands[3]) == UNSPEC)
     {
+      char off = which == RS6000_PLTSEQ_PLT_PCREL34 ? '8' : '4';
       if (XINT (operands[3], 1) == UNSPEC_TLSGD)
-       sprintf (tls, ".reloc .,R_PPC%s_TLSGD,%%3\n\t",
-                rel64);
+       sprintf (tls, ".reloc .-%c,R_PPC%s_TLSGD,%%3\n\t",
+                off, rel64);
       else if (XINT (operands[3], 1) == UNSPEC_TLSLD)
-       sprintf (tls, ".reloc .,R_PPC%s_TLSLD,%%&\n\t",
-                rel64);
+       sprintf (tls, ".reloc .-%c,R_PPC%s_TLSLD,%%&\n\t",
+                off, rel64);
       else
        gcc_unreachable ();
     }
 
   gcc_assert (DEFAULT_ABI == ABI_ELFv2 || DEFAULT_ABI == ABI_V4);
-  static char str[96];  /* 15 spare */
-  const char *off = WORDS_BIG_ENDIAN ? "+2" : "";
+  static char str[96];  /* 10 spare */
+  char off = WORDS_BIG_ENDIAN ? '2' : '4';
   const char *addend = (DEFAULT_ABI == ABI_V4 && TARGET_SECURE_PLT
                        && flag_pic == 2 ? "+32768" : "");
   switch (which)
     {
-    case 0:
+    case RS6000_PLTSEQ_TOCSAVE:
       sprintf (str,
-              "%s.reloc .,R_PPC%s_PLTSEQ,%%z2\n\t"
-              "st%s",
-              tls, rel64, TARGET_64BIT ? "d 2,24(1)" : "w 2,12(1)");
+              "st%s\n\t"
+              "%s.reloc .-4,R_PPC%s_PLTSEQ,%%z2",
+              TARGET_64BIT ? "d 2,24(1)" : "w 2,12(1)",
+              tls, rel64);
       break;
-    case 1:
+    case RS6000_PLTSEQ_PLT16_HA:
       if (DEFAULT_ABI == ABI_V4 && !flag_pic)
        sprintf (str,
-                "%s.reloc .%s,R_PPC%s_PLT16_HA,%%z2\n\t"
-                "lis %%0,0",
+                "lis %%0,0\n\t"
+                "%s.reloc .-%c,R_PPC%s_PLT16_HA,%%z2",
                 tls, off, rel64);
       else
        sprintf (str,
-                "%s.reloc .%s,R_PPC%s_PLT16_HA,%%z2%s\n\t"
-                "addis %%0,%%1,0",
+                "addis %%0,%%1,0\n\t"
+                "%s.reloc .-%c,R_PPC%s_PLT16_HA,%%z2%s",
                 tls, off, rel64, addend);
       break;
-    case 2:
+    case RS6000_PLTSEQ_PLT16_LO:
       sprintf (str,
-              "%s.reloc .%s,R_PPC%s_PLT16_LO%s,%%z2%s\n\t"
-              "l%s %%0,0(%%1)",
-              tls, off, rel64, TARGET_64BIT ? "_DS" : "", addend,
-              TARGET_64BIT ? "d" : "wz");
+              "l%s %%0,0(%%1)\n\t"
+              "%s.reloc .-%c,R_PPC%s_PLT16_LO%s,%%z2%s",
+              TARGET_64BIT ? "d" : "wz",
+              tls, off, rel64, TARGET_64BIT ? "_DS" : "", addend);
       break;
-    case 3:
+    case RS6000_PLTSEQ_MTCTR:
       sprintf (str,
-              "%s.reloc .,R_PPC%s_PLTSEQ,%%z2%s\n\t"
-              "mtctr %%1",
+              "mtctr %%1\n\t"
+              "%s.reloc .-4,R_PPC%s_PLTSEQ,%%z2%s",
               tls, rel64, addend);
       break;
+    case RS6000_PLTSEQ_PLT_PCREL34:
+      sprintf (str,
+              "pl%s %%0,0(0),1\n\t"
+              "%s.reloc .-8,R_PPC%s_PLT_PCREL34_NOTOC,%%z2",
+              TARGET_64BIT ? "d" : "wz",
+              tls, rel64);
+      break;
     default:
       gcc_unreachable ();
     }
@@ -21537,6 +21573,71 @@ rs6000_pltseq_template (rtx *operands, int which)
 }
 #endif
 
+/* Helper function to return whether a MODE can do prefixed loads/stores.
+   VOIDmode is used when we are loading the pc-relative address into a base
+   register, but we are not using it as part of a memory operation.  As modes
+   add support for prefixed memory, they will be added here.  */
+
+static bool
+mode_supports_prefixed_address_p (machine_mode mode)
+{
+  return mode == VOIDmode;
+}
+
+/* Function to return true if ADDR is a valid prefixed memory address that uses
+   mode MODE.  */
+
+bool
+rs6000_prefixed_address (rtx addr, machine_mode mode)
+{
+  if (!TARGET_PREFIXED_ADDR || !mode_supports_prefixed_address_p (mode))
+    return false;
+
+  /* Check for PC-relative addresses.  */
+  if (pcrel_address (addr, Pmode))
+    return true;
+
+  /* Check for prefixed memory addresses that have a large numeric offset,
+     or an offset that can't be used for a DS/DQ-form memory operation.  */
+  if (GET_CODE (addr) == PLUS)
+    {
+      rtx op0 = XEXP (addr, 0);
+      rtx op1 = XEXP (addr, 1);
+
+      if (!base_reg_operand (op0, Pmode) || !CONST_INT_P (op1))
+       return false;
+
+      HOST_WIDE_INT value = INTVAL (op1);
+      if (!SIGNED_34BIT_OFFSET_P (value, 0))
+       return false;
+
+      /* Offset larger than 16-bits?  */
+      if (!SIGNED_16BIT_OFFSET_P (value, 0))
+       return true;
+
+      /* DQ instruction (bottom 4 bits must be 0) for vectors.  */
+      HOST_WIDE_INT mask;
+      if (GET_MODE_SIZE (mode) >= 16)
+       mask = 15;
+
+      /* DS instruction (bottom 2 bits must be 0).  For 32-bit integers, we
+        need to use DS instructions if we are sign-extending the value with
+        LWA.  For 32-bit floating point, we need DS instructions to load and
+        store values to the traditional Altivec registers.  */
+      else if (GET_MODE_SIZE (mode) >= 4)
+       mask = 3;
+
+      /* QImode/HImode has no restrictions.  */
+      else
+       return true;
+
+      /* Return true if we must use a prefixed instruction.  */
+      return (value & mask) != 0;
+    }
+
+  return false;
+}
+\f
 #if defined (HAVE_GAS_HIDDEN) && !TARGET_MACHO
 /* Emit an assembler directive to set symbol visibility for DECL to
    VISIBILITY_TYPE.  */
@@ -24708,6 +24809,52 @@ rs6000_return_addr (int count, rtx frame)
   return get_hard_reg_initial_val (Pmode, LR_REGNO);
 }
 
+/* Helper function for rs6000_function_ok_for_sibcall.  */
+
+static bool
+rs6000_decl_ok_for_sibcall (tree decl)
+{
+  /* Sibcalls are always fine for the Darwin ABI.  */
+  if (DEFAULT_ABI == ABI_DARWIN)
+    return true;
+
+  if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
+    {
+      /* Under the AIX or ELFv2 ABIs we can't allow calls to non-local
+        functions, because the callee may have a different TOC pointer to
+        the caller and there's no way to ensure we restore the TOC when
+        we return.  */
+      if (!decl || DECL_EXTERNAL (decl) || DECL_WEAK (decl)
+         || !(*targetm.binds_local_p) (decl))
+       return false;
+
+      /* Similarly, if the caller preserves the TOC pointer and the callee
+        doesn't (or vice versa), proper TOC setup or restoration will be
+        missed.  For example, suppose A, B, and C are in the same binary
+        and A -> B -> C.  A and B preserve the TOC pointer but C does not,
+        and B -> C is eligible as a sibcall.  A will call B through its
+        local entry point, so A will not restore its TOC itself.  B calls
+        C with a sibcall, so it will not restore the TOC.  C does not
+        preserve the TOC, so it may clobber r2 with impunity.  Returning
+        from C will result in a corrupted TOC for A.  */
+      else if (rs6000_fndecl_pcrel_p (decl) != rs6000_pcrel_p (cfun))
+       return false;
+
+      else
+       return true;
+    }
+
+  /*  With the secure-plt SYSV ABI we can't make non-local calls when
+      -fpic/PIC because the plt call stubs use r30.  */
+  if (DEFAULT_ABI != ABI_V4
+      || (TARGET_SECURE_PLT
+         && flag_pic
+         && (!decl || !((*targetm.binds_local_p) (decl)))))
+    return false;
+
+  return true;
+}
+
 /* Say whether a function is a candidate for sibcall handling or not.  */
 
 static bool
@@ -24753,22 +24900,7 @@ rs6000_function_ok_for_sibcall (tree decl, tree exp)
        return false;
     }
 
-  /* Under the AIX or ELFv2 ABIs we can't allow calls to non-local
-     functions, because the callee may have a different TOC pointer to
-     the caller and there's no way to ensure we restore the TOC when
-     we return.  With the secure-plt SYSV ABI we can't make non-local
-     calls when -fpic/PIC because the plt call stubs use r30.  */
-  if (DEFAULT_ABI == ABI_DARWIN
-      || ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
-         && decl
-         && !DECL_EXTERNAL (decl)
-         && !DECL_WEAK (decl)
-         && (*targetm.binds_local_p) (decl))
-      || (DEFAULT_ABI == ABI_V4
-         && (!TARGET_SECURE_PLT
-             || !flag_pic
-             || (decl
-                 && (*targetm.binds_local_p) (decl)))))
+  if (rs6000_decl_ok_for_sibcall (decl))
     {
       tree attr_list = TYPE_ATTRIBUTES (fntype);
 
@@ -26185,7 +26317,7 @@ split_stack_arg_pointer_used_p (void)
 /* Return whether we need to emit an ELFv2 global entry point prologue.  */
 
 static bool
-rs6000_global_entry_point_needed_p (void)
+rs6000_global_entry_point_prologue_needed_p (void)
 {
   /* Only needed for the ELFv2 ABI.  */
   if (DEFAULT_ABI != ABI_ELFv2)
@@ -26196,6 +26328,10 @@ rs6000_global_entry_point_needed_p (void)
   if (TARGET_SINGLE_PIC_BASE)
     return false;
 
+  /* PC-relative functions never generate a global entry point prologue.  */
+  if (rs6000_pcrel_p (cfun))
+    return false;
+
   /* Ensure we have a global entry point for thunks.   ??? We could
      avoid that if the target routine doesn't need a global entry point,
      but we do not know whether this is the case at this point.  */
@@ -27538,14 +27674,23 @@ static void
 rs6000_output_function_prologue (FILE *file)
 {
   if (!cfun->is_thunk)
-    rs6000_output_savres_externs (file);
+    {
+      rs6000_output_savres_externs (file);
+#ifdef USING_ELFOS_H
+      const char *curr_machine = rs6000_machine_from_flags ();
+      if (rs6000_machine != curr_machine)
+       {
+         rs6000_machine = curr_machine;
+         emit_asm_machine ();
+       }
+#endif
+    }
 
   /* ELFv2 ABI r2 setup code and local entry point.  This must follow
      immediately after the global entry point label.  */
-  if (rs6000_global_entry_point_needed_p ())
+  if (rs6000_global_entry_point_prologue_needed_p ())
     {
       const char *name = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
-
       (*targetm.asm_out.internal_label) (file, "LCF", rs6000_pic_labelno);
 
       if (TARGET_CMODEL != CMODEL_LARGE)
@@ -27596,6 +27741,19 @@ rs6000_output_function_prologue (FILE *file)
       fputs ("\n", file);
     }
 
+  else if (rs6000_pcrel_p (cfun))
+    {
+      const char *name = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
+      /* All functions compiled to use PC-relative addressing will
+        have a .localentry value of 0 or 1.  For now we set it to
+        1 all the time, indicating that the function may clobber
+        the TOC register r2.  Later we may optimize this by setting
+        it to 0 if the function is a leaf and does not clobber r2.  */
+      fputs ("\t.localentry\t", file);
+      assemble_name (file, name);
+      fputs (",1\n", file);
+    }
+
   /* Output -mprofile-kernel code.  This needs to be done here instead of
      in output_function_profile since it must go after the ELFv2 ABI
      local entry point.  */
@@ -29275,8 +29433,7 @@ rs6000_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
 
   /* Run just enough of rest_of_compilation to get the insns emitted.
      There's not really enough bulk here to make other passes such as
-     instruction scheduling worth while.  Note that use_thunk calls
-     assemble_start_function and assemble_end_function.  */
+     instruction scheduling worth while.  */
   insn = get_insns ();
   shorten_branches (insn);
   assemble_start_function (thunk_fndecl, fnname);
@@ -30194,7 +30351,8 @@ rs6000_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn, int cost,
           some cycles later.  */
 
        /* Separate a load from a narrower, dependent store.  */
-       if ((rs6000_sched_groups || rs6000_tune == PROCESSOR_POWER9)
+       if ((rs6000_sched_groups || rs6000_tune == PROCESSOR_POWER9
+            || rs6000_tune == PROCESSOR_FUTURE)
            && GET_CODE (PATTERN (insn)) == SET
            && GET_CODE (PATTERN (dep_insn)) == SET
            && MEM_P (XEXP (PATTERN (insn), 1))
@@ -30232,6 +30390,7 @@ rs6000_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn, int cost,
                 || rs6000_tune == PROCESSOR_POWER7
                 || rs6000_tune == PROCESSOR_POWER8
                 || rs6000_tune == PROCESSOR_POWER9
+                || rs6000_tune == PROCESSOR_FUTURE
                  || rs6000_tune == PROCESSOR_CELL)
                 && recog_memoized (dep_insn)
                 && (INSN_CODE (dep_insn) >= 0))
@@ -30811,6 +30970,7 @@ rs6000_issue_rate (void)
   case PROCESSOR_POWER8:
     return 7;
   case PROCESSOR_POWER9:
+  case PROCESSOR_FUTURE:
     return 6;
   default:
     return 1;
@@ -32568,12 +32728,18 @@ rs6000_longcall_ref (rtx call_ref, rtx arg)
   if (TARGET_PLTSEQ)
     {
       rtx base = const0_rtx;
-      int regno;
-      if (DEFAULT_ABI == ABI_ELFv2)
+      int regno = 12;
+      if (rs6000_pcrel_p (cfun))
        {
-         base = gen_rtx_REG (Pmode, TOC_REGISTER);
-         regno = 12;
+         rtx reg = gen_rtx_REG (Pmode, regno);
+         rtx u = gen_rtx_UNSPEC (Pmode, gen_rtvec (3, base, call_ref, arg),
+                                 UNSPEC_PLT_PCREL);
+         emit_insn (gen_rtx_SET (reg, u));
+         return reg;
        }
+
+      if (DEFAULT_ABI == ABI_ELFv2)
+       base = gen_rtx_REG (Pmode, TOC_REGISTER);
       else
        {
          if (flag_pic)
@@ -33327,7 +33493,8 @@ rs6000_elf_declare_function_name (FILE *file, const char *name, tree decl)
   ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function");
   ASM_DECLARE_RESULT (file, DECL_RESULT (decl));
 
-  if (TARGET_CMODEL == CMODEL_LARGE && rs6000_global_entry_point_needed_p ())
+  if (TARGET_CMODEL == CMODEL_LARGE
+      && rs6000_global_entry_point_prologue_needed_p ())
     {
       char buf[256];
 
@@ -34657,8 +34824,15 @@ rs6000_register_move_cost (machine_mode mode,
        {
          if (TARGET_DIRECT_MOVE)
            {
-             if (rs6000_tune == PROCESSOR_POWER9)
-               ret = 2 * hard_regno_nregs (FIRST_GPR_REGNO, mode);
+             /* Keep the cost for direct moves above that for within
+                a register class even if the actual processor cost is
+                comparable.  We do this because a direct move insn
+                can't be a nop, whereas with ideal register
+                allocation a move within the same class might turn
+                out to be a nop.  */
+             if (rs6000_tune == PROCESSOR_POWER9
+                 || rs6000_tune == PROCESSOR_FUTURE)
+               ret = 3 * hard_regno_nregs (FIRST_GPR_REGNO, mode);
              else
                ret = 4 * hard_regno_nregs (FIRST_GPR_REGNO, mode);
              /* SFmode requires a conversion when moving between gprs
@@ -36259,14 +36433,16 @@ static struct rs6000_opt_mask const rs6000_opt_masks[] =
   { "float128",                        OPTION_MASK_FLOAT128_KEYWORD,   false, true  },
   { "float128-hardware",       OPTION_MASK_FLOAT128_HW,        false, true  },
   { "fprnd",                   OPTION_MASK_FPRND,              false, true  },
+  { "future",                  OPTION_MASK_FUTURE,             false, true  },
   { "hard-dfp",                        OPTION_MASK_DFP,                false, true  },
   { "htm",                     OPTION_MASK_HTM,                false, true  },
   { "isel",                    OPTION_MASK_ISEL,               false, true  },
   { "mfcrf",                   OPTION_MASK_MFCRF,              false, true  },
-  { "mfpgpr",                  OPTION_MASK_MFPGPR,             false, true  },
+  { "mfpgpr",                  0,                              false, true  },
   { "modulo",                  OPTION_MASK_MODULO,             false, true  },
   { "mulhw",                   OPTION_MASK_MULHW,              false, true  },
   { "multiple",                        OPTION_MASK_MULTIPLE,           false, true  },
+  { "pcrel",                   OPTION_MASK_PCREL,              false, true  },
   { "popcntb",                 OPTION_MASK_POPCNTB,            false, true  },
   { "popcntd",                 OPTION_MASK_POPCNTD,            false, true  },
   { "power8-fusion",           OPTION_MASK_P8_FUSION,          false, true  },
@@ -36277,6 +36453,7 @@ static struct rs6000_opt_mask const rs6000_opt_masks[] =
   { "power9-vector",           OPTION_MASK_P9_VECTOR,          false, true  },
   { "powerpc-gfxopt",          OPTION_MASK_PPC_GFXOPT,         false, true  },
   { "powerpc-gpopt",           OPTION_MASK_PPC_GPOPT,          false, true  },
+  { "prefixed-addr",           OPTION_MASK_PREFIXED_ADDR,      false, true  },
   { "quad-memory",             OPTION_MASK_QUAD_MEMORY,        false, true  },
   { "quad-memory-atomic",      OPTION_MASK_QUAD_MEMORY_ATOMIC, false, true  },
   { "recip-precision",         OPTION_MASK_RECIP_PRECISION,    false, true  },
@@ -37672,37 +37849,36 @@ rs6000_call_aix (rtx value, rtx func_desc, rtx tlsarg, rtx cookie)
   if (!SYMBOL_REF_P (func)
       || (DEFAULT_ABI == ABI_AIX && !SYMBOL_REF_FUNCTION_P (func)))
     {
-      /* Save the TOC into its reserved slot before the call,
-        and prepare to restore it after the call.  */
-      rtx stack_toc_offset = GEN_INT (RS6000_TOC_SAVE_SLOT);
-      rtx stack_toc_unspec = gen_rtx_UNSPEC (Pmode,
-                                            gen_rtvec (1, stack_toc_offset),
-                                            UNSPEC_TOCSLOT);
-      toc_restore = gen_rtx_SET (toc_reg, stack_toc_unspec);
-
-      /* Can we optimize saving the TOC in the prologue or
-        do we need to do it at every call?  */
-      if (TARGET_SAVE_TOC_INDIRECT && !cfun->calls_alloca)
-       cfun->machine->save_toc_in_prologue = true;
-      else
+      if (!rs6000_pcrel_p (cfun))
        {
-         rtx stack_ptr = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
-         rtx stack_toc_mem = gen_frame_mem (Pmode,
-                                            gen_rtx_PLUS (Pmode, stack_ptr,
-                                                          stack_toc_offset));
-         MEM_VOLATILE_P (stack_toc_mem) = 1;
-         if (is_pltseq_longcall)
+         /* Save the TOC into its reserved slot before the call,
+            and prepare to restore it after the call.  */
+         rtx stack_toc_offset = GEN_INT (RS6000_TOC_SAVE_SLOT);
+         rtx stack_toc_unspec = gen_rtx_UNSPEC (Pmode,
+                                                gen_rtvec (1, stack_toc_offset),
+                                                UNSPEC_TOCSLOT);
+         toc_restore = gen_rtx_SET (toc_reg, stack_toc_unspec);
+
+         /* Can we optimize saving the TOC in the prologue or
+            do we need to do it at every call?  */
+         if (TARGET_SAVE_TOC_INDIRECT && !cfun->calls_alloca)
+           cfun->machine->save_toc_in_prologue = true;
+         else
            {
-             /* Use USPEC_PLTSEQ here to emit every instruction in an
-                inline PLT call sequence with a reloc, enabling the
-                linker to edit the sequence back to a direct call
-                when that makes sense.  */
-             rtvec v = gen_rtvec (3, toc_reg, func_desc, tlsarg);
-             rtx mark_toc_reg = gen_rtx_UNSPEC (Pmode, v, UNSPEC_PLTSEQ);
-             emit_insn (gen_rtx_SET (stack_toc_mem, mark_toc_reg));
+             rtx stack_ptr = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
+             rtx stack_toc_mem = gen_frame_mem (Pmode,
+                                                gen_rtx_PLUS (Pmode, stack_ptr,
+                                                              stack_toc_offset));
+             MEM_VOLATILE_P (stack_toc_mem) = 1;
+             if (is_pltseq_longcall)
+               {
+                 rtvec v = gen_rtvec (3, toc_reg, func_desc, tlsarg);
+                 rtx mark_toc_reg = gen_rtx_UNSPEC (Pmode, v, UNSPEC_PLTSEQ);
+                 emit_insn (gen_rtx_SET (stack_toc_mem, mark_toc_reg));
+               }
+             else
+               emit_move_insn (stack_toc_mem, toc_reg);
            }
-         else
-           emit_move_insn (stack_toc_mem, toc_reg);
        }
 
       if (DEFAULT_ABI == ABI_ELFv2)
@@ -37779,10 +37955,12 @@ rs6000_call_aix (rtx value, rtx func_desc, rtx tlsarg, rtx cookie)
     }
   else
     {
-      /* Direct calls use the TOC: for local calls, the callee will
-        assume the TOC register is set; for non-local calls, the
-        PLT stub needs the TOC register.  */
-      abi_reg = toc_reg;
+      /* No TOC register needed for calls from PC-relative callers.  */
+      if (!rs6000_pcrel_p (cfun))
+       /* Direct calls use the TOC: for local calls, the callee will
+          assume the TOC register is set; for non-local calls, the
+          PLT stub needs the TOC register.  */
+       abi_reg = toc_reg;
       func_addr = func;
     }
 
@@ -37832,7 +38010,9 @@ rs6000_sibcall_aix (rtx value, rtx func_desc, rtx tlsarg, rtx cookie)
   insn = emit_call_insn (insn);
 
   /* Note use of the TOC register.  */
-  use_reg (&CALL_INSN_FUNCTION_USAGE (insn), gen_rtx_REG (Pmode, TOC_REGNUM));
+  if (!rs6000_pcrel_p (cfun))
+    use_reg (&CALL_INSN_FUNCTION_USAGE (insn),
+            gen_rtx_REG (Pmode, TOC_REGNUM));
 }
 
 /* Expand code to perform a call under the SYSV4 ABI.  */
@@ -38106,6 +38286,34 @@ rs6000_save_toc_in_prologue_p (void)
   return (cfun && cfun->machine && cfun->machine->save_toc_in_prologue);
 }
 
+/* Return whether we should generate PC-relative code for FNDECL.  */
+bool
+rs6000_fndecl_pcrel_p (const_tree fndecl)
+{
+  if (DEFAULT_ABI != ABI_ELFv2)
+    return false;
+
+  struct cl_target_option *opts = target_opts_for_fn (fndecl);
+
+  return ((opts->x_rs6000_isa_flags & OPTION_MASK_PCREL) != 0
+         && TARGET_CMODEL == CMODEL_MEDIUM);
+}
+
+/* Return whether we should generate PC-relative code for *FN.  */
+bool
+rs6000_pcrel_p (struct function *fn)
+{
+  if (DEFAULT_ABI != ABI_ELFv2)
+    return false;
+
+  /* Optimize usual case.  */
+  if (fn == cfun)
+    return ((rs6000_isa_flags & OPTION_MASK_PCREL) != 0
+           && TARGET_CMODEL == CMODEL_MEDIUM);
+
+  return rs6000_fndecl_pcrel_p (fn->decl);
+}
+
 #ifdef HAVE_GAS_HIDDEN
 # define USE_HIDDEN_LINKONCE 1
 #else