@@ -1641,6 +1641,110 @@ INITIALIZE_PASS(DxilEmitMetadata, "hlsl-dxilemit", "HLSL DXIL Metadata Emit",
16411641
16421642namespace {
16431643
1644+ // DxilTrimTargetTypes pass makes sure the !dx.targetTypes metadata only
1645+ // contains types that are actually used by the shader.
1646+
1647+ class DxilTrimTargetTypes : public ModulePass {
1648+ public:
1649+ static char ID; // Pass identification, replacement for typeid
1650+ explicit DxilTrimTargetTypes () : ModulePass(ID) {}
1651+
1652+ StringRef getPassName () const override {
1653+ return " HLSL DXIL Trim Target Types" ;
1654+ }
1655+
1656+ // Map of target type to its metadata node and usage flag.
1657+ using TargetTypesUsageMap =
1658+ SmallDenseMap<llvm::Type *, std::pair<MDTuple *, bool >, 16 >;
1659+
1660+ void markTargetTypeAsUsed (TargetTypesUsageMap &Map, llvm::Type *Ty) {
1661+ auto It = Map.find (Ty);
1662+ assert (It != Map.end () &&
1663+ " used target type is not in dx.targetTypes metadata list" );
1664+ (*It).second .second = true ;
1665+ }
1666+
1667+ bool runOnModule (Module &M) override {
1668+ NamedMDNode *TargetTypesMDNode =
1669+ M.getNamedMetadata (DxilMDHelper::kDxilTargetTypesMDName );
1670+ if (!TargetTypesMDNode)
1671+ return false ;
1672+
1673+ // Add all target types that from "dx.targetTypes" metadata to the map
1674+ // to track their usage.
1675+ TargetTypesUsageMap TargetTypesMap;
1676+ for (MDNode *Node : TargetTypesMDNode->operands ()) {
1677+ MDTuple *TypeMD = dyn_cast<MDTuple>(Node);
1678+ if (!TypeMD || TypeMD->getNumOperands () == 0 )
1679+ continue ;
1680+
1681+ ConstantAsMetadata *ConstMD =
1682+ dyn_cast<ConstantAsMetadata>(TypeMD->getOperand (0 ).get ());
1683+ if (!ConstMD)
1684+ continue ;
1685+
1686+ Constant *TypeUndefPtr = ConstMD->getValue ();
1687+ llvm::Type *Ty = TypeUndefPtr->getType ();
1688+ TargetTypesMap.try_emplace (Ty, std::make_pair (TypeMD, false ));
1689+ }
1690+
1691+ // Scan all LinAlgMatrix functions and check the return type and argument
1692+ // types to find all used target types.
1693+ for (const llvm::Function &F : M.functions ()) {
1694+ if (!F.isDeclaration ())
1695+ continue ;
1696+
1697+ // Currently only LinAlgMatrix ops use target types.
1698+ if (!OP::IsDxilOpLinAlgFuncName (F.getName ()))
1699+ continue ;
1700+
1701+ llvm::Type *RetTy = F.getReturnType ();
1702+ if (dxilutil::IsHLSLKnownTargetType (RetTy))
1703+ markTargetTypeAsUsed (TargetTypesMap, RetTy);
1704+
1705+ for (const auto &Arg : F.args ()) {
1706+ llvm::Type *Ty = Arg.getType ();
1707+ if (dxilutil::IsHLSLKnownTargetType (Ty))
1708+ markTargetTypeAsUsed (TargetTypesMap, Ty);
1709+ }
1710+ }
1711+
1712+ // Remove old metadata node from the module.
1713+ TargetTypesMDNode->eraseFromParent ();
1714+
1715+ // Create a new one with the used target types.
1716+ NamedMDNode *NewTargetTypesMDNode =
1717+ M.getOrInsertNamedMetadata (DxilMDHelper::kDxilTargetTypesMDName );
1718+ for (auto &Entry : TargetTypesMap) {
1719+ MDTuple *Node = Entry.second .first ;
1720+ bool IsUsed = Entry.second .second ;
1721+ if (IsUsed)
1722+ NewTargetTypesMDNode->addOperand (Node);
1723+ }
1724+
1725+ // If no target type is used, remove the new metadata node from module.
1726+ if (NewTargetTypesMDNode->getNumOperands () == 0 )
1727+ NewTargetTypesMDNode->eraseFromParent ();
1728+
1729+ return true ;
1730+ }
1731+ };
1732+
1733+ } // namespace
1734+
1735+ char DxilTrimTargetTypes::ID = 0 ;
1736+
1737+ ModulePass *llvm::createDxilTrimTargetTypesPass () {
1738+ return new DxilTrimTargetTypes ();
1739+ }
1740+
1741+ INITIALIZE_PASS (DxilTrimTargetTypes, " hlsl-trim-target-types" ,
1742+ " HLSL DXIL Trim Target Types" , false , false )
1743+
1744+ // /////////////////////////////////////////////////////////////////////////////
1745+
1746+ namespace {
1747+
16441748const StringRef UniNoWaveSensitiveGradientErrMsg =
16451749 " Gradient operations are not affected by wave-sensitive data or control "
16461750 " flow." ;
0 commit comments