Skip to content
Merged
18 changes: 9 additions & 9 deletions llvm/lib/Target/DirectX/DXILFinalizeLinkage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,20 @@
using namespace llvm;

static bool finalizeLinkage(Module &M) {
SmallPtrSet<Function *, 8> EntriesAndExports;
SmallPtrSet<Function *, 8> Funcs;

// Find all entry points and export functions
// Collect non-entry and non-exported functions to set to internal linkage.
for (Function &EF : M.functions()) {
if (!EF.hasFnAttribute("hlsl.shader") && !EF.hasFnAttribute("hlsl.export"))
if (EF.hasFnAttribute("hlsl.shader") || EF.hasFnAttribute("hlsl.export"))
continue;
EntriesAndExports.insert(&EF);
Funcs.insert(&EF);
}

for (Function &F : M.functions()) {
if (F.getLinkage() == GlobalValue::ExternalLinkage &&
!EntriesAndExports.contains(&F)) {
F.setLinkage(GlobalValue::InternalLinkage);
}
for (Function *F : Funcs) {
if (F->getLinkage() == GlobalValue::ExternalLinkage)
F->setLinkage(GlobalValue::InternalLinkage);
if (F->isDefTriviallyDead())
M.getFunctionList().erase(F);
}

return false;
Expand Down
3 changes: 2 additions & 1 deletion llvm/test/CodeGen/DirectX/ShaderFlags/double-extensions.ll
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ target triple = "dxil-pc-shadermodel6.7-library"
; CHECK-NEXT: ; Double-precision extensions for 11.1
; CHECK-NEXT: ; Note: extra DXIL module flags:
; CHECK-NEXT: {{^;$}}
define double @div(double %a, double %b) {
define double @div(double %a, double %b) #0 {
%res = fdiv double %a, %b
ret double %res
}

attributes #0 = { convergent norecurse nounwind "hlsl.export"}

; DXC: - Name: SFI0
; DXC-NEXT: Size: 8
Expand Down
4 changes: 3 additions & 1 deletion llvm/test/CodeGen/DirectX/ShaderFlags/doubles.ll
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ target triple = "dxil-pc-shadermodel6.7-library"
; CHECK-NEXT: ; Note: extra DXIL module flags:
; CHECK-NEXT: {{^;$}}

define double @add(double %a, double %b) {
define double @add(double %a, double %b) #0 {
%sum = fadd double %a, %b
ret double %sum
}

attributes #0 = { convergent norecurse nounwind "hlsl.export"}

; DXC: - Name: SFI0
; DXC-NEXT: Size: 8
; DXC-NEXT: Flags:
Expand Down
10 changes: 6 additions & 4 deletions llvm/test/CodeGen/DirectX/conflicting-bitcast-insert.ll
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
; RUN: llc --filetype=asm %s -o - | FileCheck %s
target triple = "dxil-unknown-shadermodel6.7-library"

define i64 @test(ptr %p) {
define i64 @test(ptr %p) #0 {
store i32 0, ptr %p
%v = load i64, ptr %p
ret i64 %v
}

; CHECK: define internal i64 @test(ptr %p) {
; CHECK: define i64 @test(ptr %p) #0 {
; CHECK-NEXT: %1 = bitcast ptr %p to ptr
; CHECK-NEXT: store i32 0, ptr %1, align 4
; CHECK-NEXT: %2 = bitcast ptr %p to ptr
; CHECK-NEXT: %3 = load i64, ptr %2, align 8

define i64 @testGEP(ptr %p) {
define i64 @testGEP(ptr %p) #0 {
%ptr = getelementptr i32, ptr %p, i32 4
%val = load i64, ptr %p
ret i64 %val
}

; CHECK: define internal i64 @testGEP(ptr %p) {
attributes #0 = { convergent norecurse nounwind "hlsl.export"}

; CHECK: define i64 @testGEP(ptr %p) #0 {
; CHECK-NEXT: %1 = bitcast ptr %p to ptr
; CHECK-NEXT: %ptr = getelementptr i32, ptr %1, i32 4
; CHECK-NEXT: %2 = bitcast ptr %p to ptr
Expand Down
223 changes: 223 additions & 0 deletions llvm/test/CodeGen/DirectX/finalize-linkage-remove-dead.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
; RUN: opt -S -dxil-finalize-linkage -mtriple=dxil-unknown-shadermodel6.5-compute %s | FileCheck %s
; RUN: opt -S -dxil-finalize-linkage -mtriple=dxil-unknown-shadermodel6.5-library %s | FileCheck %s
; RUN: llc %s --filetype=asm -o - | FileCheck %s

target triple = "dxilv1.5-pc-shadermodel6.5-compute"

; Confirm that DXILFinalizeLinkage will remove functions that have compatible
; linkage and are not called from anywhere. This should be any function that
; is not explicitly marked export and is not an entry point.

; Has no specified inlining/linking behavior and is uncalled, this should be removed.
; CHECK-NOT: define {{.*}}doNothingUncalled
define void @"?doNothingUncalled@@YAXXZ"() #2 {
entry:
ret void
}

; Alwaysinline and uncalled, this should be removed.
; CHECK-NOT: define {{.*}}doAlwaysInlineUncalled
define void @"?doAlwaysInlineUncalled@@YAXXZ"() #0 {
entry:
ret void
}

; Noinline and uncalled, this should be removed.
; CHECK-NOT: define {{.*}}doNoinlineUncalled
define void @"?doNoinlineUncalled@@YAXXZ"() #4 {
entry:
ret void
}

; No inlining attribute, internal, and uncalled; this should be removed.
; CHECK-NOT: define {{.*}}doInternalUncalled
define internal void @"?doInternalUncalled@@YAXXZ"() #2 {
entry:
ret void
}

