Regclass preferencing fix.

Jan Hubicka hubicka@atrey.karlin.mff.cuni.cz
Mon Nov 15 06:25:00 GMT 1999


Hi

The cost calculation regclass for output operands is incorrect. When class
is selected and cost for superset class is calculated, the may_move_cost
is used in reversed order as for input operands. This is incorrect, since
it will contain 0, because class is "subset" for it's point of view.

This results in choice of GENERAL_REGS for all output operands. (superset of
all classes and thus cost is always 0).

What we need is may_move_cost in reversed order for input operands.

As testcase consider for example the divmod patterns in i386. There is "output
only register" used for remainder value, that have constraint "=d". Because
of the bug, the GENERAL_REGS gets lowest cost, eax is choosed by local alloc
and many redundant moves are generated.

Mon Nov 15 12:06:35 CET 1999  Jan Hubicka  <hubicka@freesoft.cz>
	* regclass.c (may_move_in_cost): Rename from may_move_cost, all
	references updated.
	(may_move_out_cost): New variable.
	(init_reg_sets_1): Initialize may_move_out_cost.
	(record_reg_classes): Use may_move_out_cost.

*** regclass.c.old	Mon Nov 15 12:03:53 1999
--- regclass.c	Mon Nov 15 11:58:42 1999
*************** static int move_cost[N_REG_CLASSES][N_RE
*** 175,181 ****
  /* Similar, but here we don't have to move if the first index is a subset
     of the second so in that case the cost is zero.  */
  
! static int may_move_cost[N_REG_CLASSES][N_REG_CLASSES];
  
  #ifdef FORBIDDEN_INC_DEC_CLASSES
  
--- 175,186 ----
  /* Similar, but here we don't have to move if the first index is a subset
     of the second so in that case the cost is zero.  */
  
! static int may_move_in_cost[N_REG_CLASSES][N_REG_CLASSES];
! 
! /* Similar, but here we don't have to move if the first index is a superset
!    of the second so in that case the cost is zero.  */
! 
! static int may_move_out_cost[N_REG_CLASSES][N_REG_CLASSES];
  
  #ifdef FORBIDDEN_INC_DEC_CLASSES
  
*************** init_reg_sets_1 ()
*** 413,421 ****
  	move_cost[i][j] = cost;
  
  	if (reg_class_subset_p (i, j))
! 	  cost = 0;
  
! 	may_move_cost[i][j] = cost;
        }
  }
  
--- 418,431 ----
  	move_cost[i][j] = cost;
  
  	if (reg_class_subset_p (i, j))
! 	  may_move_in_cost[i][j] = 0;
! 	else
! 	  may_move_in_cost[i][j] = cost;
  
! 	if (reg_class_subset_p (j, i))
! 	  may_move_out_cost[i][j] = 0;
! 	else
! 	  may_move_out_cost[i][j] = cost;
        }
  }
  
*************** record_reg_classes (n_alts, n_ops, ops, 
*** 1251,1258 ****
  		  for (class = 0; class < N_REG_CLASSES; class++)
  		    pp->cost[class]
  		      = (recog_data.operand_type[i] == OP_IN
! 			 ? may_move_cost[class][(int) classes[i]]
! 			 : may_move_cost[(int) classes[i]][class]);
  		  
  		  /* If the alternative actually allows memory, make things
  		     a bit cheaper since we won't need an extra insn to
--- 1261,1268 ----
  		  for (class = 0; class < N_REG_CLASSES; class++)
  		    pp->cost[class]
  		      = (recog_data.operand_type[i] == OP_IN
! 			 ? may_move_in_cost[class][(int) classes[i]]
! 			 : may_move_out_cost[(int) classes[i]][class]);
  		  
  		  /* If the alternative actually allows memory, make things
  		     a bit cheaper since we won't need an extra insn to
*************** record_reg_classes (n_alts, n_ops, ops, 
*** 1270,1276 ****
  
  		  if (prefclass)
  		    alt_cost
! 		      += (may_move_cost[(unsigned char) prefclass[REGNO (op)]]
  			  [(int) classes[i]]);
  
  		  if (REGNO (ops[i]) != REGNO (ops[j])
--- 1280,1286 ----
  
  		  if (prefclass)
  		    alt_cost
! 		      += (may_move_in_cost[(unsigned char) prefclass[REGNO (op)]]
  			  [(int) classes[i]]);
  
  		  if (REGNO (ops[i]) != REGNO (ops[j])
*************** record_reg_classes (n_alts, n_ops, ops, 
*** 1472,1479 ****
  		  for (class = 0; class < N_REG_CLASSES; class++)
  		    pp->cost[class]
  		      = (recog_data.operand_type[i] == OP_IN
! 			 ? may_move_cost[class][(int) classes[i]]
! 			 : may_move_cost[(int) classes[i]][class]);
  
  		  /* If the alternative actually allows memory, make things
  		     a bit cheaper since we won't need an extra insn to
--- 1482,1489 ----
  		  for (class = 0; class < N_REG_CLASSES; class++)
  		    pp->cost[class]
  		      = (recog_data.operand_type[i] == OP_IN
! 			 ? may_move_in_cost[class][(int) classes[i]]
! 			 : may_move_out_cost[(int) classes[i]][class]);
  
  		  /* If the alternative actually allows memory, make things
  		     a bit cheaper since we won't need an extra insn to
*************** record_reg_classes (n_alts, n_ops, ops, 
*** 1491,1497 ****
  
  		  if (prefclass)
  		    alt_cost
! 		      += (may_move_cost[(unsigned char) prefclass[REGNO (op)]]
  			  [(int) classes[i]]);
  		}
  	    }
--- 1501,1507 ----
  
  		  if (prefclass)
  		    alt_cost
! 		      += (may_move_in_cost[(unsigned char) prefclass[REGNO (op)]]
  			  [(int) classes[i]]);
  		}
  	    }
*************** record_address_regs (x, class, scale)
*** 1809,1815 ****
  	pp->mem_cost += (MEMORY_MOVE_COST (Pmode, class, 1) * scale) / 2;
  
  	for (i = 0; i < N_REG_CLASSES; i++)
! 	  pp->cost[i] += (may_move_cost[i][(int) class] * scale) / 2;
        }
        break;
  
--- 1819,1825 ----
  	pp->mem_cost += (MEMORY_MOVE_COST (Pmode, class, 1) * scale) / 2;
  
  	for (i = 0; i < N_REG_CLASSES; i++)
! 	  pp->cost[i] += (may_move_in_cost[i][(int) class] * scale) / 2;
        }
        break;
  


More information about the Gcc-patches mailing list