diff --git a/gcc/config/pa/pa.cc b/gcc/config/pa/pa.cc
index 84aa4f1b1f2..62f8764b7ca 100644
--- a/gcc/config/pa/pa.cc
+++ b/gcc/config/pa/pa.cc
@@ -209,6 +209,7 @@ static bool pa_can_change_mode_class (machine_mode, machine_mode, reg_class_t);
 static HOST_WIDE_INT pa_starting_frame_offset (void);
 static section* pa_elf_select_rtx_section(machine_mode, rtx, unsigned HOST_WIDE_INT) ATTRIBUTE_UNUSED;
 static void pa_atomic_assign_expand_fenv (tree *, tree *, tree *);
+static bool pa_use_lra_p (void);
 
 /* The following extra sections are only used for SOM.  */
 static GTY(()) section *som_readonly_data_section;
@@ -412,7 +413,7 @@ static size_t n_deferred_plabels = 0;
 #define TARGET_LEGITIMATE_ADDRESS_P pa_legitimate_address_p
 
 #undef TARGET_LRA_P
-#define TARGET_LRA_P hook_bool_void_false
+#define TARGET_LRA_P pa_use_lra_p
 
 #undef TARGET_HARD_REGNO_NREGS
 #define TARGET_HARD_REGNO_NREGS pa_hard_regno_nregs
@@ -973,7 +974,7 @@ legitimize_pic_address (rtx orig, machine_mode mode, rtx reg)
 
       /* During and after reload, we need to generate a REG_LABEL_OPERAND note
 	 and update LABEL_NUSES because this is not done automatically.  */
