The following patch fixes some testsuite regressions of LRA in comparison with reload on PA-RISC. There are still few regressions which I'll work on later.

The patch was bootstrapped on x86/x86-64.

Committed as rev. 186823.

2012-04-25  Vladimir Makarov <vmaka...@redhat.com>

        * lra-constraints.c (get_op_mode): Take mode from operand first
        for asm.
        (match_reload): Use gen_lowpart_SUBREG for scalar int modes.
        (curr_insn_transform): Unshare subregs for inout operands.

Index: lra-constraints.c
===================================================================
--- lra-constraints.c	(revision 186357)
+++ lra-constraints.c	(working copy)
@@ -797,16 +797,19 @@ static inline enum machine_mode
 get_op_mode (int nop)
 {
   rtx *loc;
-  enum machine_mode mode = curr_static_id->operand[nop].mode;
+  enum machine_mode mode;
+  bool md_first_p = asm_noperands (PATTERN (curr_insn)) < 0;
 
   /* Take mode from the machine description first.  */
-  if (mode != VOIDmode)
+  if (md_first_p && (mode = curr_static_id->operand[nop].mode) != VOIDmode)
     return mode;
   loc = curr_id->operand_loc[nop];
   /* Take mode from the operand second.  */
   mode = GET_MODE (*loc);
   if (mode != VOIDmode)
     return mode;
+  if (! md_first_p && (mode = curr_static_id->operand[nop].mode) != VOIDmode)
+    return mode;
   /* Here is a very rare case.  Take mode from the context.  */
   return find_mode (&PATTERN (curr_insn), VOIDmode, loc);
 }
@@ -858,14 +861,20 @@ match_reload (signed char out, signed ch
 	  reg = new_in_reg
 	    = lra_create_new_reg_with_unique_value (inmode, in_rtx,
 						    goal_class, "");
-	  new_out_reg = gen_lowpart_SUBREG (outmode, reg);
+	  if (SCALAR_INT_MODE_P (inmode))
+	    new_out_reg = gen_lowpart_SUBREG (outmode, reg);
+	  else
+	    new_out_reg = gen_rtx_SUBREG (outmode, reg, 0);
 	}
       else
 	{
 	  reg = new_out_reg
 	    = lra_create_new_reg_with_unique_value (outmode, out_rtx,
 						    goal_class, "");
-	  new_in_reg = gen_lowpart_SUBREG (inmode, new_out_reg);
+	  if (SCALAR_INT_MODE_P (outmode))
+	    new_in_reg = gen_lowpart_SUBREG (inmode, new_out_reg);
+	  else
+	    new_in_reg = gen_rtx_SUBREG (inmode, new_out_reg, 0);
 	}
       bitmap_set_bit (&lra_matched_pseudos, REGNO (reg));
       bitmap_set_bit (&lra_bound_pseudos, REGNO (reg));
@@ -3247,7 +3256,7 @@ curr_insn_transform (void)
 	      && type != OP_OUT)
 	    {
 	      push_to_sequence (before);
-	      lra_emit_move (new_reg, *loc);
+	      lra_emit_move (new_reg, old);
 	      before = get_insns ();
 	      end_sequence ();
 	    }
@@ -3257,7 +3266,12 @@ curr_insn_transform (void)
 	      if (find_reg_note (curr_insn, REG_UNUSED, old) == NULL_RTX)
 		{
 		  start_sequence ();
-		  lra_emit_move (old, new_reg);
+		  /* We don't want sharing subregs as the pseudo can
+		     get a memory and the memory can be processed
+		     several times for eliminations.  */
+		  lra_emit_move (GET_CODE (old) == SUBREG && type == OP_INOUT
+				 ? copy_rtx (old) : old,
+				 new_reg);
 		  emit_insn (after);
 		  after = get_insns ();
 		  end_sequence ();

Reply via email to