Skip to content

Commit 8f182cd

Browse files
authored
[SYCL] Insert annotation in annotated_ptr::get() (#12343)
When properties like alignment is specified in a `annotated_ptr` type, certain operators (like `[]`, `+=`, `++`) are disabled. This results in loop code to be written as follows: ``` annotated_ptr<int, decltype(properties{...alignment<8>...})> ann_ptr; ... int *p = ann_ptr.get(); // ann_ptr cannot be used in the for loop directly for (int i = 0; i < n; i++) { p[i] = i; } ``` When getting the underlying pointer, the annotation gets lost, so does the the possible optimization on the for-loop brought by the annotated_ptr properties. This PR includes changes on spec, header and clang compiler: 1. In `annotated_ptr` spec, update the spec for the `get()` function 2. In the `annotated_ptr` header, update the `get()` function by inserting `llvm.ptr.annotation`, so that on the target machines like FPGA for which clang FE only performs O0 optimization, the annotation inserted can be preserved for the corresponding backends to perform platform-specific optimizations. For the example above, the `alignment` information can help the FPGA compiler to build aligned loads/stores. 3. In the clang compiler, the pass `CompileTimePropertiesPass` used to always drop `alignment` from the annotation string. This PR changes this behavior to dropping `alignment` only when the compiler finds load/store/MemIntrinsics in the users of `llvm.ptr.annotation` and applies the alignment to these instructions.
1 parent 6863dfc commit 8f182cd

File tree

8 files changed

+139
-52
lines changed

8 files changed

+139
-52
lines changed

llvm/include/llvm/SYCLLowerIR/CompileTimePropertiesPass.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class CompileTimePropertiesPass
4040
Module &M, IntrinsicInst *IntrInst,
4141
SmallVectorImpl<IntrinsicInst *> &RemovableAnnotations);
4242

43-
void parseAlignmentAndApply(Module &M, IntrinsicInst *IntrInst);
43+
bool parseAlignmentAndApply(Module &M, IntrinsicInst *IntrInst);
4444

4545
// Map for keeping track of global variables generated for annotation strings.
4646
// This allows reuse for annotations with the same generated annotation

llvm/lib/SYCLLowerIR/CompileTimePropertiesPass.cpp

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -685,7 +685,7 @@ PreservedAnalyses CompileTimePropertiesPass::run(Module &M,
685685
: PreservedAnalyses::all();
686686
}
687687

