Skip to content

Commit

Permalink
- Refactoring (#1133)
Browse files Browse the repository at this point in the history
  • Loading branch information
tgiphil committed Sep 2, 2023
1 parent 8558225 commit c4e1030
Show file tree
Hide file tree
Showing 13 changed files with 481 additions and 272 deletions.
58 changes: 58 additions & 0 deletions Source/Mosa.Compiler.Framework/BaseBlockTransform.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright (c) MOSA Project. Licensed under the New BSD License.

using System;

namespace Mosa.Compiler.Framework;

public abstract class BaseBlockTransform : IComparable<BaseBlockTransform>
{
#region Properties

public bool Log { get; private set; }

public string Name { get; }

public virtual int Priority { get; } = 0;

#endregion Properties

#region Constructors

public BaseBlockTransform(bool log = false)
{
Log = log;

Name = GetType().FullName.Replace("Mosa.Compiler.", string.Empty).Replace("Mosa.Compiler.Framework.Transforms", "IR").Replace("Transforms.", string.Empty);
}

#endregion Constructors

#region Abstract Methods

public abstract bool Process(TransformContext transformContext);

#endregion Abstract Methods

#region Internals

int IComparable<BaseBlockTransform>.CompareTo(BaseBlockTransform other)
{
return Priority.CompareTo(other.Priority);
}

#endregion Internals

#region Block Helpers

protected static void RemoveRemainingInstructionInBlock(Context context)
{
BaseTransform.RemoveRemainingInstructionInBlock(context);
}

protected static BasicBlock GetOtherBranchTarget(BasicBlock block, BasicBlock target)
{
return BaseTransform.GetOtherBranchTarget(block, target);
}

#endregion Block Helpers
}
238 changes: 0 additions & 238 deletions Source/Mosa.Compiler.Framework/BaseMethodCompilerStage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -359,246 +359,8 @@ protected Context Split(Context context)
return new Context(Split(context.Node));
}

/// <summary>
/// Determines whether [is empty block with single jump] [the specified block].
/// </summary>
/// <param name="block">The block.</param>
/// <returns>
/// <c>true</c> if [is empty block with single jump] [the specified block]; otherwise, <c>false</c>.
/// </returns>
protected static bool IsEmptyBlockWithSingleJump(BasicBlock block)
{
if (block.NextBlocks.Count != 1)
return false;

for (var node = block.AfterFirst; !node.IsBlockEndInstruction; node = node.Next)
{
if (node.IsEmptyOrNop)
continue;

if (!node.Instruction.IsUnconditionalBranch)
return false;
}

return true;
}

/// <summary>
/// Empties the block of all instructions.
/// </summary>
/// <param name="block">The block.</param>
protected static bool EmptyBlockOfAllInstructions(BasicBlock block, bool useNop = false)
{
var found = false;

for (var node = block.AfterFirst; !node.IsBlockEndInstruction; node = node.Next)
{
if (node.IsEmpty)
continue;

if (node.IsNop)
{
if (!useNop)
node.Empty();

continue;
}

node.SetNop();

found = true;
}

return found;
}

/// <summary>
/// Replaces the branch targets.
/// </summary>
/// <param name="target">The current from block.</param>
/// <param name="oldTarget">The current destination block.</param>
/// <param name="newTarget">The new target block.</param>
protected static void ReplaceBranchTargets(BasicBlock target, BasicBlock oldTarget, BasicBlock newTarget)
{
for (var node = target.BeforeLast; !node.IsBlockStartInstruction; node = node.Previous)
{
if (node.IsEmptyOrNop)
continue;

if (node.BranchTargetsCount == 0)
continue;

// TODO: When non branch instruction encountered, return (fast out)

var targets = node.BranchTargets;

for (var index = 0; index < targets.Count; index++)
{
if (targets[index] == oldTarget)
{
node.UpdateBranchTarget(index, newTarget);
}
}
}
}

protected static void RemoveEmptyBlockWithSingleJump(BasicBlock block, bool useNop = false)
{
Debug.Assert(block.NextBlocks.Count == 1);

var target = block.NextBlocks[0];

foreach (var previous in block.PreviousBlocks.ToArray())
{
ReplaceBranchTargets(previous, block, target);
}

EmptyBlockOfAllInstructions(block, useNop);

Debug.Assert(block.PreviousBlocks.Count == 0);
}

#endregion Block Operations

