Ejemplo n.º 1
0
        private void OptimizePhi(InstructionNode node)
        {
            var newInstruction = BuiltInOptimizations.PhiSimplication(node);

            if (newInstruction != null)
            {
                node.SetInstruction(newInstruction);
            }
        }
Ejemplo n.º 2
0
        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;
            }

            trace = CreateTraceLog(5);

            var change = true;

            while (change)
            {
                change = false;

                foreach (var virtualRegister in MethodCompiler.VirtualRegisters)
                {
                    if (!ValidateSSAForm(virtualRegister))
                    {
                        continue;
                    }

                    var node = virtualRegister.Definitions[0];

                    if ((node.Instruction == IRInstruction.MoveInt32 ||
                         node.Instruction == IRInstruction.MoveInt64) &&
                        node.Operand1.IsResolvedConstant)
                    {
                        // Propagate Constant

                        var source = node.Operand1;

                        // for each statement T that uses operand, substituted c in statement T
                        foreach (var useNode in virtualRegister.Uses.ToArray())
                        {
                            for (int i = 0; i < useNode.OperandCount; i++)
                            {
                                var operand = useNode.GetOperand(i);

                                if (operand == virtualRegister)
                                {
                                    trace?.Log("*** PropagateConstant");
                                    trace?.Log($"BEFORE:\t{useNode}");

                                    useNode.SetOperand(i, source);
                                    trace?.Log($"AFTER: \t{useNode}");
                                }
                            }
                        }

                        change = true;
                        PropagateConstantCount.Increment();
                    }
                    else if ((node.Instruction == IRInstruction.MoveInt32 ||
                              node.Instruction == IRInstruction.MoveInt64 ||
                              node.Instruction == IRInstruction.MoveFloatR4 ||
                              node.Instruction == IRInstruction.MoveFloatR8) &&
                             node.Operand1.IsVirtualRegister &&
                             ValidateSSAForm(node.Operand1))
                    {
                        //  Propagate Move Value

                        var source = node.Operand1;

                        foreach (var useNode in virtualRegister.Uses.ToArray())
                        {
                            for (int i = 0; i < useNode.OperandCount; i++)
                            {
                                var operand = useNode.GetOperand(i);

                                if (virtualRegister == operand)
                                {
                                    trace?.Log("*** PropagateMove");
                                    trace?.Log($"BEFORE:\t{useNode}");
                                    useNode.SetOperand(i, source);
                                    trace?.Log($"AFTER: \t{useNode}");
                                }
                            }
                        }

                        change = true;
                    }

                    if (BuiltInOptimizations.IsDeadCode(node))
                    {
                        // Remove Dead Code

                        trace?.Log("*** DeadCode");
                        trace?.Log($"REMOVED:\t{node}");

                        node.SetInstruction(IRInstruction.Nop);
                        DeadCodeEliminationCount.Increment();
                        InstructionsRemovedCount.Increment();
                        continue;
                    }
                }
            }
        }
Ejemplo n.º 3
0
        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.IsEmpty)
                {
                    continue;
                }

                if (node.Instruction == IRInstruction.Phi)
                {
                    // 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);

                var newInstruction = BuiltInOptimizations.DeadCodeElimination(node);
                if (newInstruction != null)
                {
                    node.SetInstruction(newInstruction);
                    DeadCodeEliminationCount++;
                    InstructionRemovalCount++;
                    continue;
                }

                newInstruction = BuiltInOptimizations.StrengthReduction(node)
                                 ?? BuiltInOptimizations.Simplification(node);

                if (newInstruction != null)
                {
                    node.SetInstruction(newInstruction);
                    StrengthReductionAndSimplificationCount++;
                }

                // 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.MoveInt32 ||
                    node.Instruction == IRInstruction.MoveInt64 ||
                    node.Instruction == IRInstruction.MoveFloatR4 ||
                    node.Instruction == IRInstruction.MoveFloatR8)
                {
                    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;
                }

                // Simplify expression: constant folding & strength reduction
                var newOperand = BuiltInOptimizations.ConstantFoldingAndStrengthReductionIntegerToOperand(node);

                if (newOperand != null)
                {
                    Debug.Assert(newOperand != node.Result);

                    SetValueNumber(node.Result, newOperand);
                    node.SetInstruction(IRInstruction.Nop);
                    ConstantFoldingAndStrengthReductionCount++;
                    InstructionRemovalCount++;
                    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);
                        }
                    }
                }
            }
        }