[PATCH] D90231: [GVN] Don't replace argument to @llvm.is.constant.*()
Jonas Paulsson via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 29 04:19:06 PDT 2020
jonpa added a comment.
In D90231#2358870 <https://reviews.llvm.org/D90231#2358870>, @joerg wrote:
> I completely agree with Roman that this patch is very undesirable since it has a high chance of breaking other reasonable uses of the intrinsic.
Would it help if the replaceXXXUsesWith() only excluded the intrinsic from this particular GVN optimization, and not all the time?
> In fact, I would say that the observed behavior here is perfectly reasonable under the definition of @lllvm.is.constant. The original code for LLVM at least should be just `__builtin_constant_p(b) && b > -129 && b < 128)`.
The example is reduced but still represents code in the Linux kernel compilable by GCC, but not by clang. Here is a bigger picture (still reduced, but not as much:
static inline __attribute__((__gnu_inline__)) __attribute__((__unused__))
__attribute__((__no_instrument_function__))
__attribute__((__always_inline__)) void
__atomic_add_const(int val, int *ptr)
{
asm volatile("asi"
" %[ptr],%[val]\n"
"\n"
: [ptr] "+Q"(*ptr)
: [val] "i"(val)
: "cc", "memory");
}
static inline __attribute__((__gnu_inline__)) __attribute__((__unused__))
__attribute__((__no_instrument_function__)) int
__atomic_add(int val, int *ptr)
{
int old;
asm volatile("laa"
" %[old],%[val],%[ptr]\n"
"\n"
: [old] "=d"(old), [ptr] "+Q"(*ptr)
: [val] "d"(val)
: "cc", "memory");
return old;
}
static inline __attribute__((__gnu_inline__)) __attribute__((__unused__))
__attribute__((__no_instrument_function__)) void
atomic_add(int i, atomic_t *v)
{
if ((__builtin_constant_p(
!!((i > -129) && (i < 128) && __builtin_constant_p(i))) ?
(!!((i > -129) && (i < 128) && __builtin_constant_p(i))) :
({ (!!((i > -129) && (i < 128) && __builtin_constant_p(i))) ? 1 : 0; }))) {
__atomic_add_const(i, &v->counter);
return;
}
__atomic_add(i, &v->counter);
}
void tty_buffer_reset(long size);
void tty_buffer_alloc(atomic_t v, long size)
{
size = ((((size)) + ((255))) & ~((255)));
tty_buffer_reset(size);
atomic_add(size, &v);
}
#define IB_SET_POST_CREDITS(v) ((v) << 16)
void rds_ib_advertise_credits(atomic_t v, unsigned int posted)
{
atomic_add(IB_SET_POST_CREDITS(posted), &v);
}
/*
* more cases like:
* atomic64_add((u64)bo->num_pages << PAGE_SHIFT, &rdev->num_bytes_moved);
*/
As this shows, atomic_add_const() is supposed to be called only when atomic_add() is called with a compile-time constant. Note that __atomic_add_const() (after inlining etc) will not even compile if the argument is not const, since it uses the "i" inline asm constraint. So having a runtime check against 0 is not acceptable - it doesn't compile!
I wonder
- what other use case of __builtin_constant_p() would make this runtime check desirable?
- what other way than disabling this in GVN is there to make the test case compile?
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D90231/new/
https://reviews.llvm.org/D90231
More information about the llvm-commits
mailing list