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