Skip to content

Commit

Permalink
[SYCL][FPGA] Implement task_sequence header, properties, and add new …
Browse files Browse the repository at this point in the history
…fpga_cluster kernel property (#12453)

Implement task_sequence header, task_sequence properties, and
fpga_cluster kernel property according to the spec updates
#6348 (almost ready to be merged)
Header
- Refactor invocation and response capacity to be on the Create
intrinsic, so Async and Get do not take in respective argument
- Remove max_outstanding argument of Create intrinsic
- Add pipelined and fpga_cluster arguments to Create intrinsic
- Async, Get, and Release intrinsic now accept the TargetExtType
target("spirv.TaskSequenceINTEL") returned from the Create intrinsic,
and do not take in object pointer or task function pointer arguments
- Task Sequence accepts properties

Task Sequence Properties
- Convert invocation and response capacity from template parameters to
properties
- Add balanced property to remove Get intrinsic loop in destructor

FPGA Kernel properties
- Add fpga_cluster property
- Support fpga_cluster and pipelined property for task sequence
  • Loading branch information
bowenxue-intel authored Mar 12, 2024
1 parent 2525570 commit 7b9001e
Show file tree
Hide file tree
Showing 32 changed files with 1,206 additions and 33 deletions.
5 changes: 5 additions & 0 deletions clang/lib/CodeGen/CodeGenTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,11 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
"__spv::__spirv_JointMatrixINTEL") {
ResultType = ConvertSYCLJointMatrixINTELType(RD);
break;
} else if (RD && RD->getQualifiedNameAsString() ==
"__spv::__spirv_TaskSequenceINTEL") {
ResultType = llvm::TargetExtType::get(getLLVMContext(),
"spirv.TaskSequenceINTEL");
break;
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10235,7 +10235,8 @@ void SPIRVTranslator::ConstructJob(Compilation &C, const JobAction &JA,
",+SPV_INTEL_fpga_buffer_location"
",+SPV_INTEL_fpga_argument_interfaces"
",+SPV_INTEL_fpga_invocation_pipelining_attributes"
",+SPV_INTEL_fpga_latency_control";
",+SPV_INTEL_fpga_latency_control"
",+SPV_INTEL_task_sequence";
ExtArg = ExtArg + DefaultExtArg + INTELExtArg;
if (C.getDriver().IsFPGAHWMode())
// Enable several extensions on FPGA H/W exclusively
Expand Down
11 changes: 11 additions & 0 deletions clang/test/CodeGenSYCL/intel-task-sequence.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// RUN: %clang_cc1 -triple spir64-unknown-unknown -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s

// Test that SPIR-V codegen generates the expected LLVM struct name for the
// TaskSequenceINTEL type

namespace __spv {
struct __spirv_TaskSequenceINTEL;
} // namespace __spv

// CHECK: @_Z4func{{.*}}(target("spirv.TaskSequenceINTEL")
void func(__spv::__spirv_TaskSequenceINTEL *task_seq) {}
3 changes: 3 additions & 0 deletions clang/test/Driver/sycl-spirv-ext.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
// CHECK-DEFAULT-SAME:,+SPV_INTEL_fpga_argument_interfaces
// CHECK-DEFAULT-SAME:,+SPV_INTEL_fpga_invocation_pipelining_attributes
// CHECK-DEFAULT-SAME:,+SPV_INTEL_fpga_latency_control
// CHECK-DEFAULT-SAME:,+SPV_INTEL_task_sequence
// CHECK-DEFAULT-SAME:,+SPV_INTEL_token_type
// CHECK-DEFAULT-SAME:,+SPV_INTEL_bfloat16_conversion
// CHECK-DEFAULT-SAME:,+SPV_INTEL_joint_matrix
Expand Down Expand Up @@ -77,6 +78,7 @@
// CHECK-FPGA-HW-SAME:,+SPV_INTEL_fpga_buffer_location
// CHECK-FPGA-HW-SAME:,+SPV_INTEL_fpga_argument_interfaces
// CHECK-FPGA-HW-SAME:,+SPV_INTEL_fpga_latency_control
// CHECK-FPGA-HW-SAME:,+SPV_INTEL_task_sequence
// CHECK-FPGA-HW-SAME:,+SPV_INTEL_usm_storage_classes
// CHECK-FPGA-HW-SAME:,+SPV_INTEL_runtime_aligned
// CHECK-FPGA-HW-SAME:,+SPV_INTEL_fpga_cluster_attributes,+SPV_INTEL_loop_fuse
Expand Down Expand Up @@ -108,6 +110,7 @@
// CHECK-CPU-SAME:,+SPV_INTEL_fpga_argument_interfaces
// CHECK-CPU-SAME:,+SPV_INTEL_fpga_invocation_pipelining_attributes
// CHECK-CPU-SAME:,+SPV_INTEL_fpga_latency_control
// CHECK-CPU-SAME:,+SPV_INTEL_task_sequence
// CHECK-CPU-SAME:,+SPV_INTEL_token_type
// CHECK-CPU-SAME:,+SPV_INTEL_bfloat16_conversion
// CHECK-CPU-SAME:,+SPV_INTEL_joint_matrix
Expand Down
4 changes: 3 additions & 1 deletion llvm/include/llvm/SYCLLowerIR/DeviceConfigFile.td
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ def AspectExt_intel_matrix : Aspect<"ext_intel_matrix">;
def AspectExt_oneapi_is_composite : Aspect<"ext_oneapi_is_composite">;
def AspectExt_oneapi_is_component : Aspect<"ext_oneapi_is_component">;
def AspectExt_oneapi_graph : Aspect<"ext_oneapi_graph">;
def AspectExt_intel_fpga_task_sequence : Aspect<"ext_intel_fpga_task_sequence">;
// Deprecated aspects
def AspectInt64_base_atomics : Aspect<"int64_base_atomics">;
def AspectInt64_extended_atomics : Aspect<"int64_extended_atomics">;
Expand Down Expand Up @@ -120,7 +121,8 @@ def : TargetInfo<"__TestAspectList",
AspectExt_oneapi_interop_semaphore_import, AspectExt_oneapi_interop_semaphore_export,
AspectExt_oneapi_mipmap, AspectExt_oneapi_mipmap_anisotropy, AspectExt_oneapi_mipmap_level_reference, AspectExt_intel_esimd,
AspectExt_oneapi_ballot_group, AspectExt_oneapi_fixed_size_group, AspectExt_oneapi_opportunistic_group,
AspectExt_oneapi_tangle_group, AspectExt_intel_matrix, AspectExt_oneapi_is_composite, AspectExt_oneapi_is_component, AspectExt_oneapi_graph],
AspectExt_oneapi_tangle_group, AspectExt_intel_matrix, AspectExt_oneapi_is_composite, AspectExt_oneapi_is_component,
AspectExt_oneapi_graph, AspectExt_intel_fpga_task_sequence],
[]>;
// This definition serves the only purpose of testing whether the deprecated aspect list defined in here and in SYCL RT
// match.
Expand Down
16 changes: 16 additions & 0 deletions llvm/lib/SYCLLowerIR/CompileTimePropertiesPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,7 @@ attributeToExecModeMetadata(const Attribute &Attr, Function &F) {

if (AttrKindStr == "sycl-streaming-interface") {
// generate either:
// !ip_interface !N
// !N = !{!"streaming"} or
// !N = !{!"streaming", !"stall_free_return"}
SmallVector<Metadata *, 2> MD;
Expand All @@ -428,6 +429,7 @@ attributeToExecModeMetadata(const Attribute &Attr, Function &F) {

if (AttrKindStr == "sycl-register-map-interface") {
// generate either:
// !ip_interface !N
// !N = !{!"csr"} or
// !N = !{!"csr", !"wait_for_done_write"}
SmallVector<Metadata *, 2> MD;
Expand All @@ -438,6 +440,20 @@ attributeToExecModeMetadata(const Attribute &Attr, Function &F) {
MDNode::get(Ctx, MD));
}

if (AttrKindStr == "sycl-fpga-cluster") {
// generate either:
// !stall_free !N
// !N = !{i32 1} or
// !stall_enable !N
// !N = !{i32 1}
std::string ClusterType =
getAttributeAsInteger<uint32_t>(Attr) ? "stall_enable" : "stall_free";
Metadata *ClusterMDArgs[] = {
ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(Ctx), 1))};
return std::pair<std::string, MDNode *>(ClusterType,
MDNode::get(Ctx, ClusterMDArgs));
}

if ((AttrKindStr == SYCL_REGISTER_ALLOC_MODE_ATTR ||
AttrKindStr == SYCL_GRF_SIZE_ATTR) &&
!llvm::esimd::isESIMD(F)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
; Check conversion of sycl-fpga-cluster attribute
; RUN: opt -passes="compile-time-properties" %s -S -o - | FileCheck %s --check-prefix CHECK-IR

; CHECK-IR-DAG: @stallFree() #0 {{.*}}!stall_free [[MD_TRUE:![0-9]+]] {
; Function Attrs: convergent norecurse
define weak_odr dso_local spir_kernel void @stallFree() #0 {
entry:
ret void
}

; CHECK-IR-DAG: @stallEnable() #1 {{.*}}!stall_enable [[MD_TRUE:![0-9]+]] {
; Function Attrs: convergent norecurse
define weak_odr dso_local spir_kernel void @stallEnable() #1 {
entry:
ret void
}

