https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63184
--- Comment #19 from Richard Biener <rguenth at gcc dot gnu.org> --- Btw, we alread manage to do sth like that on RTL. typedef __UINTPTR_TYPE__ uintptr_t; char a[1024]; char foo (uintptr_t b, uintptr_t c, uintptr_t d, uintptr_t e, uintptr_t f) { uintptr_t tem = b + c + d + e + f + 1; return *(a + tem); } with the patch changes - _14 = f_10(D) + 1; - _15 = e_9(D) + _14; - _16 = d_8(D) + _15; - _17 = c_7(D) + _16; - tem_11 = b_6(D) + _17; - _5 = &a + tem_11; + _14 = e_9(D) + f_10(D); + _15 = d_8(D) + _14; + _16 = c_7(D) + _15; + tem_11 = b_6(D) + _16; + _5 = &MEM[(void *)&a + 1B] + tem_11; _13 = *_5; return _13; but the asssembler is the same addq %rsi, %rdi addq %rdx, %rdi addq %rcx, %rdi movzbl a+1(%r8,%rdi), %eax ret disabling TER makes it worse without the patch but not with: leaq 1(%r8,%rcx), %rax addq %rax, %rdx addq %rdx, %rsi movzbl a(%rsi,%rdi), %eax ret so I guess the incremental RTL build canonicalizes the constant outermost. At least the patch looks like being in the correct direction for the goal of removing TER... Still most of the time the issue will be that ptr + a + b + c + 1 cannot be handled because of the intermediate conversion. That could be mitigated by moving the constant part out of an outer conversion (when permitted).