Showstopper in g77 in prerelease on Linux-Alpha

Richard Henderson rth@cygnus.com
Sat Jul 31 23:33:00 GMT 1999


On Fri, Jul 09, 1999 at 02:07:51AM -0700, Richard Henderson wrote:
> (insn 76 75 78 (set (reg:DI 92)
>         (fix:DI (reg:DF 91))) 122 {fix_truncdfdi2} (insn_list 75 (nil))
>     (expr_list:REG_DEAD (reg:DF 91)
>         (nil)))
> 
> (insn 78 76 79 (set (reg:SI 81)
>         (subreg:SI (reg:DI 92) 0)) 283 {movdf+1} (insn_list 76 (nil))
>     (expr_list:REG_DEAD (reg:DI 92)
>         (nil)))
> 
> In global, reg 92 gets allocated to $f10, and isn't fixed up in
> reload, despite CLASS_CANNOT_CHANGE_SIZE and the subreg.

Regclass is at fault for suggesting that FLOAT_REGS is a viable
class for reg 92.  The following rather direct solution works for
the problem as presented.

Something that should be attended to in mainline is that NINT
can often be implemented in one insn, rather than 

	if (x > 0)
	  result = (int) (x + 0.5);
	else
	  result = (int) (x - 0.5);

At minimum on those that don't, we should rewrite this to

	if (x > 0)
	  tmp = +0.5;
	else
	  tmp = -0.5;
	result = (int) (x + tmp);

or, if available,

	tmp = copysign(0.5, x);
	result = (int) (x + tmp);

just to factor the code a bit better.



r~


	* regclass.c (scan_one_insn): Notice subregs that change the
	size of their operand.
	(record_reg_classes): Use that to obey CLASS_CANNOT_CHANGE_SIZE.

Index: regclass.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/regclass.c,v
retrieving revision 1.54
diff -c -p -d -r1.54 regclass.c
*** regclass.c	1999/02/25 23:45:28	1.54
--- regclass.c	1999/07/14 05:59:19
*************** static int loop_cost;
*** 693,699 ****
  
  static rtx scan_one_insn	PROTO((rtx, int));
  static void record_reg_classes	PROTO((int, int, rtx *, enum machine_mode *,
! 				       const char **, rtx));
  static int copy_cost		PROTO((rtx, enum machine_mode, 
  				       enum reg_class, int));
  static void record_address_regs	PROTO((rtx, enum reg_class, int));
--- 693,699 ----
  
  static rtx scan_one_insn	PROTO((rtx, int));
  static void record_reg_classes	PROTO((int, int, rtx *, enum machine_mode *,
! 				       char *, const char **, rtx));
  static int copy_cost		PROTO((rtx, enum machine_mode, 
  				       enum reg_class, int));
  static void record_address_regs	PROTO((rtx, enum reg_class, int));
*************** scan_one_insn (insn, pass)
*** 757,762 ****
--- 757,763 ----
    enum rtx_code pat_code;
    const char *constraints[MAX_RECOG_OPERANDS];
    enum machine_mode modes[MAX_RECOG_OPERANDS];
+   char subreg_changes_size[MAX_RECOG_OPERANDS];
    rtx set, note;
    int i, j;
  
*************** scan_one_insn (insn, pass)
*** 794,799 ****
--- 795,801 ----
        constraints[i] = recog_constraints[i];
        modes[i] = recog_operand_mode[i];
      }
+   memset (subreg_changes_size, 0, sizeof (subreg_changes_size));
  
    /* If this insn loads a parameter from its stack slot, then
       it represents a savings, rather than a cost, if the
*************** scan_one_insn (insn, pass)
*** 881,887 ****
        op_costs[i] = init_cost;
  
        if (GET_CODE (recog_operand[i]) == SUBREG)
! 	recog_operand[i] = SUBREG_REG (recog_operand[i]);
  
        if (GET_CODE (recog_operand[i]) == MEM)
  	record_address_regs (XEXP (recog_operand[i], 0),
--- 883,894 ----
        op_costs[i] = init_cost;
  
        if (GET_CODE (recog_operand[i]) == SUBREG)
! 	{
! 	  rtx inner = SUBREG_REG (recog_operand[i]);
! 	  if (GET_MODE_SIZE (modes[i]) != GET_MODE_SIZE (GET_MODE (inner)))
! 	    subreg_changes_size[i] = 1;
! 	  recog_operand[i] = inner;
! 	}
  
        if (GET_CODE (recog_operand[i]) == MEM)
  	record_address_regs (XEXP (recog_operand[i], 0),
*************** scan_one_insn (insn, pass)
*** 910,921 ****
  	xconstraints[i] = constraints[i+1];
  	xconstraints[i+1] = constraints[i];
  	record_reg_classes (recog_n_alternatives, recog_n_operands,
! 			    recog_operand, modes, xconstraints,
! 			    insn);
        }
  
    record_reg_classes (recog_n_alternatives, recog_n_operands, recog_operand,
! 		      modes, constraints, insn);
  
    /* Now add the cost for each operand to the total costs for
       its register.  */
--- 917,928 ----
  	xconstraints[i] = constraints[i+1];
  	xconstraints[i+1] = constraints[i];
  	record_reg_classes (recog_n_alternatives, recog_n_operands,
! 			    recog_operand, modes, subreg_changes_size,
! 			    xconstraints, insn);
        }
  
    record_reg_classes (recog_n_alternatives, recog_n_operands, recog_operand,
! 		      modes, subreg_changes_size, constraints, insn);
  
    /* Now add the cost for each operand to the total costs for
       its register.  */
*************** regclass (f, nregs)
*** 1131,1141 ****
     alternatives.  */
  
  static void
! record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn)
       int n_alts;
       int n_ops;
       rtx *ops;
       enum machine_mode *modes;
       const char **constraints;
       rtx insn;
  {
--- 1138,1150 ----
     alternatives.  */
  
  static void
! record_reg_classes (n_alts, n_ops, ops, modes, subreg_changes_size,
! 		    constraints, insn)
       int n_alts;
       int n_ops;
       rtx *ops;
       enum machine_mode *modes;
+      char *subreg_changes_size;
       const char **constraints;
       rtx insn;
  {
*************** record_reg_classes (n_alts, n_ops, ops, 
*** 1393,1398 ****
--- 1402,1417 ----
  	      }
  
  	  constraints[i] = p;
+ 
+ #ifdef CLASS_CANNOT_CHANGE_SIZE
+ 	  /* If we noted a subreg earlier, and the selected class is a 
+ 	     subclass of CLASS_CANNOT_CHANGE_SIZE, zap it.  */
+ 	  if (subreg_changes_size[i]
+ 	      && (reg_class_subunion[(int) CLASS_CANNOT_CHANGE_SIZE]
+ 				    [(int) classes[i]]
+ 		  == CLASS_CANNOT_CHANGE_SIZE))
+ 	    classes[i] = NO_REGS;
+ #endif
  
  	  /* How we account for this operand now depends on whether it is  a
  	     pseudo register or not.  If it is, we first check if any



More information about the Gcc-bugs mailing list