[IndirectFunctions] Skip propagating attributes to address taken functions

In case of indirect calls or address taken functions,
skip propagating any attributes to them. We just
propagate features to such functions.

Reviewed By: rampitec

Differential Revision: https://reviews.llvm.org/D94585
This commit is contained in:
madhur13490 2021-01-13 09:32:29 +00:00
parent 6de4865545
commit dd8ae42674
5 changed files with 235 additions and 1 deletions

View File

@ -240,6 +240,14 @@ bool AMDGPUPropagateAttributes::process() {
if (F.isDeclaration())
continue;
// Skip propagating attributes and features to
// address taken functions.
if (F.hasAddressTaken()) {
if (!Roots.count(&F))
NewRoots.insert(&F);
continue;
}
const FnProperties CalleeProps(*TM, F);
SmallVector<std::pair<CallBase *, Function *>, 32> ToReplace;
SmallSet<CallBase *, 32> Visited;
@ -259,7 +267,11 @@ bool AMDGPUPropagateAttributes::process() {
const FnProperties CallerProps(*TM, *Caller);
if (CalleeProps == CallerProps) {
// Convergence is allowed if the caller has its
// address taken because all callee's (attributes + features)
// may not agree as the callee may be the target of
// more than one function (called directly or indirectly).
if (Caller->hasAddressTaken() || CalleeProps == CallerProps) {
if (!Roots.count(&F))
NewRoots.insert(&F);
continue;

View File

@ -0,0 +1,59 @@
; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -amdgpu-propagate-attributes-early %s | FileCheck %s
; Complicated call graph where a function is called
; directly from a kernel abd also from a function
; whose address is taken.
; CHECK-LABEL: define float @common_callee.gc() #0 {
define float @common_callee.gc() {
ret float 0.0
}
; CHECK-LABEL: define float @foo() {
define float @foo() {
ret float 0.0
}
; CHECK-LABEL: define float @bar() {
define float @bar() {
ret float 0.0
}
; CHECK-LABEL: define float @baz() {
define float @baz() {
ret float 0.0
}
define amdgpu_kernel void @switch_indirect_kernel(float *%result, i32 %type) #1 {
%fn = alloca float ()*
switch i32 %type, label %sw.default [
i32 1, label %sw.bb
i32 2, label %sw.bb2
i32 3, label %sw.bb3
]
sw.bb:
store float ()* @foo, float ()** %fn
br label %sw.epilog
sw.bb2:
store float ()* @bar, float ()** %fn
br label %sw.epilog
sw.bb3:
store float ()* @baz, float ()** %fn
br label %sw.epilog
sw.default:
br label %sw.epilog
sw.epilog:
%fp = load float ()*, float ()** %fn
%direct_call = call contract float @common_callee.gc()
%indirect_call = call contract float %fp()
store float %indirect_call, float* %result
ret void
}
attributes #0 = { "amdgpu-flat-work-group-size"="1,256" "target-features"="-wavefrontsize16,-wavefrontsize32,+wavefrontsize64" }
attributes #1 = { "amdgpu-flat-work-group-size"="1,256" }

View File

@ -0,0 +1,53 @@
; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -amdgpu-propagate-attributes-early %s | FileCheck %s
; Test to check if we skip propgating attributes even if
; a function is called directly as well as
; indirectly. "baz" is called directly as well indirectly.
; CHECK-LABEL: define float @foo() {
define float @foo() {
ret float 0.0
}
; CHECK-LABEL: define float @bar() {
define float @bar() {
ret float 0.0
}
; CHECK-LABEL: define float @baz() {
define float @baz() {
ret float 0.0
}
define amdgpu_kernel void @switch_indirect_kernel(float *%result, i32 %type) #1 {
%fn = alloca float ()*
switch i32 %type, label %sw.default [
i32 1, label %sw.bb
i32 2, label %sw.bb2
i32 3, label %sw.bb3
]
sw.bb:
store float ()* @foo, float ()** %fn
br label %sw.epilog
sw.bb2:
store float ()* @bar, float ()** %fn
br label %sw.epilog
sw.bb3:
store float ()* @baz, float ()** %fn
br label %sw.epilog
sw.default:
br label %sw.epilog
sw.epilog:
%fp = load float ()*, float ()** %fn
%direct_call = call contract float @baz()
%indirect_call = call contract float %fp()
store float %indirect_call, float* %result
ret void
}
attributes #1 = { "amdgpu-flat-work-group-size"="1,256" }

View File

@ -0,0 +1,58 @@
; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -amdgpu-propagate-attributes-early %s | FileCheck %s
; Test to check if we skip attributes on address
; taken functions but pass to direct callees.
; CHECK-LABEL: define float @foo() {
define float @foo() {
ret float 0.0
}
; CHECK-LABEL: define float @bar() {
define float @bar() {
ret float 0.0
}
; CHECK-LABEL: define float @baz() {
define float @baz() {
ret float 0.0
}
; CHECK-LABEL: define float @baz2() #0 {
define float @baz2() {
ret float 0.0
}
define amdgpu_kernel void @switch_indirect_kernel(float *%result, i32 %type) #1 {
%fn = alloca float ()*
switch i32 %type, label %sw.default [
i32 1, label %sw.bb
i32 2, label %sw.bb2
i32 3, label %sw.bb3
]
sw.bb:
store float ()* @foo, float ()** %fn
br label %sw.epilog
sw.bb2:
store float ()* @bar, float ()** %fn
br label %sw.epilog
sw.bb3:
store float ()* @baz, float ()** %fn
br label %sw.epilog
sw.default:
br label %sw.epilog
sw.epilog:
%fp = load float ()*, float ()** %fn
%direct_call = call contract float @baz2()
%indirect_call = call contract float %fp()
store float %indirect_call, float* %result
ret void
}
attributes #0 = { "amdgpu-flat-work-group-size"="1,256" "target-features"="-wavefrontsize16,-wavefrontsize32,+wavefrontsize64" }
attributes #1 = { "amdgpu-flat-work-group-size"="1,256"}

View File

@ -0,0 +1,52 @@
; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -amdgpu-propagate-attributes-early %s | FileCheck %s
; Test to check if we skip attributes on address
; taken functions in a simple call graph.
; CHECK-LABEL: define float @foo() {
define float @foo() {
ret float 0.0
}
; CHECK-LABEL: define float @bar() {
define float @bar() {
ret float 0.0
}
; CHECK-LABEL: define float @baz() {
define float @baz() {
ret float 0.0
}
define amdgpu_kernel void @switch_indirect_kernel(float *%result, i32 %type) #1 {
%fn = alloca float ()*
switch i32 %type, label %sw.default [
i32 1, label %sw.bb
i32 2, label %sw.bb2
i32 3, label %sw.bb3
]
sw.bb:
store float ()* @foo, float ()** %fn
br label %sw.epilog
sw.bb2:
store float ()* @bar, float ()** %fn
br label %sw.epilog
sw.bb3:
store float ()* @baz, float ()** %fn
br label %sw.epilog
sw.default:
br label %sw.epilog
sw.epilog:
%fp = load float ()*, float ()** %fn
%indirect_call = call contract float %fp()
store float %indirect_call, float* %result
ret void
}
attributes #1 = { "amdgpu-flat-work-group-size"="1,256" }