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
  • [Bug tree-optimizat... javier.martinez.bugzilla at gmail dot com via Gcc-bugs

Reply via email to