Skip to content

Commit

Permalink
- WIP - Loop Range Tracker Stage
Browse files Browse the repository at this point in the history
  • Loading branch information
tgiphil committed Apr 2, 2024
1 parent 3d4084d commit fd50420
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 52 deletions.
11 changes: 9 additions & 2 deletions Source/Mosa.Compiler.Framework/Loop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ namespace Mosa.Compiler.Framework;
public sealed class Loop
{
public BasicBlock Header { get; set; }
public readonly List<BasicBlock> Backedges = new List<BasicBlock>();
public readonly List<BasicBlock> LoopBlocks = new List<BasicBlock>();
public readonly List<BasicBlock> Backedges = new();
public readonly List<BasicBlock> LoopBlocks = new();
//private readonly HashSet<BasicBlock> LoopBlocksSet = new();

public Loop(BasicBlock header, BasicBlock backedge)
{
Expand All @@ -25,5 +26,11 @@ public void AddNode(BasicBlock block)
{
Debug.Assert(!LoopBlocks.Contains(block));
LoopBlocks.Add(block);
//LoopBlocksSet.Add(block);
}

//public bool Contains(BasicBlock block)
//{
// return LoopBlocksSet.Contains(block);
//}
}
92 changes: 43 additions & 49 deletions Source/Mosa.Compiler.Framework/Stages/LoopRangeTrackerStage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,22 +75,16 @@ private void ProcessLoop(Loop loop)
continue;

if (node.Instruction == IR.Phi32)
ProcessNode32(node, loop);

//if (node.Instruction == IR.Phi64))
//ProcessNode64(node, loop);
ProcessNode(node, loop, true);
else if (node.Instruction == IR.Phi64)
ProcessNode(node, loop, false);
}
}

private void ProcessNode32(Node node, Loop loop)
private void ProcessNode(Node node, Loop loop, bool is32Bit)
{
var headerblock = node.Block.PreviousBlocks[0];

// match a = phi(x, y) { B1, B2}
// in header loop
// where x is constant
// B1 is loop.header.previous

var result = node.Result;
var x = node.Operand1;
var y = node.Operand2;
Expand All @@ -110,19 +104,14 @@ private void ProcessNode32(Node node, Loop loop)
if (b1 != headerblock)
return;

//y.defined by
//instruction = Add
//op1 = x
//op2 = positive constant c (increment)
//in block within loop // may not be necessary in SSA form
// => at this point, we know the lower of a is constant x

if (!y.IsDefinedOnce)
return;

var d = y.Definitions[0];

if (d.Instruction != IR.Add32)
// Future: determine direction base on IR.Add or IR.Sub and constant

if (!(d.Instruction == IR.Add32 || d.Instruction == IR.Add64))
return;

if (d.Result != y)
Expand All @@ -134,18 +123,18 @@ private void ProcessNode32(Node node, Loop loop)
if (!d.Operand2.IsResolvedConstant)
return;

if (d.Operand2.ConstantUnsigned32 <= 0)
if (d.Operand2.ConstantUnsigned64 <= 0)
return;

if (!loop.LoopBlocks.Contains(d.Block))
return;

result.BitValue.NarrowMin(x.ConstantUnsigned32);
result.BitValue.NarrowMin(x.ConstantUnsigned64);

trace?.Log($"{result} MinValue = {x.ConstantUnsigned32}");
trace?.Log($"{result} MinValue = {x.ConstantUnsigned64}");
MinDetermined.Increment();

if (DetermineMaxOut32(d.Operand1, d.Operand2, loop, out var max))
if (DetermineMaxOut(d.Operand1, d.Operand2, loop, out var max))
{
result.BitValue.NarrowMax((ulong)max);

Expand All @@ -154,22 +143,14 @@ private void ProcessNode32(Node node, Loop loop)
}
}

