http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50762
--- Comment #10 from Ulrich Weigand <uweigand at gcc dot gnu.org> 2011-11-10
10:10:04 UTC ---
(In reply to comment #9)
> (In reply to comment #8)
>
> > The zero_extend is a fixed part of the insn pattern in question:
> >
> > (define_insn "*lea_4_zext"
> > [(set (match_operand:DI 0 "register_operand" "=r")
> > (zero_extend:DI
> > (match_operand:SI 1 "lea_address_operand" "p")))]
> >
> > Reload only ever changes what is *inside* the operands. It does not change
> > the
> > fixed parts of the pattern (outside of operands).
>
> If this is the case, then (const_int 1) is perfectly acceptable here.
However, it is rejected by the lea_address_operand predicate check
due to its mode (VOIDmode != SImode). This is a bit odd because most
standard predicates accept a CONST_INT no matter what mode is requested.
But in this case, lea_address_operand is defined as "normal" predicate
(using define_predicate), but does not fall back onto any other normal
predicate, only the "special" predicate address_operand. Therefore,
genpreds thinks it needs to add the mode check by itself, and this
version is quite strict and does not special-case CONST_INTs.
(Note that "address_operand" is special in that it uses its mode not
to check the mode of the address, but the mode of the memory operand
that is to be referred to -- on some machines, this makes a difference.)
Maybe one way to fix this would be to define lea_address_operand
using define_special_predicate and then implement an appropriate
mode check that handles CONST_INT by hand ...
> > Not sure why that doesn't happen. I'll have a look.
Hmm, there's this special code in find_reloads that attempts to
re-recognize patterns after structural changes to an address
were made:
/* If we now have a simple operand where we used to have a
PLUS or MULT, re-recognize and try again. */
if ((OBJECT_P (*recog_data.operand_loc[i])
|| GET_CODE (*recog_data.operand_loc[i]) == SUBREG)
&& (GET_CODE (recog_data.operand[i]) == MULT
|| GET_CODE (recog_data.operand[i]) == PLUS))
{
INSN_CODE (insn) = -1;
retval = find_reloads (insn, replace, ind_levels, live_known,
reload_reg_p);
return retval;
}
It's a bit unfortunate that this just ICEs if the modified
address is no longer recognized.
But if the lea_address_operand predicate is fixed as outlined
above, the problem should go away since the insn would then
be recognized.