attributes #0 = { convergent norecurse "frame-pointer"="all" "sycl-fpga-cluster"="0" }
attributes #1 = { convergent norecurse "frame-pointer"="all" "sycl-fpga-cluster"="1" }

!opencl.spir.version = !{!0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0}
!spirv.Source = !{!1, !1, !1, !1, !1, !1, !1, !1, !1, !1, !1}
!llvm.ident = !{!2, !2, !2, !2, !2, !2, !2, !2, !2, !2, !2}
!llvm.module.flags = !{!3, !4}

!0 = !{i32 1, i32 2}
!1 = !{i32 4, i32 100000}
!2 = !{!"clang version 13.0.0 (https://github.com/intel/llvm)"}
!3 = !{i32 1, !"wchar_size", i32 4}
!4 = !{i32 7, !"frame-pointer", i32 2}

; Confirm the decorations for the functions
; CHECK-IR-DAG: [[MD_TRUE]] = !{i32 1}
19 changes: 19 additions & 0 deletions sycl/include/CL/__spirv/spirv_ops.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1267,6 +1267,25 @@ extern __DPCPP_SYCL_EXTERNAL
std::enable_if_t<std::is_integral_v<to> && std::is_unsigned_v<to>, to>
__spirv_ConvertPtrToU(from val) noexcept;

