[WHLSL] Inline typedef'd types during Metal code generation to simplify generated...
authorweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 28 Aug 2019 18:11:12 +0000 (18:11 +0000)
committerweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 28 Aug 2019 18:11:12 +0000 (18:11 +0000)
https://bugs.webkit.org/show_bug.cgi?id=201185

Reviewed by Saam Barati.

The current Metal code generation generates many unnecessary typedefs during TypeNamer::emitMetalTypeDefinitions
such as 'typedef float2 type19;' that can be removed by just using resolved type whereever the typedef would have
been used. The only types that actually need to be predefined are the types that declare a new struct or enum, which
means we can stop emitting for AST::TypeReference, AST::Pointer, AST::Array, and AST::TypeDefinition. Instead, the
relevent mangledNameForType constructs the computed name on the fly.

This is a 25% speedup in the metal code generation phase.

* Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp:
(WebCore::WHLSL::Metal::FunctionDefinitionWriter::visit):
Switch to using auto rather than Mangled*Name when it is obvious and the actual return type
may need to become more complicated (e.g. MangledOrNativeTypeName).

* Modules/webgpu/WHLSL/Metal/WHLSLTypeNamer.h:
* Modules/webgpu/WHLSL/Metal/WHLSLTypeNamer.cpp:
(WebCore::WHLSL::Metal::TypeNamer::visit):
There is no need to generate typenames for AST::TypeDefinitions if they are never used.

(WebCore::WHLSL::Metal::TypeNamer::generateUniquedTypeName):
The only UnnamedType that needs a generated typename now is AST::ArrayReferenceType, which emits a struct interface.

(WebCore::WHLSL::Metal::TypeNamer::emitUnnamedTypeDefinition):
Stop generating type definitions for AST::TypeReference, AST::Pointer, AST::Array.

(WebCore::WHLSL::Metal::TypeNamer::emitNamedTypeDefinition):
Stop generating type definitions for AST::TypeDefinition.

(WebCore::WHLSL::Metal::TypeNamer::emitMetalTypeDefinitions):
Update for rename from m_unnamedTypeMapping to m_arrayReferenceTypeMapping.

(WebCore::WHLSL::Metal::TypeNamer::mangledNameForType):
Look into the types and generate a concrete type name when necessary. Lazily cache the constructed
names for AST::ArrayType and AST::Pointer.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@249209 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp
Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLTypeNamer.cpp
Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLTypeNamer.h

index 2f1360b..1431478 100644 (file)
@@ -1,3 +1,44 @@
+2019-08-28  Sam Weinig  <weinig@apple.com>
+
+        [WHLSL] Inline typedef'd types during Metal code generation to simplify generated code while also making it easier to read
+        https://bugs.webkit.org/show_bug.cgi?id=201185
+
+        Reviewed by Saam Barati.
+
+        The current Metal code generation generates many unnecessary typedefs during TypeNamer::emitMetalTypeDefinitions
+        such as 'typedef float2 type19;' that can be removed by just using resolved type whereever the typedef would have
+        been used. The only types that actually need to be predefined are the types that declare a new struct or enum, which 
+        means we can stop emitting for AST::TypeReference, AST::Pointer, AST::Array, and AST::TypeDefinition. Instead, the
+        relevent mangledNameForType constructs the computed name on the fly. 
+        
+        This is a 25% speedup in the metal code generation phase.
+
+        * Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp:
+        (WebCore::WHLSL::Metal::FunctionDefinitionWriter::visit):
+        Switch to using auto rather than Mangled*Name when it is obvious and the actual return type
+        may need to become more complicated (e.g. MangledOrNativeTypeName).
+
+        * Modules/webgpu/WHLSL/Metal/WHLSLTypeNamer.h:
+        * Modules/webgpu/WHLSL/Metal/WHLSLTypeNamer.cpp:
+        (WebCore::WHLSL::Metal::TypeNamer::visit):
+        There is no need to generate typenames for AST::TypeDefinitions if they are never used.
+
+        (WebCore::WHLSL::Metal::TypeNamer::generateUniquedTypeName):
+        The only UnnamedType that needs a generated typename now is AST::ArrayReferenceType, which emits a struct interface.
+
+        (WebCore::WHLSL::Metal::TypeNamer::emitUnnamedTypeDefinition):
+        Stop generating type definitions for AST::TypeReference, AST::Pointer, AST::Array.
+
+        (WebCore::WHLSL::Metal::TypeNamer::emitNamedTypeDefinition):
+        Stop generating type definitions for AST::TypeDefinition.
+
+        (WebCore::WHLSL::Metal::TypeNamer::emitMetalTypeDefinitions):
+        Update for rename from m_unnamedTypeMapping to m_arrayReferenceTypeMapping.
+
+        (WebCore::WHLSL::Metal::TypeNamer::mangledNameForType):
+        Look into the types and generate a concrete type name when necessary. Lazily cache the constructed
+        names for AST::ArrayType and AST::Pointer.
+
 2019-08-28  Keith Rollin  <krollin@apple.com>
 
         Remove support for macOS < 10.13 (part 2)