#region Phi Helpers

public static void UpdatePhiBlocks(BasicBlock[] phiBlocks)
{
foreach (var phiBlock in phiBlocks)
{
UpdatePhiBlock(phiBlock);
}
}

public static void UpdatePhiBlocks(List<BasicBlock> phiBlocks)
{
foreach (var phiBlock in phiBlocks)
{
UpdatePhiBlock(phiBlock);
}
}

public static void UpdatePhiBlock(BasicBlock phiBlock)
{
for (var node = phiBlock.AfterFirst; !node.IsBlockEndInstruction; node = node.Next)
{
if (node.IsEmptyOrNop)
continue;

if (!node.Instruction.IsPhi)
break;

UpdatePhi(node);
}
}

public static void UpdatePhi(InstructionNode node)
{
Debug.Assert(node.OperandCount != node.Block.PreviousBlocks.Count);

// One or more of the previous blocks was removed, fix up the operand blocks

var previousBlocks = node.Block.PreviousBlocks;
var phiBlocks = node.PhiBlocks;

for (var index = 0; index < node.OperandCount; index++)
{
var phiBlock = phiBlocks[index];

if (previousBlocks.Contains(phiBlock))
continue;

phiBlocks.RemoveAt(index);

for (var i = index; index < node.OperandCount - 1; index++)
{
node.SetOperand(i, node.GetOperand(i + 1));
}

node.SetOperand(node.OperandCount - 1, null);
node.OperandCount--;

index--;
}

Debug.Assert(node.OperandCount == node.Block.PreviousBlocks.Count);
}

public static void RemoveBlockFromPhi(BasicBlock removedBlock, BasicBlock phiBlock)
{
for (var node = phiBlock.AfterFirst; !node.IsBlockEndInstruction; node = node.Next)
{
if (node.IsEmptyOrNop)
continue;

if (!node.Instruction.IsPhi)
break;

var sourceBlocks = node.PhiBlocks;

var index = sourceBlocks.IndexOf(removedBlock);

if (index < 0)
continue;

sourceBlocks.RemoveAt(index);

for (var i = index; index < node.OperandCount - 1; index++)
{
node.SetOperand(i, node.GetOperand(i + 1));
}

node.SetOperand(node.OperandCount - 1, null);
node.OperandCount--;
}
}

public static void UpdatePhiTargets(List<BasicBlock> targets, BasicBlock source, BasicBlock newSource)
{
foreach (var target in targets)
{
UpdatePhiTarget(target, source, newSource);
}
}

public static void UpdatePhiTarget(BasicBlock phiBlock, BasicBlock source, BasicBlock newSource)
{
Debug.Assert(phiBlock.PreviousBlocks.Count > 0);

for (var node = phiBlock.AfterFirst; !node.IsBlockEndInstruction; node = node.Next)
{
if (node.IsEmptyOrNop)
continue;

if (!node.Instruction.IsPhi)
break;

var index = node.PhiBlocks.IndexOf(source);

//Debug.Assert(index >= 0);

node.PhiBlocks[index] = newSource;
}
}

public static bool HasPhiInstruction(BasicBlock target)
{
for (var node = target.AfterFirst; !node.IsBlockEndInstruction; node = node.Next)
{
if (node.IsEmptyOrNop)
continue;

if (node.Instruction.IsPhi)
return true;

return false;
}

return false;
}

#endregion Phi Helpers

#region Protected Region Methods

protected MosaExceptionHandler FindImmediateExceptionHandler(int label)
Expand Down
4 changes: 2 additions & 2 deletions Source/Mosa.Compiler.Framework/BaseTransform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1007,7 +1007,7 @@ protected static bool IsNormal(ConditionCode conditionCode)

#region Block Helpers

protected static void RemoveRemainingInstructionInBlock(Context context)
public static void RemoveRemainingInstructionInBlock(Context context)
{
var node = context.Node.Next;

Expand All @@ -1021,7 +1021,7 @@ protected static void RemoveRemainingInstructionInBlock(Context context)
}
}

protected static BasicBlock GetOtherBranchTarget(BasicBlock block, BasicBlock target)
public static BasicBlock GetOtherBranchTarget(BasicBlock block, BasicBlock target)
{
return block.NextBlocks[0] == target ? block.NextBlocks[1] : block.NextBlocks[0];
}
Expand Down

0 comments on commit c4e1030

Please sign in to comment.