-      if (reload_in_progress || reload_completed)
+      if (lra_in_progress || reload_in_progress || reload_completed)
 	{
 	  /* Extract LABEL_REF.  */
 	  if (GET_CODE (orig) == CONST)
@@ -998,7 +999,7 @@ legitimize_pic_address (rtx orig, machine_mode mode, rtx reg)
       /* Before reload, allocate a temporary register for the intermediate
 	 result.  This allows the sequence to be deleted when the final
 	 result is unused and the insns are trivially dead.  */
-      tmp_reg = ((reload_in_progress || reload_completed)
+      tmp_reg = ((lra_in_progress || reload_in_progress || reload_completed)
 		 ? reg : gen_reg_rtx (Pmode));
 
       if (function_label_operand (orig, VOIDmode))
@@ -1959,11 +1960,13 @@ pa_emit_move_sequence (rtx *operands, machine_mode mode, rtx scratch_reg)
 			       copy_to_mode_reg (Pmode, XEXP (operand1, 0)));
 
   if (scratch_reg
-      && reload_in_progress && GET_CODE (operand0) == REG
+      && reload_in_progress
+      && GET_CODE (operand0) == REG
       && REGNO (operand0) >= FIRST_PSEUDO_REGISTER)
     operand0 = reg_equiv_mem (REGNO (operand0));
   else if (scratch_reg
-	   && reload_in_progress && GET_CODE (operand0) == SUBREG
+	   && reload_in_progress
+	   && GET_CODE (operand0) == SUBREG
 	   && GET_CODE (SUBREG_REG (operand0)) == REG
 	   && REGNO (SUBREG_REG (operand0)) >= FIRST_PSEUDO_REGISTER)
     {
@@ -1976,11 +1979,13 @@ pa_emit_move_sequence (rtx *operands, machine_mode mode, rtx scratch_reg)
     }
 
   if (scratch_reg
-      && reload_in_progress && GET_CODE (operand1) == REG
+      && reload_in_progress
+      && GET_CODE (operand1) == REG
       && REGNO (operand1) >= FIRST_PSEUDO_REGISTER)
     operand1 = reg_equiv_mem (REGNO (operand1));
   else if (scratch_reg
-	   && reload_in_progress && GET_CODE (operand1) == SUBREG
+	   && reload_in_progress
+	   && GET_CODE (operand1) == SUBREG
 	   && GET_CODE (SUBREG_REG (operand1)) == REG
 	   && REGNO (SUBREG_REG (operand1)) >= FIRST_PSEUDO_REGISTER)
     {
@@ -1992,12 +1997,16 @@ pa_emit_move_sequence (rtx *operands, machine_mode mode, rtx scratch_reg)
       operand1 = alter_subreg (&temp, true);
     }
 
-  if (scratch_reg && reload_in_progress && GET_CODE (operand0) == MEM
+  if (scratch_reg
+      && (lra_in_progress || reload_in_progress)
+      && GET_CODE (operand0) == MEM
       && ((tem = find_replacement (&XEXP (operand0, 0)))
 	  != XEXP (operand0, 0)))
     operand0 = replace_equiv_address (operand0, tem);
 
-  if (scratch_reg && reload_in_progress && GET_CODE (operand1) == MEM
+  if (scratch_reg
+      && (lra_in_progress || reload_in_progress)
+      && GET_CODE (operand1) == MEM
       && ((tem = find_replacement (&XEXP (operand1, 0)))
 	  != XEXP (operand1, 0)))
     operand1 = replace_equiv_address (operand1, tem);
@@ -2255,7 +2264,7 @@ pa_emit_move_sequence (rtx *operands, machine_mode mode, rtx scratch_reg)
   else if (GET_CODE (operand0) == MEM)
     {
       if (mode == DFmode && operand1 == CONST0_RTX (mode)
-	  && !(reload_in_progress || reload_completed))
+	  && !(lra_in_progress || reload_in_progress || reload_completed))
 	{
 	  rtx temp = gen_reg_rtx (DFmode);
 
@@ -2269,7 +2278,7 @@ pa_emit_move_sequence (rtx *operands, machine_mode mode, rtx scratch_reg)
 	  emit_insn (gen_rtx_SET (operand0, operand1));
 	  return 1;
 	}
-      if (! (reload_in_progress || reload_completed))
+      if (! (lra_in_progress || reload_in_progress || reload_completed))
 	{
 	  operands[0] = validize_mem (operand0);
 	  operands[1] = operand1 = force_reg (mode, operand1);
@@ -2309,7 +2318,7 @@ pa_emit_move_sequence (rtx *operands, machine_mode mode, rtx scratch_reg)
 	      rtx temp, const_part;
 
 	      /* Figure out what (if any) scratch register to use.  */
-	      if (reload_in_progress || reload_completed)
+	      if (lra_in_progress || reload_in_progress || reload_completed)
 		{
 		  scratch_reg = scratch_reg ? scratch_reg : operand0;
 		  /* SCRATCH_REG will hold an address and maybe the actual
@@ -2367,7 +2376,7 @@ pa_emit_move_sequence (rtx *operands, machine_mode mode, rtx scratch_reg)
 	      rtx_insn *insn;
 	      rtx temp;
 
-	      if (reload_in_progress || reload_completed)
+	      if (lra_in_progress || reload_in_progress || reload_completed)
 		{
 		  temp = scratch_reg ? scratch_reg : operand0;
 		  /* TEMP will hold an address and maybe the actual
@@ -2411,7 +2420,7 @@ pa_emit_move_sequence (rtx *operands, machine_mode mode, rtx scratch_reg)
 	    {
 	      rtx temp, set;
 
-	      if (reload_in_progress || reload_completed)
+	      if (lra_in_progress || reload_in_progress || reload_completed)
 		{
 		  temp = scratch_reg ? scratch_reg : operand0;
 		  /* TEMP will hold an address and maybe the actual
@@ -2502,7 +2511,7 @@ pa_emit_move_sequence (rtx *operands, machine_mode mode, rtx scratch_reg)
 		}
 	    }
 
-	  if (reload_in_progress || reload_completed)
+	  if (lra_in_progress || reload_in_progress || reload_completed)
 	    temp = scratch_reg ? scratch_reg : operand0;
 	  else
 	    temp = gen_reg_rtx (mode);
@@ -6408,24 +6417,21 @@ pa_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
   if (regno >= FIRST_PSEUDO_REGISTER || GET_CODE (x) == SUBREG)
     regno = true_regnum (x);
 
-  /* Handle reloads for floating point loads and stores.  */
-  if ((regno >= FIRST_PSEUDO_REGISTER || regno == -1)
-      && FP_REG_CLASS_P (rclass))
+  /* Handle reloads for floating-point loads and stores.  */
+  if (regno < 0 && FP_REG_CLASS_P (rclass))
     {
-      if (MEM_P (x))
-	{
-	  x = XEXP (x, 0);
+      if (REG_P (x) || GET_CODE (x) == SUBREG)
+	return NO_REGS;
 
-	  /* We don't need a secondary reload for indexed memory addresses.
+      /* We don't need a secondary reload for indexed memory addresses.
 
-	     When INT14_OK_STRICT is true, it might appear that we could
-	     directly allow register indirect memory addresses.  However,
-	     this doesn't work because we don't support SUBREGs in
-	     floating-point register copies and reload doesn't tell us
-	     when it's going to use a SUBREG.  */
-	  if (IS_INDEX_ADDR_P (x))
-	    return NO_REGS;
-	}
+	 When INT14_OK_STRICT is true, it might appear that we could
+	 directly allow register indirect memory addresses.  However,
+	 this doesn't work because we don't support SUBREGs in
+	 floating-point register copies and reload doesn't tell us
+	 when it's going to use a SUBREG.  */
+      if (MEM_P (x) && IS_INDEX_ADDR_P (XEXP (x, 0)))
+	return NO_REGS;
 
       /* Request a secondary reload with a general scratch register
 	 for everything else.  ??? Could symbolic operands be handled
@@ -6442,8 +6448,14 @@ pa_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
   if (rclass == SHIFT_REGS)
     {
       /* Handle spill.  */
-      if (regno >= FIRST_PSEUDO_REGISTER || regno < 0)
+      if (regno < 0)
 	{
+	  if (REG_P (x) || GET_CODE (x) == SUBREG)
+	    return GENERAL_REGS;
+
+	  if (TARGET_64BIT && GET_CODE (x) == CONST_INT)
+	    return GENERAL_REGS;
+
 	  sri->icode = (in_p
 			? direct_optab_handler (reload_in_optab, mode)
 			: direct_optab_handler (reload_out_optab, mode));
@@ -10875,6 +10887,7 @@ pa_legitimate_constant_p (machine_mode mode, rtx x)
   if (TARGET_64BIT
       && HOST_BITS_PER_WIDE_INT > 32
       && GET_CODE (x) == CONST_INT
+      && !lra_in_progress
       && !reload_in_progress
       && !reload_completed
       && !LEGITIMATE_64BIT_CONST_INT_P (INTVAL (x))
@@ -11026,7 +11039,8 @@ pa_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
 	     reload on targets with non-equivalent space registers.  */
 	  && (TARGET_NO_SPACE_REGS
 	      || reload_completed
-	      || (reload_in_progress && HARD_REGISTER_P (base))
+	      || ((lra_in_progress || reload_in_progress)
+		   && HARD_REGISTER_P (base))
 	      || REG_POINTER (base))
 	  && GET_CODE (index) == MULT
 	  && REG_P (XEXP (index, 0))
@@ -11334,4 +11348,12 @@ pa_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update)
 			    reload_fenv, restore_fnenv), update_call);
 }
 
+/* Implement TARGET_LRA_P.  */
+
+static bool
+pa_use_lra_p ()
+{
+  return pa_lra_p;
+}
+
 #include "gt-pa.h"
diff --git a/gcc/config/pa/pa.opt b/gcc/config/pa/pa.opt
index 6863f917628..d4b3063674c 100644
--- a/gcc/config/pa/pa.opt
+++ b/gcc/config/pa/pa.opt
@@ -86,6 +86,10 @@ mlong-calls
 Target Mask(LONG_CALLS)
 Always generate long calls.
 
+mlra
+Target Var(pa_lra_p) Init(0)
+Use LRA instead of reload (transitional).
+
 mlong-load-store
 Target Mask(LONG_LOAD_STORE)
 Emit long load/store sequences.
diff --git a/gcc/config/pa/predicates.md b/gcc/config/pa/predicates.md
index 0c6e41be31f..0defd2282fb 100644
--- a/gcc/config/pa/predicates.md
+++ b/gcc/config/pa/predicates.md
@@ -300,7 +300,7 @@
 (define_predicate "integer_store_memory_operand"
   (match_code "reg,mem")
 {
-  if (reload_in_progress
+  if ((lra_in_progress || reload_in_progress)
       && REG_P (op)
       && REGNO (op) >= FIRST_PSEUDO_REGISTER
       && reg_renumber [REGNO (op)] < 0)
@@ -312,7 +312,7 @@
 	 REG+D instructions in pa_emit_move_sequence.  Further, the Q
 	 constraint is used in more than simple move instructions.  So,
 	 we must return true and let reload handle the reload.  */
-      if (reload_in_progress)
+      if (lra_in_progress || reload_in_progress)
 	return true;
 
       /* Extract CONST_INT operand.  */
@@ -326,7 +326,8 @@
   if (!MEM_P (op))
     return false;
 
-  return ((reload_in_progress || memory_address_p (mode, XEXP (op, 0)))
+  return ((lra_in_progress || reload_in_progress
+	   || memory_address_p (mode, XEXP (op, 0)))
 	  && !IS_LO_SUM_DLT_ADDR_P (XEXP (op, 0))
 	  && !IS_INDEX_ADDR_P (XEXP (op, 0)));
 })
@@ -346,7 +347,7 @@
 (define_predicate "floating_point_store_memory_operand"
   (match_code "reg,mem")
 {
-  if (reload_in_progress
+  if ((lra_in_progress || reload_in_progress)
       && REG_P (op)
       && REGNO (op) >= FIRST_PSEUDO_REGISTER
       && reg_renumber [REGNO (op)] < 0)
@@ -366,7 +367,8 @@
   if (!MEM_P (op))
     return false;
 
-  return ((reload_in_progress || memory_address_p (mode, XEXP (op, 0)))
+  return ((lra_in_progress || reload_in_progress
+	   || memory_address_p (mode, XEXP (op, 0)))
 	  && (INT14_OK_STRICT || !symbolic_memory_operand (op, VOIDmode))
 	  && !IS_LO_SUM_DLT_ADDR_P (XEXP (op, 0))
 	  && !IS_INDEX_ADDR_P (XEXP (op, 0)));
@@ -555,7 +557,7 @@
   if (register_operand (op, mode))
     return true;
 
-  if (!reload_in_progress && !reload_completed)
+  if (!lra_in_progress && !reload_in_progress && !reload_completed)
     return false;
 
   if (! MEM_P (op))
