[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:
parent
6de4865545
commit
dd8ae42674
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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" }
|
||||
|
|
@ -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" }
|
||||
|
|
@ -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"}
|
||||
|
|
@ -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" }
|
||||
|
||||
Loading…
Reference in New Issue