template <typename RetT, typename... ArgsT>
extern __DPCPP_SYCL_EXTERNAL __spv::__spirv_TaskSequenceINTEL *
__spirv_TaskSequenceCreateINTEL(RetT (*f)(ArgsT...), int Pipelined = -1,
int ClusterMode = -1,
unsigned int ResponseCapacity = 0,
unsigned int InvocationCapacity = 0) noexcept;

template <typename... ArgsT>
extern __DPCPP_SYCL_EXTERNAL void
__spirv_TaskSequenceAsyncINTEL(__spv::__spirv_TaskSequenceINTEL *TaskSequence,
ArgsT... Args) noexcept;

template <typename RetT>
extern __DPCPP_SYCL_EXTERNAL RetT __spirv_TaskSequenceGetINTEL(
__spv::__spirv_TaskSequenceINTEL *TaskSequence) noexcept;

extern __DPCPP_SYCL_EXTERNAL void __spirv_TaskSequenceReleaseINTEL(
__spv::__spirv_TaskSequenceINTEL *TaskSequence) noexcept;

#else // if !__SYCL_DEVICE_ONLY__

template <typename dataT>
Expand Down
2 changes: 2 additions & 0 deletions sycl/include/CL/__spirv/spirv_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ template <typename T, std::size_t R, std::size_t C, MatrixLayout L,
MatrixUse U = MatrixUse::MatrixA>
struct __spirv_JointMatrixINTEL;

struct __spirv_TaskSequenceINTEL;

} // namespace __spv

#ifdef __SYCL_DEVICE_ONLY__
Expand Down
10 changes: 10 additions & 0 deletions sycl/include/sycl/device_aspect_macros.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,11 @@
#define __SYCL_ALL_DEVICES_HAVE_ext_oneapi_graph__ 0
#endif

#ifndef __SYCL_ALL_DEVICES_HAVE_ext_intel_fpga_task_sequence__
// __SYCL_ASPECT(ext_intel_fpga_task_sequence, 62)
#define __SYCL_ALL_DEVICES_HAVE_ext_intel_fpga_task_sequence__ 0
#endif

#ifndef __SYCL_ANY_DEVICE_HAS_host__
// __SYCL_ASPECT(host, 0)
#define __SYCL_ANY_DEVICE_HAS_host__ 0
Expand Down Expand Up @@ -627,3 +632,8 @@
// __SYCL_ASPECT(ext_oneapi_graph, 61)
#define __SYCL_ANY_DEVICE_HAS_ext_oneapi_graph__ 0
#endif

