Hi! The C FE always keeps DECL_BUILT_IN_CLASS when types match, even when newdecl defines a function. if (DECL_BUILT_IN (olddecl)) { /* If redeclaring a builtin function, it stays built in. But it gets tagged as having been declared. */ DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl); DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl); C_DECL_DECLARED_BUILTIN (newdecl) = 1; if (new_is_prototype) C_DECL_BUILTIN_PROTOTYPE (newdecl) = 0; else C_DECL_BUILTIN_PROTOTYPE (newdecl) = C_DECL_BUILTIN_PROTOTYPE (olddecl); } But the C++ FE doesn't do this: if (new_defines_function) ... else if (types_match) { /* If redeclaring a builtin function, and not a definition, it stays built in. */ if (DECL_BUILT_IN (olddecl)) { DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl); DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl); /* If we're keeping the built-in definition, keep the rtl, regardless of declaration matches. */ COPY_DECL_RTL (olddecl, newdecl); } ... This causes quite undesirable behavior e.g. on glibc headers on ppc with -mlong-double-64 (as shown on the testcase). Attached are two different patches, one does what the C FE does and copies DECL_BUILT_IN_CLASS etc. whenever types_match (bootstrapped/regtested on x86_64-linux). IMHO when you define memcpy in current CU (or some other builtins), there is no reason why any calls to that builtin from within other functions in the CU shouldn't be suddenly optimized as builtins. The second alternative patch only does that for gnu_inline wrappers - especially if the function is just extern inline __attribute__((gnu_inline)) without always_inline attribute, it might not be inlined in some places. Still they should be treated as builtin calls. I very much prefer the first patch though. Ok for trunk? Jakub