; Alwaysinline, internal, and uncalled; this should be removed.
; CHECK-NOT: define {{.*}}doAlwaysInlineInternalUncalled
define internal void @"?doAlwaysInlineInternalUncalled@@YAXXZ"() #0 {
entry:
ret void
}

; Noinline, internal, and uncalled; this should be removed.
; CHECK-NOT: define {{.*}}doNoinlineInternalUncalled
define internal void @"?doNoinlineInternalUncalled@@YAXXZ"() #4 {
entry:
ret void
}

; Marked external and uncalled, this should become internal and be removed.
; CHECK-NOT: define {{.*}}doExternalUncalled
define external void @"?doExternalUncalled@@YAXXZ"() #2 {
entry:
ret void
}

; Alwaysinline, external and uncalled, this should become internal and be removed.
; CHECK-NOT: define {{.*}}doAlwaysInlineExternalUncalled
define external void @"?doAlwaysInlineExternalUncalled@@YAXXZ"() #0 {
entry:
ret void
}

; Noinline, external and uncalled, this should become internal and be removed.
; CHECK-NOT: define {{.*}}doNoinlineExternalUncalled
define external void @"?doNoinlineExternalUncalled@@YAXXZ"() #4 {
entry:
ret void
}

; No inlining attribute and called, this should stay.
; CHECK: define {{.*}}doNothingCalled
define void @"?doNothingCalled@@YAXXZ"() #2 {
entry:
ret void
}

; Alwaysinline and called, this should stay.
; CHECK: define {{.*}}doAlwaysInlineCalled
define void @"?doAlwaysInlineCalled@@YAXXZ"() #0 {
entry:
ret void
}

; Noinline and called, this should stay.
; CHECK: define {{.*}}doNoinlineCalled
define void @"?doNoinlineCalled@@YAXXZ"() #4 {
entry:
ret void
}

; No inlining attribute, internal, and called; this should stay.
; CHECK: define {{.*}}doInternalCalled
define internal void @"?doInternalCalled@@YAXXZ"() #2 {
entry:
ret void
}

; Alwaysinline, internal, and called; this should stay.
; CHECK: define {{.*}}doAlwaysInlineInternalCalled
define internal void @"?doAlwaysInlineInternalCalled@@YAXXZ"() #0 {
entry:
ret void
}

; Noinline, internal, and called; this should stay.
; CHECK: define {{.*}}doNoinlineInternalCalled
define internal void @"?doNoinlineInternalCalled@@YAXXZ"() #4 {
entry:
ret void
}

; Marked external and called, this should become internal and stay.
; CHECK: define {{.*}}doExternalCalled
define external void @"?doExternalCalled@@YAXXZ"() #2 {
entry:
ret void
}

; Always inlined, external and called, this should become internal and stay.
; CHECK: define {{.*}}doAlwaysInlineExternalCalled
define external void @"?doAlwaysInlineExternalCalled@@YAXXZ"() #0 {
entry:
ret void
}

; Noinline, external and called, this should become internal and stay.
; CHECK: define {{.*}}doNoinlineExternalCalled
define external void @"?doNoinlineExternalCalled@@YAXXZ"() #4 {
entry:
ret void
}

; No inlining attribute and exported, this should stay.
; CHECK: define {{.*}}doNothingExported
define void @"?doNothingExported@@YAXXZ"() #3 {
entry:
ret void
}

; Alwaysinline and exported, this should stay.
; CHECK: define {{.*}}doAlwaysInlineExported
define void @"?doAlwaysInlineExported@@YAXXZ"() #1 {
entry:
ret void
}

; Noinline attribute and exported, this should stay.
; CHECK: define {{.*}}doNoinlineExported
define void @"?doNoinlineExported@@YAXXZ"() #5 {
entry:
ret void
}

; No inlining attribute, internal, and exported; this should stay.
; CHECK: define {{.*}}doInternalExported
define internal void @"?doInternalExported@@YAXXZ"() #3 {
entry:
ret void
}

; Alwaysinline, internal, and exported; this should stay.
; CHECK: define {{.*}}doAlwaysInlineInternalExported
define internal void @"?doAlwaysInlineInternalExported@@YAXXZ"() #1 {
entry:
ret void
}

