This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Reload fix to handle unarry operators in operands correctly V2


Hi
This is my second approach to solve the SECONDARY_MEMORY_NEEDED and unary
operators matched in operands problem.
Now the behaviour of reload is unchanged and I've only modified the code
handling SECONDARY_MEMORY_NEEDED to not miss the necesary reloads. The
reloading code now looks like:
(the reload of (reg:SF 0 eax) to (float_extend:DF (reg:SF )) where
the result must be in FLOAT_REGS class.

(insn 32 14 33 (set (mem:SF (plus:SI (reg:SI 6 ebp)
                (const_int -4 [0xfffffffc])) 0)
        (reg/v:SF 0 eax)) 69 {*movsf_1} (nil)
    (nil))

(insn 33 32 15 (set (reg:DF 8 st(0))
        (float_extend:DF (mem:SF (plus:SI (reg:SI 6 ebp)
                    (const_int -4 [0xfffffffc])) 0))) 126 {*extendsfdf2_1} (nil)
    (nil))

So the unary operator is not kept in the original insn, but moved to the
load insn. This is consistent to what we already do with the normal spills.

I've also made operands_match_p to ignore the unary operators so the
operand with unary operator can match with operand without. This is
required to make matching constraints work (in current tree this is
done separately in recog.c, but not allowed elsewhere, so reload
produced worse results). I've verified that all callers of match_operand_p.

Now my predicate patch passes testsuite as well as work for my testcases
requiring secondary reloads.

Can someone plase tell me soon if this patch makes sense or not?
I've yesterday read trought whole reload sources trying to understand
it, but I still don't fell like reload expert :))

Honza

Sun Jan  9 16:01:16 MET 2000  Jan Hubicka  <jh@suse.cz>
	* reload1.c (gen_reload): Correctly emit secondary reloads for the unary
	operators matched in operands.
	* reload.c (push_secondary_reload): Ignore the unary operators
	matched in operands.
	(find_dummy_reload): Likewise.
	(operands_match_p): Likewise.
	(push_reload) Correctly detect secondary reloads for the unary
	operators matched in operands.
	* recog.c (constrain_operands): Do not ignore the unary operators
	matched in operands.

Index: egcs/gcc/reload1.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload1.c,v
retrieving revision 1.193
diff -c -3 -p -r1.193 reload1.c
*** reload1.c	2000/01/05 12:41:07	1.193
--- reload1.c	2000/01/09 15:00:20
*************** gen_reload (out, in, opnum, type)
*** 7081,7087 ****
--- 7081,7091 ----
  {
    rtx last = get_last_insn ();
    rtx tem;
+   rtx true_in = in;
  
+   if (GET_RTX_CLASS (GET_CODE (true_in)) == '1')
+     true_in = XEXP (true_in, 0);
+ 
    /* If IN is a paradoxical SUBREG, remove it and try to put the
       opposite SUBREG on OUT.  Likewise for a paradoxical SUBREG on OUT.  */
    if (GET_CODE (in) == SUBREG
*************** gen_reload (out, in, opnum, type)
*** 7243,7264 ****
  
  #ifdef SECONDARY_MEMORY_NEEDED
    /* If we need a memory location to do the move, do it that way.  */
!   else if (GET_CODE (in) == REG && REGNO (in) < FIRST_PSEUDO_REGISTER
  	   && GET_CODE (out) == REG && REGNO (out) < FIRST_PSEUDO_REGISTER
! 	   && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (in)),
  				       REGNO_REG_CLASS (REGNO (out)),
  				       GET_MODE (out)))
      {
        /* Get the memory to use and rewrite both registers to its mode.  */
!       rtx loc = get_secondary_mem (in, GET_MODE (out), opnum, type);
  
        if (GET_MODE (loc) != GET_MODE (out))
  	out = gen_rtx_REG (GET_MODE (loc), REGNO (out));
  
-       if (GET_MODE (loc) != GET_MODE (in))
- 	in = gen_rtx_REG (GET_MODE (loc), REGNO (in));
- 
-       gen_reload (loc, in, opnum, type);
        gen_reload (out, loc, opnum, type);
      }
  #endif
--- 7247,7281 ----
  
  #ifdef SECONDARY_MEMORY_NEEDED
    /* If we need a memory location to do the move, do it that way.  */
!   else if (GET_CODE (true_in) == REG && REGNO (true_in) < FIRST_PSEUDO_REGISTER
  	   && GET_CODE (out) == REG && REGNO (out) < FIRST_PSEUDO_REGISTER
! 	   && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (true_in)),
  				       REGNO_REG_CLASS (REGNO (out)),
  				       GET_MODE (out)))
      {
        /* Get the memory to use and rewrite both registers to its mode.  */
!       rtx loc = get_secondary_mem (true_in, GET_MODE (true_in), opnum, type);
! 
!       /* For unary operators matched in operands we would like to generate
! 	 following code to reload (unop:outmode (reg:inmode X))
! 
! 	 (set (mem:inmode X) (reg:inmode X))
! 	 (set (reg:outmode Y) (unop:outmode (reg:inmode Y)))
! 
! 	 So for our purposes ignore unary operators and we will get correct mode
! 	 in the memory references.  */
  
+       if (GET_MODE (loc) != GET_MODE (true_in))
+ 	true_in = gen_rtx_REG (GET_MODE (loc), REGNO (true_in));
+ 
+       gen_reload (loc, true_in, opnum, type);
+ 
+       if (GET_RTX_CLASS (GET_CODE (in)) == '1')
+ 	loc = gen_rtx_fmt_e (GET_CODE (in), GET_MODE (in), loc);
+ 
        if (GET_MODE (loc) != GET_MODE (out))
  	out = gen_rtx_REG (GET_MODE (loc), REGNO (out));
  
        gen_reload (out, loc, opnum, type);
      }
  #endif
