Limit reload creativity on load 1 into xmm register

Jan Hubicka jh@suse.cz
Tue May 17 14:13:00 GMT 2005


> On Fri, May 13, 2005 at 11:54:48PM +0200, Jan Hubicka wrote:
> > While fixing the constraints I also noticed one missing #rf in movsf_1
> > so fixed it one the way.
> 
> I'm largely convinced that these # constraints *are* the bug that you're
> trying to work around.  When I was re-doing the SSE stuff a couple of 
> months ago, I got better results by removing them.
> 
> I don't see how adding "!", meaning "last resort", is appropriate.

Hi,
apparently I suceeded with my homework and created self contained
testcase for some reason working on i386 only, but it gives the idea.
(it is tricky to do so as the wrong reload happens only when we have
reg-reg copy where source is REG_EQUIV of 1 and it is reloaded out.  For
example replacing the test2 asm in the testcase makes caller save code
to save&load the constant on stack that is wrong too.)

/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
/* { dg-options "-O2 -msse -m32" } */
/* { dg-final { scan-assembler-not "fld" } } */
t()
{
	float a=1;
	 asm("test"::"x"((float)1));
	 asm("test2"::"x"((float)10),
		 "x"((float)11),
		 "x"((float)12),
		 "x"((float)13),
		 "x"((float)14),
		 "x"((float)15),
		 "x"((float)16),
		 "x"((float)17)
		 );
	 asm volatile ("test3":"+&x"(a));
}

With little reload dumping one gets:

  Register 58 pref SSE_REGS or none
  Register 60 pref SSE_REGS or none

;; Register 58 in 22.
;; Register 60 in 22.

(insn 40 22 25 0 (set (reg/v:SF 58 [ a ])
        (reg:SF 60)) 90 {*movsf_1} (nil)
    (expr_list:REG_DEAD (reg:SF 60)
        (nil)))

Trying reloads for INSN 40, swapped 0
   Alternative 0 bad 0 losers 2 reject 5
   Alternative 0 so far the best
   Alternative 1 bad 1 losers 2 reject 5
   Alternative 2 bad 0 losers 1 reject 3
   Alternative 2 so far the best
   Alternative 3 bad 0 losers 1 reject 3
   Alternative 4 bad 1 losers 1 reject 3
   Alternative 5 bad 1 losers 1 reject 2
   Alternative 6 bad 0 losers 2 reject 2
   Alternative 7 bad 0 losers 2 reject 0
   Alternative 8 bad 1 losers 3 reject 5
   Alternative 9 bad 0 losers 2 reject 605
   Alternative 10 bad 0 losers 3 reject 605
   Alternative 11 bad 0 losers 3 reject 605

Alternative 6 would result in proper load from constant pool, but it is
disqualified by code:

	      /* If this is a constant that is reloaded into the desired
		 class by copying it to memory first, count that as another
		 reload.  This is consistent with other code and is
		 required to avoid choosing another alternative when
		 the constant is moved into memory by this function on
		 an early reload pass.  Note that the test here is
		 precisely the same as in the code below that calls
		 force_const_mem.  */
	      if (CONST_POOL_OK_P (operand)
		  && ((PREFERRED_RELOAD_CLASS (operand,
					       (enum reg_class) this_alternative[i])
		       == NO_REGS)
		      || no_input_reloads)
		  && operand_mode[i] != VOIDmode)
		{
		  const_to_mem = 1;
		  if (this_alternative[i] != (int) NO_REGS)
		    losers++;
		}
I am not quite sure what "other code" and "early reload pass" reffer
to... 
On the other hand, reload is clearly not considering all the information
here as the fld case triggers secondary reload and I am not quite sure
why the losers computation is not based on REG_MOVE_COST at all?
(I know it worked this way for an ages...)

It is also curious that alternative 0 (fm->f) gets same cost as
alternative 6 (xm->x) even thought the former clearly requires one extra
reload.

I am attaching the reload dumping code, it might be interesting at it's
own right.

Index: reload.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload.c,v
retrieving revision 1.271
diff -c -3 -p -r1.271 reload.c
*** reload.c	28 Apr 2005 20:36:56 -0000	1.271
--- reload.c	17 May 2005 14:03:14 -0000
*************** find_reloads (rtx insn, int replace, int
*** 2874,2879 ****
--- 2874,2882 ----
    swapped = 0;
    goal_alternative_swapped = 0;
   try_swapped:
+   if (dump_file)
+     fprintf (dump_file, "Trying reloads for INSN %i, swapped %i\n",
+ 	     INSN_UID (insn), swapped);
  
    /* The constraints are made of several alternatives.
       Each operand's constraint looks like foo,bar,... with commas
*************** find_reloads (rtx insn, int replace, int
*** 3597,3606 ****
--- 3602,3618 ----
  	      }
  	  }
  
+       if (dump_file)
+ 	fprintf (dump_file, "   Alternative %i bad %i losers %i reject %i\n",
+ 		 this_alternative_number, bad, losers, reject);
+ 
        /* If one alternative accepts all the operands, no reload required,
  	 choose that alternative; don't consider the remaining ones.  */
        if (losers == 0)
  	{
+ 	  if (dump_file)
+ 	    fprintf (dump_file, "   No reloading required for alternative %i\n",
+ 		     this_alternative_number);
  	  /* Unswap these so that they are never swapped at `finish'.  */
  	  if (commutative >= 0)
  	    {
*************** find_reloads (rtx insn, int replace, int
*** 3635,3640 ****
--- 3647,3655 ----
  	 record it as the chosen goal for reloading.  */
        if (! bad && best > losers)
  	{
+ 	  if (dump_file)
+ 	    fprintf (dump_file, "   Alternative %i so far the best\n",
+ 		     this_alternative_number);
  	  for (i = 0; i < noperands; i++)
  	    {
  	      goal_alternative[i] = this_alternative[i];



More information about the Gcc-patches mailing list