This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
cse fold_rtx tweek
- To: gcc-patches at gcc dot gnu dot org
- Subject: cse fold_rtx tweek
- From: Richard Henderson <rth at cygnus dot com>
- Date: Fri, 29 Sep 2000 16:21:11 -0700
! for (j = 0;
! j < 2 && replacements[j]
! && COST (replacements[j]) < COST (XEXP (x, i));
With the cost changes that happened a while back, this line
prevents constants (or anything else for that matter) from
ever being substituted for a register. Since registers now
have cost 0, nothing is ever cheaper. The following changes
this so that we prefer constants if they have the same cost.
I'm wondering if maybe we shouldn't prefer *anything* over a
register, so long as the outer code isn't a SET, since this
would provide some measure of height reduction. E.g.
(set r101 (plus r100 r99))
(set r102 (plus r100 r99))
(set r103 (plus r102 1))
-- r101 and r103 used later
At present this will simplify to
(set r101 (plus r100 r99))
(set r103 (plus r101 1))
but a better simplification for ia64 would be
(set r101 (plus r100 r99))
(set r103 (plus (plus r100 r99) 1))
Combine will not do this because both r101 and r103 are used,
and it doesn't have any concept of combination for height
reduction instead of reducing instruction count. Similar
examples can be shown with lea-type shift-and-add instructions.
I do not do anything with this idea here; I may shortly just
to see what sorts of effect it does have.
In addition to the > vs >= change, I also rearrange things
slightly so that we can provide the extra knowledge of the
outer code, which rtx_cost knows how to deal with, but we
were not providing in this instance.
Frankly, our treatment of costs here seems extremely hackful.
Note the apparently arbitrary scaling in notreg_cost. Note
the code in find_best_addr which appears to revert this
scaling, despite the fact that we only compare apples to
apples. Why aren't we examining the cost of the insn as a
whole instead of just looking at some random subexpression?
Tested on alpha, and ia64.
It's mostly a wash on alpha; we do get occasional substitutions
that help, e.g.
- lda $4,1
- cmpeq $19,$4,$1
+ cmpeq $19,1,$1
+ lda $5,1
but others that don't, e.g.
- cmovne $3,$9,$11
+ mov $9,$11
+ cmoveq $3,0,$11
Clearly this is a problem with whole-insn costs and/or the
register allocator. Not sure what to do about this...
On ia64 we can now simplify a sequence of shifts into a rotate
instruction, when the shift count was a constant argument to an
inline function. I've not examined the assembly differences in
more detail there.
r~
* cse.c (notreg_cost): New argument outer.
(COST): Pass in SET to notreg_cost
(COST_IN): New.
(fold_rtx): Use COST_IN. Prefer constants when costs
are the same.
Index: cse.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cse.c,v
retrieving revision 1.160
diff -c -p -d -r1.160 cse.c
*** cse.c 2000/09/15 02:56:02 1.160
--- cse.c 2000/09/29 07:16:25
*************** struct table_elt
*** 502,508 ****
|| ((N) < FIRST_PSEUDO_REGISTER \
&& FIXED_REGNO_P (N) && REGNO_REG_CLASS (N) != NO_REGS))
! #define COST(X) (GET_CODE (X) == REG ? 0 : notreg_cost (X))
/* Get the info associated with register N. */
--- 502,509 ----
|| ((N) < FIRST_PSEUDO_REGISTER \
&& FIXED_REGNO_P (N) && REGNO_REG_CLASS (N) != NO_REGS))
! #define COST(X) (GET_CODE (X) == REG ? 0 : notreg_cost (X, SET))
! #define COST_IN(X,OUTER) (GET_CODE (X) == REG ? 0 : notreg_cost (X, OUTER))
/* Get the info associated with register N. */
*************** struct cse_basic_block_data
*** 636,642 ****
|| XEXP (X, 0) == virtual_outgoing_args_rtx)) \
|| GET_CODE (X) == ADDRESSOF)
! static int notreg_cost PARAMS ((rtx));
static int approx_reg_cost_1 PARAMS ((rtx *, void *));
static int approx_reg_cost PARAMS ((rtx));
static int preferrable PARAMS ((int, int, int, int));
--- 637,643 ----
|| XEXP (X, 0) == virtual_outgoing_args_rtx)) \
|| GET_CODE (X) == ADDRESSOF)
! static int notreg_cost PARAMS ((rtx, enum rtx_code));
static int approx_reg_cost_1 PARAMS ((rtx *, void *));
static int approx_reg_cost PARAMS ((rtx));
static int preferrable PARAMS ((int, int, int, int));
*************** preferrable (cost_a, regcost_a, cost_b,
*** 800,807 ****
from COST macro to keep it simple. */
static int
! notreg_cost (x)
rtx x;
{
return ((GET_CODE (x) == SUBREG
&& GET_CODE (SUBREG_REG (x)) == REG
--- 801,809 ----
from COST macro to keep it simple. */
static int
! notreg_cost (x, outer)
rtx x;
+ enum rtx_code outer;
{
return ((GET_CODE (x) == SUBREG
&& GET_CODE (SUBREG_REG (x)) == REG
*************** notreg_cost (x)
*** 813,819 ****
&& TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (GET_MODE (x)),
GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x)))))
? 0
! : rtx_cost (x, SET) * 2);
}
/* Return an estimate of the cost of computing rtx X.
--- 815,821 ----
&& TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (GET_MODE (x)),
GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x)))))
? 0
! : rtx_cost (x, outer) * 2);
}
/* Return an estimate of the cost of computing rtx X.
*************** fold_rtx (x, insn)
*** 3752,3758 ****
/* Pick the least expensive of the folded argument and an
equivalent constant argument. */
if (const_arg == 0 || const_arg == folded_arg
! || COST (const_arg) > COST (folded_arg))
cheap_arg = folded_arg, expensive_arg = const_arg;
else
cheap_arg = const_arg, expensive_arg = folded_arg;
--- 3754,3760 ----
/* Pick the least expensive of the folded argument and an
equivalent constant argument. */
if (const_arg == 0 || const_arg == folded_arg
! || COST_IN (const_arg, code) > COST_IN (folded_arg, code))
cheap_arg = folded_arg, expensive_arg = const_arg;
else
cheap_arg = const_arg, expensive_arg = folded_arg;
*************** fold_rtx (x, insn)
*** 3772,3783 ****
copied = 1;
}
! replacements[0] = cheap_arg, replacements[1] = expensive_arg;
! for (j = 0;
! j < 2 && replacements[j]
! && COST (replacements[j]) < COST (XEXP (x, i));
! j++)
{
if (validate_change (insn, &XEXP (x, i), replacements[j], 0))
break;
--- 3774,3794 ----
copied = 1;
}
! /* Order the replacements from cheapest to most expensive. */
! replacements[0] = cheap_arg;
! replacements[1] = expensive_arg;
!
! for (j = 0; j < 2 && replacements[j]; j++)
{
+ int old_cost = COST_IN (XEXP (x, i), code);
+ int new_cost = COST_IN (replacements[j], code);
+
+ /* Stop if what existed before was cheaper. Prefer constants
+ in the case of a tie. */
+ if (new_cost > old_cost
+ || (new_cost == old_cost && CONSTANT_P (XEXP (x, i))))
+ break;
+
if (validate_change (insn, &XEXP (x, i), replacements[j], 0))
break;