Skip to content

Commit

Permalink
Updated PhiBindings analysis. (#1064)
Browse files Browse the repository at this point in the history
* Adapted PhiBindings to support gathering of all phi nodes in a function.
* Simplified PhiBindings analysis.
* Adapted backends to new PhiBindings.
  • Loading branch information
m4rs-mt authored Sep 5, 2023
1 parent d1758bb commit 9ee9d9d
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 162 deletions.
109 changes: 29 additions & 80 deletions Src/ILGPU/Backends/OpenCL/CLCodeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -156,83 +156,6 @@ protected interface IParametersSetupLogic
Variable? HandleIntrinsicParameter(int parameterOffset, Parameter parameter);
}

/// <summary>
/// Represents a specialized phi binding allocator.
/// </summary>
private readonly struct PhiBindingAllocator : IPhiBindingAllocator
{
private readonly Dictionary<BasicBlock, List<Variable>> phiMapping;

/// <summary>
/// Constructs a new phi binding allocator.
/// </summary>
/// <param name="parent">The parent code generator.</param>
/// <param name="blocks">The blocks to use.</param>
public PhiBindingAllocator(
CLCodeGenerator parent,
in BasicBlockCollection<ReversePostOrder, Forwards> blocks)
{
phiMapping = new Dictionary<BasicBlock, List<Variable>>(
blocks.Count);
Parent = parent;
Dominators = blocks.CreateDominators();
}

/// <summary>
/// Returns the parent code generator.
/// </summary>
public CLCodeGenerator Parent { get; }

/// <summary>
/// Returns the referenced dominators.
/// </summary>
public Dominators<Forwards> Dominators { get; }

/// <summary>
/// Does not perform any operation.
/// </summary>
public void Process(BasicBlock block, Phis phis) { }

/// <summary>
/// Allocates a new phi value in the dominator block.
/// </summary>
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<Variable>();
phiMapping.Add(targetBlock, phiVariables);
}
phiVariables.Add(variable);
}

/// <summary>
/// Tries to get phi variables to declare in the given block.
/// </summary>
/// <param name="block">The block.</param>
/// <param name="phisToDeclare">The variables to declare (if any).</param>
/// <returns>True, if there are some phi variables to declare.</returns>
public bool TryGetPhis(
BasicBlock block,
[NotNullWhen(true)] out List<Variable>? phisToDeclare) =>
phiMapping.TryGetValue(block, out phisToDeclare);
}

#endregion

#region Static
Expand Down Expand Up @@ -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<BasicBlock, List<Variable>>();
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<Variable>();
phiMapping.Add(targetBlock, phiVariables);
}
phiVariables.Add(variable);
});
var intermediatePhiVariables = new Dictionary<Value, Variable>(
phiBindings.MaxNumIntermediatePhis);

Expand All @@ -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);
Expand Down
12 changes: 6 additions & 6 deletions Src/ILGPU/Backends/PTX/Analyses/PTXBlockSchedule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -57,11 +59,10 @@ protected PTXBlockSchedule(
/// <summary>
/// Creates a new phi bindings mapping.
/// </summary>
/// <typeparam name="TAllocator">The custom allocator type.</typeparam>
/// <param name="allocator">The allocator to use.</param>
/// <returns>The created phi bindings.</returns>
public abstract PhiBindings ComputePhiBindings<TAllocator>(TAllocator allocator)
where TAllocator : struct, IPhiBindingAllocator;
public abstract PhiBindings ComputePhiBindings(
Action<BasicBlock, PhiValue> allocator);

/// <summary>
/// Returns true if the given <paramref name="successor"/> is an implicit
Expand Down Expand Up @@ -127,11 +128,10 @@ protected PTXBlockSchedule(in BasicBlockCollection<TOrder, TDirection> blocks)
/// <summary>
/// Creates a new phi bindings mapping.
/// </summary>
/// <typeparam name="TAllocator">The custom allocator type.</typeparam>
/// <param name="allocator">The allocator to use.</param>
/// <returns>The created phi bindings.</returns>
public override PhiBindings ComputePhiBindings<TAllocator>(
TAllocator allocator) =>
public override PhiBindings ComputePhiBindings(
Action<BasicBlock, PhiValue> allocator) =>
PhiBindings.Create(BasicBlockCollection, allocator);

#endregion
Expand Down
33 changes: 1 addition & 32 deletions Src/ILGPU/Backends/PTX/PTXCodeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -190,37 +190,6 @@ internal interface IParameterSetupLogic
null;
}

/// <summary>
/// Represents a specialized phi binding allocator.
/// </summary>
private readonly struct PhiBindingAllocator : IPhiBindingAllocator
{
/// <summary>
/// Constructs a new phi binding allocator.
/// </summary>
/// <param name="parent">The parent code generator.</param>
public PhiBindingAllocator(PTXCodeGenerator parent)
{
Parent = parent;
}

/// <summary>
/// Returns the parent code generator.
/// </summary>
public PTXCodeGenerator Parent { get; }

/// <summary>
/// Does not perform any operation.
/// </summary>
public void Process(BasicBlock block, Phis phis) { }

/// <summary>
/// Allocates a new phi node in the parent code generator.
/// </summary>
public void Allocate(BasicBlock block, PhiValue phiValue) =>
Parent.Allocate(phiValue);
}

#endregion

#region Static
Expand Down Expand Up @@ -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<Value, Register>(
phiBindings.MaxNumIntermediatePhis);
Builder.AppendLine();
Expand Down
Loading

0 comments on commit 9ee9d9d

Please sign in to comment.