private void OutputDiagram()
        {
            var trace = CreateTraceLog("Diagram");
            var sb    = new StringBuilder();

            trace.Log("digraph blocks {");

            foreach (var headBlock in BasicBlocks.HeadBlocks)
            {
                var dominance = new SimpleFastDominance(BasicBlocks, headBlock);

                for (int i = 0; i < BasicBlocks.Count; i++)
                {
                    var block = BasicBlocks[i];

                    var children = dominance.GetChildren(block);
                    if (children != null && children.Count != 0)
                    {
                        foreach (var child in children)
                        {
                            trace.Log("\t" + block + " -> " + child);
                        }
                    }
                }
            }

            trace.Log("}");
        }
示例#2
0
        /// <summary>
        /// Renames the variables.
        /// </summary>
        /// <param name="headBlock">The head block.</param>
        /// <param name="dominanceAnalysis">The dominance analysis.</param>
        private void RenameVariables(BasicBlock headBlock, SimpleFastDominance dominanceAnalysis)
        {
            var worklist = new Stack <BasicBlock>();

            worklist.Push(headBlock);

            while (worklist.Count != 0)
            {
                var block = worklist.Pop();

                if (block != null)
                {
                    if (trace.Active)
                    {
                        trace.Log("Processing: " + block);
                    }

                    UpdateOperands(block);
                    UpdatePHIs(block);

                    worklist.Push(block);
                    worklist.Push(null);

                    if (trace.Active)
                    {
                        trace.Log("  >Pushed: " + block + " (Return)");
                    }

                    // Repeat for all children of the dominance block, if any
                    var children = dominanceAnalysis.GetChildren(block);
                    if (children != null && children.Count > 0)
                    {
                        foreach (var s in children)
                        {
                            worklist.Push(s);

                            if (trace.Active)
                            {
                                trace.Log("  >Pushed: " + s);
                            }
                        }
                    }
                }
                else
                {
                    block = worklist.Pop();

                    if (trace.Active)
                    {
                        trace.Log("Processing: " + block + " (Back)");
                    }
                    UpdateResultOperands(block);
                }
            }
        }
