[Bug c/95448] New: Missing optimization: pointer untag, re-tag should be no-op

dancol at dancol dot org gcc-bugzilla@gcc.gnu.org
Sun May 31 01:37:00 GMT 2020


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95448

            Bug ID: 95448
           Summary: Missing optimization: pointer untag, re-tag should be
                    no-op
           Product: gcc
           Version: 11.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: dancol at dancol dot org
  Target Milestone: ---

Consider the following code. make_vector2() ought to be equivalent to just
"return make_vector_val()", and under Clang (10.0), it is. But GCC generates
this code for make_vector2:

make_vector2:
        sub     rsp, 8
        call    make_vector_val
        add     rsp, 8
        and     rax, -8
        or      rax, 1
        ret

The assume() in the code ought to be sufficient for convincing GCC that it
doesn't need to munge the return value of make_vector_val(). Emacs uses
patterns like this one pretty frequently.

---

#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>

#define assume(x) do { if(!(x)) __builtin_unreachable(); } while(0)

enum { tagbits = 3 };

#define TAG_MASK (((uintptr_t)(1)<<tagbits) - 1)
#define TAG_VECTOR ((uintptr_t) 1)

typedef struct vector { double x; } vector;
typedef struct val {
    uintptr_t v;
} val;

static inline void *PTR_OF(val v)
{
    return (void *)(v.v & ~TAG_MASK);
}

static inline val TAG(void *v, uintptr_t tag)
{
    uintptr_t l = (uintptr_t) v;
    assume((l & TAG_MASK) == 0);
    return (val){l | tag};
}

extern val make_vector_val(void);

val make_vector2(void)
{
    val v = make_vector_val();
    assume((v.v & TAG_MASK) == TAG_VECTOR);
    struct vector *vs = PTR_OF(v);
    return TAG(vs, TAG_VECTOR);
}


More information about the Gcc-bugs mailing list