https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85090
--- Comment #11 from Uroš Bizjak <ubizjak at gmail dot com> --- (In reply to Jakub Jelinek from comment #5) > I guess it depends on what exactly a normal subreg on lhs means. > The documentation says: > When used as an lvalue, 'subreg' is a word-based accessor. > Storing to a 'subreg' modifies all the words of REG that > overlap the 'subreg', but it leaves the other words of REG > alone. I believe that the above wording is intended to describe the following test: --cut here-- union u { long long ll; int i[2]; }; union u test (union u a) { a.ll >>= 3; a.i[0] = 5; a.ll <<= 3; return a; } --cut here-- gcc -O2 -m27332: _.273r.ira shows: (insn 8 7 9 2 (parallel [ (set (reg/v:DI 92 [ a ]) (ashiftrt:DI (reg/v:DI 92 [ a ]) (const_int 3 [0x3]))) (clobber (reg:CC 17 flags)) ]) "subr.c":9 532 {*ashrdi3_doubleword} (expr_list:REG_UNUSED (reg:CC 17 flags) (nil))) (insn 9 8 10 2 (set (subreg:SI (reg/v:DI 92 [ a ]) 0) (const_int 5 [0x5])) "subr.c":10 82 {*movsi_internal} (nil)) (insn 10 9 12 2 (parallel [ (set (reg:DI 94) (ashift:DI (reg/v:DI 92 [ a ]) (const_int 3 [0x3]))) (clobber (reg:CC 17 flags)) ]) "subr.c":11 503 {*ashldi3_doubleword} (expr_list:REG_DEAD (reg/v:DI 92 [ a ]) (expr_list:REG_UNUSED (reg:CC 17 flags) (expr_list:REG_EQUIV (mem/c:DI (reg/f:SI 91 [ .result_ptr ]) [1 <retval>+0 S8 A32]) (nil))))) please note (insn 9), which LRA converts to: (insn 8 7 9 2 (parallel [ (set (reg/v:DI 4 si [orig:92 a ] [92]) (ashiftrt:DI (reg/v:DI 4 si [orig:92 a ] [92]) (const_int 3 [0x3]))) (clobber (reg:CC 17 flags)) ]) "subr.c":9 532 {*ashrdi3_doubleword} (nil)) (insn 9 8 20 2 (set (reg:SI 4 si [orig:92 a ] [92]) (const_int 5 [0x5])) "subr.c":10 82 {*movsi_internal} (nil)) (insn 20 9 10 2 (set (reg:DI 2 cx [94]) (reg/v:DI 4 si [orig:92 a ] [92])) "subr.c":11 81 {*movdi_internal} (nil)) (insn 10 20 12 2 (parallel [ (set (reg:DI 2 cx [94]) (ashift:DI (reg:DI 2 cx [94]) (const_int 3 [0x3]))) (clobber (reg:CC 17 flags)) ]) "subr.c":11 503 {*ashldi3_doubleword} (expr_list:REG_EQUIV (mem/c:DI (reg/f:SI 0 ax [orig:91 .result_ptr ] [91]) [1 <retval>+0 S8 A32]) (nil))) In the above pass, using (insn 9), the compiler inserted a 32-bit word into the lowpart (%esi) of the multi-word register pair (%esi/%edi). In effect, "the other words of REG" are left alone, as the documentation says. But this wording applies only to multi-word registers. We can't use the above wording for 512bit single-word register, since we don't know how the move will affect the bits outside the subreg. We can say that the move "modifies all the words of REG that overlap the 'subreg', since we have only one 512-bit word of a 512-bit register. So, I think that the transformation in the Comment 10 is invalid for registers that can't be decomposed to independent word-sized registers (to use "word-based accessor"), e.g. V32HImode xmm20. Perhaps the mentioned alter_subreg should choose correct approach based on TARGET_HARD_REGNO_NREGS?