>> Now, in order to get rid of the subregs in the pattern combine creates, >> I would need to be able to do something like >> >> (define_subst "subreg_subst" >> [(set (match_operand:DI 0 "" "") >> (shift:DI (match_operand:DI 1 "" "") >> (subreg:SI (match_dup:DI 2)))] >> >> where the (match_dup:DI 2) would capture both (and:SI ...) [with the >> first argument being either a register or an already substituted >> (plus:SI ...)] as well as a simple (plus:SI ...). >> >> As far as I can tell match_dup:mode can be used to change the mode of >> the top-level operation but the operands will remain the same. For >> this, a match_dup_deep or whatever would be useful. I'm pretty sure we >> don't want to open this can of worms, though :) [..]
> Painful. I doubt exposing the masking during the RTL expansion phase > and hoping the standard optimizers will eliminate it would work better > -- though perhaps if the expanders queried the global range information > and elided the masking when the range of the shift was known to be in range. I went for another approach - creating a dedicated big predicate and a constraint that captures the full subreg (and (plus ...))) block. This, however lead to reload problems: When needing to spill the shiftcount register, it would not be able to reload the full operation including and/plus etc. and just bail out/ICE. I guess that's expected behavior since the predicate is too generic to handle now. Andreas suggested a secondary reload for that but we're not sure whether we really want that. Thinking back at the mode-changing "match_dup_deep", I still cannot imagine how to define this in a sane way or rather where to stop with mode changing (e.g. what about mems). What I would need it to do is (and:SI (reg:SI const_int)) --> (and:DI (reg:DI) const_int) (plus:SI (reg:SI const_int)) --> (plus:DI (reg:DI const_int)) (and:SI (plus:SI (reg:SI const_int)) const_int) --> (and:DI (plus:DI (reg:DI const_int)) const_int) Any other ideas how to achieve that without tons of boilerplate code? Regards Robin