688-
void CompileTimePropertiesPass::parseAlignmentAndApply(
688+
bool CompileTimePropertiesPass::parseAlignmentAndApply(
689689
Module &M, IntrinsicInst *IntrInst) {
690690
// Get the global variable with the annotation string.
691691
const GlobalVariable *AnnotStrArgGV = nullptr;
@@ -695,11 +695,11 @@ void CompileTimePropertiesPass::parseAlignmentAndApply(
695695
else if (auto *GEP = dyn_cast<GEPOperator>(IntrAnnotStringArg))
696696
AnnotStrArgGV = dyn_cast<GlobalVariable>(GEP->getOperand(0));
697697
if (!AnnotStrArgGV)
698-
return;
698+
return false;
699699

700700
std::optional<StringRef> AnnotStr = getGlobalVariableString(AnnotStrArgGV);
701701
if (!AnnotStr)
702-
return;
702+
return false;
703703

704704
// parse properties string to decoration-value pairs
705705
auto Properties = parseSYCLPropertiesString(M, IntrInst);
@@ -710,6 +710,7 @@ void CompileTimePropertiesPass::parseAlignmentAndApply(
710710
getUserListIgnoringCast<StoreInst>(IntrInst, TargetedInstList);
711711
getUserListIgnoringCast<MemTransferInst>(IntrInst, TargetedInstList);
712712

713+
bool AlignApplied = false;
713714
for (auto &Property : Properties) {
714715
auto DecorStr = Property.first->str();
715716
auto DecorValue = Property.second;
@@ -733,18 +734,26 @@ void CompileTimePropertiesPass::parseAlignmentAndApply(
733734
auto Op_num = Pair.second;
734735
if (auto *LInst = dyn_cast<LoadInst>(Inst)) {
735736
LInst->setAlignment(Align_val);
737+
AlignApplied = true;
736738
} else if (auto *SInst = dyn_cast<StoreInst>(Inst)) {
737-
if (Op_num == 1)
739+
if (Op_num == 1) {
738740
SInst->setAlignment(Align_val);
741+
AlignApplied = true;
742+
}
739743
} else if (auto *MI = dyn_cast<MemTransferInst>(Inst)) {
740-
if (Op_num == 0)
744+
if (Op_num == 0) {
741745
MI->setDestAlignment(Align_val);
742-
else if (Op_num == 1)
746+
AlignApplied = true;
747+
} else if (Op_num == 1) {
743748
MI->setSourceAlignment(Align_val);
749+
AlignApplied = true;
750+
}
744751
}
745752
}
746753
}
747754
}
755+
756+
return AlignApplied;
748757
}
749758

750759
// Returns true if the transformation changed IntrInst.
@@ -773,7 +782,7 @@ bool CompileTimePropertiesPass::transformSYCLPropertiesAnnotation(
773782
return false;
774783

775784
// check alignment annotation and apply it to load/store
776-
parseAlignmentAndApply(M, IntrInst);
785+
bool AlignApplied = parseAlignmentAndApply(M, IntrInst);
777786

778787
// Read the annotation values and create new annotation strings.
779788
std::string NewAnnotString = "";
@@ -782,9 +791,9 @@ bool CompileTimePropertiesPass::transformSYCLPropertiesAnnotation(
782791
bool CacheProp = false;
783792
bool FPGAProp = false;
784793
for (const auto &[PropName, PropVal] : Properties) {
785-
// sycl-alignment is converted to align on
786-
// previous parseAlignmentAndApply(), dropping here
787-
if (PropName == "sycl-alignment")
794+
// if sycl-alignment is converted to align on IR constructs
795+
// during parseAlignmentAndApply(), dropping here
796+
if (PropName == "sycl-alignment" && AlignApplied)
788797
continue;
789798

790799
auto DecorIt = SpirvDecorMap.find(*PropName);

llvm/test/SYCLLowerIR/CompileTimePropertiesPass/sycl-properties-alignment-loadstore.ll renamed to llvm/test/SYCLLowerIR/CompileTimePropertiesPass/sycl-properties-alignment.ll

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
; RUN: opt -passes=compile-time-properties -S %s -o %t.ll
22
; RUN: FileCheck %s -input-file=%t.ll
33
;
4-
; Tests the translation of "sycl-alignment" to alignment attributes on load/store
4+
; Tests the translation of "sycl-alignment" to alignment attributes on load/store/non-memory instructions
55

66
target triple = "spir64_fpga-unknown-unknown"
77

@@ -11,13 +11,14 @@ target triple = "spir64_fpga-unknown-unknown"
1111
$_ZN7ann_refIiEC2EPi = comdat any
1212
$_ZN7ann_refIiEcvRiEv = comdat any
1313
$_ZN7ann_refIiEC2EPi1= comdat any
14+
$no_load_store = comdat any
1415

1516
@.str = private unnamed_addr addrspace(1) constant [16 x i8] c"sycl-properties\00", section "llvm.metadata"
1617
@.str.1 = private unnamed_addr addrspace(1) constant [9 x i8] c"main.cpp\00", section "llvm.metadata"
1718
@.str.2 = private unnamed_addr addrspace(1) constant [15 x i8] c"sycl-alignment\00", section "llvm.metadata"
1819
@.str.3 = private unnamed_addr addrspace(1) constant [3 x i8] c"64\00", section "llvm.metadata"
19-
@.args = private unnamed_addr addrspace(1) constant { ptr addrspace(1), ptr addrspace(1) } { ptr addrspace(1) @.str.2, ptr addrspace(1) @.str.3 }, section "llvm.met
20-
adata"
20+
@.args = private unnamed_addr addrspace(1) constant { ptr addrspace(1), ptr addrspace(1) } { ptr addrspace(1) @.str.2, ptr addrspace(1) @.str.3 }, section "llvm.metadata"
21+
; CHECK: @[[AnnoStr:.*]] = private unnamed_addr addrspace(1) constant [10 x i8] c"{44:\2264\22}\00"
2122

2223
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite)
2324
declare ptr addrspace(4) @llvm.ptr.annotation.p4.p1(ptr addrspace(4), ptr addrspace(1), ptr addrspace(1), i32, ptr addrspace(1)) #5
@@ -77,4 +78,19 @@ entry:
7778
ret void
7879
}
7980

81+
; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone
82+
define linkonce_odr dso_local spir_func noundef ptr addrspace(4) @no_load_store(ptr addrspace(4) noundef %ptr) comdat align 2 {
83+
entry:
84+
%retval = alloca ptr addrspace(4), align 8
85+
%ptr.addr = alloca ptr addrspace(4), align 8
86+
%retval.ascast = addrspacecast ptr %retval to ptr addrspace(4)
87+
%ptr.addr.ascast = addrspacecast ptr %ptr.addr to ptr addrspace(4)
88+
store ptr addrspace(4) %ptr, ptr addrspace(4) %ptr.addr.ascast, align 8
89+
%0 = load ptr addrspace(4), ptr addrspace(4) %ptr.addr.ascast, align 8
90+
; CHECK: %[[AnnoPtr:.*]] = call ptr addrspace(4) @llvm.ptr.annotation.p4.p1(ptr addrspace(4) %0, ptr addrspace(1) @[[AnnoStr]]
91+
; CHECK: ret ptr addrspace(4) %[[AnnoPtr]]
92+
%1 = call ptr addrspace(4) @llvm.ptr.annotation.p4.p1(ptr addrspace(4) %0, ptr addrspace(1) @.str, ptr addrspace(1) @.str.1, i32 73, ptr addrspace(1) @.args)
93+
ret ptr addrspace(4) %1
94+
}
95+
8096
declare void @llvm.memcpy.p4.p4.i32(ptr addrspace(4), ptr addrspace(4), i32, i1)

sycl/doc/extensions/experimental/sycl_ext_oneapi_annotated_ptr.asciidoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -476,8 +476,8 @@ a|
476476
T* get() const noexcept;
477477
----
478478
|
479-
Returns the underlying raw pointer. The raw pointer will not retain the
480-
annotations.
479+
Returns the underlying raw pointer. Implementations are free to propagate information from properties of
480+
an annotated_ptr to the raw pointer.
481481

482482
// --- ROW BREAK ---
483483
a|

sycl/include/sycl/ext/oneapi/experimental/annotated_ptr/annotated_ptr.hpp

Lines changed: 45 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,41 @@ template <typename... Ts>
5353
using contains_alignment =
5454
detail::ContainsProperty<alignment_key, std::tuple<Ts...>>;
5555

56+
// properties filter
57+
template <typename property_list, template <class...> typename filter>
58+
using PropertiesFilter =
59+
sycl::detail::boost::mp11::mp_copy_if<property_list, filter>;
60+
61+
// filter properties that are applied on annotations
62+
template <typename... Props>
63+
using annotation_filter = properties<
64+
PropertiesFilter<std::tuple<Props...>, propagateToPtrAnnotation>>;
5665
} // namespace detail
5766

67+
template <typename I, typename P> struct annotationHelper {};
68+
69+
// unpack properties to varadic template
70+
template <typename I, typename... P>
71+
struct annotationHelper<I, detail::properties_t<P...>> {
72+
static I *annotate(I *ptr) {
73+
return __builtin_intel_sycl_ptr_annotation(
74+
ptr, detail::PropertyMetaInfo<P>::name...,
75+
detail::PropertyMetaInfo<P>::value...);
76+
}
77+
78+
static I load(I *ptr) {
79+
return *__builtin_intel_sycl_ptr_annotation(
80+
ptr, detail::PropertyMetaInfo<P>::name...,
81+
detail::PropertyMetaInfo<P>::value...);
82+
}
83+
84+
template <class O> static I store(I *ptr, O &&Obj) {
85+
return *__builtin_intel_sycl_ptr_annotation(
86+
ptr, detail::PropertyMetaInfo<P>::name...,
87+
detail::PropertyMetaInfo<P>::value...) = std::forward<O>(Obj);
88+
}
89+
};
90+
5891
template <typename T, typename... Props>
5992
class annotated_ref<T, detail::properties_t<Props...>> {
6093
using property_list_t = detail::properties_t<Props...>;
@@ -67,44 +100,14 @@ class annotated_ref<T, detail::properties_t<Props...>> {
67100
T *m_Ptr;
68101
explicit annotated_ref(T *Ptr) : m_Ptr(Ptr) {}
69102

70-
// properties filter
71-
template <typename property_list, template <class...> typename filter>
72-
using PropertiesFilter =
73-
sycl::detail::boost::mp11::mp_copy_if<property_list, filter>;
74-
75-
template <typename p>
76-
using annotation_filter = propagateToPtrAnnotation<typename p::key_t>;
77-
78-
// filter properties that are applied on annotations
79-
using property_tuple_t = std::tuple<Props...>;
80-
using annotation_props =
81-
properties<PropertiesFilter<property_tuple_t, annotation_filter>>;
82-
83-
template <typename I, typename P> struct annotationHelper {};
84-
85-
// unpack properties to varadic template
86-
template <typename I, typename... P>
87-
struct annotationHelper<I, detail::properties_t<P...>> {
88-
static I load(I *ptr) {
89-
return *__builtin_intel_sycl_ptr_annotation(
90-
ptr, detail::PropertyMetaInfo<P>::name...,
91-
detail::PropertyMetaInfo<P>::value...);
92-
}
93-
94-
template <class O> static I store(I *ptr, O &&Obj) {
95-
return *__builtin_intel_sycl_ptr_annotation(
96-
ptr, detail::PropertyMetaInfo<P>::name...,
97-
detail::PropertyMetaInfo<P>::value...) = std::forward<O>(Obj);
98-
}
99-
};
100-
101103
public:
102104
annotated_ref(const annotated_ref &) = delete;
103105

104106
// implicit conversion with annotaion
105107
operator T() const {
106108
#ifdef __SYCL_DEVICE_ONLY__
107-
return annotationHelper<T, annotation_props>::load(m_Ptr);
109+
return annotationHelper<T, detail::annotation_filter<Props...>>::load(
110+
m_Ptr);
108111
#else
109112
return *m_Ptr;
110113
#endif
@@ -114,7 +117,8 @@ class annotated_ref<T, detail::properties_t<Props...>> {
114117
template <class O, typename = std::enable_if_t<!detail::is_ann_ref_v<O>>>
115118
T operator=(O &&Obj) const {
116119
#ifdef __SYCL_DEVICE_ONLY__
117-
return annotationHelper<T, annotation_props>::store(m_Ptr, Obj);
120+
return annotationHelper<T, detail::annotation_filter<Props...>>::store(
121+
m_Ptr, Obj);
118122
#else
119123
return *m_Ptr = std::forward<O>(Obj);
120124
#endif
@@ -376,7 +380,14 @@ __SYCL_TYPE(annotated_ptr) annotated_ptr<T, detail::properties_t<Props...>> {
376380

377381
operator T *() const noexcept = delete;
378382

379-
T *get() const noexcept { return m_Ptr; }
383+
T *get() const noexcept {
384+
#ifdef __SYCL_DEVICE_ONLY__
385+
return annotationHelper<T, detail::annotation_filter<Props...>>::annotate(
386+
m_Ptr);
387+
#else
388+
return m_Ptr;
389+
#endif
390+
}
380391

381392
// When the properties contain alignment, operator '[]', '+', '++' and '--'
382393
// (both post- and prefix) are disabled. Calling these operators when

sycl/include/sycl/ext/oneapi/experimental/common_annotated_properties/properties.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ struct check_property_list<T, Prop, Props...>
5858

5959
template <typename PropTy> struct propagateToPtrAnnotation : std::false_type {};
6060

61+
// Partial specilization for property_value
62+
template <typename PropKeyT, typename... PropValuesTs>
63+
struct propagateToPtrAnnotation<property_value<PropKeyT, PropValuesTs...>>
64+
: propagateToPtrAnnotation<PropKeyT> {};
65+
6166
//===----------------------------------------------------------------------===//
6267
// Common properties of annotated_arg/annotated_ptr
6368
//===----------------------------------------------------------------------===//
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// RUN: %clangxx -fsycl-device-only -fsycl-targets=spir64_fpga -S -emit-llvm %s -o - | FileCheck %s
2+
3+
// Tests that `@llvm.ptr.annotation` is inserted when calling
4+
// `annotated_ptr::get()`
5+
6+
#include "sycl/sycl.hpp"
7+
#include <sycl/ext/intel/fpga_extensions.hpp>
8+
9+
#include <iostream>
10+
11+
// clang-format on
12+
13+
using namespace sycl;
14+
using namespace ext::oneapi::experimental;
15+
using namespace ext::intel::experimental;
16+
17+
// CHECK: @[[AnnStr:.*]] = private unnamed_addr addrspace(1) constant [19 x i8] c"{5921:\220\22}{44:\228\22}\00"
18+
19+
using ann_ptr_t1 =
20+
annotated_ptr<int, decltype(properties(buffer_location<0>, alignment<8>))>;
21+
22+
struct MyIP {
23+
ann_ptr_t1 a;
24+
25+
MyIP(int *a_) : a(a_) {}
26+
27+
void operator()() const {
28+
// CHECK: %ptr.addr = alloca ptr addrspace(4), align 8
29+
// CHECK: store ptr addrspace(4) %ptr, ptr %ptr.addr, align 8
30+
// CHECK: %[[LoadPtr:.*]] = load ptr addrspace(4), ptr %ptr.addr, align 8
31+
// CHECK: %[[AnnPtr:.*]] = call ptr addrspace(4) @llvm.ptr.annotation.p4.p1(ptr addrspace(4) %[[LoadPtr]], ptr addrspace(1) @[[AnnStr]]
32+
// CHECK: ret ptr addrspace(4) %[[AnnPtr]]
33+
int *ptr = a.get(); // llvm.ptr.annotation is inserted
34+
*ptr = 15;
35+
}
36+
};
37+
38+
void TestVectorAddWithAnnotatedMMHosts() {
39+
sycl::queue q;
40+
auto raw = malloc_shared<int>(5, q);
41+
q.submit([&](handler &h) { h.single_task(MyIP{raw}); }).wait();
42+
free(raw, q);
43+
}
44+
45+
int main() {
46+
TestVectorAddWithAnnotatedMMHosts();
47+
return 0;
48+
}

sycl/test/extensions/properties/properties_cache_control.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,12 @@ using namespace ext::intel::experimental;
99

1010
using load_hint = annotated_ptr<
1111
float, decltype(properties(
12-
alignment<8>,
1312
read_hint<cache_control<cache_mode::cached, cache_level::L1>,
1413
cache_control<cache_mode::uncached, cache_level::L2,
1514
cache_level::L3>>))>;
1615
using load_assertion = annotated_ptr<
1716
int,
1817
decltype(properties(
19-
alignment<8>,
2018
read_assertion<cache_control<cache_mode::constant, cache_level::L1>,
2119
cache_control<cache_mode::invalidate, cache_level::L2,
2220
cache_level::L3>>))>;

0 commit comments

Comments
 (0)