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 @@ -15,6 +15,7 @@ #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 +80,55 @@ 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) { + constexpr StringLiteral DeadKeys[] = {"frame-pointer"}; + // Collect DeadKeys in ModuleFlags. + StringSet<> DeadKeySet; + for (auto &Key : DeadKeys) { + if (M.getModuleFlag(Key)) + DeadKeySet.insert(Key); + } + if (DeadKeySet.empty()) + return; + + SmallVector ModuleFlags; + M.getModuleFlagsMetadata(ModuleFlags); + NamedMDNode *MDFlags = M.getModuleFlagsMetadata(); + MDFlags->eraseFromParent(); + // Add ModuleFlag which not dead. + for (auto &Flag : ModuleFlags) { + StringRef Key = Flag.Key->getString(); + if (DeadKeySet.contains(Key)) + continue; + M.addModuleFlag(Flag.Behavior, Key, Flag.Val); + } +} + class DXILPrepareModule : public ModulePass { static Value *maybeGenerateBitcast(IRBuilder<> &Builder, @@ -112,6 +162,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,6 +221,8 @@ } } } + // Remove flags not in llvm3.7. + cleanModuleFlags(M); return true; } diff --git a/llvm/test/CodeGen/DirectX/clean_string_attr.ll b/llvm/test/CodeGen/DirectX/clean_string_attr.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/clean_string_attr.ll @@ -0,0 +1,23 @@ +; RUN: opt -S -dxil-prepare < %s | FileCheck %s + +; Make sure function attribute like "frame-pointer" is removed. +; CHECK:attributes #0 = { nounwind memory(readwrite, inaccessiblemem: read) } + +; Make sure "frame-pointer" is removed from module flags. +; CHECK:!llvm.module.flags = !{![[SIZE:[0-9]+]]} +; CHECK:![[SIZE]] = !{i32 1, !"wchar_size", i32 4} + +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" + +; Function Attrs: mustprogress nofree nounwind willreturn memory(readwrite, inaccessiblemem: read) +define void @CSMain() local_unnamed_addr #0 { + ret void +} + +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" }