Index: egcs/gcc/reload.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload.c,v
retrieving revision 1.97
diff -c -3 -p -r1.97 reload.c
*** reload.c	2000/01/04 16:29:40	1.97
--- reload.c	2000/01/09 15:00:41
*************** push_secondary_reload (in_p, x, opnum, o
*** 316,321 ****
--- 316,336 ----
  
    *picode = CODE_FOR_nothing;
  
+   /* For unary operators matched in operands we would like to generate
+      following code to reload (unop:outmode (reg:inmode X))
+ 
+      (set (mem:inmode X) (reg:inmode X))
+      (set (reg:outmode Y) (unop:outmode (reg:inmode Y)))
+ 
+      So for our purposes ignore unary operators and we will get correct mode
+      in the memory references.  */
+ 
+   if (GET_RTX_CLASS (GET_CODE (x)) == '1')
+     {
+       x = XEXP (x, 0);
+       reload_mode = GET_MODE (x);
+     }
+ 
    /* If X is a paradoxical SUBREG, use the inner value to determine both the
       mode and object being reloaded.  */
    if (GET_CODE (x) == SUBREG
*************** push_reload (in, out, inloc, outloc, cla
*** 819,825 ****
--- 834,842 ----
    int secondary_in_reload = -1, secondary_out_reload = -1;
    enum insn_code secondary_in_icode = CODE_FOR_nothing;
    enum insn_code secondary_out_icode = CODE_FOR_nothing;
+   rtx true_in;
+   enum machine_mode true_inmode;
  
    /* INMODE and/or OUTMODE could be VOIDmode if no mode
       has been specified for the operand.  In that case,
       use the operand's mode as the mode to reload.  */
*************** push_reload (in, out, inloc, outloc, cla
*** 1224,1239 ****
  				   type, &secondary_out_icode);
  #endif
  
        /* We found no existing reload suitable for re-use.
  	 So add an additional reload.  */
  
  #ifdef SECONDARY_MEMORY_NEEDED
        /* If a memory location is needed for the copy, make one.  */
!       if (in != 0 && GET_CODE (in) == REG
! 	  && REGNO (in) < FIRST_PSEUDO_REGISTER
! 	  && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (in)),
  				      class, inmode))
! 	get_secondary_mem (in, inmode, opnum, type);
  #endif
  
        i = n_reloads;
--- 1241,1265 ----
  				   type, &secondary_out_icode);
  #endif
  