private bool DetermineMaxOut32(Operand incrementVariable, Operand incrementValue, Loop loop, out int max)
private static bool DetermineMaxOut(Operand incrementVariable, Operand incrementValue, Loop loop, out long max)
{
bool determined = false;
max = int.MaxValue;

//a.used by
//instruction = branch
//compare: <
//op1 = result
//op2 = constant d
//branch is to phi node
//in block within loop
max = long.MaxValue;

foreach (var b in incrementVariable.Uses)
{
if (b.Instruction != IR.Branch32)
if (!(b.Instruction == IR.Branch32 || b.Instruction == IR.Branch64))
continue;

// only that are the header or backedge (if only one)
Expand All @@ -184,22 +165,35 @@ private bool DetermineMaxOut32(Operand incrementVariable, Operand incrementValue
? b.Block.NextBlocks[0]
: b.Block.NextBlocks[1];

if (!(condition == ConditionCode.Less
|| condition == ConditionCode.LessOrEqual
|| condition == ConditionCode.UnsignedLess
|| condition == ConditionCode.UnsignedLessOrEqual
|| condition == ConditionCode.Equal))
// form: x (variable) </<=/== y (constant) -> where branch exits the loop

// change form - on condition
if (condition is not (ConditionCode.Less
or ConditionCode.LessOrEqual
or ConditionCode.UnsignedLess
or ConditionCode.UnsignedLessOrEqual
or ConditionCode.Equal))
{
// swap
(x, y, condition, target, othertarget) = (y, x, condition.GetOpposite(), othertarget, target);
(x, y, condition) = (y, x, condition.GetOpposite()); // swap
}

// form: x (variable) </<=/== y (constant) -> which branch exits the loop
if (!(condition == ConditionCode.Less
|| condition == ConditionCode.LessOrEqual
|| condition == ConditionCode.UnsignedLess
|| condition == ConditionCode.UnsignedLessOrEqual
|| condition == ConditionCode.Equal))
// change form - on branch
if (!loop.LoopBlocks.Contains(target))
{
(condition, target, othertarget) = (condition.GetOpposite(), othertarget, target); // swap
}

// change form - on constant to right
if (!y.IsResolvedConstant && condition == ConditionCode.Equal)
{
(x, y) = (y, x);
}

if (condition is not (ConditionCode.Less
or ConditionCode.LessOrEqual
or ConditionCode.UnsignedLess
or ConditionCode.UnsignedLessOrEqual
or ConditionCode.Equal))
continue;

if (x != incrementVariable)
Expand All @@ -208,12 +202,12 @@ private bool DetermineMaxOut32(Operand incrementVariable, Operand incrementValue
if (!y.IsResolvedConstant)
continue;

if (!loop.LoopBlocks.Contains(target)) // exits loop
continue;
if (!loop.LoopBlocks.Contains(target))
continue; // exits loop

var adj = condition == ConditionCode.LessOrEqual || condition == ConditionCode.Equal ? 1 : 0;

var branchmax = y.ConstantSigned32 + incrementValue.ConstantSigned32 - 1 + adj;
var branchmax = y.ConstantSigned64 + incrementValue.ConstantSigned64 - 1 + adj;

max = Math.Min(max, branchmax);

Expand Down
1 change: 1 addition & 0 deletions Source/Mosa.Tool.Explorer/MainForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -974,6 +974,7 @@ private void ToggleOptimization(bool state)
cbEnableLongExpansion.Checked = state;
cbEnableTwoPassOptimizations.Checked = state;
cbEnableBitTracker.Checked = state;
cbEnableLoopRangeTracker.Checked = state;
cbLoopInvariantCodeMotion.Checked = state;
cbPlatformOptimizations.Checked = state;
cbEnableDevirtualization.Checked = state;
Expand Down
104 changes: 103 additions & 1 deletion Source/Mosa.UnitTests/Optimization/LoopStrengthReduction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public static int Reduction6()

for (var i = 0; i < n; i++)
{
a *= i;
a += i;

if (i > 20)
return 0;
Expand All @@ -91,6 +91,108 @@ public static int Reduction6()
return a;
}

[MosaUnitTest]
public static int Reduction6a()
{
var a = 8;
var n = 10;

for (var i = 0; i < n; i++)
{
a += i;

if (i > 9)
return 0;
}

return a;
}

[MosaUnitTest]
public static int Reduction6b()
{
var a = 8;
var n = 10;

for (var i = 0; i < n; i++)
{
a += i;

if (i > 10)
return 0;
}

return a;
}

[MosaUnitTest]
public static int Reduction6c()
{
var a = 8;
var n = 10;

for (var i = 0; i < n; i++)
{
a += i;

if (i > 11)
return 0;
}

return a;
}

[MosaUnitTest]
public static int Reduction6d()
{
var a = 8;
var n = 10;

for (var i = 0; i != n; i++)
{
a += i;

if (i > 9)
return 0;
}

return a;
}

[MosaUnitTest]
public static int Reduction6e()
{
var a = 8;
var n = 10;

for (var i = 0; i != n; i++)
{
a += i;

if (i > 10)
return 0;
}

return a;
}

[MosaUnitTest]
public static int Reduction6f()
{
var a = 8;
var n = 10;

for (var i = 0; i != n; i++)
{
a += i;

if (i > 11)
return 0;
}

return a;
}

[MosaUnitTest]
public static int Reduction7()
{
Expand Down

0 comments on commit fd50420

Please sign in to comment.