This is an archive of the discontinued LLVM Phabricator instance.

[libc++] Factor out common logic for calling aligned allocation
ClosedPublic

Authored by ldionne on Nov 12 2020, 12:28 PM.

Details

Reviewers
EricWF
Group Reviewers
Restricted Project
Restricted Project
Commits
rGa78aaa1ad512: [libc++] Factor out common logic for calling aligned allocation
Summary

There were a couple of places where we needed to call the underlying
platform's aligned allocation/deallocation function. Instead of having
the same logic all over the place, extract the logic into a pair of
helper functions libcpp_aligned_alloc and libcpp_aligned_free.

The code in libcxxabi/src/fallback_malloc.cpp looks like it could be
simplified after this change -- I purposefully did not simplify it
further to keep this change as straightforward as possible, since it
is touching very important parts of the library.

Also, the changes in libcxx/src/new.cpp and libcxxabi/src/stdlib_new_delete.cpp
are basically the same -- I just kept both source files in sync.

The underlying reason for this refactoring is to make it easier to support
platforms that provide aligned allocation through C11's aligned_alloc
function instead of posix_memalign. After this change, we'll only have
to add support for that in a single place.

Diff Detail

Event Timeline

ldionne created this revision.Nov 12 2020, 12:28 PM
Herald added projects: Restricted Project, Restricted Project. · View Herald TranscriptNov 12 2020, 12:28 PM
Herald added a reviewer: Restricted Project. · View Herald Transcript
Herald added a reviewer: Restricted Project. · View Herald Transcript
ldionne requested review of this revision.Nov 12 2020, 12:28 PM
EricWF accepted this revision.Nov 12 2020, 1:30 PM
This revision is now accepted and ready to land.Nov 12 2020, 1:30 PM
ldionne updated this revision to Diff 307381.Nov 24 2020, 9:07 AM

Guard with !defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION)

This revision was landed with ongoing or failed builds.Nov 25 2020, 12:45 PM
This revision was automatically updated to reflect the committed changes.
dmajor added a subscriber: dmajor.Nov 30 2020, 10:01 AM

Our mingw builds are failing with error: no member named '_aligned_malloc' in the global namespace. Should the new header have an #include <malloc.h> somewhere?

Our mingw builds are failing with error: no member named '_aligned_malloc' in the global namespace. Should the new header have an #include <malloc.h> somewhere?

That's weird, as we were not including <malloc.h> anywhere before either. Can you confirm that including <malloc.h> fixes your issue? I'm wary of adding non standard includes in our headers, since it causes all kinds of problems.

dmajor added a subscriber: mstorsjo.Dec 1 2020, 8:10 PM

Our mingw builds are failing with error: no member named '_aligned_malloc' in the global namespace. Should the new header have an #include <malloc.h> somewhere?

That's weird, as we were not including <malloc.h> anywhere before either. Can you confirm that including <malloc.h> fixes your issue? I'm wary of adding non standard includes in our headers, since it causes all kinds of problems.

That didn't fix our issue. On closer inspection I think this is a weirdness in the mingw headers but I could use a double check: https://github.com/mirror/mingw-w64/search?q=_MM_MALLOC_H_INCLUDED

_aligned_malloc can be provided by either <malloc.h> or <stdlib.h>, as long as you haven't defined _MM_MALLOC_H_INCLUDED. Previously, new.cpp worked because it included <stdlib.h> first thing. Now, in our build, translation units that first include <intrin.h> will set _MM_MALLOC_H_INCLUDED which prevents anything later from picking up _aligned_malloc. Am I interpreting that correctly? This trickery in <intrin.h> seems very strange...

That didn't fix our issue. On closer inspection I think this is a weirdness in the mingw headers but I could use a double check: https://github.com/mirror/mingw-w64/search?q=_MM_MALLOC_H_INCLUDED

_aligned_malloc can be provided by either <malloc.h> or <stdlib.h>, as long as you haven't defined _MM_MALLOC_H_INCLUDED. Previously, new.cpp worked because it included <stdlib.h> first thing. Now, in our build, translation units that first include <intrin.h> will set _MM_MALLOC_H_INCLUDED which prevents anything later from picking up _aligned_malloc. Am I interpreting that correctly? This trickery in <intrin.h> seems very strange...

I haven't run into this issue - how do you end up getting intrin.h included before the other includes here?

As for the mingw headers, yeah that aspect with _mm_malloc vs _aligned_malloc does seem like a bit of a mess - digging through the history finds commits from 2009 and 2010 that touched that, but I can't entirely make out what they attempted to do... I'll see if I can manage to fix that (figure out exactly what it did attempt to do back in 2010, and straighten out a bit of it). Anything relating to intrin.h is a huge mess though, as it is pretty tightly coupled with the compiler and interacts with compiler provided headers.

dmajor added a comment.Dec 2 2020, 8:41 AM

I haven't run into this issue - how do you end up getting intrin.h included before the other includes here?

Any case with intrin.h coming first should do it:

$ cat test.cpp
#include <intrin.h>
#include <new>

$ ./clang/bin/x86_64-w64-mingw32-clang++ -c test.cpp 
In file included from test.cpp:2:
/home/vm/Desktop/mingwtest/clang/bin/../x86_64-w64-mingw32/include/c++/v1/new:314:12: error: no member named '_aligned_malloc' in the global namespace
  return ::_aligned_malloc(__size, __alignment);
         ~~^
/home/vm/Desktop/mingwtest/clang/bin/../x86_64-w64-mingw32/include/c++/v1/new:326:5: error: no type named '_aligned_free' in the global namespace
  ::_aligned_free(__ptr);
  ~~^
2 errors generated.

I haven't run into this issue - how do you end up getting intrin.h included before the other includes here?

