From 48c7b967f21c7ed361e92ca797a7644a1da8ffea Mon Sep 17 00:00:00 2001 From: Marcel Koester Date: Tue, 29 Aug 2023 04:54:34 +0100 Subject: [PATCH] Simplified loop processing of IR-based loops. --- Src/ILGPU/IR/Analyses/LoopInfo.cs | 2 +- Src/ILGPU/IR/Analyses/Loops.cs | 69 ++++++------------- .../LoopInvariantCodeMotion.cs | 44 +++--------- Src/ILGPU/IR/Transformations/LoopUnrolling.cs | 59 +++------------- 4 files changed, 42 insertions(+), 132 deletions(-) diff --git a/Src/ILGPU/IR/Analyses/LoopInfo.cs b/Src/ILGPU/IR/Analyses/LoopInfo.cs index 793436f590..dd0d7a235d 100644 --- a/Src/ILGPU/IR/Analyses/LoopInfo.cs +++ b/Src/ILGPU/IR/Analyses/LoopInfo.cs @@ -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)) diff --git a/Src/ILGPU/IR/Analyses/Loops.cs b/Src/ILGPU/IR/Analyses/Loops.cs index 89cf2b932f..0d12616add 100644 --- a/Src/ILGPU/IR/Analyses/Loops.cs +++ b/Src/ILGPU/IR/Analyses/Loops.cs @@ -38,18 +38,6 @@ public sealed class Loops { #region Nested Types - /// - /// Represents an abstract loop processor. - /// - public interface ILoopProcessor - { - /// - /// Processes the given loop. - /// - /// The current loop node. - void Process(Node node); - } - /// /// A specialized successor provider for loop members that exclude all exit /// blocks of an associated loop. @@ -88,8 +76,7 @@ public MembersSuccessorProvider(Node node) /// of the associated loop exit blocks. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly ReadOnlySpan GetSuccessors( - BasicBlock basicBlock) + public ReadOnlySpan GetSuccessors(BasicBlock basicBlock) { var successors = basicBlock.CurrentSuccessors; @@ -114,7 +101,7 @@ public readonly ReadOnlySpan GetSuccessors( /// The current successors. /// The adjusted span that contains header blocks only. [MethodImpl(MethodImplOptions.AggressiveInlining)] - private readonly ReadOnlySpan AdjustEntrySuccessors( + private ReadOnlySpan AdjustEntrySuccessors( ReadOnlySpan currentSuccessors) { var successors = InlineList.Create(currentSuccessors.Length); @@ -132,7 +119,7 @@ private readonly ReadOnlySpan AdjustEntrySuccessors( /// The current successors. /// The adjusted span without any exit block. [MethodImpl(MethodImplOptions.AggressiveInlining)] - private readonly ReadOnlySpan AdjustExitSuccessors( + private ReadOnlySpan AdjustExitSuccessors( ReadOnlySpan currentSuccessors) { var successors = currentSuccessors.ToInlineList(); @@ -181,6 +168,7 @@ internal Node( { Parent = parent; parent?.AddChild(this); + Level = (parent?.Level ?? -1) + 1; headerBlocks.MoveTo(ref headers); breakerBlocks.MoveTo(ref breakers); @@ -195,6 +183,11 @@ internal Node( #region Properties + /// + /// Returns the loop level. + /// + public int Level { get; } + /// /// Returns the number of members. /// @@ -259,7 +252,7 @@ internal Node( /// /// The block to map to an loop. /// True, if the node belongs to this loop. - public bool Contains(BasicBlock block) => + public bool Contains(BasicBlock? block) => block != null && AllMembers.Contains(block); /// @@ -305,13 +298,13 @@ public Phis ComputePhis() } /// - /// 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. /// /// The blocks to test. /// - /// True, if the given block contain at least one backedge block. + /// True, if the given block contain at least one back edge block. /// - public bool ContainsBackedgeBlock(ReadOnlySpan blocks) + public bool ContainsBackEdgeBlock(ReadOnlySpan blocks) { foreach (var block in blocks) { @@ -508,19 +501,6 @@ public void Push(List stack, ref int index) } } - /// - /// Provides new intermediate list instances. - /// - private readonly struct NodeListProvider : IBasicBlockMapValueProvider> - { - /// - /// Creates a new instance. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly List GetValue(BasicBlock block, int _) => - new List(2); - } - /// /// Provides new intermediate instances. /// @@ -544,7 +524,7 @@ public NodeDataProvider(CFG cfg) /// Creates a new instance. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly NodeData GetValue(BasicBlock block, int traversalIndex) => + public NodeData GetValue(BasicBlock block, int traversalIndex) => new NodeData(CFG[block]); } @@ -858,33 +838,28 @@ public bool TryGetLoops(BasicBlock block, [NotNullWhen(true)] out Node? loop) => /// /// Processes all loops starting with the innermost loops. /// - /// The processor type. - /// The processor instance. + /// The loop processor action. /// The resulting processor instance. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public TProcessor ProcessLoops(TProcessor processor) - where TProcessor : struct, ILoopProcessor + public void ProcessLoops(Action processor) { foreach (var header in Headers) - ProcessLoopsRecursive(header, ref processor); - return processor; + ProcessLoopsRecursive(header, processor); } /// /// Unrolls loops in a recursive way by unrolling the innermost loops first. /// - /// The processor type. /// The current loop node. - /// The processor instance. - private static void ProcessLoopsRecursive( + /// The loop processor action. + private static void ProcessLoopsRecursive( Node loop, - ref TProcessor processor) - where TProcessor : struct, ILoopProcessor + Action processor) { foreach (var child in loop.Children) - ProcessLoopsRecursive(child, ref processor); + ProcessLoopsRecursive(child, processor); - processor.Process(loop); + processor(loop); } #endregion diff --git a/Src/ILGPU/IR/Transformations/LoopInvariantCodeMotion.cs b/Src/ILGPU/IR/Transformations/LoopInvariantCodeMotion.cs index 66c7ad410e..25d576b961 100644 --- a/Src/ILGPU/IR/Transformations/LoopInvariantCodeMotion.cs +++ b/Src/ILGPU/IR/Transformations/LoopInvariantCodeMotion.cs @@ -1,6 +1,6 @@ // --------------------------------------------------------------------------------------- // ILGPU -// Copyright (c) 2020-2022 ILGPU Project +// Copyright (c) 2020-2023 ILGPU Project // www.ilgpu.net // // File: LoopInvariantCodeMotion.cs @@ -172,39 +172,6 @@ public readonly bool ShouldBeMoved(Value value) } } - /// - /// Applies the LICM transformation to all loops. - /// - private struct LoopProcessor : Loops.ILoopProcessor - { - public LoopProcessor(Method.Builder builder) - { - Builder = builder; - Applied = false; - } - - /// - /// Returns the parent method builder. - /// - public Method.Builder Builder { get; } - - /// - /// Returns true if the loop processor could be applied. - /// - public bool Applied { get; private set; } - - /// - /// Applies the LICM transformation. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Process(Loop loop) - { - if (loop.Entries.Length > 1) - return; - Applied |= ApplyLICM(Builder, loop); - } - } - #endregion #region Static @@ -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 diff --git a/Src/ILGPU/IR/Transformations/LoopUnrolling.cs b/Src/ILGPU/IR/Transformations/LoopUnrolling.cs index f992c4c0d6..51ba055f09 100644 --- a/Src/ILGPU/IR/Transformations/LoopUnrolling.cs +++ b/Src/ILGPU/IR/Transformations/LoopUnrolling.cs @@ -387,51 +387,6 @@ public readonly void ClearBody() #endregion } - /// - /// Applies the unrolling transformation to all loops. - /// - private struct LoopProcessor : Loops.ILoopProcessor - { - private readonly LoopInfos loopInfos; - - public LoopProcessor( - in LoopInfos infos, - Method.Builder builder, - int maxUnrollFactor) - { - loopInfos = infos; - Builder = builder; - MaxUnrollFactor = maxUnrollFactor; - Applied = false; - } - - /// - /// Returns the parent method builder. - /// - public Method.Builder Builder { get; } - - /// - /// Returns the maximum unrolling factor. - /// - public int MaxUnrollFactor { get; } - - /// - /// Returns true if the loop processor could be applied. - /// - public bool Applied { get; private set; } - - /// - /// Applies the unrolling transformation. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Process(Loop loop) => - Applied |= TryUnroll( - Builder, - loop, - loopInfos, - MaxUnrollFactor); - } - #endregion #region Static @@ -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