Skip to content

Efficient memcpy when src or dest can be nullptr #146484

Open
@QrczakMK

Description

@QrczakMK

How to obtain efficient memcpy() when src or dest can be nullptr (when the size is 0)? C++ only is relevant for me.

memcpy(_, nullptr, 0) and memcpy(nullptr, _, 0) have UB according to C and C++ standards, except that https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf has been accepted for the next C standard; I could find nothing for C++.

GCC makes use of that UB, e.g. by skipping explicit nullptr checks after memcpy(). Clang does not. Sanitizers are consistent with that.

In GCC, __builtin_memcpy() behaves like memcpy() in this respect, i.e. does not allow nullptr. This suggests that portable code (at least including GCC) one should not blindly issue memcpy() nor __builtin_memcpy() if null pointers are possible.

According to #49459, llvm.memcpy is safe to call with some null pointers and zero size, but I could not find a documentation that __builtin_memcpy() has this property too. The issue concludes with 'I think we can safely close this, with the answer being "yes, you can pass null pointer arguments"', but I feel uneasy relying on that comment without a more official documentation.

Clang nor GCC do not optimize portable if (len != 0) memcpy(dest, src, len) to a plain call to memcpy(), even though Clang could if it indeed assumes that actual memcpy() in the runtime library is valid with some null pointers and zero size.

Explicit zero checks slow down my implementation of joining a bunch of string_views by 14%.

What should I do, so that this is efficient at least on Clang?

In practice using __builtin_memcpy() or even memcpy() inside #ifdef __clang__ should work, but I would like to have a more official guarantee that this must work. And perhaps this requires some version check if the behavior changed in Clang in the past.

The same applies to memset().

Metadata

Metadata

Assignees

No one assigned

    Labels

    llvm:optimizationsquestionA question, not bug report. Check out https://llvm.org/docs/GettingInvolved.html instead!

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions