diff --git a/Source/Mosa.Compiler.Framework/Compiler.cs b/Source/Mosa.Compiler.Framework/Compiler.cs index 2aa07be6d3..797dc82b11 100644 --- a/Source/Mosa.Compiler.Framework/Compiler.cs +++ b/Source/Mosa.Compiler.Framework/Compiler.cs @@ -161,12 +161,14 @@ public sealed class Compiler mosaSettings.SparseConditionalConstantPropagation && mosaSettings.SSA ? new SparseConditionalConstantPropagationStage() : null, mosaSettings.BasicOptimizations && mosaSettings.SSA && (mosaSettings.ValueNumbering || mosaSettings.LoopInvariantCodeMotion || mosaSettings.SparseConditionalConstantPropagation) ? new OptimizationStage(false) : null, mosaSettings.BitTracker ? new BitTrackerStage() : null, - mosaSettings.BasicOptimizations && mosaSettings.LongExpansion ? new OptimizationStage(mosaSettings.LongExpansion) : null, + mosaSettings.LoopRangeTracker && mosaSettings.SSA ? new LoopRangeTrackerStage() : null, + mosaSettings.BasicOptimizations ? new OptimizationStage(mosaSettings.LongExpansion) : null, mosaSettings.TwoPassOptimization && mosaSettings.ValueNumbering && mosaSettings.SSA ? new ValueNumberingStage() : null, mosaSettings.TwoPassOptimization && mosaSettings.LoopInvariantCodeMotion && mosaSettings.SSA ? new LoopInvariantCodeMotionStage() : null, mosaSettings.TwoPassOptimization && mosaSettings.SparseConditionalConstantPropagation && mosaSettings.SSA ? new SparseConditionalConstantPropagationStage() : null, mosaSettings.TwoPassOptimization && mosaSettings.BitTracker ? new BitTrackerStage() : null, + mosaSettings.TwoPassOptimization && mosaSettings.LoopRangeTracker && mosaSettings.SSA ? new LoopRangeTrackerStage() : null, mosaSettings.TwoPassOptimization && mosaSettings.BasicOptimizations && mosaSettings.SSA ? new OptimizationStage(mosaSettings.LongExpansion) : null, new NopRemovalStage(), diff --git a/Source/Mosa.Compiler.Framework/Loop.cs b/Source/Mosa.Compiler.Framework/Loop.cs index 1fff89812e..ee940e4afd 100644 --- a/Source/Mosa.Compiler.Framework/Loop.cs +++ b/Source/Mosa.Compiler.Framework/Loop.cs @@ -7,8 +7,9 @@ namespace Mosa.Compiler.Framework; public sealed class Loop { public BasicBlock Header { get; set; } - public readonly List Backedges = new List(); - public readonly List LoopBlocks = new List(); + public readonly List Backedges = new(); + public readonly List LoopBlocks = new(); + //private readonly HashSet LoopBlocksSet = new(); public Loop(BasicBlock header, BasicBlock backedge) { @@ -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); + //} } diff --git a/Source/Mosa.Compiler.Framework/Stages/LoopRangeTrackerStage.cs b/Source/Mosa.Compiler.Framework/Stages/LoopRangeTrackerStage.cs new file mode 100644 index 0000000000..9ec7d87a76 --- /dev/null +++ b/Source/Mosa.Compiler.Framework/Stages/LoopRangeTrackerStage.cs @@ -0,0 +1,219 @@ +// Copyright (c) MOSA Project. Licensed under the New BSD License. + +using Mosa.Compiler.Framework.Analysis; + +namespace Mosa.Compiler.Framework.Stages; + +/// +/// Loop Range Tracker Stage +/// +public sealed class LoopRangeTrackerStage : BaseMethodCompilerStage +{ + private readonly Counter MinDetermined = new("LoopRangeTrackerStage.MinDetermined"); + private readonly Counter MaxDetermined = new("LoopRangeTrackerStage.MaxDetermined"); + + private TraceLog trace; + + protected override void Initialize() + { + Register(MinDetermined); + Register(MaxDetermined); + } + + protected override void Finish() + { + trace = null; + } + + protected override void Run() + { + if (HasProtectedRegions) + return; + + // Method is empty - must be a plugged method + if (BasicBlocks.HeadBlocks.Count != 1) + return; + + if (BasicBlocks.PrologueBlock == null) + return; + + if (!MethodCompiler.IsInSSAForm) + return; + + trace = CreateTraceLog(5); + + var loops = LoopDetector.FindLoops(BasicBlocks); + + if (loops.Count == 0) + return; + + ProcessLoops(loops); + } + + private void ProcessLoops(List loops) + { + foreach (var loop in loops) + { + ProcessLoop(loop); + } + } + + private void ProcessLoop(Loop loop) + { + if (loop.Header.PreviousBlocks.Count != 2) + return; + + for (var node = loop.Header.AfterFirst; !node.IsBlockEndInstruction; node = node.Next) + { + if (node.IsEmptyOrNop) + continue; + + if (!node.Instruction.IsPhi) + return; + + if (node.OperandCount != 2) + continue; + + if (node.Instruction == IR.Phi32) + ProcessNode(node, loop, true); + else if (node.Instruction == IR.Phi64) + ProcessNode(node, loop, false); + } + } + + private void ProcessNode(Node node, Loop loop, bool is32Bit) + { + var headerblock = node.Block.PreviousBlocks[0]; + + var result = node.Result; + var x = node.Operand1; + var y = node.Operand2; + + var b1 = node.PhiBlocks[0]; + var b2 = node.PhiBlocks[1]; + + if (!x.IsResolvedConstant || b1 != headerblock) + { + // swap + (x, y, b1, b2) = (y, x, b2, b1); + } + + if (!x.IsResolvedConstant) + return; + + if (b1 != headerblock) + return; + + if (!y.IsDefinedOnce) + return; + + var d = y.Definitions[0]; + + // 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) + return; + + if (d.Operand1 != result) + return; + + if (!d.Operand2.IsResolvedConstant) + return; + + if (d.Operand2.ConstantUnsigned64 <= 0) + return; + + if (!loop.LoopBlocks.Contains(d.Block)) + return; + + result.BitValue.NarrowMin(x.ConstantUnsigned64); + + trace?.Log($"{result} MinValue = {x.ConstantUnsigned64}"); + MinDetermined.Increment(); + + if (DetermineMaxOut(d.Operand1, d.Operand2, loop, out var max)) + { + result.BitValue.NarrowMax((ulong)max); + + trace?.Log($"{result} MaxValue = {max}"); + MaxDetermined.Increment(); + } + } + + private static bool DetermineMaxOut(Operand incrementVariable, Operand incrementValue, Loop loop, out long max) + { + bool determined = false; + max = long.MaxValue; + + foreach (var b in incrementVariable.Uses) + { + if (!(b.Instruction == IR.Branch32 || b.Instruction == IR.Branch64)) + continue; + + // only that are the header or backedge (if only one) + if (!(b.Block == loop.Header || (loop.Backedges.Count == 1 && loop.Backedges.Contains(b.Block)))) + continue; + + var x = b.Operand1; + var y = b.Operand2; + var condition = b.ConditionCode; + var target = b.BranchTarget1; + var othertarget = target != b.Block.NextBlocks[0] + ? b.Block.NextBlocks[0] + : b.Block.NextBlocks[1]; + + // form: x (variable) 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)) + { + (x, y, condition) = (y, x, condition.GetOpposite()); // swap + } + + // 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) + continue; + + if (!y.IsResolvedConstant) + continue; + + if (!loop.LoopBlocks.Contains(target)) + continue; // exits loop + + var adj = condition == ConditionCode.LessOrEqual || condition == ConditionCode.Equal ? 1 : 0; + + var branchmax = y.ConstantSigned64 + incrementValue.ConstantSigned64 - 1 + adj; + + max = Math.Min(max, branchmax); + + determined = true; + } + + return determined; + } +} diff --git a/Source/Mosa.Tool.Explorer/MainForm.Designer.cs b/Source/Mosa.Tool.Explorer/MainForm.Designer.cs index 431d4119c7..ecdc98b7c3 100644 --- a/Source/Mosa.Tool.Explorer/MainForm.Designer.cs +++ b/Source/Mosa.Tool.Explorer/MainForm.Designer.cs @@ -136,6 +136,7 @@ private void InitializeComponent() folderBrowserDialog1 = new FolderBrowserDialog(); timer1 = new System.Windows.Forms.Timer(components); saveFileDialog1 = new SaveFileDialog(); + cbEnableLoopRangeTracker = new ToolStripMenuItem(); statusStrip1.SuspendLayout(); menuStrip1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)splitContainer1).BeginInit(); @@ -244,7 +245,7 @@ private void InitializeComponent() // // optionsToolStripMenuItem // - optionsToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { cbEnableAllOptimizations, cbDisableAllOptimizations, toolStripSeparator4, cbEnableSSA, cbEnableBasicOptimizations, cbEnableValueNumbering, cbEnableSparseConditionalConstantPropagation, cbEnableDevirtualization, cbEnableInline, cbInlineExplicit, cbEnableLongExpansion, cbLoopInvariantCodeMotion, cbEnableBitTracker, cbEnableTwoPassOptimizations, cbPlatformOptimizations, cbEnableBinaryCodeGeneration, cbEnableCodeSizeReduction }); + optionsToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { cbEnableAllOptimizations, cbDisableAllOptimizations, toolStripSeparator4, cbEnableSSA, cbEnableBasicOptimizations, cbEnableValueNumbering, cbEnableSparseConditionalConstantPropagation, cbEnableDevirtualization, cbEnableInline, cbInlineExplicit, cbEnableLongExpansion, cbLoopInvariantCodeMotion, cbEnableBitTracker, cbEnableLoopRangeTracker, cbEnableTwoPassOptimizations, cbPlatformOptimizations, cbEnableBinaryCodeGeneration, cbEnableCodeSizeReduction }); optionsToolStripMenuItem.Name = "optionsToolStripMenuItem"; optionsToolStripMenuItem.Size = new Size(93, 20); optionsToolStripMenuItem.Text = "Optimizations"; @@ -546,7 +547,7 @@ private void InitializeComponent() tabControl.Controls.Add(tabMethodCounters); tabControl.Controls.Add(tabLogs); tabControl.Controls.Add(tabCompilerCounters); - tabControl.Font = new Font("Microsoft Sans Serif", 10F, FontStyle.Regular, GraphicsUnit.Point); + tabControl.Font = new Font("Microsoft Sans Serif", 10F); tabControl.Location = new Point(1, 3); tabControl.Margin = new Padding(0); tabControl.Name = "tabControl"; @@ -595,7 +596,7 @@ private void InitializeComponent() // // label1 // - label1.Font = new Font("Microsoft Sans Serif", 10F, FontStyle.Regular, GraphicsUnit.Point); + label1.Font = new Font("Microsoft Sans Serif", 10F); label1.Location = new Point(352, 9); label1.Margin = new Padding(5); label1.Name = "label1"; @@ -606,7 +607,7 @@ private void InitializeComponent() // cbInstructionLabels // cbInstructionLabels.DropDownStyle = ComboBoxStyle.DropDownList; - cbInstructionLabels.Font = new Font("Microsoft Sans Serif", 8.25F, FontStyle.Regular, GraphicsUnit.Point); + cbInstructionLabels.Font = new Font("Microsoft Sans Serif", 8.25F); cbInstructionLabels.FormattingEnabled = true; cbInstructionLabels.Location = new Point(413, 8); cbInstructionLabels.Margin = new Padding(5); @@ -619,7 +620,7 @@ private void InitializeComponent() // cbInstructionStages // cbInstructionStages.DropDownStyle = ComboBoxStyle.DropDownList; - cbInstructionStages.Font = new Font("Microsoft Sans Serif", 8.25F, FontStyle.Regular, GraphicsUnit.Point); + cbInstructionStages.Font = new Font("Microsoft Sans Serif", 8.25F); cbInstructionStages.FormattingEnabled = true; cbInstructionStages.ItemHeight = 13; cbInstructionStages.Location = new Point(64, 8); @@ -632,7 +633,7 @@ private void InitializeComponent() // // stageLabel // - stageLabel.Font = new Font("Microsoft Sans Serif", 10F, FontStyle.Regular, GraphicsUnit.Point); + stageLabel.Font = new Font("Microsoft Sans Serif", 10F); stageLabel.Location = new Point(5, 9); stageLabel.Margin = new Padding(5); stageLabel.Name = "stageLabel"; @@ -643,7 +644,7 @@ private void InitializeComponent() // tbInstructions // tbInstructions.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; - tbInstructions.Font = new Font("Lucida Console", 8F, FontStyle.Regular, GraphicsUnit.Point); + tbInstructions.Font = new Font("Lucida Console", 8F); tbInstructions.Location = new Point(0, 37); tbInstructions.Margin = new Padding(4, 3, 4, 3); tbInstructions.Name = "tbInstructions"; @@ -681,7 +682,7 @@ private void InitializeComponent() // cbDebugStages // cbDebugStages.DropDownStyle = ComboBoxStyle.DropDownList; - cbDebugStages.Font = new Font("Microsoft Sans Serif", 8.25F, FontStyle.Regular, GraphicsUnit.Point); + cbDebugStages.Font = new Font("Microsoft Sans Serif", 8.25F); cbDebugStages.FormattingEnabled = true; cbDebugStages.Location = new Point(64, 8); cbDebugStages.Margin = new Padding(5); @@ -693,7 +694,7 @@ private void InitializeComponent() // // label3 // - label3.Font = new Font("Microsoft Sans Serif", 10F, FontStyle.Regular, GraphicsUnit.Point); + label3.Font = new Font("Microsoft Sans Serif", 10F); label3.Location = new Point(5, 9); label3.Margin = new Padding(5); label3.Name = "label3"; @@ -704,7 +705,7 @@ private void InitializeComponent() // tbDebugResult // tbDebugResult.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; - tbDebugResult.Font = new Font("Lucida Console", 8F, FontStyle.Regular, GraphicsUnit.Point); + tbDebugResult.Font = new Font("Lucida Console", 8F); tbDebugResult.Location = new Point(0, 37); tbDebugResult.Margin = new Padding(4, 3, 4, 3); tbDebugResult.Name = "tbDebugResult"; @@ -831,7 +832,7 @@ private void InitializeComponent() // tbTransforms // tbTransforms.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; - tbTransforms.Font = new Font("Lucida Console", 8F, FontStyle.Regular, GraphicsUnit.Point); + tbTransforms.Font = new Font("Lucida Console", 8F); tbTransforms.Location = new Point(0, 34); tbTransforms.Margin = new Padding(0); tbTransforms.Name = "tbTransforms"; @@ -864,7 +865,7 @@ private void InitializeComponent() dataGridView1.Name = "dataGridView1"; dataGridView1.ReadOnly = true; dataGridView1.RowHeadersVisible = false; - dataGridView1.RowTemplate.DefaultCellStyle.Font = new Font("Consolas", 8F, FontStyle.Regular, GraphicsUnit.Point); + dataGridView1.RowTemplate.DefaultCellStyle.Font = new Font("Consolas", 8F); dataGridView1.RowTemplate.Height = 18; dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect; dataGridView1.Size = new Size(253, 290); @@ -873,7 +874,7 @@ private void InitializeComponent() // // label7 // - label7.Font = new Font("Microsoft Sans Serif", 10F, FontStyle.Regular, GraphicsUnit.Point); + label7.Font = new Font("Microsoft Sans Serif", 10F); label7.Location = new Point(352, 9); label7.Margin = new Padding(5); label7.Name = "label7"; @@ -884,7 +885,7 @@ private void InitializeComponent() // cbTransformLabels // cbTransformLabels.DropDownStyle = ComboBoxStyle.DropDownList; - cbTransformLabels.Font = new Font("Microsoft Sans Serif", 8.25F, FontStyle.Regular, GraphicsUnit.Point); + cbTransformLabels.Font = new Font("Microsoft Sans Serif", 8.25F); cbTransformLabels.FormattingEnabled = true; cbTransformLabels.Location = new Point(413, 8); cbTransformLabels.Margin = new Padding(5); @@ -897,7 +898,7 @@ private void InitializeComponent() // cbTransformStages // cbTransformStages.DropDownStyle = ComboBoxStyle.DropDownList; - cbTransformStages.Font = new Font("Microsoft Sans Serif", 8.25F, FontStyle.Regular, GraphicsUnit.Point); + cbTransformStages.Font = new Font("Microsoft Sans Serif", 8.25F); cbTransformStages.FormattingEnabled = true; cbTransformStages.ItemHeight = 13; cbTransformStages.Location = new Point(64, 8); @@ -910,7 +911,7 @@ private void InitializeComponent() // // label8 // - label8.Font = new Font("Microsoft Sans Serif", 10F, FontStyle.Regular, GraphicsUnit.Point); + label8.Font = new Font("Microsoft Sans Serif", 10F); label8.Location = new Point(5, 9); label8.Margin = new Padding(5); label8.Name = "label8"; @@ -988,7 +989,7 @@ private void InitializeComponent() gridMethodCounters.ReadOnly = true; gridMethodCounters.RowHeadersVisible = false; gridMethodCounters.RowHeadersWidth = 51; - gridMethodCounters.RowTemplate.DefaultCellStyle.Font = new Font("Microsoft Sans Serif", 7.8F, FontStyle.Regular, GraphicsUnit.Point); + gridMethodCounters.RowTemplate.DefaultCellStyle.Font = new Font("Microsoft Sans Serif", 7.8F); gridMethodCounters.RowTemplate.Height = 20; gridMethodCounters.ShowCellErrors = false; gridMethodCounters.ShowCellToolTips = false; @@ -1012,7 +1013,7 @@ private void InitializeComponent() // tbMethodCounters // tbMethodCounters.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; - tbMethodCounters.Font = new Font("Lucida Console", 8F, FontStyle.Regular, GraphicsUnit.Point); + tbMethodCounters.Font = new Font("Lucida Console", 8F); tbMethodCounters.Location = new Point(0, 3); tbMethodCounters.Margin = new Padding(4, 3, 4, 3); tbMethodCounters.Name = "tbMethodCounters"; @@ -1037,7 +1038,7 @@ private void InitializeComponent() // cbCompilerSections // cbCompilerSections.DropDownStyle = ComboBoxStyle.DropDownList; - cbCompilerSections.Font = new Font("Microsoft Sans Serif", 8.25F, FontStyle.Regular, GraphicsUnit.Point); + cbCompilerSections.Font = new Font("Microsoft Sans Serif", 8.25F); cbCompilerSections.FormattingEnabled = true; cbCompilerSections.Location = new Point(77, 8); cbCompilerSections.Margin = new Padding(5); @@ -1049,7 +1050,7 @@ private void InitializeComponent() // // label4 // - label4.Font = new Font("Microsoft Sans Serif", 10F, FontStyle.Regular, GraphicsUnit.Point); + label4.Font = new Font("Microsoft Sans Serif", 10F); label4.Location = new Point(5, 9); label4.Margin = new Padding(5); label4.Name = "label4"; @@ -1060,7 +1061,7 @@ private void InitializeComponent() // tbCompilerLogs // tbCompilerLogs.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; - tbCompilerLogs.Font = new Font("Lucida Console", 8F, FontStyle.Regular, GraphicsUnit.Point); + tbCompilerLogs.Font = new Font("Lucida Console", 8F); tbCompilerLogs.Location = new Point(0, 37); tbCompilerLogs.Margin = new Padding(4, 3, 4, 3); tbCompilerLogs.Name = "tbCompilerLogs"; @@ -1140,7 +1141,7 @@ private void InitializeComponent() gridCompilerCounters.ReadOnly = true; gridCompilerCounters.RowHeadersVisible = false; gridCompilerCounters.RowHeadersWidth = 51; - gridCompilerCounters.RowTemplate.DefaultCellStyle.Font = new Font("Microsoft Sans Serif", 7.8F, FontStyle.Regular, GraphicsUnit.Point); + gridCompilerCounters.RowTemplate.DefaultCellStyle.Font = new Font("Microsoft Sans Serif", 7.8F); gridCompilerCounters.RowTemplate.Height = 20; gridCompilerCounters.ShowCellErrors = false; gridCompilerCounters.ShowCellToolTips = false; @@ -1164,7 +1165,7 @@ private void InitializeComponent() // tbCompilerCounters // tbCompilerCounters.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; - tbCompilerCounters.Font = new Font("Lucida Console", 8F, FontStyle.Regular, GraphicsUnit.Point); + tbCompilerCounters.Font = new Font("Lucida Console", 8F); tbCompilerCounters.Location = new Point(0, 0); tbCompilerCounters.Margin = new Padding(4, 3, 4, 3); tbCompilerCounters.Name = "tbCompilerCounters"; @@ -1244,6 +1245,15 @@ private void InitializeComponent() timer1.Enabled = true; timer1.Tick += timer1_Tick; // + // cbEnableLoopRangeTracker + // + cbEnableLoopRangeTracker.Checked = true; + cbEnableLoopRangeTracker.CheckOnClick = true; + cbEnableLoopRangeTracker.CheckState = CheckState.Checked; + cbEnableLoopRangeTracker.Name = "cbEnableLoopRangeTracker"; + cbEnableLoopRangeTracker.Size = new Size(293, 22); + cbEnableLoopRangeTracker.Text = "Enable Loop Range Tracker"; + // // MainForm // AutoScaleDimensions = new SizeF(7F, 15F); @@ -1407,5 +1417,6 @@ private void InitializeComponent() private Button button1; private Button button2; private ToolStripMenuItem cbEnableCodeSizeReduction; + private ToolStripMenuItem cbEnableLoopRangeTracker; } } diff --git a/Source/Mosa.Tool.Explorer/MainForm.cs b/Source/Mosa.Tool.Explorer/MainForm.cs index a0836d5056..ec1530c0d1 100644 --- a/Source/Mosa.Tool.Explorer/MainForm.cs +++ b/Source/Mosa.Tool.Explorer/MainForm.cs @@ -7,6 +7,7 @@ using Mosa.Compiler.Common; using Mosa.Compiler.Framework; using Mosa.Compiler.Framework.CompilerStages; +using Mosa.Compiler.Framework.Stages; using Mosa.Compiler.MosaTypeSystem; using Mosa.Compiler.MosaTypeSystem.CLR; using Mosa.Tool.Explorer.Stages; @@ -588,6 +589,7 @@ private void ExtendMethodCompilerPipeline(Pipeline pipe } else { + pipeline.InsertAfterLast(new GraphVizStage()); pipeline.Add(new GraphVizStage()); } } @@ -972,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; @@ -1076,6 +1079,7 @@ private void UpdateDisplay() cbLoopInvariantCodeMotion.Checked = MosaSettings.LoopInvariantCodeMotion; cbEnableValueNumbering.Checked = MosaSettings.ValueNumbering; cbEnableBitTracker.Checked = MosaSettings.BitTracker; + cbEnableLoopRangeTracker.Checked = MosaSettings.LoopRangeTracker; cbEnableBinaryCodeGeneration.Checked = MosaSettings.EmitBinary; cbEnableMethodScanner.Checked = MosaSettings.MethodScanner; cbEnableMultithreading.Checked = MosaSettings.Multithreading; @@ -1197,6 +1201,7 @@ private void UpdateSettings() MosaSettings.SparseConditionalConstantPropagation = cbEnableSparseConditionalConstantPropagation.Checked; MosaSettings.Devirtualization = cbEnableDevirtualization.Checked; MosaSettings.BitTracker = cbEnableBitTracker.Checked; + MosaSettings.LoopRangeTracker = cbEnableLoopRangeTracker.Checked; MosaSettings.LoopInvariantCodeMotion = cbLoopInvariantCodeMotion.Checked; MosaSettings.LongExpansion = cbEnableLongExpansion.Checked; MosaSettings.TwoPassOptimization = cbEnableTwoPassOptimizations.Checked; diff --git a/Source/Mosa.Tool.Explorer/MainForm.resx b/Source/Mosa.Tool.Explorer/MainForm.resx index 37daeada8d..3d84ea4827 100644 --- a/Source/Mosa.Tool.Explorer/MainForm.resx +++ b/Source/Mosa.Tool.Explorer/MainForm.resx @@ -200,7 +200,7 @@ 17, 17 - 55 + 39 diff --git a/Source/Mosa.Tool.Launcher/MainWindow.axaml.cs b/Source/Mosa.Tool.Launcher/MainWindow.axaml.cs index 319d41bc85..a732c913a6 100644 --- a/Source/Mosa.Tool.Launcher/MainWindow.axaml.cs +++ b/Source/Mosa.Tool.Launcher/MainWindow.axaml.cs @@ -171,6 +171,7 @@ private void UpdateGuiSettings() TwoOptPass.IsChecked = MosaSettings.TwoPassOptimization; ValueNumOpts.IsChecked = MosaSettings.ValueNumbering; BtOpts.IsChecked = MosaSettings.BitTracker; + //BtOpts.IsChecked = MosaSettings.LoopRangeTracker; PlatOpts.IsChecked = MosaSettings.PlatformOptimizations; LicmOpts.IsChecked = MosaSettings.LoopInvariantCodeMotion; @@ -278,6 +279,7 @@ private void UpdateSettings() MosaSettings.TwoPassOptimization = TwoOptPass.IsChecked!.Value; MosaSettings.ValueNumbering = ValueNumOpts.IsChecked!.Value; MosaSettings.BitTracker = BtOpts.IsChecked!.Value; + MosaSettings.LoopRangeTracker = BtOpts.IsChecked!.Value; // until GUI updated MosaSettings.PlatformOptimizations = PlatOpts.IsChecked!.Value; MosaSettings.LoopInvariantCodeMotion = LicmOpts.IsChecked!.Value; diff --git a/Source/Mosa.UnitTests/Mosa.UnitTests.csproj b/Source/Mosa.UnitTests/Mosa.UnitTests.csproj index 62ebae4116..1d2672882b 100644 --- a/Source/Mosa.UnitTests/Mosa.UnitTests.csproj +++ b/Source/Mosa.UnitTests/Mosa.UnitTests.csproj @@ -3,7 +3,7 @@ - + diff --git a/Source/Mosa.UnitTests/Optimization/LoopStrengthReduction.cs b/Source/Mosa.UnitTests/Optimization/LoopStrengthReduction.cs index 778258e95a..d75e2a55ba 100644 --- a/Source/Mosa.UnitTests/Optimization/LoopStrengthReduction.cs +++ b/Source/Mosa.UnitTests/Optimization/LoopStrengthReduction.cs @@ -1,13 +1,10 @@ // Copyright (c) MOSA Project. Licensed under the New BSD License. -using System.Runtime.CompilerServices; - namespace Mosa.UnitTests.Optimization; public static class LoopStrengthReduction { - [MethodImpl(MethodImplOptions.NoInlining)] - public static int Reduction1(int[] n) + private static int Reduction1(int[] n) { var a = 0; @@ -19,8 +16,7 @@ public static int Reduction1(int[] n) return a; } - [MethodImpl(MethodImplOptions.NoInlining)] - public static int Reduction2(int[] n) + private static int Reduction2(int[] n) { var a = 0; @@ -32,7 +28,7 @@ public static int Reduction2(int[] n) return a; } - [MethodImpl(MethodImplOptions.NoInlining)] + [MosaUnitTest] public static int Reduction3() { var a = 8; @@ -50,7 +46,7 @@ public static int Reduction3() return a; } - [MethodImpl(MethodImplOptions.NoInlining)] + [MosaUnitTest] public static int Reduction4() { var a = 8; @@ -63,4 +59,154 @@ public static int Reduction4() return a; } + + [MosaUnitTest] + public static int Reduction5() + { + var a = 8; + var n = 10; + + for (var i = 0; i < n; i++) + { + a *= i; + } + + return a; + } + + [MosaUnitTest] + public static int Reduction6() + { + var a = 8; + var n = 10; + + for (var i = 0; i < n; i++) + { + a += i; + + if (i > 20) + return 0; + } + + 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() + { + var a = 8; + var n = 10; + + for (var i = n; i > 0; i--) + { + a *= i; + + if (i < 0) + return 0; + } + + return a; + } } diff --git a/Source/Mosa.UnitTests/Optimization/LoopUnrollingTests.cs b/Source/Mosa.UnitTests/Optimization/LoopUnrollingTests.cs index cbd5628357..3384e499fa 100644 --- a/Source/Mosa.UnitTests/Optimization/LoopUnrollingTests.cs +++ b/Source/Mosa.UnitTests/Optimization/LoopUnrollingTests.cs @@ -1,12 +1,10 @@ // Copyright (c) MOSA Project. Licensed under the New BSD License. -using System.Runtime.CompilerServices; - namespace Mosa.UnitTests.Optimization; public static class LoopUnrollingTests { - [MethodImpl(MethodImplOptions.NoInlining)] + [MosaUnitTest] public static int SimpleUnroll() { var v = 0; @@ -19,7 +17,7 @@ public static int SimpleUnroll() return v; } - [MethodImpl(MethodImplOptions.NoInlining)] + [MosaUnitTest(Series = "I4")] public static int SimpleUnroll2(int a) { var v = 0; diff --git a/Source/Mosa.Utility.Configuration/MOSASettings.cs b/Source/Mosa.Utility.Configuration/MOSASettings.cs index 750e9910b9..1faa758886 100644 --- a/Source/Mosa.Utility.Configuration/MOSASettings.cs +++ b/Source/Mosa.Utility.Configuration/MOSASettings.cs @@ -566,6 +566,12 @@ public bool BitTracker set => Settings.SetValue(Name.Optimizations_BitTracker, value); } + public bool LoopRangeTracker + { + get => Settings.GetValue(Name.Optimizations_LoopRangeTracker, true); + set => Settings.SetValue(Name.Optimizations_LoopRangeTracker, value); + } + public int OptimizationBasicWindow { get => Settings.GetValue(Name.Optimizations_Basic_Window, 5); @@ -763,6 +769,7 @@ public void SetDefaultSettings() SparseConditionalConstantPropagation = true; Devirtualization = true; BitTracker = true; + LoopRangeTracker = true; LoopInvariantCodeMotion = true; LongExpansion = true; TwoPassOptimization = true; diff --git a/Source/Mosa.Utility.Configuration/Name.cs b/Source/Mosa.Utility.Configuration/Name.cs index 0583958403..03ef8bae07 100644 --- a/Source/Mosa.Utility.Configuration/Name.cs +++ b/Source/Mosa.Utility.Configuration/Name.cs @@ -96,6 +96,7 @@ public static class Name public const string Optimizations_Basic = "Optimizations.Basic"; public const string Optimizations_Basic_Window = "Optimizations.Basic.Window"; public const string Optimizations_BitTracker = "Optimizations.BitTracker"; + public const string Optimizations_LoopRangeTracker = "Optimizations.LoopRangeTracker"; public const string Optimizations_Devirtualization = "Optimizations.Devirtualization"; public const string Optimizations_Inline = "Optimizations.Inline"; public const string Optimizations_Inline_Aggressive = "Optimizations.Inline.Aggressive";