diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 28a403e8bd..e17a4041c9 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -75,3 +75,9 @@ SYCL/BFloat16 @AlexeySotkin @MrSidims # Deprecated features SYCL/DeprecatedFeatures @intel/llvm-reviewers-runtime + +# XPTI and XPTI Framework +SYCL/XPTI @tovinkere @andykaylor @alexbatashev + +# Additional SYCL tools +SYCL/Tools @intel/llvm-reviewers-runtime diff --git a/SYCL/Tools/sanitize_buffer_device_ptr.cpp b/SYCL/Tools/sanitize_buffer_device_ptr.cpp new file mode 100644 index 0000000000..17facc8111 --- /dev/null +++ b/SYCL/Tools/sanitize_buffer_device_ptr.cpp @@ -0,0 +1,27 @@ +// REQUIRES: sycl-sanitizer +// RUN: %clangxx -fsycl -fsycl-unnamed-lambda -fsycl-targets=%sycl_triple %s -o %t.out +// RUN: %CPU_RUN_PLACEHOLDER not sycl-sanitizer %t.out %CPU_CHECK_PLACEHOLDER + +#include + +int main() { + sycl::queue Q{sycl::default_selector()}; + + int *Ptr = sycl::malloc_device(200, Q); + + sycl::buffer Buf(Ptr, sycl::range{200}, + sycl::property::buffer::use_host_ptr()); + + Q.submit([&](sycl::handler &CGH) { + sycl::accessor Acc{Buf, CGH, sycl::write_only}; + CGH.parallel_for(sycl::range{200}, [=](const auto I) { Acc[I] = 1; }); + }); + + Q.wait(); + + return 0; +} + +// CHECK: Attempt to construct a buffer with non-host pointer. +// CHECK-NEXT: Allocation location: function main at :10 +// CHECK-NEXT: Buffer location: function at :0 diff --git a/SYCL/Tools/sanitize_buffer_host_small_ptr.cpp b/SYCL/Tools/sanitize_buffer_host_small_ptr.cpp new file mode 100644 index 0000000000..b992243254 --- /dev/null +++ b/SYCL/Tools/sanitize_buffer_host_small_ptr.cpp @@ -0,0 +1,27 @@ +// REQUIRES: sycl-sanitizer +// RUN: %clangxx -fsycl -fsycl-unnamed-lambda -fsycl-targets=%sycl_triple %s -o %t.out +// RUN: %CPU_RUN_PLACEHOLDER not sycl-sanitizer %t.out %CPU_CHECK_PLACEHOLDER + +#include + +int main() { + sycl::queue Q{sycl::default_selector()}; + + int *Ptr = sycl::malloc_host(100, Q); + + sycl::buffer Buf(Ptr, sycl::range{200}, + sycl::property::buffer::use_host_ptr()); + + Q.submit([&](sycl::handler &CGH) { + sycl::accessor Acc{Buf, CGH, sycl::write_only}; + CGH.parallel_for(sycl::range{200}, [=](const auto I) { Acc[I] = 1; }); + }); + + Q.wait(); + + return 0; +} + +// CHECK: Buffer size exceeds allocated host memory size. +// CHECK-NEXT: Allocation location: function main at :10 +// CHECK-NEXT: Buffer location: function at :0 diff --git a/SYCL/Tools/sanitize_memleak.cpp b/SYCL/Tools/sanitize_memleak.cpp new file mode 100644 index 0000000000..4ff0064f2b --- /dev/null +++ b/SYCL/Tools/sanitize_memleak.cpp @@ -0,0 +1,23 @@ +// REQUIRES: sycl-sanitizer +// RUN: %clangxx -fsycl -fsycl-targets=%sycl_triple %s -o %t.out +// RUN: %CPU_RUN_PLACEHOLDER not sycl-sanitizer %t.out %CPU_CHECK_PLACEHOLDER + +#include + +int main() { + sycl::queue Q{sycl::default_selector()}; + + sycl::malloc_device(100, Q); + sycl::malloc_host(100, Q); + sycl::malloc_shared(100, Q); + + return 0; +} + +// CHECK: Found 3 leaked memory allocations +// CHECK-NEXT: Leaked pointer: 0x7f8070000000 +// CHECK-NEXT: Location: function main at :12 +// CHECK-NEXT: Leaked pointer: 0x7f8076c00000 +// CHECK-NEXT: Location: function main at :10 +// CHECK-NEXT: Leaked pointer: 0x7f8076e00000 +// CHECK-NEXT: Location: function main at :11 diff --git a/SYCL/XPTI/Inputs/test_collector.cpp b/SYCL/XPTI/Inputs/test_collector.cpp new file mode 100644 index 0000000000..5cef9c8734 --- /dev/null +++ b/SYCL/XPTI/Inputs/test_collector.cpp @@ -0,0 +1,128 @@ +#include "xpti/xpti_trace_framework.hpp" + +#include +#include +#include + +std::mutex GMutex; + +XPTI_CALLBACK_API void syclCallback(uint16_t, + xpti::trace_event_data_t *, + xpti::trace_event_data_t *, + uint64_t, const void *); +XPTI_CALLBACK_API void syclPiCallback(uint16_t, + xpti::trace_event_data_t *, + xpti::trace_event_data_t *, + uint64_t, const void *); + +XPTI_CALLBACK_API void xptiTraceInit(unsigned int MajorVersion, + unsigned int MinorVersion, + const char *VersionStr, + const char *StreamName) { + std::cout << "xptiTraceInit: Stream Name = " << StreamName << "\n"; + std::string_view NameView{StreamName}; + + if (NameView == "sycl.pi") { + uint8_t StreamID = xptiRegisterStream(StreamName); + xptiRegisterCallback( + StreamID, static_cast(xpti::trace_point_type_t::function_begin), + syclPiCallback); + xptiRegisterCallback( + StreamID, static_cast(xpti::trace_point_type_t::function_with_args_end), + syclPiCallback); + } + if (NameView == "sycl") { + uint8_t StreamID = xptiRegisterStream(StreamName); + xptiRegisterCallback(StreamID, + static_cast(xpti::trace_point_type_t::graph_create), + syclCallback); + xptiRegisterCallback( + StreamID, static_cast(xpti::trace_point_type_t::node_create), syclCallback); + xptiRegisterCallback( + StreamID, static_cast(xpti::trace_point_type_t::edge_create), syclCallback); + xptiRegisterCallback( + StreamID, static_cast(xpti::trace_point_type_t::task_begin), syclCallback); + xptiRegisterCallback( + StreamID, static_cast(xpti::trace_point_type_t::task_end), syclCallback); + xptiRegisterCallback( + StreamID, static_cast(xpti::trace_point_type_t::signal), syclCallback); + xptiRegisterCallback(StreamID, + static_cast(xpti::trace_point_type_t::barrier_begin), + syclCallback); + xptiRegisterCallback( + StreamID, static_cast(xpti::trace_point_type_t::barrier_end), syclCallback); + xptiRegisterCallback( + StreamID, static_cast(xpti::trace_point_type_t::wait_begin), syclCallback); + xptiRegisterCallback( + StreamID, static_cast(xpti::trace_point_type_t::wait_end), syclCallback); + xptiRegisterCallback(StreamID, static_cast(xpti::trace_point_type_t::signal), + syclCallback); + } +} + +XPTI_CALLBACK_API void xptiTraceFinish(const char *streamName) { + std::cout << "xptiTraceFinish: Stream Name = " << streamName << "\n"; +} + +XPTI_CALLBACK_API void syclPiCallback(uint16_t TraceType, + xpti::trace_event_data_t *, + xpti::trace_event_data_t *, + uint64_t, const void *UserData) { + std::lock_guard Lock{GMutex}; + auto Type = static_cast(TraceType); + const char *funcName = static_cast(UserData); + if (Type == xpti::trace_point_type_t::function_begin) { + std::cout << "PI Call Begin : "; + } else if (Type == xpti::trace_point_type_t::function_end){ + std::cout << "PI Call End : "; + } + std::cout << funcName << "\n"; +} + +XPTI_CALLBACK_API void syclCallback(uint16_t TraceType, + xpti::trace_event_data_t *, + xpti::trace_event_data_t *Event, + uint64_t, const void *UserData) { + std::lock_guard Lock{GMutex}; + auto Type = static_cast(TraceType); + switch (Type) { + case xpti::trace_point_type_t::graph_create: + std::cout << "Graph create\n"; + break; + case xpti::trace_point_type_t::node_create: + std::cout << "Node create\n"; + break; + case xpti::trace_point_type_t::edge_create: + std::cout << "Edge create\n"; + break; + case xpti::trace_point_type_t::task_begin: + std::cout << "Task begin\n"; + break; + case xpti::trace_point_type_t::task_end: + std::cout << "Task end\n"; + break; + case xpti::trace_point_type_t::signal: + std::cout << "Signal\n"; + break; + case xpti::trace_point_type_t::wait_begin: + std::cout << "Wait begin\n"; + break; + case xpti::trace_point_type_t::wait_end: + std::cout << "Wait end\n"; + break; + case xpti::trace_point_type_t::barrier_begin: + std::cout << "Barrier begin\n"; + break; + case xpti::trace_point_type_t::barrier_end: + std::cout << "Barrier end\n"; + break; + default: + std::cout << "Unknown tracepoint\n"; + } + + xpti::metadata_t *Metadata = xptiQueryMetadata(Event); + for (auto &Item : *Metadata) { + std::cout << " " << xptiLookupString(Item.first) + << " : " << xptiLookupString(Item.second) << "\n"; + } +} diff --git a/SYCL/XPTI/basic_event_collection.cpp b/SYCL/XPTI/basic_event_collection.cpp new file mode 100644 index 0000000000..1210da7e0e --- /dev/null +++ b/SYCL/XPTI/basic_event_collection.cpp @@ -0,0 +1,179 @@ +// REQUIRES: xptifw +// RUN: %clangxx -fsycl %s -DXPTI_COLLECTOR -shared -fPIC -std=c++17 -o %t_collector.dll -lxptifw +// RUN: %clangxx -fsycl -fsycl-unnamed-lambda -fsycl-targets=%sycl_triple %s -o %t.out +// RUN: env XPTI_TRACE_ENABLED=1 env XPTI_FRAMEWORK_DISPATCHER=%xptifw_lib env XPTI_SUBSCRIBERS=%t_collector.dll %CPU_RUN_PLACEHOLDER %t %CPU_CHECK_PLACEHOLDER + +#ifdef XPTI_COLLECTOR + +#include "Inputs/test_collector.cpp" + +#else + +#include + +int main() { + sycl::queue Q{sycl::default_selector{}}; + + auto Ptr = sycl::malloc_device(1, Q); + + auto Evt1 = Q.single_task([=]() { + Ptr[0] = 1; + }); + + auto Evt2 = Q.submit([&](sycl::handler &CGH) { + CGH.depends_on(Evt1); + CGH.single_task([=]() { + Ptr[0]++; + }); + }); + + Evt2.wait(); + + int Res = 0; + Q.memcpy(&Res, Ptr, 1); + Q.wait(); + + assert(Res == 2); + + return 0; +} + +#endif + +// CHECK: xptiTraceInit: Stream Name = sycl +// CHECK-NEXT: Graph create +// CHECK-NEXT: xptiTraceInit: Stream Name = sycl.pi +// CHECK-NEXT: xptiTraceInit: Stream Name = sycl.pi.debug +// CHECK-NEXT: PI Call Begin : piPlatformsGet +// CHECK-NEXT: PI Call Begin : piPlatformsGet +// CHECK-NEXT: PI Call Begin : piDevicesGet +// CHECK-NEXT: PI Call Begin : piDevicesGet +// CHECK-NEXT: PI Call Begin : piDeviceGetInfo +// CHECK-NEXT: PI Call Begin : piDeviceGetInfo +// CHECK-NEXT: PI Call Begin : piDeviceGetInfo +// CHECK-NEXT: PI Call Begin : piDeviceRetain +// CHECK-NEXT: PI Call Begin : piDeviceGetInfo +// CHECK-NEXT: PI Call Begin : piDeviceGetInfo +// CHECK-NEXT: PI Call Begin : piPlatformGetInfo +// CHECK-NEXT: PI Call Begin : piPlatformGetInfo +// CHECK-NEXT: PI Call Begin : piDeviceRelease +// CHECK-NEXT: PI Call Begin : piDevicesGet +// CHECK-NEXT: PI Call Begin : piDevicesGet +// CHECK-NEXT: PI Call Begin : piDeviceGetInfo +// CHECK-NEXT: PI Call Begin : piDevicesGet +// CHECK-NEXT: PI Call Begin : piDevicesGet +// CHECK-NEXT: PI Call Begin : piDeviceGetInfo +// CHECK-NEXT: PI Call Begin : piDevicesGet +// CHECK-NEXT: PI Call Begin : piDevicesGet +// CHECK-NEXT: PI Call Begin : piDeviceGetInfo +// CHECK-NEXT: PI Call Begin : piDeviceGetInfo +// CHECK-NEXT: PI Call Begin : piDeviceGetInfo +// CHECK-NEXT: PI Call Begin : piDeviceRetain +// CHECK-NEXT: PI Call Begin : piDeviceGetInfo +// CHECK-NEXT: PI Call Begin : piDeviceGetInfo +// CHECK-NEXT: PI Call Begin : piDeviceGetInfo +// CHECK-NEXT: PI Call Begin : piDeviceGetInfo +// CHECK-NEXT: PI Call Begin : piDeviceGetInfo +// CHECK-NEXT: PI Call Begin : piDevicesGet +// CHECK-NEXT: PI Call Begin : piDevicesGet +// CHECK-NEXT: PI Call Begin : piDeviceGetInfo +// CHECK-NEXT: PI Call Begin : piContextCreate +// CHECK-NEXT: PI Call Begin : piQueueCreate +// CHECK-NEXT: PI Call Begin : piextUSMDeviceAlloc +// CHECK-NEXT: PI Call Begin : piextDeviceSelectBinary +// CHECK-NEXT: Node create +// CHECK-NEXT: from_source : false +// CHECK-NEXT: kernel_name : +// CHECK-NEXT: sycl_device : CPU +// CHECK-NEXT: Task begin +// CHECK-NEXT: from_source : false +// CHECK-NEXT: kernel_name : +// CHECK-NEXT: sycl_device : CPU +// CHECK-NEXT: PI Call Begin : piextDeviceSelectBinary +// CHECK-NEXT: PI Call Begin : piDeviceGetInfo +// CHECK-NEXT: PI Call Begin : piDeviceGetInfo +// CHECK-NEXT: PI Call Begin : piDeviceGetInfo +// CHECK-NEXT: PI Call Begin : piDeviceGetInfo +// CHECK-NEXT: PI Call Begin : piDeviceGetInfo +// CHECK-NEXT: PI Call Begin : piDeviceGetInfo +// CHECK-NEXT: PI Call Begin : piPlatformGetInfo +// CHECK-NEXT: PI Call Begin : piPlatformGetInfo +// CHECK-NEXT: PI Call Begin : piDeviceGetInfo +// CHECK-NEXT: PI Call Begin : piPlatformGetInfo +// CHECK-NEXT: PI Call Begin : piPlatformGetInfo +// CHECK-NEXT: PI Call Begin : piProgramCreate +// CHECK-NEXT: PI Call Begin : piProgramBuild +// CHECK-NEXT: PI Call Begin : piDeviceGetInfo +// CHECK-NEXT: PI Call Begin : piDeviceGetInfo +// CHECK-NEXT: PI Call Begin : piDeviceGetInfo +// CHECK-NEXT: PI Call Begin : piDeviceGetInfo +// CHECK-NEXT: PI Call Begin : piDeviceGetInfo +// CHECK-NEXT: PI Call Begin : piDeviceGetInfo +// CHECK-NEXT: PI Call Begin : piPlatformGetInfo +// CHECK-NEXT: PI Call Begin : piPlatformGetInfo +// CHECK-NEXT: PI Call Begin : piKernelCreate +// CHECK-NEXT: PI Call Begin : piKernelSetExecInfo +// CHECK-NEXT: PI Call Begin : piextKernelSetArgPointer +// CHECK-NEXT: PI Call Begin : piKernelGetGroupInfo +// CHECK-NEXT: PI Call Begin : piEnqueueKernelLaunch +// CHECK-NEXT: Signal +// CHECK-NEXT: from_source : false +// CHECK-NEXT: kernel_name : +// CHECK-NEXT: sycl_device : CPU +// CHECK-NEXT: Task end +// CHECK-NEXT: from_source : false +// CHECK-NEXT: kernel_name : +// CHECK-NEXT: sycl_device : CPU +// CHECK-NEXT: PI Call Begin : piextDeviceSelectBinary +// CHECK-NEXT: Node create +// CHECK-NEXT: from_source : false +// CHECK-NEXT: kernel_name : +// CHECK-NEXT: sycl_device : CPU +// CHECK-NEXT: Node create +// CHECK-NEXT: kernel_name : virtual_node +// CHECK-NEXT: Edge create +// CHECK-NEXT: event : Event +// CHECK-NEXT: kernel_name : virtual_node +// CHECK-NEXT: Task begin +// CHECK-NEXT: from_source : false +// CHECK-NEXT: kernel_name : +// CHECK-NEXT: sycl_device : CPU +// CHECK-NEXT: PI Call Begin : piKernelCreate +// CHECK-NEXT: PI Call Begin : piKernelSetExecInfo +// CHECK-NEXT: PI Call Begin : piextKernelSetArgPointer +// CHECK-NEXT: PI Call Begin : piKernelGetGroupInfo +// CHECK-NEXT: PI Call Begin : piEnqueueKernelLaunch +// CHECK-NEXT: Signal +// CHECK-NEXT: from_source : false +// CHECK-NEXT: kernel_name : +// CHECK-NEXT: sycl_device : CPU +// CHECK-NEXT: Task end +// CHECK-NEXT: from_source : false +// CHECK-NEXT: kernel_name : +// CHECK-NEXT: sycl_device : CPU +// CHECK-NEXT: Wait begin +// CHECK-NEXT: PI Call Begin : piEventsWait +// CHECK-NEXT: Wait end +// CHECK-NEXT: PI Call Begin : piextUSMEnqueueMemcpy +// CHECK-NEXT: PI Call Begin : piEventRelease +// CHECK-NEXT: Wait begin +// CHECK-NEXT: sym_line_no : 34 +// CHECK-NEXT: sym_function_name : main +// CHECK-NEXT: sycl_device : CPU +// CHECK-NEXT: PI Call Begin : piQueueFinish +// CHECK-NEXT: Wait end +// CHECK-NEXT: sym_line_no : 34 +// CHECK-NEXT: sym_function_name : main +// CHECK-NEXT: sycl_device : CPU +// CHECK-NEXT: PI Call Begin : piEventRelease +// CHECK-NEXT: PI Call Begin : piEventRelease +// CHECK-NEXT: PI Call Begin : piQueueRelease +// CHECK-NEXT: PI Call Begin : piContextRelease +// CHECK-NEXT: PI Call Begin : piKernelRelease +// CHECK-NEXT: PI Call Begin : piKernelRelease +// CHECK-NEXT: PI Call Begin : piProgramRelease +// CHECK-NEXT: PI Call Begin : piDeviceRelease +// CHECK-NEXT: PI Call Begin : piTearDown +// CHECK-NEXT: xptiTraceFinish: Stream Name = sycl.pi +// CHECK-NEXT: xptiTraceFinish: Stream Name = sycl.pi.debug +// CHECK-NEXT: xptiTraceFinish: Stream Name = sycl diff --git a/SYCL/lit.cfg.py b/SYCL/lit.cfg.py index 2484d67119..510b493ef0 100644 --- a/SYCL/lit.cfg.py +++ b/SYCL/lit.cfg.py @@ -313,6 +313,22 @@ if find_executable('sycl-ls'): config.available_features.add('sycl-ls') +# TODO properly set XPTIFW include and runtime dirs +if find_executable('sycl-ls'): + sycl_ls_full_path = find_executable('sycl-ls') + sycl_ls_loc = os.path.dirname(sycl_ls_full_path) + xptifw_lib = "" + if platform.system() == "Linux": + xptifw_lib = os.path.join(sycl_ls_loc, '..', 'lib', 'libxptifw.so') + elif platform.system() == "Windows": + xptifw_lib = os.path.join(sycl_ls_loc, 'xptifw.dll') + if (os.path.exists(xptifw_lib)): + config.available_features.add('xptifw') + config.substitutions.append(('%xptifw_lib', xptifw_lib)) + +if find_executable('sycl-sanitizer'): + config.available_features.add('sycl-sanitizer') + llvm_tools = ["llvm-spirv", "llvm-link"] for llvm_tool in llvm_tools: llvm_tool_path = find_executable(llvm_tool)