On Tue, Dec 10, 2013 at 9:57 AM, Richard Sandiford <rdsandif...@googlemail.com> wrote: > "H.J. Lu" <hjl.to...@gmail.com> writes: >> On Tue, Dec 10, 2013 at 8:05 AM, Kirill Yukhin <kirill.yuk...@gmail.com> >> wrote: >>> On 09 Dec 14:08, H.J. Lu wrote: >>>> >>>> There are no regressions on Linux/x86-64 with -m32 and -m64. >>>> Can you check if it improves code quality on x886? >>> >>> As second thought. If Tejas and Richard are right and it is simply incorrect >>> to check any offsets in this hook, may be we can end up with patch in the >>> bottom? >> >> What is wrong to pass the correct offset to >> CANNOT_CHANGE_MODE_CLASS? Backends are free to >> ignore it. > > The point is that: > >>> - /* Vector registers do not support subreg with nonzero offsets, which >>> - are otherwise valid for integer registers. Since we can't see >>> - whether we have a nonzero offset from here, prohibit all >>> - nonparadoxical subregs changing size. */ >>> - if (GET_MODE_SIZE (to) < GET_MODE_SIZE (from)) >>> - return true; > > seems to be trying to reject things like (subreg:SF (reg:V4SF X) 1), > which is always invalid for a single-register V4SF. See:
That is correct. > http://gcc.gnu.org/ml/gcc-patches/2013-12/msg00824.html > > for the longer version. In all places where CANNOT_CHANGE_MODE_CLASS is used, only mode_change_ok, record_subregs_of_mode and inherit_piecemeal_p don't have the known subreg offset. In all other places, we know what exactly the subreg offset is. When the subreg offset is passed to CANNOT_CHANGE_MODE_CLASS, a backend can have (subreg:DI (match_operand:V4SF 1 "register_operand" "x,x") 0) in patterns. I pushed hjl/subreg branch to GCC git repo with a new pattern: (define_insn "*mov<VMOVE:mode><VMOVE_SWI48:mode>_subreg" [(set (match_operand:VMOVE_SWI48 0 "nonimmediate_operand" "=rxm") (subreg:VMOVE_SWI48 (match_operand:VMOVE 1 "register_operand" "x") 0))] "" { #if 1 /* Help check where the subreg pattern is used. */ debug_rtx (insn); abort (); #else /* Handle broken assemblers that require movd instead of movq. */ if (<VMOVE_SWI48:MODE>mode == SImode || (!HAVE_AS_IX86_INTERUNIT_MOVQ && (GENERAL_REG_P (operands[0])))) return "%vmovd\t{%x1, %0|%0, %x1}"; return "%vmovq\t{%x1, %0|%0, %1x}"; #endif } [(set_attr "type" "ssemov") (set_attr "prefix" "maybe_vex") (set_attr "mode" "<VMOVE_SWI48:MODE>")]) I ran GCC testsuites with all languages enabled. This pattern is triggered 1178 times. I checked a few of them. The new patten leads to reg-reg move instead of mem-reg load. -- H.J.