diff --git a/llvm/lib/SYCLLowerIR/SYCLPropagateAspectsUsage.cpp b/llvm/lib/SYCLLowerIR/SYCLPropagateAspectsUsage.cpp index 6d8c248a8160..126a03bdf03b 100644 --- a/llvm/lib/SYCLLowerIR/SYCLPropagateAspectsUsage.cpp +++ b/llvm/lib/SYCLLowerIR/SYCLPropagateAspectsUsage.cpp @@ -647,6 +647,38 @@ void setSyclFixedTargetsMD(const std::vector &EntryPoints, F->setMetadata("sycl_fixed_targets", MDN); } +void collectVirtualFunctionSetInfo( + Function &F, StringMap> &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 &Visited, + StringMap> &VirtualFunctionSets) { + if (!F->hasFnAttribute("calls-indirectly")) + return; + Attribute CallsIndirectlyAttr = F->getFnAttribute("calls-indirectly"); + SmallVector 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 buildFunctionsToAspectsMap(Module &M, TypeToAspectsMapTy &TypesWithAspects, @@ -655,16 +687,21 @@ buildFunctionsToAspectsMap(Module &M, TypeToAspectsMapTy &TypesWithAspects, bool ValidateAspects, bool FP64ConvEmu) { FunctionToAspectsMapTy FunctionToUsedAspects; FunctionToAspectsMapTy FunctionToDeclaredAspects; + StringMap> VirtualFunctionSets; CallGraphTy CG; for (Function &F : M.functions()) { processFunction(F, FunctionToUsedAspects, FunctionToDeclaredAspects, TypesWithAspects, CG, AspectValues, FP64ConvEmu); + collectVirtualFunctionSetInfo(F, VirtualFunctionSets); } SmallPtrSet 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, diff --git a/llvm/test/SYCLLowerIR/PropagateAspectsUsage/VirtualFunctions/virtual-functions-1.ll b/llvm/test/SYCLLowerIR/PropagateAspectsUsage/VirtualFunctions/virtual-functions-1.ll new file mode 100644 index 000000000000..709ca33eae3b --- /dev/null +++ b/llvm/test/SYCLLowerIR/PropagateAspectsUsage/VirtualFunctions/virtual-functions-1.ll @@ -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} diff --git a/llvm/test/SYCLLowerIR/PropagateAspectsUsage/VirtualFunctions/virtual-functions-2.ll b/llvm/test/SYCLLowerIR/PropagateAspectsUsage/VirtualFunctions/virtual-functions-2.ll new file mode 100644 index 000000000000..ae600413378f --- /dev/null +++ b/llvm/test/SYCLLowerIR/PropagateAspectsUsage/VirtualFunctions/virtual-functions-2.ll @@ -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} diff --git a/llvm/test/SYCLLowerIR/PropagateAspectsUsage/VirtualFunctions/virtual-functions-3.ll b/llvm/test/SYCLLowerIR/PropagateAspectsUsage/VirtualFunctions/virtual-functions-3.ll new file mode 100644 index 000000000000..ada0f533ced5 --- /dev/null +++ b/llvm/test/SYCLLowerIR/PropagateAspectsUsage/VirtualFunctions/virtual-functions-3.ll @@ -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} diff --git a/llvm/test/SYCLLowerIR/PropagateAspectsUsage/VirtualFunctions/virtual-functions-4.ll b/llvm/test/SYCLLowerIR/PropagateAspectsUsage/VirtualFunctions/virtual-functions-4.ll new file mode 100644 index 000000000000..700a2dc7a8b7 --- /dev/null +++ b/llvm/test/SYCLLowerIR/PropagateAspectsUsage/VirtualFunctions/virtual-functions-4.ll @@ -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} \ No newline at end of file