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.