Any case with intrin.h coming first should do it:

$ cat test.cpp
#include <intrin.h>
#include <new>

$ ./clang/bin/x86_64-w64-mingw32-clang++ -c test.cpp 
In file included from test.cpp:2:
/home/vm/Desktop/mingwtest/clang/bin/../x86_64-w64-mingw32/include/c++/v1/new:314:12: error: no member named '_aligned_malloc' in the global namespace
  return ::_aligned_malloc(__size, __alignment);
         ~~^
/home/vm/Desktop/mingwtest/clang/bin/../x86_64-w64-mingw32/include/c++/v1/new:326:5: error: no type named '_aligned_free' in the global namespace
  ::_aligned_free(__ptr);
  ~~^
2 errors generated.

Ah, doh. Indeed, I can reproduce that. Apparently the code I build regularly doesn't happen to use that setup.

I'll look into fixing the mingw-w64 header bug.

I haven't run into this issue - how do you end up getting intrin.h included before the other includes here?

Any case with intrin.h coming first should do it:

$ cat test.cpp
#include <intrin.h>
#include <new>

$ ./clang/bin/x86_64-w64-mingw32-clang++ -c test.cpp 
In file included from test.cpp:2:
/home/vm/Desktop/mingwtest/clang/bin/../x86_64-w64-mingw32/include/c++/v1/new:314:12: error: no member named '_aligned_malloc' in the global namespace
  return ::_aligned_malloc(__size, __alignment);
         ~~^
/home/vm/Desktop/mingwtest/clang/bin/../x86_64-w64-mingw32/include/c++/v1/new:326:5: error: no type named '_aligned_free' in the global namespace
  ::_aligned_free(__ptr);
  ~~^
2 errors generated.

Ah, doh. Indeed, I can reproduce that. Apparently the code I build regularly doesn't happen to use that setup.

I'll look into fixing the mingw-w64 header bug.

Actually, is there any chance that mingw could implement aligned_alloc from C11? This would increase their level of conformance, and solve this issue at the same time by providing a canonical, standardized name to do aligned allocation.

Actually, is there any chance that mingw could implement aligned_alloc from C11? This would increase their level of conformance, and solve this issue at the same time by providing a canonical, standardized name to do aligned allocation.

Hmm, maybe... But it's hard for a public header to use it unless we drop support for older versions of the mingw headers. Which might of course be pretty doable (as it doesn't require any newer version of windows, just a newer toolchain).

I haven't run into this issue - how do you end up getting intrin.h included before the other includes here?

Any case with intrin.h coming first should do it:

$ cat test.cpp
#include <intrin.h>
#include <new>

$ ./clang/bin/x86_64-w64-mingw32-clang++ -c test.cpp 
In file included from test.cpp:2:
/home/vm/Desktop/mingwtest/clang/bin/../x86_64-w64-mingw32/include/c++/v1/new:314:12: error: no member named '_aligned_malloc' in the global namespace
  return ::_aligned_malloc(__size, __alignment);
         ~~^
/home/vm/Desktop/mingwtest/clang/bin/../x86_64-w64-mingw32/include/c++/v1/new:326:5: error: no type named '_aligned_free' in the global namespace
  ::_aligned_free(__ptr);
  ~~^
2 errors generated.

Ah, doh. Indeed, I can reproduce that. Apparently the code I build regularly doesn't happen to use that setup.

I'll look into fixing the mingw-w64 header bug.

See https://sourceforge.net/p/mingw-w64/mailman/message/37168701/ and https://sourceforge.net/p/mingw-w64/mailman/message/37168702/ for patches that should fix this. It turned out to be less obvious and a bit more convolved than it first seemed.

I haven't run into this issue - how do you end up getting intrin.h included before the other includes here?

Any case with intrin.h coming first should do it:

$ cat test.cpp
#include <intrin.h>
#include <new>

$ ./clang/bin/x86_64-w64-mingw32-clang++ -c test.cpp 
In file included from test.cpp:2:
/home/vm/Desktop/mingwtest/clang/bin/../x86_64-w64-mingw32/include/c++/v1/new:314:12: error: no member named '_aligned_malloc' in the global namespace
  return ::_aligned_malloc(__size, __alignment);
         ~~^
/home/vm/Desktop/mingwtest/clang/bin/../x86_64-w64-mingw32/include/c++/v1/new:326:5: error: no type named '_aligned_free' in the global namespace
  ::_aligned_free(__ptr);
  ~~^
2 errors generated.

Ah, doh. Indeed, I can reproduce that. Apparently the code I build regularly doesn't happen to use that setup.

I'll look into fixing the mingw-w64 header bug.

See https://sourceforge.net/p/mingw-w64/mailman/message/37168701/ and https://sourceforge.net/p/mingw-w64/mailman/message/37168702/ for patches that should fix this. It turned out to be less obvious and a bit more convolved than it first seemed.

A fix for this is pushed now in https://sourceforge.net/p/mingw-w64/mingw-w64/ci/660e09f3cb20f181b6d6435cb623d65a3922a063/.

dmajor added a comment.Dec 7 2020, 9:46 AM

A fix for this is pushed now in https://sourceforge.net/p/mingw-w64/mingw-w64/ci/660e09f3cb20f181b6d6435cb623d65a3922a063/.

Confirmed that our mingw build flavors are successful at this revision. Thanks @mstorsjo !

A fix for this is pushed now in https://sourceforge.net/p/mingw-w64/mingw-w64/ci/660e09f3cb20f181b6d6435cb623d65a3922a063/.

Confirmed that our mingw build flavors are successful at this revision. Thanks @mstorsjo !

Thanks a lot folks! I think that's by far the best resolution.