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

            Bug ID: 80148
           Summary: operand has impossible constraints
           Product: gcc
           Version: 7.0.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: inline-asm
          Assignee: unassigned at gcc dot gnu.org
          Reporter: dvyukov at google dot com
  Target Milestone: ---

This pop up in kernel code. We have:

#define __cmpxchg_double(pfx, p1, p2, o1, o2, n1, n2)                   \
({                                                                      \
        bool __ret;                                                     \
        __typeof__(*(p1)) __old1 = (o1), __new1 = (n1);                 \
        __typeof__(*(p2)) __old2 = (o2), __new2 = (n2);                 \
        asm volatile(pfx "cmpxchg%c4b %2; sete %0"                      \
                     : "=a" (__ret), "+d" (__old2),                     \
                       "+m" (*(p1)), "+m" (*(p2))                       \
                     : "i" (2 * sizeof(long)), "a" (__old1),            \
                       "b" (__new1), "c" (__new2));                     \
        __ret;                                                          \
})

#define arch_cmpxchg_double(p1, p2, o1, o2, n1, n2) \
        __cmpxchg_double(LOCK_PREFIX, p1, p2, o1, o2, n1, n2)

#define cmpxchg_double(p1, p2, o1, o2, n1, n2)                          \
({                                                                      \
        __typeof__(p1) ____p1 = (p1);                                   \
        kasan_check_write(____p1, 2 * sizeof(*____p1));                 \
        arch_cmpxchg_double(____p1, (p2), (o1), (o2), (n1), (n2));      \
})

And this is invoked as:

                if (cmpxchg_double(&page->freelist, &page->counters,
                                   freelist_old, counters_old,
                                   freelist_new, counters_new))

This fails with:
error: ‘asm’ operand has impossible constraints

However if I change cmpxchg_double as:

-       arch_cmpxchg_double(____p1, (p2), (o1), (o2), (n1), (n2));      \
+       arch_cmpxchg_double((p1), (p2), (o1), (o2), (n1), (n2));        \

It works.

I've tested with gcc version 7.0.1 20170307 (experimental) (GCC). Arnd Bergmann
reported that the problem happens with 4.9 through 7.0.1 for him. I've also
tried with gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3) and both versions
work.

It's unclear to me why introducing a local variable as "__typeof__(p1) ____p1 =
(p1)" and then using it fails. Whereas using p1 works. Essentially we have:

asm volatile("" "cmpxchg%c4b %2; sete %0" : "=a" (__ret), "+d" (__old2), "+m"
(*((&page->freelist))), "+m" (*((&page->counters))) : "i" (2 * sizeof(long)),
"a" (__old1), "b" (__new1), "c" (__new2));

vs:

__typeof__(&page->freelist) ____p1 = (&page->freelist);
...
asm volatile("" "cmpxchg%c4b %2; sete %0" : "=a" (__ret), "+d" (__old2), "+m"
(*(____p1)), "+m" (*((&page->counters))) : "i" (2 * sizeof(long)), "a"
(__old1), "b" (__new1), "c" (__new2));


It seems to me that both versions should work the same way.

I will attach preprocessed sources for both versions. They can be compiled as:

gcc slub1.c -fno-strict-aliasing -fno-common -Wno-format-security -std=gnu89
-fno-PIE -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -m32 -msoft-float
-mregparm=3 -freg-struct-return -fno-pic -mpreferred-stack-boundary=2
-march=i686 -mtune=pentium3 -Wa,-mtune=generic32 -ffreestanding
-DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -DCONFIG_AS_CFI_SECTIONS=1
-DCONFIG_AS_SSSE3=1 -DCONFIG_AS_CRC32=1 -DCONFIG_AS_AVX=1 -DCONFIG_AS_AVX2=1
-DCONFIG_AS_SHA1_NI=1 -DCONFIG_AS_SHA256_NI=1 -pipe -Wno-sign-compare
-fno-asynchronous-unwind-tables -fno-delete-null-pointer-checks
-Wno-frame-address -O2 --param=allow-store-data-races=0
-Wframe-larger-than=1024 -fno-stack-protector -Wno-unused-but-set-variable
-Wno-unused-const-variable -fno-omit-frame-pointer -fno-optimize-sibling-calls
-fno-var-tracking-assignments -fno-inline-functions-called-once
-Wdeclaration-after-statement -Wno-pointer-sign -fno-strict-overflow
-fconserve-stack -Werror=implicit-int -Werror=strict-prototypes
-Werror=date-time -Werror=incompatible-pointer-types -c

Reply via email to