Skip to content

Commit

Permalink
[SYCL] Update aspect propagation for virtual functions (#15703)
Browse files Browse the repository at this point in the history
Spec & design: intel/llvm#10540
  • Loading branch information
jzc authored Nov 6, 2024
1 parent f77c81f commit 37b339e
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 1 deletion.
39 changes: 38 additions & 1 deletion llvm/lib/SYCLLowerIR/SYCLPropagateAspectsUsage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,38 @@ void setSyclFixedTargetsMD(const std::vector<Function *> &EntryPoints,
F->setMetadata("sycl_fixed_targets", MDN);
}

void collectVirtualFunctionSetInfo(
Function &F, StringMap<SmallVector<Function *, 4>> &VirtualFunctionSets) {
if (!F.hasFnAttribute("indirectly-callable"))
return;
Attribute IndirectlyCallableAttr = F.getFnAttribute("indirectly-callable");
StringRef SetName = IndirectlyCallableAttr.getValueAsString();
VirtualFunctionSets[SetName].push_back(&F);
}

// For each set S of virtual functions that F declares,
// propagate S through the CG and then add the aspects
// used by S to F.
void processDeclaredVirtualFunctionSets(
Function *F, CallGraphTy &CG, FunctionToAspectsMapTy &AspectsMap,
SmallPtrSet<const Function *, 16> &Visited,
StringMap<SmallVector<Function *, 4>> &VirtualFunctionSets) {
if (!F->hasFnAttribute("calls-indirectly"))
return;
Attribute CallsIndirectlyAttr = F->getFnAttribute("calls-indirectly");
SmallVector<StringRef, 4> DeclaredVirtualFunctionSetNames;
CallsIndirectlyAttr.getValueAsString().split(DeclaredVirtualFunctionSetNames,
",");
auto &AspectsF = AspectsMap[F];
for (auto Name : DeclaredVirtualFunctionSetNames) {
for (auto VFn : VirtualFunctionSets[Name]) {
propagateAspectsThroughCG(VFn, CG, AspectsMap, Visited);
for (auto Aspect : AspectsMap[VFn])
AspectsF.insert(Aspect);
}
}
}

/// Returns a map of functions with corresponding used aspects.
std::pair<FunctionToAspectsMapTy, FunctionToAspectsMapTy>
buildFunctionsToAspectsMap(Module &M, TypeToAspectsMapTy &TypesWithAspects,
Expand All @@ -655,16 +687,21 @@ buildFunctionsToAspectsMap(Module &M, TypeToAspectsMapTy &TypesWithAspects,
bool ValidateAspects, bool FP64ConvEmu) {
FunctionToAspectsMapTy FunctionToUsedAspects;
FunctionToAspectsMapTy FunctionToDeclaredAspects;
StringMap<SmallVector<Function *, 4>> VirtualFunctionSets;
CallGraphTy CG;

for (Function &F : M.functions()) {
processFunction(F, FunctionToUsedAspects, FunctionToDeclaredAspects,
TypesWithAspects, CG, AspectValues, FP64ConvEmu);
collectVirtualFunctionSetInfo(F, VirtualFunctionSets);
}

SmallPtrSet<const Function *, 16> Visited;
for (Function *F : EntryPoints)
for (Function *F : EntryPoints) {
propagateAspectsThroughCG(F, CG, FunctionToUsedAspects, Visited);
processDeclaredVirtualFunctionSets(F, CG, FunctionToUsedAspects, Visited,
VirtualFunctionSets);
}

if (ValidateAspects)
validateUsedAspectsForFunctions(FunctionToUsedAspects, AspectValues,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
; RUN: opt -passes=sycl-propagate-aspects-usage < %s -S | FileCheck %s

; CHECK: @vfn() #0 !sycl_used_aspects ![[#aspects:]]
define spir_func void @vfn() #0 {
%tmp = alloca double
ret void
}

; CHECK: @foo() #1 !sycl_used_aspects ![[#aspects]]
define spir_kernel void @foo() #1 {
ret void
}

; CHECK: ![[#aspects]] = !{i32 6}

attributes #0 = { "indirectly-callable"="_ZTSv" }
attributes #1 = { "calls-indirectly"="_ZTSv" }

!sycl_aspects = !{!0}
!0 = !{!"fp64", i32 6}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
; RUN: opt -passes=sycl-propagate-aspects-usage < %s -S | FileCheck %s

%Foo = type { i32 }
%Bar = type { i32 }

; CHECK: @vfnFoo() #0 !sycl_used_aspects ![[#aspectsFoo:]]
define spir_func void @vfnFoo() #0 {
%tmp = alloca %Foo
ret void
}

; CHECK: @vfnBar() #1 !sycl_used_aspects ![[#aspectsBar:]]
define spir_func void @vfnBar() #1 {
%tmp = alloca %Bar
ret void
}

; CHECK: @kernel() #2 !sycl_used_aspects ![[#aspectsKernel:]]
define spir_kernel void @kernel() #2 {
ret void
}

; CHECK: ![[#aspectsFoo]] = !{i32 1}
; CHECK: ![[#aspectsBar]] = !{i32 2}
; CHECK: ![[#aspectsKernel]] = !{i32 1, i32 2}

attributes #0 = { "indirectly-callable"="setFoo" }
attributes #1 = { "indirectly-callable"="setBar" }
attributes #2 = { "calls-indirectly"="setFoo,setBar" }

!sycl_aspects = !{!0}
!0 = !{!"fp64", i32 6}

!sycl_types_that_use_aspects = !{!1, !2}
!1 = !{!"Foo", i32 1}
!2 = !{!"Bar", i32 2}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
; RUN: opt -passes=sycl-propagate-aspects-usage < %s -S | FileCheck %s

%Foo = type { i32 }
%Bar = type { i32 }

; CHECK: @vfnFoo() #0 !sycl_used_aspects ![[#aspectsFoo:]]
define spir_func void @vfnFoo() #0 {
call void @subFoo()
ret void
}

define spir_func void @subFoo() {
%tmp = alloca %Foo
ret void
}

; CHECK: @vfnBar() #1 !sycl_used_aspects ![[#aspectsBar:]]
define spir_func void @vfnBar() #1 {
call void @subBar()
ret void
}

define spir_func void @subBar() {
%tmp = alloca %Bar
ret void
}

; CHECK: @kernelA() #2 !sycl_used_aspects ![[#aspectsFoo]]
define spir_kernel void @kernelA() #2 {
ret void
}

; CHECK: @kernelB() #3 !sycl_used_aspects ![[#aspectsBar]]
define spir_kernel void @kernelB() #3 {
ret void
}

; CHECK: ![[#aspectsFoo]] = !{i32 1}
; CHECK: ![[#aspectsBar]] = !{i32 2}

attributes #0 = { "indirectly-callable"="setFoo" }
attributes #1 = { "indirectly-callable"="setBar" }
attributes #2 = { "calls-indirectly"="setFoo" }
attributes #3 = { "calls-indirectly"="setBar" }

!sycl_aspects = !{!0}
!0 = !{!"fp64", i32 6}

!sycl_types_that_use_aspects = !{!1, !2}
!1 = !{!"Foo", i32 1}
!2 = !{!"Bar", i32 2}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
; RUN: opt -passes=sycl-propagate-aspects-usage < %s -S | FileCheck %s
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1"
target triple = "spir64-unknown-unknown"

@vtable = linkonce_odr dso_local unnamed_addr addrspace(1) constant { [3 x ptr addrspace(4)] } { [3 x ptr addrspace(4)] [ptr addrspace(4) null, ptr addrspace(4) null, ptr addrspace(4) addrspacecast (ptr @foo to ptr addrspace(4))] }, align 8

; CHECK: @foo() #0 !sycl_used_aspects ![[#aspects:]]
define linkonce_odr spir_func void @foo() #0 {
entry:
%tmp = alloca double
ret void
}

; CHECK-NOT: @construct({{.*}}){{.*}}!sycl_used_aspects
define weak_odr dso_local spir_kernel void @construct(ptr addrspace(1) noundef align 8 %_arg_StorageAcc) {
entry:
store ptr addrspace(1) getelementptr inbounds inrange(-16, 8) (i8, ptr addrspace(1) @vtable, i64 16), ptr addrspace(1) %_arg_StorageAcc, align 8
ret void
}

; CHECK: ![[#aspects]] = !{i32 6}

attributes #0 = { "indirectly-callable"="set-foo" }

!sycl_aspects = !{!0}
!0 = !{!"fp64", i32 6}

0 comments on commit 37b339e

Please sign in to comment.