diff --git a/llvm/lib/Target/DirectX/DXILPrepare.cpp b/llvm/lib/Target/DirectX/DXILPrepare.cpp --- a/llvm/lib/Target/DirectX/DXILPrepare.cpp +++ b/llvm/lib/Target/DirectX/DXILPrepare.cpp @@ -11,10 +11,12 @@ /// Language (DXIL). //===----------------------------------------------------------------------===// +#include "DXILResourceAnalysis.h" #include "DirectX.h" #include "DirectXIRPasses/PointerTypeAnalysis.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringSet.h" #include "llvm/CodeGen/Passes.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instruction.h" @@ -79,6 +81,49 @@ Attr); } +static void collectDeadStringAttrs(AttributeMask &DeadAttrs, AttributeSet &&AS, + StringSet<> LiveKeys) { + for (auto &Attr : AS) { + if (!Attr.isStringAttribute()) + continue; + StringRef Key = Attr.getKindAsString(); + if (LiveKeys.contains(Key)) + continue; + DeadAttrs.addAttribute(Key); + } +} + +static void removeStringFunctionAttributes(Function &F) { + AttributeList Attrs = F.getAttributes(); + StringSet<> LiveKeys = {"waveops-include-helper-lanes" + "fp32-denorm-mode"}; + // Collect DeadKeys in FnAttrs. + AttributeMask DeadAttrs; + collectDeadStringAttrs(DeadAttrs, Attrs.getFnAttrs(), LiveKeys); + collectDeadStringAttrs(DeadAttrs, Attrs.getRetAttrs(), LiveKeys); + + F.removeFnAttrs(DeadAttrs); + F.removeRetAttrs(DeadAttrs); +} + +static void cleanModuleFlags(Module &M) { + NamedMDNode *MDFlags = M.getModuleFlagsMetadata(); + if (!MDFlags) + return; + + StringSet<> LiveKeys = {"Dwarf Version", "Debug Info Version"}; + + SmallVector FlagEntries; + M.getModuleFlagsMetadata(FlagEntries); + MDFlags->eraseFromParent(); + + for (auto &Flag : FlagEntries) { + if (!LiveKeys.count(Flag.Key->getString())) + continue; + M.addModuleFlag(Flag.Behavior, Flag.Key->getString(), Flag.Val); + } +} + class DXILPrepareModule : public ModulePass { static Value *maybeGenerateBitcast(IRBuilder<> &Builder, @@ -112,6 +157,7 @@ for (auto &F : M.functions()) { F.removeFnAttrs(AttrMask); F.removeRetAttrs(AttrMask); + removeStringFunctionAttributes(F); for (size_t Idx = 0, End = F.arg_size(); Idx < End; ++Idx) F.removeParamAttrs(Idx, AttrMask); @@ -170,11 +216,17 @@ } } } + // Remove flags not in llvm3.7. + cleanModuleFlags(M); return true; } DXILPrepareModule() : ModulePass(ID) {} + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.addPreserved(); + } + static char ID; // Pass identification. }; char DXILPrepareModule::ID = 0; diff --git a/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp b/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp --- a/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp +++ b/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp @@ -76,8 +76,8 @@ FunctionPass *createTargetRegisterAllocator(bool) override { return nullptr; } void addCodeGenPrepare() override { addPass(createDXILOpLoweringLegacyPass()); - addPass(createDXILPrepareModulePass()); addPass(createDXILTranslateMetadataPass()); + addPass(createDXILPrepareModulePass()); } }; diff --git a/llvm/test/CodeGen/DirectX/UAVMetadata.ll b/llvm/test/CodeGen/DirectX/UAVMetadata.ll --- a/llvm/test/CodeGen/DirectX/UAVMetadata.ll +++ b/llvm/test/CodeGen/DirectX/UAVMetadata.ll @@ -1,6 +1,6 @@ ; RUN: opt -S -dxil-metadata-emit < %s | FileCheck %s ; RUN: opt -S --passes="print-dxil-resource" < %s 2>&1 | FileCheck %s --check-prefix=PRINT -; RUN: llc %s --filetype=asm -o - < %s 2>&1 | FileCheck %s --check-prefixes=CHECK,PRINT +; RUN: llc --filetype=asm -o - < %s 2>&1 | FileCheck %s --check-prefixes=CHECK,PRINT target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" target triple = "dxil-pc-shadermodel6.0-library" diff --git a/llvm/test/CodeGen/DirectX/strip-string-fn-attrs-module-flags.ll b/llvm/test/CodeGen/DirectX/strip-string-fn-attrs-module-flags.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/strip-string-fn-attrs-module-flags.ll @@ -0,0 +1,47 @@ +; RUN: opt -S -dxil-prepare < %s | FileCheck %s +target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" +target triple = "dxil-unknown-shadermodel6.0-compute" + +; make sure string function attribute and module flags are clear for llvm3.7. + +; CHECK-LABEL:define void @CSMain() +; CHECK:attributes #0 = { nounwind memory(readwrite, inaccessiblemem: read) } +; CHECK-NOT:!llvm.module.flags + + +%"class.hlsl::RWBuffer" = type { ptr } +%dx.types.Handle = type { ptr } +%dx.types.ResRet.i32 = type { i32, i32, i32, i32, i32 } + +@"?srcBuffer@@3V?$RWBuffer@T?$__vector@H$01@__clang@@@hlsl@@A" = local_unnamed_addr global %"class.hlsl::RWBuffer" zeroinitializer, align 4 +@"?dstBuffer@@3V?$RWBuffer@T?$__vector@H$01@__clang@@@hlsl@@A" = local_unnamed_addr global %"class.hlsl::RWBuffer" zeroinitializer, align 4 + +; Function Attrs: mustprogress nofree nounwind willreturn memory(readwrite, inaccessiblemem: read) +define void @CSMain() local_unnamed_addr #0 { +entry: + %0 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 1, i32 0, i1 false) + %1 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 0, i32 1, i1 false) + %2 = call i32 @dx.op.threadId.i32(i32 93, i32 0) + %3 = call %dx.types.ResRet.i32 @dx.op.bufferLoad.i32(i32 68, %dx.types.Handle %1, i32 %2, i32 poison) + %4 = extractvalue %dx.types.ResRet.i32 %3, 0 + %5 = extractvalue %dx.types.ResRet.i32 %3, 1 + %add.i.i0 = add i32 %4, 10 + %add.i.i1 = add i32 %5, 10 + call void @dx.op.bufferStore.i32(i32 69, %dx.types.Handle %0, i32 %2, i32 poison, i32 %add.i.i0, i32 %add.i.i1, i32 %add.i.i0, i32 %add.i.i0, i8 15) + ret void +} + +declare %dx.types.Handle @dx.op.createHandle(i32 %0, i8 %1, i32 %2, i32 %3, i1 %4) + +declare %dx.types.ResRet.i32 @dx.op.bufferLoad.i32(i32 %0, %dx.types.Handle %1, i32 %2, i32 %3) + +declare void @dx.op.bufferStore.i32(i32 %0, %dx.types.Handle %1, i32 %2, i32 %3, i32 %4, i32 %5, i32 %6, i32 %7, i8 %8) + +declare i32 @dx.op.threadId.i32(i32 %0, i32 %1) + +attributes #0 = { mustprogress nofree nounwind willreturn memory(readwrite, inaccessiblemem: read) "frame-pointer"="all" "hlsl.numthreads"="1024,1,1" "hlsl.shader"="compute" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } + +!llvm.module.flags = !{!0, !1} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{i32 7, !"frame-pointer", i32 2} diff --git a/llvm/test/tools/dxil-dis/attribute-filter.ll b/llvm/test/tools/dxil-dis/attribute-filter.ll --- a/llvm/test/tools/dxil-dis/attribute-filter.ll +++ b/llvm/test/tools/dxil-dis/attribute-filter.ll @@ -19,8 +19,8 @@ ret float %5 } -; CHECK: attributes #0 = { nounwind readnone "disable-tail-calls"="false" } +; CHECK: attributes #0 = { nounwind readnone } attributes #0 = { norecurse nounwind readnone willreturn "disable-tail-calls"="false" } -; CHECK: attributes #1 = { readnone "disable-tail-calls"="false" } +; CHECK: attributes #1 = { readnone } attributes #1 = { norecurse memory(none) willreturn "disable-tail-calls"="false" } diff --git a/llvm/test/tools/dxil-dis/di-compile-unit.ll b/llvm/test/tools/dxil-dis/di-compile-unit.ll --- a/llvm/test/tools/dxil-dis/di-compile-unit.ll +++ b/llvm/test/tools/dxil-dis/di-compile-unit.ll @@ -10,8 +10,9 @@ !3 = !{i32 7, !"Dwarf Version", i32 2} !4 = !{i32 2, !"Debug Info Version", i32 3} +; CHECK: !llvm.module.flags = !{![[DWARF:[0-9]+]], ![[DEBUG:[0-9]+]]} + ; CHECK: !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "Some Compiler", isOptimized: true, runtimeVersion: 0, emissionKind: 1, enums: !2) ; CHECK: !1 = !DIFile(filename: "di-compile-unit.src", directory: "/some-path") -; CHECK: !2 = !{} -; CHECK: !3 = !{i32 7, !"Dwarf Version", i32 2} -; CHECK: !4 = !{i32 2, !"Debug Info Version", i32 3} +; CHECK: ![[DWARF]] = !{i32 7, !"Dwarf Version", i32 2} +; CHECK: ![[DEBUG]] = !{i32 2, !"Debug Info Version", i32 3} diff --git a/llvm/test/tools/dxil-dis/di-subprogram.ll b/llvm/test/tools/dxil-dis/di-subprogram.ll --- a/llvm/test/tools/dxil-dis/di-subprogram.ll +++ b/llvm/test/tools/dxil-dis/di-subprogram.ll @@ -6,48 +6,51 @@ !llvm.used = !{!5} !llvm.lines = !{!13, !14, !15, !16} +; CHECK: !llvm.module.flags = !{![[DWARF:[0-9]+]], ![[DEBUG:[0-9]+]]} + ; CHECK: !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "Some Compiler", isOptimized: true, runtimeVersion: 0, emissionKind: 1, enums: !2) !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "Some Compiler", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None) ; CHECK: !1 = !DIFile(filename: "some-source", directory: "some-path") !1 = !DIFile(filename: "some-source", directory: "some-path") !2 = !{} -; CHECK: !3 = !{i32 7, !"Dwarf Version", i32 2} !3 = !{i32 7, !"Dwarf Version", i32 2} -; CHECK: !4 = !{i32 2, !"Debug Info Version", i32 3} !4 = !{i32 2, !"Debug Info Version", i32 3} -; CHECK: !5 = distinct !DISubprogram(name: "fma", scope: !1, file: !1, line: 1, type: !6, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, function: !0, variables: !9) +; CHECK: ![[FMA:[0-9]+]] = distinct !DISubprogram(name: "fma", scope: !1, file: !1, line: 1, type: ![[FMATY:[0-9]+]], isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, function: !0, variables: ![[VARS:[0-9]+]]) !5 = distinct !DISubprogram(name: "fma", scope: !1, file: !1, line: 1, type: !6, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !9) -; CHECK: !6 = !DISubroutineType(types: !7) +; CHECK: ![[FMATY]] = !DISubroutineType(types: ![[FMATYS:[0-9]+]]) !6 = !DISubroutineType(types: !7) -; CHECK: !7 = !{!8, !8, !8, !8} +; CHECK: ![[FMATYS]] = !{![[F32TY:[0-9]+]], ![[F32TY]], ![[F32TY]], ![[F32TY]]} !7 = !{!8, !8, !8, !8} -; CHECK: !8 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float) +; CHECK: ![[F32TY]] = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float) !8 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float) -; CHECK: !9 = !{!10, !11, !12} +; CHECK: ![[VARS]] = !{![[X:[0-9]+]], ![[Y:[0-9]+]], ![[Z:[0-9]+]]} !9 = !{!10, !11, !12} -; CHECK: !10 = !DILocalVariable(tag: DW_TAG_variable, name: "x", arg: 1, scope: !5, file: !1, line: 1, type: !8) +; CHECK: ![[X]] = !DILocalVariable(tag: DW_TAG_variable, name: "x", arg: 1, scope: ![[FMA]], file: !1, line: 1, type: ![[F32TY]]) !10 = !DILocalVariable(name: "x", arg: 1, scope: !5, file: !1, line: 1, type: !8) -; CHECK: !11 = !DILocalVariable(tag: DW_TAG_variable, name: "y", arg: 2, scope: !5, file: !1, line: 1, type: !8) +; CHECK: ![[Y]] = !DILocalVariable(tag: DW_TAG_variable, name: "y", arg: 2, scope: ![[FMA]], file: !1, line: 1, type: ![[F32TY]]) !11 = !DILocalVariable(name: "y", arg: 2, scope: !5, file: !1, line: 1, type: !8) -; CHECK: !12 = !DILocalVariable(tag: DW_TAG_variable, name: "z", arg: 3, scope: !5, file: !1, line: 1, type: !8) +; CHECK: ![[Z]] = !DILocalVariable(tag: DW_TAG_variable, name: "z", arg: 3, scope: ![[FMA]], file: !1, line: 1, type: ![[F32TY]]) !12 = !DILocalVariable(name: "z", arg: 3, scope: !5, file: !1, line: 1, type: !8) -; CHECK: !13 = !DILocation(line: 0, scope: !5) -; CHECK: !14 = !DILocation(line: 2, column: 12, scope: !5) -; CHECK: !15 = !DILocation(line: 2, column: 16, scope: !5) -; CHECK: !16 = !DILocation(line: 2, column: 3, scope: !5) +; CHECK: !{{[0-9]+}} = !DILocation(line: 0, scope: ![[FMA]]) +; CHECK: !{{[0-9]+}} = !DILocation(line: 2, column: 12, scope: ![[FMA]]) +; CHECK: !{{[0-9]+}} = !DILocation(line: 2, column: 16, scope: ![[FMA]]) +; CHECK: !{{[0-9]+}} = !DILocation(line: 2, column: 3, scope: ![[FMA]]) !13 = !DILocation(line: 0, scope: !5) !14 = !DILocation(line: 2, column: 12, scope: !5) !15 = !DILocation(line: 2, column: 16, scope: !5) !16 = !DILocation(line: 2, column: 3, scope: !5) + +; CHECK: ![[DWARF]] = !{i32 7, !"Dwarf Version", i32 2} +; CHECK: ![[DEBUG]] = !{i32 2, !"Debug Info Version", i32 3}