index bb7ddcd..43df2a5 100644 (file)
@@ -525,12 +525,12 @@ void FunctionDefinitionWriter::visit(AST::DotExpression& dotExpression)
 void FunctionDefinitionWriter::visit(AST::GlobalVariableReference& globalVariableReference)
 {
     auto valueName = generateNextVariableName();
-    MangledTypeName mangledTypeName = m_typeNamer.mangledNameForType(globalVariableReference.resolvedType());
+    auto mangledTypeName = m_typeNamer.mangledNameForType(globalVariableReference.resolvedType());
 
     checkErrorAndVisit(globalVariableReference.base());
     MangledVariableName structVariable = takeLastValue();
 
-    MangledStructureElementName mangledFieldName = m_typeNamer.mangledNameForStructureElement(globalVariableReference.structField());
+    auto mangledFieldName = m_typeNamer.mangledNameForStructureElement(globalVariableReference.structField());
 
     m_stringBuilder.append(
         m_indent, mangledTypeName, ' ', valueName, " = ", structVariable, "->", mangledFieldName, ";\n");
index 55d253e..481f203 100644 (file)
@@ -118,10 +118,6 @@ void TypeNamer::visit(AST::StructureDefinition& structureDefinition)
 
 void TypeNamer::visit(AST::TypeDefinition& typeDefinition)
 {
-    {
-        auto addResult = m_namedTypeMapping.add(&typeDefinition, generateNextTypeName());
-        ASSERT_UNUSED(addResult, addResult.isNewEntry);
-    }
     Visitor::visit(typeDefinition);
     {
         auto addResult = m_dependencyGraph.add(&typeDefinition, Vector<std::reference_wrapper<AST::UnnamedType>> { typeDefinition.type() });
@@ -146,31 +142,13 @@ String TypeNamer::mangledNameForType(AST::NativeTypeDeclaration& nativeTypeDecla
     return writeNativeType(nativeTypeDeclaration);
 }
 
-static AST::UnnamedType* parent(AST::UnnamedType& unnamedType)
-{
-    switch (unnamedType.kind()) {
-    case AST::UnnamedType::Kind::TypeReference:
-        return nullptr;
-    case AST::UnnamedType::Kind::Pointer:
-        return &downcast<AST::PointerType>(unnamedType).elementType();
-    case AST::UnnamedType::Kind::ArrayReference:
-        return &downcast<AST::ArrayReferenceType>(unnamedType).elementType();
-    case AST::UnnamedType::Kind::Array:
-        return &downcast<AST::ArrayType>(unnamedType).type();
-    default:
-        RELEASE_ASSERT_NOT_REACHED();
-    }
-}
-
 void TypeNamer::generateUniquedTypeName(AST::UnnamedType& unnamedType)
 {
-    auto* parentUnnamedType = parent(unnamedType);
-    if (parentUnnamedType)
-        generateUniquedTypeName(*parentUnnamedType);
-
-    m_unnamedTypeMapping.ensure(UnnamedTypeKey { unnamedType }, [&] {
-        return generateNextTypeName();
-    });
+    if (is<AST::ArrayReferenceType>(unnamedType)) {
+        m_arrayReferenceTypeMapping.ensure(UnnamedTypeKey { unnamedType }, [&] {
+            return generateNextTypeName();
+        });
+    }
 }
 
 class MetalTypeDeclarationWriter final : public Visitor {
@@ -200,59 +178,36 @@ void TypeNamer::emitMetalTypeDeclarations(StringBuilder& stringBuilder)
     metalTypeDeclarationWriter.Visitor::visit(m_program);
 }
 
-void TypeNamer::emitUnnamedTypeDefinition(StringBuilder& stringBuilder, AST::UnnamedType& unnamedType, MangledTypeName mangledName, HashSet<AST::NamedType*>& emittedNamedTypes, HashSet<UnnamedTypeKey>& emittedUnnamedTypes)
+void TypeNamer::emitUnnamedTypeDefinition(StringBuilder& stringBuilder, AST::UnnamedType& unnamedType, MangledOrNativeTypeName mangledName, HashSet<AST::NamedType*>& emittedNamedTypes, HashSet<UnnamedTypeKey>& emittedUnnamedTypes)
 {
     if (emittedUnnamedTypes.contains(UnnamedTypeKey { unnamedType }))
         return;
 
     switch (unnamedType.kind()) {
     case AST::UnnamedType::Kind::TypeReference: {
-        auto& typeReference = downcast<AST::TypeReference>(unnamedType);
-
-        auto& parent = typeReference.resolvedType();
-        auto parentMangledName = mangledNameForType(typeReference.resolvedType());
-        auto iterator = m_dependencyGraph.find(&parent);
-        ASSERT(iterator != m_dependencyGraph.end());
-        emitNamedTypeDefinition(stringBuilder, parent, iterator->value, emittedNamedTypes, emittedUnnamedTypes);
-
-        stringBuilder.append("typedef ", parentMangledName, ' ', mangledName, ";\n");
         break;
     }
     case AST::UnnamedType::Kind::Pointer: {
-        auto& pointerType = downcast<AST::PointerType>(unnamedType);
-
-        auto& parent = pointerType.elementType();
-        auto parentMangledName = mangledNameForType(parent);
-        emitUnnamedTypeDefinition(stringBuilder, parent, parentMangledName, emittedNamedTypes, emittedUnnamedTypes);
-
-        stringBuilder.append("typedef ", toString(pointerType.addressSpace()), ' ', parentMangledName, "* ", mangledName, ";\n");
+        break;
+    }
+    case AST::UnnamedType::Kind::Array: {
         break;
     }
     case AST::UnnamedType::Kind::ArrayReference: {
         auto& arrayReferenceType = downcast<AST::ArrayReferenceType>(unnamedType);
 
-        auto& parent = arrayReferenceType.elementType();
-        auto parentMangledName = mangledNameForType(parent);
-        emitUnnamedTypeDefinition(stringBuilder, parent, parentMangledName, emittedNamedTypes, emittedUnnamedTypes);
+        auto& elementType = arrayReferenceType.elementType();
+        auto elementTypeMangledName = mangledNameForType(elementType);
+        emitUnnamedTypeDefinition(stringBuilder, elementType, elementTypeMangledName, emittedNamedTypes, emittedUnnamedTypes);
 
         stringBuilder.append(
             "struct ", mangledName, " {\n"
-            "    ", toString(arrayReferenceType.addressSpace()), ' ', parentMangledName, "* pointer;\n"
+            "    ", toString(arrayReferenceType.addressSpace()), ' ', elementTypeMangledName, "* pointer;\n"
             "    uint32_t length;\n"
             "};\n"
         );
         break;
     }
-    case AST::UnnamedType::Kind::Array: {
-        auto& arrayType = downcast<AST::ArrayType>(unnamedType);
-
-        auto& parent = arrayType.type();
-        auto parentMangledName = mangledNameForType(parent);
-        emitUnnamedTypeDefinition(stringBuilder, parent, parentMangledName, emittedNamedTypes, emittedUnnamedTypes);
-
-        stringBuilder.append("typedef array<", parentMangledName, ", ", arrayType.numElements(), "> ", mangledName, ";\n");
-        break;
-    }
     default:
         RELEASE_ASSERT_NOT_REACHED();
     }
@@ -269,6 +224,14 @@ void TypeNamer::emitNamedTypeDefinition(StringBuilder& stringBuilder, AST::Named
         emitUnnamedTypeDefinition(stringBuilder, unnameType, mangledNameForType(unnameType), emittedNamedTypes, emittedUnnamedTypes);
 
     switch (namedType.kind()) {
+    case AST::NamedType::Kind::NativeTypeDeclaration: {
+        // Native types already have definitions. There's nothing to do.
+        break;
+    }
+    case AST::NamedType::Kind::TypeDefinition: {
+        // The mangled name of a AST::TypeDefinition looks through to the underlying type. There is nothing to do.
+        break;
+    }
     case AST::NamedType::Kind::EnumerationDefinition: {
         auto& enumerationDefinition = downcast<AST::EnumerationDefinition>(namedType);
         auto& baseType = enumerationDefinition.type().unifyNode();
@@ -279,10 +242,6 @@ void TypeNamer::emitNamedTypeDefinition(StringBuilder& stringBuilder, AST::Named
         stringBuilder.append("};\n");
         break;
     }
-    case AST::NamedType::Kind::NativeTypeDeclaration: {
-        // Native types already have definitions. There's nothing to do.
-        break;
-    }
     case AST::NamedType::Kind::StructureDefinition: {
         auto& structureDefinition = downcast<AST::StructureDefinition>(namedType);
 
@@ -292,12 +251,6 @@ void TypeNamer::emitNamedTypeDefinition(StringBuilder& stringBuilder, AST::Named
         stringBuilder.append("};\n");
         break;
     }
-    case AST::NamedType::Kind::TypeDefinition: {
-        auto& typeDefinition = downcast<AST::TypeDefinition>(namedType);
-
-        stringBuilder.append("typedef ", mangledNameForType(typeDefinition.type()), ' ', mangledNameForType(typeDefinition), ";\n");
-        break;
-    }
     default:
         RELEASE_ASSERT_NOT_REACHED();
     }
@@ -311,24 +264,57 @@ void TypeNamer::emitMetalTypeDefinitions(StringBuilder& stringBuilder)
     HashSet<UnnamedTypeKey> emittedUnnamedTypes;
     for (auto& [namedType, neighbors] : m_dependencyGraph)
         emitNamedTypeDefinition(stringBuilder, *namedType, neighbors, emittedNamedTypes, emittedUnnamedTypes);
-    for (auto& [unnamedTypeKey, mangledName] : m_unnamedTypeMapping)
+    for (auto& [unnamedTypeKey, mangledName] : m_arrayReferenceTypeMapping)
         emitUnnamedTypeDefinition(stringBuilder, unnamedTypeKey.unnamedType(), mangledName, emittedNamedTypes, emittedUnnamedTypes);
 }
 
-MangledTypeName TypeNamer::mangledNameForType(AST::UnnamedType& unnamedType)
+MangledOrNativeTypeName TypeNamer::mangledNameForType(AST::UnnamedType& unnamedType)
 {
-    auto iterator = m_unnamedTypeMapping.find(UnnamedTypeKey { unnamedType });
-    ASSERT(iterator != m_unnamedTypeMapping.end());
-    return iterator->value;
+    switch (unnamedType.kind()) {
+    case AST::UnnamedType::Kind::TypeReference: {
+        auto& typeReference = downcast<AST::TypeReference>(unnamedType);
+        return mangledNameForType(typeReference.resolvedType());
+    }
+    case AST::UnnamedType::Kind::Pointer: {
+        auto& pointerType = downcast<AST::PointerType>(unnamedType);
+        return m_lazyUnnamedTypeCache.ensure(UnnamedTypeKey { unnamedType }, [&] {
+            return makeString(toString(pointerType.addressSpace()), ' ', mangledNameForType(pointerType.elementType()), '*');
+        }).iterator->value;
+    }
+    case AST::UnnamedType::Kind::Array: {
+        auto& arrayType = downcast<AST::ArrayType>(unnamedType);
+        return m_lazyUnnamedTypeCache.ensure(UnnamedTypeKey { unnamedType }, [&] {
+            return makeString("array<", mangledNameForType(arrayType.type()), ", ", arrayType.numElements(), '>');
+        }).iterator->value;
+    }
+    case AST::UnnamedType::Kind::ArrayReference: {
+        auto iterator = m_arrayReferenceTypeMapping.find(UnnamedTypeKey { unnamedType });
+        ASSERT(iterator != m_arrayReferenceTypeMapping.end());
+        return iterator->value;
+    }
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
+    }
 }
 
 MangledOrNativeTypeName TypeNamer::mangledNameForType(AST::NamedType& namedType)
 {
-    if (is<AST::NativeTypeDeclaration>(namedType))
+    switch (namedType.kind()) {
+    case AST::NamedType::Kind::NativeTypeDeclaration: {
         return mangledNameForType(downcast<AST::NativeTypeDeclaration>(namedType));
-    auto iterator = m_namedTypeMapping.find(&namedType);
-    ASSERT(iterator != m_namedTypeMapping.end());
-    return iterator->value;
+    }
+    case AST::NamedType::Kind::TypeDefinition: {
+        return mangledNameForType(downcast<AST::TypeDefinition>(namedType).type());
+    }
+    case AST::NamedType::Kind::EnumerationDefinition:
+    case AST::NamedType::Kind::StructureDefinition: {
+        auto iterator = m_namedTypeMapping.find(&namedType);
+        ASSERT(iterator != m_namedTypeMapping.end());
+        return iterator->value;
+    }
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
+    }
 }
 
 MangledEnumerationMemberName TypeNamer::mangledNameForEnumerationMember(AST::EnumerationMember& enumerationMember)
index abef123..19b2729 100644 (file)
@@ -64,7 +64,7 @@ public:
 
     // Must be called after calling emitMetalTypes().
     String mangledNameForType(AST::NativeTypeDeclaration&);
-    MangledTypeName mangledNameForType(AST::UnnamedType&);
+    MangledOrNativeTypeName mangledNameForType(AST::UnnamedType&);
     MangledOrNativeTypeName mangledNameForType(AST::NamedType&);
     MangledEnumerationMemberName mangledNameForEnumerationMember(AST::EnumerationMember&);
     MangledStructureElementName mangledNameForStructureElement(AST::StructureElement&);
@@ -84,14 +84,15 @@ private:
     MangledEnumerationMemberName generateNextEnumerationMemberName() { return { m_enumerationMemberCount++ }; }
 
     void emitNamedTypeDefinition(StringBuilder&, AST::NamedType&, Vector<std::reference_wrapper<AST::UnnamedType>>&, HashSet<AST::NamedType*>& emittedNamedTypes, HashSet<UnnamedTypeKey>& emittedUnnamedTypes);
-    void emitUnnamedTypeDefinition(StringBuilder&, AST::UnnamedType&, MangledTypeName, HashSet<AST::NamedType*>& emittedNamedTypes, HashSet<UnnamedTypeKey>& emittedUnnamedTypes);
+    void emitUnnamedTypeDefinition(StringBuilder&, AST::UnnamedType&, MangledOrNativeTypeName, HashSet<AST::NamedType*>& emittedNamedTypes, HashSet<UnnamedTypeKey>& emittedUnnamedTypes);
     void emitMetalTypeDeclarations(StringBuilder&);
     void emitMetalTypeDefinitions(StringBuilder&);
 
     void generateUniquedTypeName(AST::UnnamedType&);
 
     Program& m_program;
-    HashMap<UnnamedTypeKey, MangledTypeName> m_unnamedTypeMapping;
+    HashMap<UnnamedTypeKey, MangledTypeName> m_arrayReferenceTypeMapping;
+    HashMap<UnnamedTypeKey, String> m_lazyUnnamedTypeCache;
     HashMap<AST::NamedType*, MangledTypeName> m_namedTypeMapping;
     HashMap<AST::NamedType*, Vector<std::reference_wrapper<AST::UnnamedType>>> m_dependencyGraph;
     HashMap<AST::EnumerationMember*, MangledEnumerationMemberName> m_enumerationMemberMapping;