// REQUIRES: any-device // RUN: %clangxx %sycl_options %s -o %t.out // RUN: %t.out #include #include #include #include using namespace sycl; constexpr size_t Align = 256; struct alignas(Align) Aligned { int x; }; int main() { queue q; context ctx = q.get_context(); device d = q.get_device(); auto check = [&q](size_t Alignment, auto AllocFn, int Line = __builtin_LINE(), int Case = 0) { // First allocation might naturally be over-aligned. Do several of them to // do the verification; decltype(AllocFn()) Arr[10]; for (auto *&Elem : Arr) Elem = AllocFn(); for (auto *Ptr : Arr) { auto v = reinterpret_cast(Ptr); if ((v & (Alignment - 1)) != 0) { std::cout << "Failed at line " << Line << ", case " << Case << std::endl; assert(false && "Not properly aligned!"); break; // To be used with commented out assert above. } } for (auto *Ptr : Arr) free(Ptr, q); }; // The strictest (largest) fundamental alignment of any type is the alignment // of max_align_t. This is, however, smaller than the minimal alignment // returned by the underlying runtime as of now. constexpr size_t FAlign = alignof(std::max_align_t); auto CheckAll = [&](size_t Expected, auto Funcs, int Line = __builtin_LINE()) { std::apply( [&](auto... Fs) { int Case = 0; (void)std::initializer_list{ (check(Expected, Fs, Line, Case++), 0)...}; }, Funcs); }; auto MDevice = [&](auto... args) { return malloc_device(sizeof(std::max_align_t), args...); }; CheckAll(FAlign, std::tuple{[&]() { return MDevice(q); }, [&]() { return MDevice(d, ctx); }, [&]() { return MDevice(q, property_list{}); }, [&]() { return MDevice(d, ctx, property_list{}); }}); auto MHost = [&](auto... args) { return malloc_host(sizeof(std::max_align_t), args...); }; CheckAll(FAlign, std::tuple{[&]() { return MHost(q); }, [&]() { return MHost(ctx); }, [&]() { return MHost(q, property_list{}); }, [&]() { return MHost(ctx, property_list{}); }}); if (d.has(aspect::usm_shared_allocations)) { auto MShared = [&](auto... args) { return malloc_shared(sizeof(std::max_align_t), args...); }; CheckAll(FAlign, std::tuple{[&]() { return MShared(q); }, [&]() { return MShared(d, ctx); }, [&]() { return MShared(q, property_list{}); }, [&]() { return MShared(d, ctx, property_list{}); }}); } auto TDevice = [&](auto... args) { return malloc_device(1, args...); }; CheckAll(Align, std::tuple{[&]() { return TDevice(q); }, [&]() { return TDevice(d, ctx); }}); auto THost = [&](auto... args) { return malloc_host(1, args...); }; CheckAll(Align, std::tuple{[&]() { return THost(q); }, [&]() { return THost(ctx); }}); if (d.has(aspect::usm_shared_allocations)) { auto TShared = [&](auto... args) { return malloc_shared(1, args...); }; CheckAll(Align, std::tuple{[&]() { return TShared(q); }, [&]() { return TShared(d, ctx); }}); } auto Malloc = [&](auto... args) { return malloc(sizeof(std::max_align_t), args...); }; CheckAll( FAlign, std::tuple{ [&]() { return Malloc(q, usm::alloc::host); }, [&]() { return Malloc(d, ctx, usm::alloc::host); }, [&]() { return Malloc(q, usm::alloc::host, property_list{}); }, [&]() { return Malloc(d, ctx, usm::alloc::host, property_list{}); }}); auto TMalloc = [&](auto... args) { return malloc(1, args...); }; CheckAll(Align, std::tuple{[&]() { return TMalloc(q, usm::alloc::host); }, [&]() { return TMalloc(d, ctx, usm::alloc::host); }}); return 0; }