示例#3
0
        /// <summary>
        /// Renames the variables.
        /// </summary>
        /// <param name="block">The block.</param>
        /// <param name="dominanceAnalysis">The dominance analysis.</param>
        private void RenameVariables2(BasicBlock block, SimpleFastDominance dominanceAnalysis)
        {
            trace?.Log($"Processing: {block}");

            UpdateOperands(block);
            UpdatePHIs(block);

            // Repeat for all children of the dominance block, if any
            var children = dominanceAnalysis.GetChildren(block);

            if (children != null && children.Count != 0)
            {
                foreach (var s in children)
                {
                    RenameVariables2(s, dominanceAnalysis);
                }
            }

            UpdateResultOperands(block);
        }
        private void OutputList()
        {
            var trace = CreateTraceLog("List");
            var sb    = new StringBuilder();

            foreach (var headBlock in BasicBlocks.HeadBlocks)
            {
                trace.Log("Head: " + headBlock);
                var dominance = new SimpleFastDominance(BasicBlocks, headBlock);

                for (int i = 0; i < BasicBlocks.Count; i++)
                {
                    var block = BasicBlocks[i];

                    sb.Clear();
                    sb.Append("  Block ");
                    sb.Append(block);
                    sb.Append(" : ");

                    var children = dominance.GetChildren(block);

                    if (children != null && children.Count != 0)
                    {
                        foreach (var child in children)
                        {
                            sb.Append(child);
                            sb.Append(", ");
                        }

                        sb.Length -= 2;
                    }

                    trace.Log(sb.ToString());
                }

                trace.Log();
            }
        }
        private void ValueNumber(BasicBlock block, out List <BasicBlock> nextblocks, out List <Expression> newExpressions)
        {
            trace?.Log($"Processing Block: {block}");

            //Debug.Assert(!Processed.Get(block.Sequence));

            newExpressions = null;
            nextblocks     = null;

            // Mark the beginning of the new scope by keeping a list
            bool successorValidated = false;
            bool successorProcessed = true;

            Processed.Set(block.Sequence, true);

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

                if (IsPhiInstruction(node.Instruction))
                {
                    // Validate all successor are already processed
                    // and if not, just set the value number
                    if (!successorValidated)
                    {
                        successorValidated = true;
                        foreach (var processed in block.PreviousBlocks)
                        {
                            if (!Processed.Get(block.Sequence))
                            {
                                successorProcessed = false;
                                break;
                            }
                        }
                    }

                    if (successorValidated && !successorProcessed)
                    {
                        SetValueNumber(node.Result, node.Result);
                        continue;
                    }

                    // check for useless
                    if (IsPhiUseless(node))
                    {
                        var w = GetValueNumber(node.Operand1);
                        SetValueNumber(node.Result, w);

                        trace?.Log($"Removed Unless PHI: {node}");

                        node.SetInstruction(IRInstruction.Nop);
                        InstructionRemovalCount++;
                        continue;
                    }

                    // check for redundant
                    var redundant = CheckRedundant(node);

                    if (redundant != null)
                    {
                        var w = GetValueNumber(redundant);
                        SetValueNumber(node.Result, w);

                        trace?.Log($"Removed Redundant PHI: {node}");

                        node.SetInstruction(IRInstruction.Nop);
                        InstructionRemovalCount++;
                        continue;
                    }

                    SetValueNumber(node.Result, node.Result);

                    continue;
                }

                UpdateNodeWithValueNumbers(node);

                // move constant to right for commutative operations - helpful later
                if (node.Instruction.IsCommutative && node.Operand1.IsResolvedConstant && node.Operand2.IsVirtualRegister)
                {
                    var operand1 = node.Operand1;
                    node.Operand1 = node.Operand2;
                    node.Operand2 = operand1;
                }

                if (node.Instruction == IRInstruction.Move32 ||
                    node.Instruction == IRInstruction.Move64 ||
                    node.Instruction == IRInstruction.MoveR4 ||
                    node.Instruction == IRInstruction.MoveR8)
                {
                    if (node.Result.IsCPURegister || node.Operand1.IsCPURegister)
                    {
                        SetValueNumber(node.Result, node.Result);
                        continue;
                    }

                    // FUTURE: The check for IsSymbol (unresolved constant) should not be necessary
                    if (node.Operand1.IsStackLocal || node.Operand1.IsOnStack || node.Operand1.IsSymbol)
                    {
                        SetValueNumber(node.Result, node.Result);
                        continue;
                    }

                    SetValueNumber(node.Result, node.Operand1);
                    node.SetInstruction(IRInstruction.Nop);
                    InstructionRemovalCount++;
                    continue;
                }

                if (!CanAssignValueNumberToExpression(node))
                {
                    if (node.ResultCount == 1)
                    {
                        SetValueNumber(node.Result, node.Result);
                    }
                    else if (node.ResultCount == 2)
                    {
                        SetValueNumber(node.Result, node.Result);
                        SetValueNumber(node.Result2, node.Result2);
                    }

                    continue;
                }

                var hash  = ComputeExpressionHash(node);
                var list  = GetExpressionsByHash(hash);
                var match = FindMatch(list, node);

                if (match != null)
                {
                    var w = GetValueNumber(match.ValueNumber);

                    trace?.Log($"Found Expression Match: {node}");

                    SetValueNumber(node.Result, w);

                    if (node.Instruction.IsParameterLoad)
                    {
                        ParameterLoadEliminationCount++;
                    }

                    node.SetInstruction(IRInstruction.Nop);
                    InstructionRemovalCount++;
                    SubexpressionEliminationCount++;
                    continue;
                }
                else
                {
                    trace?.Log($"No Expression Found: {node}");
                }

                var newExpression = new Expression()
                {
                    Hash        = hash,
                    Instruction = node.Instruction,
                    Operand1    = node.Operand1,
                    Operand2    = node.Operand2,
                    ValueNumber = node.Result
                };

                AddExpressionToHashTable(newExpression);

                Debug.Assert(FindMatch(GetExpressionsByHash(ComputeExpressionHash(node)), node) == newExpression);

                (newExpressions ?? (newExpressions = new List <Expression>())).Add(newExpression);

                if (node.Instruction.IsCommutative && node.Operand1 != node.Operand2)
                {
                    var newExpression2 = new Expression()
                    {
                        Hash        = hash,
                        Instruction = node.Instruction,
                        Operand1    = node.Operand2,
                        Operand2    = node.Operand1,
                        ValueNumber = node.Result
                    };

                    AddExpressionToHashTable(newExpression2);
                    newExpressions.Add(newExpression2);
                }

                SetValueNumber(node.Result, node.Result);
            }

            // For each successor of the block, adjust the φ-function inputs
            UpdatePhiSuccesors(block);

            var children = AnalysisDominance.GetChildren(block);

            if (children != null || children.Count == 0)
            {
                nextblocks = new List <BasicBlock>(children.Capacity);

                if (children.Count == 1)
                {
                    // Efficient!
                    nextblocks.Add(children[0]);

                    //trace?.Log("Queue Block:" + children[0]);
                }
                else if (ReversePostOrder.Count < 32)
                {
                    // Efficient for small sets
                    foreach (var child in ReversePostOrder)
                    {
                        if (children.Contains(child))
                        {
                            nextblocks.Add(child);

                            //trace?.Log("Queue Block:" + child);
                        }
                    }
                }
                else
                {
                    // Scalable for large sets
                    var bitArray = new BitArray(BasicBlocks.Count, false);

                    foreach (var child in children)
                    {
                        bitArray.Set(child.Sequence, true);
                    }

                    foreach (var child in ReversePostOrder)
                    {
                        if (bitArray.Get(child.Sequence))
                        {
                            nextblocks.Add(child);

                            //trace?.Log("Queue Block:" + child);
                        }
                    }
                }
            }
        }