Skip to content

Commit

Permalink
Simplified loop processing of IR-based loops. (#1070)
Browse files Browse the repository at this point in the history
  • Loading branch information
m4rs-mt authored Sep 4, 2023
1 parent bf34de0 commit 0d39f9e
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 132 deletions.
2 changes: 1 addition & 1 deletion Src/ILGPU/IR/Analyses/LoopInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ private static bool TryGetPhis(

// Check whether this phi value is affected by the current loop; in
// other words, the phi value receives an argument via the backedge
if (loop.ContainsBackedgeBlock(phi.Sources))
if (loop.ContainsBackEdgeBlock(phi.Sources))
{
// Try to get the phi operands
if (!TryGetPhiOperands(loop, phi, out var _, out var outside))
Expand Down
69 changes: 22 additions & 47 deletions Src/ILGPU/IR/Analyses/Loops.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,6 @@ public sealed class Loops<TOrder, TDirection>
{
#region Nested Types

/// <summary>
/// Represents an abstract loop processor.
/// </summary>
public interface ILoopProcessor
{
/// <summary>
/// Processes the given loop.
/// </summary>
/// <param name="node">The current loop node.</param>
void Process(Node node);
}

/// <summary>
/// A specialized successor provider for loop members that exclude all exit
/// blocks of an associated loop.
Expand Down Expand Up @@ -88,8 +76,7 @@ public MembersSuccessorProvider(Node node)
/// of the associated loop exit blocks.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly ReadOnlySpan<BasicBlock> GetSuccessors(
BasicBlock basicBlock)
public ReadOnlySpan<BasicBlock> GetSuccessors(BasicBlock basicBlock)
{
var successors = basicBlock.CurrentSuccessors;

Expand All @@ -114,7 +101,7 @@ public readonly ReadOnlySpan<BasicBlock> GetSuccessors(
/// <param name="currentSuccessors">The current successors.</param>
/// <returns>The adjusted span that contains header blocks only.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private readonly ReadOnlySpan<BasicBlock> AdjustEntrySuccessors(
private ReadOnlySpan<BasicBlock> AdjustEntrySuccessors(
ReadOnlySpan<BasicBlock> currentSuccessors)
{
var successors = InlineList<BasicBlock>.Create(currentSuccessors.Length);
Expand All @@ -132,7 +119,7 @@ private readonly ReadOnlySpan<BasicBlock> AdjustEntrySuccessors(
/// <param name="currentSuccessors">The current successors.</param>
/// <returns>The adjusted span without any exit block.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private readonly ReadOnlySpan<BasicBlock> AdjustExitSuccessors(
private ReadOnlySpan<BasicBlock> AdjustExitSuccessors(
ReadOnlySpan<BasicBlock> currentSuccessors)
{
var successors = currentSuccessors.ToInlineList();
Expand Down Expand Up @@ -181,6 +168,7 @@ internal Node(
{
Parent = parent;
parent?.AddChild(this);
Level = (parent?.Level ?? -1) + 1;

headerBlocks.MoveTo(ref headers);
breakerBlocks.MoveTo(ref breakers);
Expand All @@ -195,6 +183,11 @@ internal Node(

#region Properties

/// <summary>
/// Returns the loop level.
/// </summary>
public int Level { get; }

/// <summary>
/// Returns the number of members.
/// </summary>
Expand Down Expand Up @@ -259,7 +252,7 @@ internal Node(
/// </summary>
/// <param name="block">The block to map to an loop.</param>
/// <returns>True, if the node belongs to this loop.</returns>
public bool Contains(BasicBlock block) =>
public bool Contains(BasicBlock? block) =>
block != null && AllMembers.Contains(block);

/// <summary>
Expand Down Expand Up @@ -305,13 +298,13 @@ public Phis ComputePhis()
}

/// <summary>
/// Returns true if the given blocks contain at least one backedge block.
/// Returns true if the given blocks contain at least one back edge block.
/// </summary>
/// <param name="blocks">The blocks to test.</param>
/// <returns>
/// True, if the given block contain at least one backedge block.
/// True, if the given block contain at least one back edge block.
/// </returns>
public bool ContainsBackedgeBlock(ReadOnlySpan<BasicBlock> blocks)
public bool ContainsBackEdgeBlock(ReadOnlySpan<BasicBlock> blocks)
{
foreach (var block in blocks)
{
Expand Down Expand Up @@ -508,19 +501,6 @@ public void Push(List<NodeData> stack, ref int index)
}
}

/// <summary>
/// Provides new intermediate <see cref="NodeData"/> list instances.
/// </summary>
private readonly struct NodeListProvider : IBasicBlockMapValueProvider<List<Node>>
{
/// <summary>
/// Creates a new <see cref="NodeData"/> instance.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly List<Node> GetValue(BasicBlock block, int _) =>
new List<Node>(2);
}

/// <summary>
/// Provides new intermediate <see cref="NodeData"/> instances.
/// </summary>
Expand All @@ -544,7 +524,7 @@ public NodeDataProvider(CFG<TOrder, TDirection> cfg)
/// Creates a new <see cref="NodeData"/> instance.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly NodeData GetValue(BasicBlock block, int traversalIndex) =>
public NodeData GetValue(BasicBlock block, int traversalIndex) =>
new NodeData(CFG[block]);
}

Expand Down Expand Up @@ -858,33 +838,28 @@ public bool TryGetLoops(BasicBlock block, [NotNullWhen(true)] out Node? loop) =>
/// <summary>
/// Processes all loops starting with the innermost loops.
/// </summary>
/// <typeparam name="TProcessor">The processor type.</typeparam>
/// <param name="processor">The processor instance.</param>
/// <param name="processor">The loop processor action.</param>
/// <returns>The resulting processor instance.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TProcessor ProcessLoops<TProcessor>(TProcessor processor)
where TProcessor : struct, ILoopProcessor
public void ProcessLoops(Action<Node> processor)
{
foreach (var header in Headers)
ProcessLoopsRecursive(header, ref processor);
return processor;
ProcessLoopsRecursive(header, processor);
}

/// <summary>
/// Unrolls loops in a recursive way by unrolling the innermost loops first.
/// </summary>
/// <typeparam name="TProcessor">The processor type.</typeparam>
/// <param name="loop">The current loop node.</param>
/// <param name="processor">The processor instance.</param>
private static void ProcessLoopsRecursive<TProcessor>(
/// <param name="processor">The loop processor action.</param>
private static void ProcessLoopsRecursive(
Node loop,
ref TProcessor processor)
where TProcessor : struct, ILoopProcessor
Action<Node> processor)
{
foreach (var child in loop.Children)
ProcessLoopsRecursive(child, ref processor);
ProcessLoopsRecursive(child, processor);

processor.Process(loop);
processor(loop);
}

#endregion
Expand Down
44 changes: 9 additions & 35 deletions Src/ILGPU/IR/Transformations/LoopInvariantCodeMotion.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// ---------------------------------------------------------------------------------------
// ILGPU
// Copyright (c) 2020-2022 ILGPU Project
// Copyright (c) 2020-2023 ILGPU Project
// www.ilgpu.net
//
// File: LoopInvariantCodeMotion.cs
Expand Down Expand Up @@ -172,39 +172,6 @@ public readonly bool ShouldBeMoved(Value value)
}
}

/// <summary>
/// Applies the LICM transformation to all loops.
/// </summary>
private struct LoopProcessor : Loops.ILoopProcessor
{
public LoopProcessor(Method.Builder builder)
{
Builder = builder;
Applied = false;
}

/// <summary>
/// Returns the parent method builder.
/// </summary>
public Method.Builder Builder { get; }

/// <summary>
/// Returns true if the loop processor could be applied.
/// </summary>
public bool Applied { get; private set; }

/// <summary>
/// Applies the LICM transformation.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Process(Loop loop)
{
if (loop.Entries.Length > 1)
return;
Applied |= ApplyLICM(Builder, loop);
}
}

#endregion

#region Static
Expand Down Expand Up @@ -270,7 +237,14 @@ protected override bool PerformTransformation(Method.Builder builder)
// need to get information about previous predecessors and successors
builder.AcceptControlFlowUpdates(accept: true);

return loops.ProcessLoops(new LoopProcessor(builder)).Applied;
bool applied = false;
loops.ProcessLoops(loop =>
{
if (loop.Entries.Length > 1)
return;
applied |= ApplyLICM(builder, loop);
});
return applied;
}

#endregion
Expand Down
59 changes: 10 additions & 49 deletions Src/ILGPU/IR/Transformations/LoopUnrolling.cs
Original file line number Diff line number Diff line change
Expand Up @@ -387,51 +387,6 @@ public readonly void ClearBody()
#endregion
}

/// <summary>
/// Applies the unrolling transformation to all loops.
/// </summary>
private struct LoopProcessor : Loops.ILoopProcessor
{
private readonly LoopInfos loopInfos;

public LoopProcessor(
in LoopInfos<ReversePostOrder, Forwards> infos,
Method.Builder builder,
int maxUnrollFactor)
{
loopInfos = infos;
Builder = builder;
MaxUnrollFactor = maxUnrollFactor;
Applied = false;
}

/// <summary>
/// Returns the parent method builder.
/// </summary>
public Method.Builder Builder { get; }

/// <summary>
/// Returns the maximum unrolling factor.
/// </summary>
public int MaxUnrollFactor { get; }

/// <summary>
/// Returns true if the loop processor could be applied.
/// </summary>
public bool Applied { get; private set; }

/// <summary>
/// Applies the unrolling transformation.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Process(Loop loop) =>
Applied |= TryUnroll(
Builder,
loop,
loopInfos,
MaxUnrollFactor);
}

#endregion

#region Static
Expand Down Expand Up @@ -664,10 +619,16 @@ protected override bool PerformTransformation(Method.Builder builder)
// need to get information about previous predecessors and successors
builder.AcceptControlFlowUpdates(accept: true);

return loops.ProcessLoops(new LoopProcessor(
loopInfos,
builder,
MaxUnrollFactor)).Applied;
bool applied = false;
loops.ProcessLoops(loop =>
{
applied |= TryUnroll(
builder,
loop,
loopInfos,
MaxUnrollFactor);
});
return applied;
}

#endregion
Expand Down

0 comments on commit 0d39f9e

Please sign in to comment.