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]
Other format: [Raw text]

Fix for PR 6104


Hi,
PR 6104 shows testcase where SSE instructions contains subreg. The subreg has
outer mode wider than word and thus by definition the result should be merged
with the previous (even when in the SSE context this is nonsential, I am not
quite sure how to deal with it, sadly).  Anyway the problem is that reload uses
find_valid_class to find temporary destination for the result that will be
later merged into the register and find_valid_class returns SSE_INT_REGS
causing secondary_memory_needed to abort. It is our decision to never use
SSE_INT_REGS class in the reload so the secondary_memory_needed can alwyas
return proper value.

The attached patch adds extra parameter dest_regno for register the value
will be moved into once computed to find_valid_class.  So find_valid_class
choose the proper one from SSE and INT regs resulting in better code and
avoiding the compiler crash.

I would like to have this patch in 3.1.1, and for mainline I would like
to discuss what to do with the subregs in general.

I've botostrapped and regstedted mainline together with the next patch.
Branch testing is in the progress.

Sat May 18 13:09:08 CEST 2002  Jan Hubicka  <jh@suse.cz>
	* reload.c (find_valid_class): Accept new argument DEST,
	choose class accordingly.
	(push_reload): Update callers.

Index: reload.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload.c,v
retrieving revision 1.182
diff -c -3 -p -r1.182 reload.c
*** reload.c	9 May 2002 01:42:27 -0000	1.182
--- reload.c	18 May 2002 11:08:53 -0000
*************** static int push_secondary_reload PARAMS 
*** 240,246 ****
  					enum machine_mode, enum reload_type,
  					enum insn_code *));
  #endif
! static enum reg_class find_valid_class PARAMS ((enum machine_mode, int));
  static int reload_inner_reg_of_subreg PARAMS ((rtx, enum machine_mode));
  static void push_replacement	PARAMS ((rtx *, int, enum machine_mode));
  static void combine_reloads	PARAMS ((void));
--- 240,247 ----
  					enum machine_mode, enum reload_type,
  					enum insn_code *));
  #endif
! static enum reg_class find_valid_class PARAMS ((enum machine_mode, int,
! 						unsigned int));
  static int reload_inner_reg_of_subreg PARAMS ((rtx, enum machine_mode));
  static void push_replacement	PARAMS ((rtx *, int, enum machine_mode));
  static void combine_reloads	PARAMS ((void));
*************** clear_secondary_mem ()
*** 661,676 ****
  #endif /* SECONDARY_MEMORY_NEEDED */
  
  /* Find the largest class for which every register number plus N is valid in
!    M1 (if in range).  Abort if no such class exists.  */
  
  static enum reg_class
! find_valid_class (m1, n)
       enum machine_mode m1 ATTRIBUTE_UNUSED;
       int n;
  {
    int class;
    int regno;
    enum reg_class best_class = NO_REGS;
    unsigned int best_size = 0;
  
    for (class = 1; class < N_REG_CLASSES; class++)
--- 662,681 ----
  #endif /* SECONDARY_MEMORY_NEEDED */
  
  /* Find the largest class for which every register number plus N is valid in
!    M1 (if in range) and is cheap to move into REGNO.
!    Abort if no such class exists.  */
  
  static enum reg_class
! find_valid_class (m1, n, dest_regno)
       enum machine_mode m1 ATTRIBUTE_UNUSED;
       int n;
+      unsigned int dest_regno;
  {
+   int best_cost = -1;
    int class;
    int regno;
    enum reg_class best_class = NO_REGS;
+   enum reg_class dest_class = REGNO_REG_CLASS (dest_regno);
    unsigned int best_size = 0;
  
    for (class = 1; class < N_REG_CLASSES; class++)
*************** find_valid_class (m1, n)
*** 682,689 ****
  	    && ! HARD_REGNO_MODE_OK (regno + n, m1))
  	  bad = 1;
  
!       if (! bad && reg_class_size[class] > best_size)
! 	best_class = class, best_size = reg_class_size[class];
      }
  
    if (best_size == 0)
--- 687,700 ----
  	    && ! HARD_REGNO_MODE_OK (regno + n, m1))
  	  bad = 1;
  
!       if (! bad && reg_class_size[class] > best_size
! 	  && (best_cost < 0
! 	      || best_cost >= REGISTER_MOVE_COST (m1, class, dest_class)))
! 	{
! 	  best_class = class;
! 	  best_size = reg_class_size[class];
! 	  best_cost = REGISTER_MOVE_COST (m1, class, dest_class);
! 	}
      }
  
    if (best_size == 0)
*************** push_reload (in, out, inloc, outloc, cla
*** 1041,1047 ****
  			      subreg_regno_offset (REGNO (SUBREG_REG (in)),
  						   GET_MODE (SUBREG_REG (in)),
  						   SUBREG_BYTE (in),
! 						   GET_MODE (in)));
  
        /* This relies on the fact that emit_reload_insns outputs the
  	 instructions for input reloads of type RELOAD_OTHER in the same
--- 1052,1059 ----
  			      subreg_regno_offset (REGNO (SUBREG_REG (in)),
  						   GET_MODE (SUBREG_REG (in)),
  						   SUBREG_BYTE (in),
! 						   GET_MODE (in)),
! 			      REGNO (SUBREG_REG (in)));
  
        /* This relies on the fact that emit_reload_insns outputs the
  	 instructions for input reloads of type RELOAD_OTHER in the same
*************** push_reload (in, out, inloc, outloc, cla
*** 1141,1147 ****
  				     subreg_regno_offset (REGNO (SUBREG_REG (out)),
  							  GET_MODE (SUBREG_REG (out)),
  							  SUBREG_BYTE (out),
! 							  GET_MODE (out))),
  		   VOIDmode, VOIDmode, 0, 0,
  		   opnum, RELOAD_OTHER);
      }
--- 1153,1160 ----
  				     subreg_regno_offset (REGNO (SUBREG_REG (out)),
  							  GET_MODE (SUBREG_REG (out)),
  							  SUBREG_BYTE (out),
! 							  GET_MODE (out)),
! 				     REGNO (SUBREG_REG (out))),
  		   VOIDmode, VOIDmode, 0, 0,
  		   opnum, RELOAD_OTHER);
      }


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