#ifndef __SYCL_ANY_DEVICE_HAS_ext_intel_fpga_task_sequence__
// __SYCL_ASPECT(ext_intel_fpga_task_sequence__, 62)
#define __SYCL_ANY_DEVICE_HAS_ext_intel_fpga_task_sequence__ 0
#endif
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//==----- fpga_kernel_properties.hpp - SYCL properties associated with FPGA
// kernel properties ---==//
//===--------------------- fpga_kernel_properties.hpp ---------------------===//
// SYCL properties associated with FPGA kernel properties
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
Expand All @@ -12,11 +12,15 @@
#include <sycl/ext/oneapi/properties/property.hpp>
#include <sycl/ext/oneapi/properties/property_value.hpp>

#include <cstdint> // for uint16_t
#include <type_traits> // for true_type

namespace sycl {
inline namespace _V1 {
namespace ext::intel::experimental {

template <typename T, typename PropertyListT> class fpga_kernel_attribute;
template <auto &f, typename PropertyListT> class task_sequence;

enum class streaming_interface_options_enum : std::uint16_t {
accept_downstream_stall,
Expand All @@ -28,6 +32,11 @@ enum class register_map_interface_options_enum : std::uint16_t {
wait_for_done_write,
};

enum class fpga_cluster_options_enum : std::uint16_t {
stall_free,
stall_enable
};

struct streaming_interface_key
: oneapi::experimental::detail::compile_time_property_key<
oneapi::experimental::detail::PropKind::StreamingInterface> {
Expand All @@ -54,6 +63,15 @@ struct pipelined_key : oneapi::experimental::detail::compile_time_property_key<
std::integral_constant<int, pipeline_directive_or_initiation_interval>>;
};

struct fpga_cluster_key
: oneapi::experimental::detail::compile_time_property_key<
oneapi::experimental::detail::PropKind::FPGACluster> {
template <fpga_cluster_options_enum option>
using value_t = ext::oneapi::experimental::property_value<
fpga_cluster_key,
std::integral_constant<fpga_cluster_options_enum, option>>;
};

template <streaming_interface_options_enum option =
streaming_interface_options_enum::accept_downstream_stall>
inline constexpr streaming_interface_key::value_t<option> streaming_interface;
Expand Down Expand Up @@ -84,6 +102,18 @@ inline constexpr pipelined_key::value_t<
pipeline_directive_or_initiation_interval>
pipelined;

template <fpga_cluster_options_enum option =
fpga_cluster_options_enum::stall_free>
inline constexpr fpga_cluster_key::value_t<option> fpga_cluster;

inline constexpr fpga_cluster_key::value_t<
fpga_cluster_options_enum::stall_free>
stall_free_clusters;

inline constexpr fpga_cluster_key::value_t<
fpga_cluster_options_enum::stall_enable>
stall_enable_clusters;

} // namespace ext::intel::experimental

namespace ext::oneapi::experimental {
Expand All @@ -103,6 +133,22 @@ struct is_property_key_of<
intel::experimental::fpga_kernel_attribute<T, PropertyListT>>
: std::true_type {};

template <typename T, typename PropertyListT>
struct is_property_key_of<
intel::experimental::fpga_cluster_key,
intel::experimental::fpga_kernel_attribute<T, PropertyListT>>
: std::true_type {};

template <auto &f, typename PropertyListT>
struct is_property_key_of<intel::experimental::pipelined_key,
intel::experimental::task_sequence<f, PropertyListT>>
: std::true_type {};

template <auto &f, typename PropertyListT>
struct is_property_key_of<intel::experimental::fpga_cluster_key,
intel::experimental::task_sequence<f, PropertyListT>>
: std::true_type {};

namespace detail {
template <intel::experimental::streaming_interface_options_enum Stall_Free>
struct PropertyMetaInfo<
Expand All @@ -124,6 +170,14 @@ struct PropertyMetaInfo<intel::experimental::pipelined_key::value_t<Value>> {
static constexpr int value = Value;
};

template <intel::experimental::fpga_cluster_options_enum ClusterType>
struct PropertyMetaInfo<
intel::experimental::fpga_cluster_key::value_t<ClusterType>> {
static constexpr const char *name = "sycl-fpga-cluster";
static constexpr intel::experimental::fpga_cluster_options_enum value =
ClusterType;
};

} // namespace detail
} // namespace ext::oneapi::experimental
} // namespace _V1
Expand Down
Loading

0 comments on commit 7b9001e

Please sign in to comment.