; Noinline, internal, and exported; this should stay.
; CHECK: define {{.*}}doNoinlineInternalExported
define internal void @"?doNoinlineInternalExported@@YAXXZ"() #5 {
entry:
ret void
}

; Marked external and exported, this should stay.
; CHECK: define {{.*}}doExternalExported
define external void @"?doExternalExported@@YAXXZ"() #3 {
entry:
ret void
}

; Alwaysinline, external and exported, this should stay.
; CHECK: define {{.*}}doAlwaysInlineExternalExported
define external void @"?doAlwaysInlineExternalExported@@YAXXZ"() #1 {
entry:
ret void
}

; Noinline, external and exported, this should stay.
; CHECK: define {{.*}}doNoinlineExternalExported
define external void @"?doNoinlineExternalExported@@YAXXZ"() #5 {
entry:
ret void
}

; Entry point function, this should stay.
; CHECK: define void @main()
define void @main() #6 {
entry:
call void @"?doNothingCalled@@YAXXZ"() #7
call void @"?doAlwaysInlineCalled@@YAXXZ"() #7
call void @"?doNoinlineCalled@@YAXXZ"() #7
call void @"?doInternalCalled@@YAXXZ"() #7
call void @"?doAlwaysInlineInternalCalled@@YAXXZ"() #7
call void @"?doNoinlineInternalCalled@@YAXXZ"() #7
call void @"?doExternalCalled@@YAXXZ"() #7
call void @"?doAlwaysInlineExternalCalled@@YAXXZ"() #7
call void @"?doNoinlineExternalCalled@@YAXXZ"() #7
ret void
}

attributes #0 = { alwaysinline convergent norecurse nounwind }
attributes #1 = { alwaysinline convergent norecurse nounwind "hlsl.export"}
attributes #2 = { convergent norecurse nounwind }
attributes #3 = { convergent norecurse nounwind "hlsl.export"}
attributes #4 = { convergent noinline norecurse nounwind }
attributes #5 = { convergent noinline norecurse nounwind "hlsl.export"}
attributes #6 = { convergent noinline norecurse "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
attributes #7 = { convergent }
2 changes: 1 addition & 1 deletion llvm/test/CodeGen/DirectX/finalize_linkage.ll
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ target triple = "dxilv1.5-pc-shadermodel6.5-compute"
; DXILFinalizeLinkage changes linkage of all functions that are not
; entry points or exported function to internal.

; CHECK: define internal void @"?f1@@YAXXZ"()
; CHECK-NOT: define internal void @"?f1@@YAXXZ"()
define void @"?f1@@YAXXZ"() #0 {
entry:
ret void
Expand Down
6 changes: 4 additions & 2 deletions llvm/test/CodeGen/DirectX/fneg-conversion.ll
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
; RUN: llc %s --filetype=asm -o - | FileCheck %s
target triple = "dxil-unknown-shadermodel6.7-library"

define float @negateF(float %0) {
define float @negateF(float %0) #0 {
; CHECK: %2 = fsub float -0.000000e+00, %0
%2 = fneg float %0
ret float %2
}

define double @negateD(double %0) {
define double @negateD(double %0) #0 {
; CHECK: %2 = fsub double -0.000000e+00, %0
%2 = fneg double %0
ret double %2
}

attributes #0 = { convergent norecurse nounwind "hlsl.export"}
14 changes: 8 additions & 6 deletions llvm/test/CodeGen/DirectX/omit-bitcast-insert.ll
Original file line number Diff line number Diff line change
@@ -1,32 +1,34 @@
; RUN: llc --filetype=asm %s -o - | FileCheck %s
target triple = "dxil-unknown-shadermodel6.7-library"

define i64 @test(ptr %p) {
define i64 @test(ptr %p) #0 {
%v = load i64, ptr %p
ret i64 %v
}

; CHECK: define internal i64 @test(ptr %p) {
; CHECK: define i64 @test(ptr %p) #0 {
; CHECK-NEXT: %v = load i64, ptr %p, align 8
; CHECK-NEXT: ret i64 %v

define i64 @test2(ptr %p) {
define i64 @test2(ptr %p) #0 {
store i64 0, ptr %p
%v = load i64, ptr %p
ret i64 %v
}

; CHECK: define internal i64 @test2(ptr %p) {
; CHECK: define i64 @test2(ptr %p) #0 {
; CHECK-NEXT: store i64 0, ptr %p
; CHECK-NEXT: %v = load i64, ptr %p, align 8
; CHECK-NEXT: ret i64 %v

define i32 @test3(ptr %0) {
define i32 @test3(ptr %0) #0 {
%2 = getelementptr i32, ptr %0, i32 4
%3 = load i32, ptr %2
ret i32 %3
}

; CHECK: define internal i32 @test3(ptr %0) {
attributes #0 = { convergent norecurse nounwind "hlsl.export"}

; CHECK: define i32 @test3(ptr %0) #0 {
; CHECK-NEXT: %2 = getelementptr i32, ptr %0, i32 4
; CHECK-NEXT: %3 = load i32, ptr %2
Loading
Loading