From 62c312646d7f41b61a9a59e6ac30dce51b218d70 Mon Sep 17 00:00:00 2001 From: Marcel Koester Date: Tue, 5 Sep 2023 12:27:03 +0200 Subject: [PATCH] Updated PhiBindings analysis. (#1064) * Adapted PhiBindings to support gathering of all phi nodes in a function. * Simplified PhiBindings analysis. * Adapted backends to new PhiBindings. --- Src/ILGPU/Backends/OpenCL/CLCodeGenerator.cs | 109 +++++------------- .../Backends/PTX/Analyses/PTXBlockSchedule.cs | 12 +- Src/ILGPU/Backends/PTX/PTXCodeGenerator.cs | 33 +----- Src/ILGPU/Backends/PhiBindings.cs | 79 ++++++------- 4 files changed, 71 insertions(+), 162 deletions(-) diff --git a/Src/ILGPU/Backends/OpenCL/CLCodeGenerator.cs b/Src/ILGPU/Backends/OpenCL/CLCodeGenerator.cs index 6c8273db8..bcc5e4882 100644 --- a/Src/ILGPU/Backends/OpenCL/CLCodeGenerator.cs +++ b/Src/ILGPU/Backends/OpenCL/CLCodeGenerator.cs @@ -156,83 +156,6 @@ protected interface IParametersSetupLogic Variable? HandleIntrinsicParameter(int parameterOffset, Parameter parameter); } - /// - /// Represents a specialized phi binding allocator. - /// - private readonly struct PhiBindingAllocator : IPhiBindingAllocator - { - private readonly Dictionary> phiMapping; - - /// - /// Constructs a new phi binding allocator. - /// - /// The parent code generator. - /// The blocks to use. - public PhiBindingAllocator( - CLCodeGenerator parent, - in BasicBlockCollection blocks) - { - phiMapping = new Dictionary>( - blocks.Count); - Parent = parent; - Dominators = blocks.CreateDominators(); - } - - /// - /// Returns the parent code generator. - /// - public CLCodeGenerator Parent { get; } - - /// - /// Returns the referenced dominators. - /// - public Dominators Dominators { get; } - - /// - /// Does not perform any operation. - /// - public void Process(BasicBlock block, Phis phis) { } - - /// - /// Allocates a new phi value in the dominator block. - /// - public void Allocate(BasicBlock block, PhiValue phiValue) - { - var variable = Parent.Allocate(phiValue); - - var targetBlock = block; - foreach (var argument in phiValue) - { - targetBlock = argument.BasicBlock == null - ? Dominators.Root - : Dominators.GetImmediateCommonDominator( - targetBlock, - argument.BasicBlock); - - if (targetBlock == Dominators.Root) - break; - } - - if (!phiMapping.TryGetValue(targetBlock, out var phiVariables)) - { - phiVariables = new List(); - phiMapping.Add(targetBlock, phiVariables); - } - phiVariables.Add(variable); - } - - /// - /// Tries to get phi variables to declare in the given block. - /// - /// The block. - /// The variables to declare (if any). - /// True, if there are some phi variables to declare. - public bool TryGetPhis( - BasicBlock block, - [NotNullWhen(true)] out List? phisToDeclare) => - phiMapping.TryGetValue(block, out phisToDeclare); - } - #endregion #region Static @@ -508,8 +431,34 @@ protected void GenerateCodeInternal() blockLookup.Add(block, DeclareLabel()); // Find all phi nodes, allocate target registers and setup internal mapping - var bindingAllocator = new PhiBindingAllocator(this, blocks); - var phiBindings = PhiBindings.Create(blocks, bindingAllocator); + var phiMapping = new Dictionary>(); + var dominators = Method.Blocks.CreateDominators(); + var phiBindings = PhiBindings.Create( + blocks, + (block, phiValue) => + { + var variable = Allocate(phiValue); + + var targetBlock = block; + foreach (var argument in phiValue) + { + targetBlock = argument.BasicBlock == null + ? dominators.Root + : dominators.GetImmediateCommonDominator( + targetBlock, + argument.BasicBlock); + + if (targetBlock == dominators.Root) + break; + } + + if (!phiMapping.TryGetValue(targetBlock, out var phiVariables)) + { + phiVariables = new List(); + phiMapping.Add(targetBlock, phiVariables); + } + phiVariables.Add(variable); + }); var intermediatePhiVariables = new Dictionary( phiBindings.MaxNumIntermediatePhis); @@ -520,7 +469,7 @@ protected void GenerateCodeInternal() MarkLabel(blockLookup[block]); // Declare phi variables (if any) - if (bindingAllocator.TryGetPhis(block, out var phisToDeclare)) + if (phiMapping.TryGetValue(block, out var phisToDeclare)) { foreach (var phiVariable in phisToDeclare) Declare(phiVariable); diff --git a/Src/ILGPU/Backends/PTX/Analyses/PTXBlockSchedule.cs b/Src/ILGPU/Backends/PTX/Analyses/PTXBlockSchedule.cs index faf6baa71..1b65610ac 100644 --- a/Src/ILGPU/Backends/PTX/Analyses/PTXBlockSchedule.cs +++ b/Src/ILGPU/Backends/PTX/Analyses/PTXBlockSchedule.cs @@ -12,6 +12,8 @@ using ILGPU.IR; using ILGPU.IR.Analyses.ControlFlowDirection; using ILGPU.IR.Analyses.TraversalOrders; +using ILGPU.IR.Values; +using System; using System.Collections.Immutable; namespace ILGPU.Backends.PTX.Analyses @@ -57,11 +59,10 @@ protected PTXBlockSchedule( /// /// Creates a new phi bindings mapping. /// - /// The custom allocator type. /// The allocator to use. /// The created phi bindings. - public abstract PhiBindings ComputePhiBindings(TAllocator allocator) - where TAllocator : struct, IPhiBindingAllocator; + public abstract PhiBindings ComputePhiBindings( + Action allocator); /// /// Returns true if the given is an implicit @@ -127,11 +128,10 @@ protected PTXBlockSchedule(in BasicBlockCollection blocks) /// /// Creates a new phi bindings mapping. /// - /// The custom allocator type. /// The allocator to use. /// The created phi bindings. - public override PhiBindings ComputePhiBindings( - TAllocator allocator) => + public override PhiBindings ComputePhiBindings( + Action allocator) => PhiBindings.Create(BasicBlockCollection, allocator); #endregion diff --git a/Src/ILGPU/Backends/PTX/PTXCodeGenerator.cs b/Src/ILGPU/Backends/PTX/PTXCodeGenerator.cs index 4b1713178..618a76a09 100644 --- a/Src/ILGPU/Backends/PTX/PTXCodeGenerator.cs +++ b/Src/ILGPU/Backends/PTX/PTXCodeGenerator.cs @@ -190,37 +190,6 @@ internal interface IParameterSetupLogic null; } - /// - /// Represents a specialized phi binding allocator. - /// - private readonly struct PhiBindingAllocator : IPhiBindingAllocator - { - /// - /// Constructs a new phi binding allocator. - /// - /// The parent code generator. - public PhiBindingAllocator(PTXCodeGenerator parent) - { - Parent = parent; - } - - /// - /// Returns the parent code generator. - /// - public PTXCodeGenerator Parent { get; } - - /// - /// Does not perform any operation. - /// - public void Process(BasicBlock block, Phis phis) { } - - /// - /// Allocates a new phi node in the parent code generator. - /// - public void Allocate(BasicBlock block, PhiValue phiValue) => - Parent.Allocate(phiValue); - } - #endregion #region Static @@ -518,7 +487,7 @@ protected void GenerateCodeInternal(int registerOffset) // Find all phi nodes, allocate target registers and setup internal mapping var phiBindings = Schedule.ComputePhiBindings( - new PhiBindingAllocator(this)); + (_, phiValue) => Allocate(phiValue)); var intermediatePhiRegisters = new Dictionary( phiBindings.MaxNumIntermediatePhis); Builder.AppendLine(); diff --git a/Src/ILGPU/Backends/PhiBindings.cs b/Src/ILGPU/Backends/PhiBindings.cs index 1eaa045d1..9ab307c06 100644 --- a/Src/ILGPU/Backends/PhiBindings.cs +++ b/Src/ILGPU/Backends/PhiBindings.cs @@ -14,6 +14,7 @@ using ILGPU.IR.Analyses.ControlFlowDirection; using ILGPU.IR.Analyses.TraversalOrders; using ILGPU.IR.Values; +using ILGPU.Util; using System; using System.Collections; using System.Collections.Generic; @@ -21,31 +22,11 @@ namespace ILGPU.Backends { - /// - /// An abstract binding allocator for the class . - /// - public interface IPhiBindingAllocator - { - /// - /// Processes all phis that are declared in the given node. - /// - /// The current block. - /// The phi nodes to process. - void Process(BasicBlock block, Phis phis); - - /// - /// Allocates the given phi node. - /// - /// The current block. - /// The phi node to allocate. - void Allocate(BasicBlock block, PhiValue phiValue); - } - /// /// Maps phi nodes to basic blocks in order to emit move command during /// the final code generation phase. /// - public readonly struct PhiBindings + readonly struct PhiBindings { #region Nested Types @@ -83,7 +64,6 @@ internal Enumerator(in BlockInfo blockInfo) void IDisposable.Dispose() { } /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() => enumerator.MoveNext(); /// @@ -115,7 +95,7 @@ internal IntermediatePhiCollection(in BlockInfo info) /// /// An enumerator to enumerate all entries in this collection. /// - public readonly Enumerator GetEnumerator() => new Enumerator(blockInfo); + public Enumerator GetEnumerator() => new(blockInfo); #endregion } @@ -153,7 +133,6 @@ internal Enumerator(in PhiBindingCollection collection) void IDisposable.Dispose() { } /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() => enumerator.MoveNext(); /// @@ -182,8 +161,7 @@ internal PhiBindingCollection(in BlockInfo info) /// /// Returns all intermediate phi values that must be assigned to temporaries. /// - public readonly IntermediatePhiCollection Intermediates => - new IntermediatePhiCollection(blockInfo); + public IntermediatePhiCollection Intermediates => new(blockInfo); #endregion @@ -194,7 +172,7 @@ internal PhiBindingCollection(in BlockInfo info) /// a temporary intermediate variable to be assigned to. /// /// The phi value to test. - public readonly bool IsIntermediate(PhiValue phi) => + public bool IsIntermediate(PhiValue phi) => blockInfo.IntermediatePhis.Contains(phi); /// @@ -203,7 +181,7 @@ public readonly bool IsIntermediate(PhiValue phi) => /// /// An enumerator to enumerate all entries in this collection. /// - public readonly Enumerator GetEnumerator() => new Enumerator(this); + public Enumerator GetEnumerator() => new(this); #endregion } @@ -247,8 +225,7 @@ public BlockInfo(int capacity) /// /// The phi value it has to be bound to. /// The source value to read from. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly void Add(PhiValue phi, Value value) + public void Add(PhiValue phi, Value value) { LHSPhis.Add(phi); // Check whether we are assigning the value of a phi value @@ -267,8 +244,8 @@ public readonly void Add(PhiValue phi, Value value) /// Creates a new instance. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly BlockInfo GetValue(BasicBlock block, int traversalIndex) => - new BlockInfo(block.Count); + public BlockInfo GetValue(BasicBlock block, int traversalIndex) => + new(block.Count); } #endregion @@ -280,30 +257,32 @@ public readonly BlockInfo GetValue(BasicBlock block, int traversalIndex) => /// /// The current order. /// The control-flow direction. - /// The custom allocator type. /// The source collection. /// The allocator to use. /// The created phi bindings. - public static PhiBindings Create( + public static PhiBindings Create( in BasicBlockCollection collection, - TAllocator allocator) + Action allocator) where TOrder : struct, ITraversalOrder where TDirection : struct, IControlFlowDirection - where TAllocator : struct, IPhiBindingAllocator { var mapping = collection.CreateMap(new InfoProvider()); + var allPhiValues = InlineList.Create( + collection.Count); foreach (var block in collection) { // Resolve phis var phis = Phis.Create(block); - allocator.Process(block, phis); // Map all phi arguments foreach (var phi in phis) { + // Remember the current phi value + allPhiValues.Add(phi); + // Allocate phi for further processing - allocator.Allocate(block, phi); + allocator(block, phi); // Determine predecessor mapping phi.Assert(block.Predecessors.Length == phi.Nodes.Length); @@ -326,7 +305,10 @@ public static PhiBindings Create( info.IntermediatePhis.Count); } - return new PhiBindings(mapping, maxNumIntermediatePhis); + return new PhiBindings( + mapping, + maxNumIntermediatePhis, + ref allPhiValues); } #endregion @@ -334,6 +316,7 @@ public static PhiBindings Create( #region Instance private readonly BasicBlockMap phiMapping; + private readonly InlineList allPhiValues; /// /// Constructs new phi bindings. @@ -342,11 +325,17 @@ public static PhiBindings Create( /// /// The maximum number of intermediate phi values. /// + /// The list of all phi values. private PhiBindings( in BasicBlockMap mapping, - int maxNumIntermediatePhis) + int maxNumIntermediatePhis, + ref InlineList phiValues) { phiMapping = mapping; + + allPhiValues = InlineList.Empty; + phiValues.MoveTo(ref allPhiValues); + MaxNumIntermediatePhis = maxNumIntermediatePhis; } @@ -359,6 +348,11 @@ private PhiBindings( /// public int MaxNumIntermediatePhis { get; } + /// + /// Returns a span including all phi values. + /// + public ReadOnlySpan PhiValues => allPhiValues; + #endregion #region Methods @@ -369,10 +363,7 @@ private PhiBindings( /// The block. /// The resolved bindings (if any) /// True, if phi bindings could be resolved. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly bool TryGetBindings( - BasicBlock block, - out PhiBindingCollection bindings) + public bool TryGetBindings(BasicBlock block, out PhiBindingCollection bindings) { bindings = default; if (!phiMapping.TryGetValue(block, out var info))