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]

Re: RFA: Fix DF--subreg->DI--truncate->SI problems in combine.c


On 08/05/09 12:43, Richard Sandiford wrote:
This patch restores mipsisa64-elf builds.  The problem is that we
try to force the expression:

     (and:DI (subreg:DI (reg:DF foo) 0)
             (const_int 1))

into SImode.  Let the whole expression be A, the subreg be S and
the reg be R.  force_to_mode simplifies the expression by calling:

simplify_and_const_int (A, SImode, S, 1)

which looks odd, but is OK: simplify_and_const allows the operands
to have a different mode from the result.  It handles this by calling:

force_to_mode (SImode, S, ...)

and the subreg case of that function calls:

force_to_mode (SImode, R, ...)

At this point we're truncating a DFmode register into SImode.
This results in a call:

gen_lowpart_or_truncate (SImode, R)

which produces:

(truncate:SI (reg:DF foo))

And that's not a meaningful combination of modes.  The question then is:
where did things go wrong?  The comments above force_to_mode don't
really say what the preconditions are, but I think it's obvious from
extracts like:

   op_mode = ((GET_MODE_CLASS (mode) == GET_MODE_CLASS (GET_MODE (x))
	&&  have_insn_for (code, mode))
	     ? mode : GET_MODE (x));

and:

   if (VECTOR_MODE_P (mode) || VECTOR_MODE_P (GET_MODE (x)))
     return gen_lowpart (mode, x);

that the function is being used for arbitrary modes.  (Experimenting with
a few asserts bears this out.)  This means that gen_lowpart_or_truncate
should also handle arbitrary modes.  Furthermore, although the SUBREG
implied by:

gen_lowpart_or_truncate (SImode, R)

is not valid, it isn't the caller's responsibility to check this.
Instead, gen_lowpart_for_combine returns a (clobber:SI (const_int 0)).

So I think the truncate code in gen_lowpart_of_truncate should
be prepared to handle the general (possibly invalid) case too.
(And TRULY_NOOP_TRUNCATION _should_ be applied to non-integer modes,
since we would otherwise lose the truncation if we did conversions
such as V2SF ->  SF, then -- perhaps separately -- SF ->  SI.)

Another thing bugged me while looking at this.  The handling of
binary operations is:

       /* For most binary operations, just propagate into the operation and
	 change the mode if we have an operation of that mode.  */

       op0 = force_to_mode (XEXP (x, 0), mode, mask, next_select);
       op1 = force_to_mode (XEXP (x, 1), mode, mask, next_select);

...

       op0 = gen_lowpart_or_truncate (op_mode, op0);
       op1 = gen_lowpart_or_truncate (op_mode, op1);

       if (op_mode != GET_MODE (x) || op0 != XEXP (x, 0) || op1 != XEXP (x, 1))
	x = simplify_gen_binary (code, op_mode, op0, op1);

I think it's clear that this only makes sense for integer modes,
but the vector condition quoted above shows that we're not just
getting integer modes.  So I think it would be safer to use an
inclusive SCALAR_INT_MODE check than an exclusive !VECTOR_MODE_P check.

Bootstrapped&  regression-tested on x86_64-linux-gnu.  Also tested
on mipsisa64-elf, where the build is restored.  OK to install?

Richard


gcc/
* combine.c (gen_lowpart_or_truncate): Exclude CONST_INTs from
mode check. Do truncations in an integer mode.
(force_to_mode): Handle subregs for all mode types. Only do
arithmetic simplifications on integer modes.
OK.
Jeff


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