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.

Reply via email to