From fcd6759b3e49756d66705dd53de9d4a47bc57c80 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Wed, 6 Jan 2021 11:42:21 -0800 Subject: [PATCH 1/5] Update specialization names in monomorphization. --- src/QsCompiler/Transformations/Monomorphization.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/QsCompiler/Transformations/Monomorphization.cs b/src/QsCompiler/Transformations/Monomorphization.cs index 662086395e..d577cb05d8 100644 --- a/src/QsCompiler/Transformations/Monomorphization.cs +++ b/src/QsCompiler/Transformations/Monomorphization.cs @@ -66,7 +66,9 @@ public static QsCompilation Apply(QsCompilation compilation) // Generate the concrete version of the callable var concrete = ReplaceTypeParamImplementations.Apply(originalGlobal, node.ParamResolutions, getAccessModifiers); - concretizations.Add(concrete.WithFullName(oldName => concreteName)); + concretizations.Add( + concrete.WithFullName(oldName => concreteName) + .WithSpecializations(specs => specs.Select(spec => spec.WithParent(_ => concreteName)).ToImmutableArray())); } else { From 3d75abd51760f6249bb0a3f1e6ab4b44e9c8b8db Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Thu, 7 Jan 2021 11:46:18 -0800 Subject: [PATCH 2/5] KeepAllIntrinsics option for monomorphization. --- .../Compiler/RewriteSteps/Monomorphization.cs | 11 ++++++-- .../Transformations/Monomorphization.cs | 25 +++++++++++-------- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/QsCompiler/Compiler/RewriteSteps/Monomorphization.cs b/src/QsCompiler/Compiler/RewriteSteps/Monomorphization.cs index 1c4b387e16..a97cbf537a 100644 --- a/src/QsCompiler/Compiler/RewriteSteps/Monomorphization.cs +++ b/src/QsCompiler/Compiler/RewriteSteps/Monomorphization.cs @@ -14,6 +14,8 @@ namespace Microsoft.Quantum.QsCompiler.BuiltInRewriteSteps /// internal class Monomorphization : IRewriteStep { + private readonly bool keepAllIntrinsics; + public string Name => "Monomorphization"; public int Priority => RewriteStepPriorities.TypeParameterElimination; @@ -28,8 +30,13 @@ internal class Monomorphization : IRewriteStep public bool ImplementsPostconditionVerification => true; - public Monomorphization() + /// + /// Constructor for the Monomorphization Rewrite Step. If keepAllIntrinsics is + /// set to true, intrinsics will not be removed as part of the rewrite step. + /// + public Monomorphization(bool keepAllIntrinsics = true) { + this.keepAllIntrinsics = keepAllIntrinsics; this.AssemblyConstants = new Dictionary(); } @@ -37,7 +44,7 @@ public Monomorphization() public bool Transformation(QsCompilation compilation, out QsCompilation transformed) { - transformed = Monomorphize.Apply(compilation); + transformed = Monomorphize.Apply(compilation, this.keepAllIntrinsics); return true; } diff --git a/src/QsCompiler/Transformations/Monomorphization.cs b/src/QsCompiler/Transformations/Monomorphization.cs index d577cb05d8..df9b5284ab 100644 --- a/src/QsCompiler/Transformations/Monomorphization.cs +++ b/src/QsCompiler/Transformations/Monomorphization.cs @@ -25,16 +25,18 @@ namespace Microsoft.Quantum.QsCompiler.Transformations.Monomorphization /// are found from uses of the callables. /// This transformation also removes all callables that are not used directly or /// indirectly from any of the marked entry point. - /// Intrinsic callables are not monomorphized or removed from the compilation. + /// Intrinsic callables are, by default, not monomorphized or removed from the compilation, but + /// may optionally be removed if unused if the keepAllIntrinsics parameter is set to false. /// There are also some built-in callables that are also exempt from /// being removed from non-use, as they are needed for later rewrite steps. /// public static class Monomorphize { /// - /// Performs Monomorphization on the given compilation. + /// Performs Monomorphization on the given compilation. If the keepAllIntrinsics parameter + /// is set to true, then unused intrinsics will not be removed from the resulting compilation. /// - public static QsCompilation Apply(QsCompilation compilation) + public static QsCompilation Apply(QsCompilation compilation, bool keepAllIntrinsics = true) { var globals = compilation.Namespaces.GlobalCallableResolutions(); var concretizations = new List(); @@ -91,16 +93,16 @@ public static QsCompilation Apply(QsCompilation compilation) final.Add(ReplaceTypeParamCalls.Apply(callable, getConcreteIdentifier, intrinsicCallableSet)); } - return ResolveGenerics.Apply(compilation, final, intrinsicCallableSet); + return ResolveGenerics.Apply(compilation, final, intrinsicCallableSet, keepAllIntrinsics); } #region ResolveGenerics private class ResolveGenerics : SyntaxTreeTransformation { - public static QsCompilation Apply(QsCompilation compilation, List callables, ImmutableHashSet intrinsicCallableSet) + public static QsCompilation Apply(QsCompilation compilation, List callables, ImmutableHashSet intrinsicCallableSet, bool keepAllIntrinsics) { - var filter = new ResolveGenerics(callables.ToLookup(res => res.FullName.Namespace), intrinsicCallableSet); + var filter = new ResolveGenerics(callables.ToLookup(res => res.FullName.Namespace), intrinsicCallableSet, keepAllIntrinsics); return filter.OnCompilation(compilation); } @@ -109,11 +111,13 @@ public class TransformationState { public readonly ILookup NamespaceCallables; public readonly ImmutableHashSet IntrinsicCallableSet; + public readonly bool KeepAllIntrinsics; - public TransformationState(ILookup namespaceCallables, ImmutableHashSet intrinsicCallableSet) + public TransformationState(ILookup namespaceCallables, ImmutableHashSet intrinsicCallableSet, bool keepAllIntrinsics) { this.NamespaceCallables = namespaceCallables; this.IntrinsicCallableSet = intrinsicCallableSet; + this.KeepAllIntrinsics = keepAllIntrinsics; } } @@ -121,8 +125,8 @@ public TransformationState(ILookup namespaceCallables, Immut /// Constructor for the ResolveGenericsSyntax class. Its transform function replaces global callables in the namespace. /// /// Maps namespace names to an enumerable of all global callables in that namespace. - private ResolveGenerics(ILookup namespaceCallables, ImmutableHashSet intrinsicCallableSet) - : base(new TransformationState(namespaceCallables, intrinsicCallableSet)) + private ResolveGenerics(ILookup namespaceCallables, ImmutableHashSet intrinsicCallableSet, bool keepAllIntrinsics) + : base(new TransformationState(namespaceCallables, intrinsicCallableSet, keepAllIntrinsics)) { this.Namespaces = new NamespaceTransformation(this); this.Statements = new StatementTransformation(this, TransformationOptions.Disabled); @@ -140,7 +144,8 @@ private bool NamespaceElementFilter(QsNamespaceElement elem) { if (elem is QsNamespaceElement.QsCallable call) { - return BuiltIn.RewriteStepDependencies.Contains(call.Item.FullName) || this.SharedState.IntrinsicCallableSet.Contains(call.Item.FullName); + return BuiltIn.RewriteStepDependencies.Contains(call.Item.FullName) || + (this.SharedState.KeepAllIntrinsics && this.SharedState.IntrinsicCallableSet.Contains(call.Item.FullName)); } else { From cdd568415f1f2a253aad72a94d80ed6a27db8b5d Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Thu, 7 Jan 2021 13:24:33 -0800 Subject: [PATCH 3/5] Add all specializations for a referenced callable to the concrete call graph. --- .../Tests.Compiler/CallGraphTests.fs | 5 ++-- .../TestCases/PopulateCallGraph.qs | 2 +- .../Tests.Compiler/TestUtils/Signatures.fs | 24 ++++++++++++------- .../CallGraph/ConcreteCallGraphWalker.cs | 19 +++++++++++---- 4 files changed, 34 insertions(+), 16 deletions(-) diff --git a/src/QsCompiler/Tests.Compiler/CallGraphTests.fs b/src/QsCompiler/Tests.Compiler/CallGraphTests.fs index 64a6ae96a6..dd260aa419 100644 --- a/src/QsCompiler/Tests.Compiler/CallGraphTests.fs +++ b/src/QsCompiler/Tests.Compiler/CallGraphTests.fs @@ -324,7 +324,7 @@ type CallGraphTests(output: ITestOutputHelper) = [] [] - member this.``Concrete Graph Trims Specializations``() = + member this.``Concrete Graph Contains All Specializations``() = let graph = PopulateCallGraphWithExe 10 |> ConcreteCallGraph let makeNode name spec = MakeNode name spec [] @@ -343,8 +343,7 @@ type CallGraphTests(output: ITestOutputHelper) = AssertInConcreteGraph graph BarAdj AssertInConcreteGraph graph BarCtl AssertInConcreteGraph graph BarCtlAdj - - AssertNotInConcreteGraph graph Unused + AssertInConcreteGraph graph Unused [] [] diff --git a/src/QsCompiler/Tests.Compiler/TestCases/PopulateCallGraph.qs b/src/QsCompiler/Tests.Compiler/TestCases/PopulateCallGraph.qs index e492499fb8..4dd3a55203 100644 --- a/src/QsCompiler/Tests.Compiler/TestCases/PopulateCallGraph.qs +++ b/src/QsCompiler/Tests.Compiler/TestCases/PopulateCallGraph.qs @@ -152,7 +152,7 @@ namespace Microsoft.Quantum.Testing.PopulateCallGraph { // ================================= -// Concrete Graph Trims Specializations +// Concrete Graph Contains All Specializations namespace Microsoft.Quantum.Testing.PopulateCallGraph { @ EntryPoint() diff --git a/src/QsCompiler/Tests.Compiler/TestUtils/Signatures.fs b/src/QsCompiler/Tests.Compiler/TestUtils/Signatures.fs index b77788381f..d945a28ca1 100644 --- a/src/QsCompiler/Tests.Compiler/TestUtils/Signatures.fs +++ b/src/QsCompiler/Tests.Compiler/TestUtils/Signatures.fs @@ -163,14 +163,22 @@ let public MonomorphizationSignatures = MonomorphizationNs, "Test3", [||], "Unit" GenericsNs, "Test3Main", [||], "Unit" - GenericsNs, "GenericCallsSpecializations", [| "Double"; "String"; "Qubit[]" |], "Unit" - GenericsNs, "GenericCallsSpecializations", [| "Double"; "String"; "Double" |], "Unit" - GenericsNs, "GenericCallsSpecializations", [| "String"; "Int"; "Unit" |], "Unit" - - GenericsNs, "BasicGeneric", [| "String"; "Qubit[]" |], "Unit" - GenericsNs, "BasicGeneric", [| "String"; "Int" |], "Unit" - - GenericsNs, "ArrayGeneric", [| "Qubit"; "Double" |], "Int" + GenericsNs, "GenericCallsSpecializations", [|"Double"; "String"; "Qubit[]"|], "Unit" + GenericsNs, "GenericCallsSpecializations", [|"Double"; "String"; "Double"|], "Unit" + GenericsNs, "GenericCallsSpecializations", [|"String"; "Int"; "Unit"|], "Unit" + + GenericsNs, "BasicGeneric", [|"Double"; "String"|], "Unit" + GenericsNs, "BasicGeneric", [|"String"; "Qubit[]"|], "Unit" + GenericsNs, "BasicGeneric", [|"String"; "Int"|], "Unit" + GenericsNs, "BasicGeneric", [|"Qubit[]"; "Qubit[]"|], "Unit" + GenericsNs, "BasicGeneric", [|"Qubit[]"; "Double"|], "Unit" + GenericsNs, "BasicGeneric", [|"Qubit[]"; "Unit"|], "Unit" + GenericsNs, "BasicGeneric", [|"String"; "Double"|], "Unit" + GenericsNs, "BasicGeneric", [|"Int"; "Unit"|], "Unit" + + GenericsNs, "ArrayGeneric", [|"Qubit"; "Double"|], "Int" + GenericsNs, "ArrayGeneric", [|"Qubit"; "Qubit[]"|], "Int" + GenericsNs, "ArrayGeneric", [|"Qubit"; "Unit"|], "Int" |]) // Test Case 4 (_DefaultTypes, diff --git a/src/QsCompiler/Transformations/CallGraph/ConcreteCallGraphWalker.cs b/src/QsCompiler/Transformations/CallGraph/ConcreteCallGraphWalker.cs index c7f8727031..b0df74b2ec 100644 --- a/src/QsCompiler/Transformations/CallGraph/ConcreteCallGraphWalker.cs +++ b/src/QsCompiler/Transformations/CallGraph/ConcreteCallGraphWalker.cs @@ -39,8 +39,11 @@ private static class ConcreteCallGraphWalker /// public static void PopulateConcreteGraph(ConcreteGraphBuilder graph, QsCompilation compilation) { + var globals = compilation.Namespaces.GlobalCallableResolutions(); var walker = new BuildGraph(graph); - var entryPointNodes = compilation.EntryPoints.Select(name => new ConcreteCallGraphNode(name, QsSpecializationKind.QsBody, TypeParameterResolutions.Empty)); + var entryPointNodes = compilation.EntryPoints.SelectMany(name => + GetSpecializationKinds(globals, name).Select(kind => + new ConcreteCallGraphNode(name, kind, TypeParameterResolutions.Empty))); foreach (var entryPoint in entryPointNodes) { // Make sure all the entry points are added to the graph @@ -48,7 +51,6 @@ public static void PopulateConcreteGraph(ConcreteGraphBuilder graph, QsCompilati walker.SharedState.RequestStack.Push(entryPoint); } - var globals = compilation.Namespaces.GlobalCallableResolutions(); while (walker.SharedState.RequestStack.TryPop(out var currentRequest)) { // If there is a call to an unknown callable, throw exception @@ -253,12 +255,21 @@ private void AddEdge(QsQualifiedName identifier, QsSpecializationKind kind, Type throw new ArgumentException("AddEdge requires CurrentNode to be non-null."); } + // Add an edge to the specific specialization kind referenced var called = new ConcreteCallGraphNode(identifier, kind, typeRes); var edge = new ConcreteCallGraphEdge(referenceRange); this.Graph.AddDependency(this.CurrentNode, called, edge); - if (!this.RequestStack.Contains(called) && !this.ResolvedNodeSet.Contains(called)) + + // Add all the specializations of the referenced callable to the graph + var newNodes = this.GetSpecializationKinds(identifier) + .Select(specKind => new ConcreteCallGraphNode(identifier, specKind, typeRes)); + foreach (var node in newNodes) { - this.RequestStack.Push(called); + if (!this.RequestStack.Contains(node) && !this.ResolvedNodeSet.Contains(node)) + { + this.Graph.AddNode(node); + this.RequestStack.Push(node); + } } } } From 45d403de10cb1dda4684483cd3eadde8bef4508e Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Thu, 7 Jan 2021 14:58:37 -0800 Subject: [PATCH 4/5] Fix spacing --- .../Tests.Compiler/TestUtils/Signatures.fs | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/QsCompiler/Tests.Compiler/TestUtils/Signatures.fs b/src/QsCompiler/Tests.Compiler/TestUtils/Signatures.fs index d945a28ca1..876e2cd53a 100644 --- a/src/QsCompiler/Tests.Compiler/TestUtils/Signatures.fs +++ b/src/QsCompiler/Tests.Compiler/TestUtils/Signatures.fs @@ -163,22 +163,22 @@ let public MonomorphizationSignatures = MonomorphizationNs, "Test3", [||], "Unit" GenericsNs, "Test3Main", [||], "Unit" - GenericsNs, "GenericCallsSpecializations", [|"Double"; "String"; "Qubit[]"|], "Unit" - GenericsNs, "GenericCallsSpecializations", [|"Double"; "String"; "Double"|], "Unit" - GenericsNs, "GenericCallsSpecializations", [|"String"; "Int"; "Unit"|], "Unit" - - GenericsNs, "BasicGeneric", [|"Double"; "String"|], "Unit" - GenericsNs, "BasicGeneric", [|"String"; "Qubit[]"|], "Unit" - GenericsNs, "BasicGeneric", [|"String"; "Int"|], "Unit" - GenericsNs, "BasicGeneric", [|"Qubit[]"; "Qubit[]"|], "Unit" - GenericsNs, "BasicGeneric", [|"Qubit[]"; "Double"|], "Unit" - GenericsNs, "BasicGeneric", [|"Qubit[]"; "Unit"|], "Unit" - GenericsNs, "BasicGeneric", [|"String"; "Double"|], "Unit" - GenericsNs, "BasicGeneric", [|"Int"; "Unit"|], "Unit" - - GenericsNs, "ArrayGeneric", [|"Qubit"; "Double"|], "Int" - GenericsNs, "ArrayGeneric", [|"Qubit"; "Qubit[]"|], "Int" - GenericsNs, "ArrayGeneric", [|"Qubit"; "Unit"|], "Int" + GenericsNs, "GenericCallsSpecializations", [| "Double"; "String"; "Qubit[]" |], "Unit" + GenericsNs, "GenericCallsSpecializations", [| "Double"; "String"; "Double" |], "Unit" + GenericsNs, "GenericCallsSpecializations", [| "String"; "Int"; "Unit" |], "Unit" + + GenericsNs, "BasicGeneric", [| "Double"; "String" |], "Unit" + GenericsNs, "BasicGeneric", [| "String"; "Qubit[]" |], "Unit" + GenericsNs, "BasicGeneric", [| "String"; "Int" |], "Unit" + GenericsNs, "BasicGeneric", [| "Qubit[]"; "Qubit[]" |], "Unit" + GenericsNs, "BasicGeneric", [| "Qubit[]"; "Double" |], "Unit" + GenericsNs, "BasicGeneric", [| "Qubit[]"; "Unit" |], "Unit" + GenericsNs, "BasicGeneric", [| "String"; "Double" |], "Unit" + GenericsNs, "BasicGeneric", [| "Int"; "Unit" |], "Unit" + + GenericsNs, "ArrayGeneric", [| "Qubit"; "Double" |], "Int" + GenericsNs, "ArrayGeneric", [| "Qubit"; "Qubit[]" |], "Int" + GenericsNs, "ArrayGeneric", [| "Qubit"; "Unit" |], "Int" |]) // Test Case 4 (_DefaultTypes, From 859868b5de8627ddfd242bb017d63e9f718c70c6 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Tue, 12 Jan 2021 11:57:59 -0800 Subject: [PATCH 5/5] Changed constructor description --- src/QsCompiler/Compiler/RewriteSteps/Monomorphization.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/QsCompiler/Compiler/RewriteSteps/Monomorphization.cs b/src/QsCompiler/Compiler/RewriteSteps/Monomorphization.cs index a97cbf537a..7802e9ee4c 100644 --- a/src/QsCompiler/Compiler/RewriteSteps/Monomorphization.cs +++ b/src/QsCompiler/Compiler/RewriteSteps/Monomorphization.cs @@ -30,10 +30,11 @@ internal class Monomorphization : IRewriteStep public bool ImplementsPostconditionVerification => true; + /// - /// Constructor for the Monomorphization Rewrite Step. If keepAllIntrinsics is - /// set to true, intrinsics will not be removed as part of the rewrite step. + /// Constructor for the Monomorphization Rewrite Step. /// + /// When true, intrinsics will not be removed as part of the rewrite step. public Monomorphization(bool keepAllIntrinsics = true) { this.keepAllIntrinsics = keepAllIntrinsics;