https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66866
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Keywords| |wrong-code Target| |x86_64-*-* CC| |uros at gcc dot gnu.org --- Comment #3 from Richard Biener <rguenth at gcc dot gnu.org> --- Expansion is already wrong: ;; MEM[(A * {ref-all})&r + 10B] = _2; (insn 6 5 7 (set (reg:TI 92) (subreg:TI (reg/v:V2DI 91 [ v ]) 0)) t.c:8 -1 (nil)) (insn 7 6 8 (set (reg:V8HI 93) (vec_merge:V8HI (vec_duplicate:V8HI (subreg:HI (reg:TI 92) 0)) (subreg:V8HI (reg/v:V2DI 89 [ r ]) 0) (const_int 32 [0x20]))) t.c:8 -1 (nil)) (insn 8 7 0 (set (reg/v:V2DI 89 [ r ]) (subreg:V2DI (reg:V8HI 93) 0)) t.c:8 -1 (nil)) (subreg:HI (reg:TI 92) 0) selects the wrong source. We go /* In cases where an aligned union has an unaligned object as a field, we might be extracting a BLKmode value from an integer-mode (e.g., SImode) object. Handle this case by doing the extract into an object as wide as the field (which we know to be the width of a basic mode), then storing into memory, and changing the mode to BLKmode. */ if (mode1 == VOIDmode ... op0 = extract_bit_field (op0, bitsize, bitpos, unsignedp, (modifier == EXPAND_STACK_PARM ? NULL_RTX : target), ext_mode, ext_mode); (gdb) p debug_rtx (op0) (reg/v:V2DI 91 [ v ]) (gdb) p bitsize $7 = 16 (gdb) p bitpos $8 = 64 (gdb) p ext_mode $9 = HImode which gets us (gdb) p debug_rtx (op0) (subreg:HI (reg:TI 92) 8) so handling the load is fine. Ultimately returned to #0 0x0000000000c1bf17 in store_field (target=0x7ffff6a49d80, bitsize=16, bitpos=80, bitregion_start=80, bitregion_end=95, mode=HImode, exp=<ssa_name 0x7ffff68d5b40>, alias_set=0, nontemporal=false) at /space/rguenther/tramp3d/trunk/gcc/expr.c:6643 #1 0x0000000000c1582a in expand_assignment (to=<mem_ref 0x7ffff6a42168>, from=<ssa_name 0x7ffff68d5b40>, nontemporal=false) at /space/rguenther/tramp3d/trunk/gcc/expr.c:5016 and leading to #0 store_bit_field_1 (str_rtx=0x7ffff6a49d80, bitsize=16, bitnum=80, bitregion_start=80, bitregion_end=95, fieldmode=HImode, value=0x7ffff6a49f18, fallback_p=true) at /space/rguenther/tramp3d/trunk/gcc/expmed.c:881 876 /* If OP0 is a multi-word register, narrow it to the affected word. 877 If the region spans two words, defer to store_split_bit_field. */ 878 if (!MEM_P (op0) && GET_MODE_SIZE (GET_MODE (op0)) > UNITS_PER_WORD) 879 { and finally using the insv path. Breakpoint 7, store_bit_field_using_insv (insv=0x7fffffffd380, op0=0x7ffff6a49f48, bitsize=16, bitnum=16, value=0x7ffff6a49f18) at /space/rguenther/tramp3d/trunk/gcc/expmed.c:508 508 rtx xop0 = op0; (gdb) p debug_rtx (op0) (subreg:DI (reg/v:V2DI 89 [ r ]) 8) $40 = void (gdb) p debug_rtx (value) (subreg:HI (reg:TI 92) 8) $41 = void creating insv with 611 create_fixed_operand (&ops[0], xop0); 612 create_integer_operand (&ops[1], bitsize); 613 create_integer_operand (&ops[2], bitnum); 614 create_input_operand (&ops[3], value1, op_mode); (gdb) p debug_rtx (xop0) (subreg:DI (reg/v:V2DI 89 [ r ]) 8) $47 = void (gdb) p debug_rtx (value1) (subreg:DI (reg:TI 92) 8) $48 = void (gdb) p bitsize $49 = 16 (gdb) p bitnum $50 = 16