+       /* Unary operators mached by the predicate by operands is irrelevant
+ 	 for purposes of secondary reloads etc.  */
+       if (in && GET_RTX_CLASS (GET_CODE (in)) == '1')
+ 	true_in = XEXP (in, 0), true_inmode = GET_MODE (true_in);
+       else
+ 	true_in = in, true_inmode = inmode;
+       if (true_in && GET_CODE (true_in) == SUBREG)
+ 	true_in = SUBREG_REG (true_in);
+ 
        /* We found no existing reload suitable for re-use.
  	 So add an additional reload.  */
  
  #ifdef SECONDARY_MEMORY_NEEDED
        /* If a memory location is needed for the copy, make one.  */
!       if (true_in != 0 && GET_CODE (true_in) == REG
! 	  && REGNO (true_in) < FIRST_PSEUDO_REGISTER
! 	  && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (true_in)),
  				      class, inmode))
! 	get_secondary_mem (true_in, true_inmode, opnum, type);
  #endif
  
        i = n_reloads;
*************** find_dummy_reload (real_in, real_out, in
*** 1802,1807 ****
--- 1828,1840 ----
  	  || GET_MODE_SIZE (inmode) > UNITS_PER_WORD))
      return 0;
  
+   /* Find the inside of any unary operators.  */
+   while (GET_RTX_CLASS (GET_CODE (in)) == '1')
+     {
+       in_offset = SUBREG_WORD (in);
+       in = SUBREG_REG (in);
+     }
+ 
    /* Find the inside of any subregs.  */
    while (GET_CODE (out) == SUBREG)
      {
*************** strict_memory_address_p (mode, addr)
*** 1985,1993 ****
    return 1;
  }
  
! /* Like rtx_equal_p except that it allows a REG and a SUBREG to match
!    if they are the same hard reg, and has special hacks for
!    autoincrement and autodecrement.
     This is specifically intended for find_reloads to use
     in determining whether two operands match.
     X is the operand whose number is the lower of the two.
--- 2018,2027 ----
    return 1;
  }
  
! /* Like rtx_equal_p except that it allows a REG, a SUBREG
!    and extra unary operators to match if they are the same
!    hard reg, and has special hacks for autoincrement and
!    autodecrement.
     This is specifically intended for find_reloads to use
     in determining whether two operands match.
     X is the operand whose number is the lower of the two.
*************** operands_match_p (x, y)
*** 2011,2016 ****
--- 2045,2058 ----
  
    if (x == y)
      return 1;
+ 
+   /* A unary operator may be accepted by the predicate,
+      but it is irrelevant for matching constraints.  */
+ 
+   if (GET_RTX_CLASS (GET_CODE (x)) == '1')
+     x = XEXP (x, 0);
+   if (GET_RTX_CLASS (GET_CODE (y)) == '1')
+     y = XEXP (y, 0);
    if ((code == REG || (code == SUBREG && GET_CODE (SUBREG_REG (x)) == REG))
        && (GET_CODE (y) == REG || (GET_CODE (y) == SUBREG
  				  && GET_CODE (SUBREG_REG (y)) == REG)))
Index: egcs/gcc/recog.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/recog.c,v
retrieving revision 1.51
diff -c -3 -p -r1.51 recog.c
*** recog.c	1999/11/01 01:11:21	1.51
--- recog.c	2000/01/09 15:01:03
*************** constrain_operands (strict)
*** 2295,2307 ****
  		    rtx op1 = recog_data.operand[c - '0'];
  		    rtx op2 = recog_data.operand[opno];
  
- 	            /* A unary operator may be accepted by the predicate,
- 		       but it is irrelevant for matching constraints.  */
- 	            if (GET_RTX_CLASS (GET_CODE (op1)) == '1')
- 	              op1 = XEXP (op1, 0);
- 	            if (GET_RTX_CLASS (GET_CODE (op2)) == '1')
- 	              op2 = XEXP (op2, 0);
- 
  		    val = operands_match_p (op1, op2);
  		  }
  
--- 2295,2300 ----

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]