https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70424
Bug ID: 70424 Summary: [4.9/5/6 Regression] Pointer derived from integer gets reduced alignment Product: gcc Version: 4.9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end Assignee: unassigned at gcc dot gnu.org Reporter: amonakov at gcc dot gnu.org Target Milestone: --- int f(long a) { int *p=(int*)(a<<1); //asm("" : "+r"(p)); return *p; } Starting from 4.9, in the above example GCC assumes that *p is aligned to 16 bits (on 4.8 and earlier, to 32 bits, like normal int*). This causes the load to be torn in two on strict-alignment targets; using -O0 or uncommenting the asm restores old behavior (one 32-bit load). This change seems unintended. On x86_64 it's visible on RTL level (note A32->A16 change): gcc-4.8.0 -S t.c -Os -o- -dP #(insn:TI 7 3 15 2 (set (reg:SI 0 ax [orig:66 *p_3 ] [66]) # (mem:SI (plus:DI (reg/v:DI 5 di [orig:63 a ] [63]) # (reg/v:DI 5 di [orig:63 a ] [63])) [2 *p_3+0 S4 A32])) align.c:5 89 {*movsi_internal} # (expr_list:REG_DEAD (reg/v:DI 5 di [orig:63 a ] [63]) # (nil))) movl (%rdi,%rdi), %eax # 7 *movsi_internal/1 [length = 3] gcc-4.9.2 -S t.c -Os -o- -dP #(insn:TI 7 3 13 2 (set (reg:SI 0 ax [orig:90 *p_3 ] [90]) # (mem:SI (plus:DI (reg/v:DI 5 di [orig:87 a ] [87]) # (reg/v:DI 5 di [orig:87 a ] [87])) [2 *p_3+0 S4 A16])) align.c:5 90 {*movsi_internal} # (expr_list:REG_DEAD (reg/v:DI 5 di [orig:87 a ] [87]) # (nil))) movl (%rdi,%rdi), %eax # 7 *movsi_internal/1 [length = 3]