https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110589
Bug ID: 110589 Summary: Missed optimization with call-clobbered restrict qualified references Product: gcc Version: 14.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: javier.martinez.bugzilla at gmail dot com Target Milestone: --- I see this on GCC trunk and do not think it is a regression, the optimization is being taken by Clang. https://godbolt.org/z/G8qrzaKn9 extern void foo(void); int test_clobber_by_call (int * restrict val_ptr) { *val_ptr = 1; foo(); return *val_ptr; } GCC 14.0 -O3 produces: test_clobber_by_call: push rbx mov rbx, rdi mov BYTE PTR [rdi], 1 call foo movzx eax, BYTE PTR [rbx] ; <--- Not expected pop rbx ret I would expect restrict to be a guarantee that foo() will not alias val_ptr, producing: test_clobber_by_call: mov DWORD PTR [rdi], 1 call foo mov eax, 1 ret This is indeed the output when the compiler recognizes that foo does not alias, as in: __attribute((noinline)) void foo(int *a) { *(a+10) = 0; } int test_clobber_by_call (int * val_ptr) { *val_ptr = 1; foo(val_ptr); return *val_ptr; } ------------------------- It looks to me as if tree-ssa-alias.c#call_may_clobber_ref_p is not considering a restrict qualified reference. The following patch produces optimized code for the above example. I do not claim that it is correct, but it does reflect what I expected to see: diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index c3f43dc..277a21e 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -3037,6 +3037,16 @@ call_may_clobber_ref_p_1 (gcall *call, ao_ref *ref, bool tbaa_p) && SSA_NAME_POINTS_TO_READONLY_MEMORY (TREE_OPERAND (base, 0))) return false; + /* perhaps should be moved further up */ + if ((TREE_CODE (base) == MEM_REF + || TREE_CODE (base) == TARGET_MEM_REF) + && TREE_CODE(TREE_OPERAND (base, 0)) == SSA_NAME) + { + struct ptr_info_def *pi = SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0)); + if (pi && pi->pt.vars_contains_restrict) + return false; + } + if (int res = check_fnspec (call, ref, true)) { if (res == 1) test_clobber_by_call: sub rsp, 8 mov BYTE PTR [rdi], 1 call may_alias mov eax, 1 ; <----- deref gone add rsp, 8 ret