https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113907
--- Comment #24 from Jakub Jelinek <jakub at gcc dot gnu.org> --- static inline int foo (int len, void *indata, void *outdata) { if (len < 0 || (len & 7) != 0) return 0; if (len != 0 && indata != outdata) __builtin_memcpy (outdata, indata, len); return len; } static inline int bar (int len, void *indata, void *outdata) { if (len < 0 || (len & 1) != 0) return 0; if (len != 0 && indata != outdata) __builtin_memcpy (outdata, indata, len); return len; } int (*volatile p1) (int, void *, void *) = foo; int (*volatile p2) (int, void *, void *) = bar; __attribute__((noipa)) int baz (int len, void *indata, void *outdata) { if ((len & 6) != 0) bar (len, indata, outdata); else foo (len, indata, outdata); } int main () { char buf[13] = "abcdefghijkl"; p2 (6, buf, buf + 6); if (__builtin_strcmp (buf, "abcdefabcdef")) __builtin_abort (); } Reproduces the wrong range in bar, but still doesn't crash nor abort. So I probably need some different size of the copying.