Example #1
0
        protected void RemoveUseless(InstructionNode node)
        {
            if (node.StatusRegister == StatusRegister.Set)
            {
                return;
            }

            if (node.ResultCount != 1)
            {
                return;
            }

            if (node.Result.IsCPURegister)             /// same as if (!node.Result.IsVirtualRegister)
            {
                return;
            }

            if (node.Result.Uses.Count != 0)
            {
                return;
            }

            // Check is split child, if so check is parent in use (Manual.Return for example)
            if (node.Result.HasLongParent && node.Result.LongParent.Uses.Count != 0)
            {
                return;
            }

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

            node.Empty();
            changed = true;
            IRInstructionRemovedCount++;
        }
Example #2
0
        public void CallReg(InstructionNode node)
        {
            Debug.Assert(node.Operand1 != null);
            Debug.Assert(node.Operand1.IsCPURegister);

            var before = node.Previous;

            while (before.IsEmpty && !before.IsBlockStartInstruction)
            {
                before = before.Previous;
            }

            if (before == null || before.IsBlockStartInstruction)
            {
                return;
            }

            if (before.Instruction != X86.Mov32)
            {
                return;
            }

            if (!before.Result.IsCPURegister)
            {
                return;
            }

            if (node.Operand1.Register != before.Result.Register)
            {
                return;
            }

            before.SetInstruction(X86.Call, null, before.Operand1);
            node.Empty();
        }
Example #3
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="methodCompiler">The method compiler.</param>
        void IIntrinsicInternalMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            var result   = context.Result;
            var operand1 = context.Operand1;

            if (operand1.IsValueType)
            {
                InstructionNode def          = operand1.Definitions[0];
                var             replacements = new List <Tuple <InstructionNode, int> >();
                foreach (var use in operand1.Uses)
                {
                    for (int i = 0; i < use.OperandCount; i++)
                    {
                        if (use.GetOperand(i) == operand1)
                        {
                            replacements.Add(new Tuple <InstructionNode, int>(use, i));
                        }
                    }
                }

                foreach (var replace in replacements)
                {
                    replace.Item1.SetOperand(replace.Item2, def.Operand1);
                }

                operand1 = def.Operand1;
                def.Empty();
            }
            context.SetInstruction(IRInstruction.MoveInteger, result, operand1);
        }
        /// <summary>
        /// Simple copy propagation.
        /// </summary>
        /// <param name="node">The node.</param>
        protected void Move(InstructionNode node)
        {
            var result = node.Result;
            var source = node.Operand1;

            if (!result.IsVirtualRegister)
            {
                return;
            }

            if (!source.IsVirtualRegister)
            {
                return;
            }

            if (result.Definitions.Count != 1)
            {
                return;
            }

            if (source.Definitions.Count != 1)
            {
                return;
            }

            if (source.IsResolvedConstant)
            {
                return;
            }

            Debug.Assert(result != source);

            changed = true;

            //ReplaceOperand(result, source);
            foreach (var useNode in result.Uses.ToArray())
            {
                for (int i = 0; i < useNode.OperandCount; i++)
                {
                    var operand = useNode.GetOperand(i);

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

            Debug.Assert(result.Uses.Count == 0);

            trace?.Log($"REMOVED:\t{node}");
            node.Empty();
            IRInstructionRemovedCount++;
        }
Example #5
0
        private bool SimplePhiUpdate(InstructionNode node)
        {
            // Experiment
            var result = node.Result;

            if (result.Definitions.Count != 1)
            {
                return(false);
            }

            for (int i = 0; i < node.OperandCount; i++)
            {
                var operand = node.GetOperand(i);

                if (operand.IsConstant)
                {
                    continue;
                }

                if (operand.Definitions.Count != 1)
                {
                    return(false);
                }

                if (!operand.IsVirtualRegister)
                {
                    return(false);
                }

                if (operand.Definitions[0].Block != node.PhiBlocks[i])
                {
                    return(false);
                }
            }

            for (int i = 0; i < node.OperandCount; i++)
            {
                var operand = node.GetOperand(i);

                if (operand.IsVirtualRegister)
                {
                    operand.Definitions[0].Result = result;

                    ReplaceOperand(operand, result);
                }
                else
                {
                    InsertCopyStatement(node.PhiBlocks[i], result, operand);
                }
            }

            node.Empty();

            return(true);
        }
Example #6
0
        /// <summary>
        /// Processes the phi instruction.
        /// </summary>
        /// <param name="node">The context.</param>
        private void ProcessPhiInstruction(InstructionNode node)
        {
            var sourceBlocks = node.PhiBlocks;

            for (var index = 0; index < node.Block.PreviousBlocks.Count; index++)
            {
                var operand     = node.GetOperand(index);
                var predecessor = sourceBlocks[index];

                InsertCopyStatement(predecessor, node.Result, operand);
            }

            node.Empty();
        }
        protected void RemoveUseless(InstructionNode node)
        {
            // Remove instruction, if useless
            if (node.ResultCount == 1 && node.Result.Uses.Count == 0 && node.Result.IsVirtualRegister)
            {
                // Check is split child, if so check is parent in use (IR.Return for example)
                if (node.Result.HasLongParent && node.Result.LongParent.Uses.Count != 0)
                {
                    return;
                }

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

                node.Empty();
                changed = true;
                IRInstructionRemovedCount++;
            }
        }
        private void RemoveUseless(InstructionNode node)
        {
            // Remove useless instructions
            if (node.ResultCount == 1 && node.Result.Uses.Count == 0 && node.Result.IsVirtualRegister)
            {
                // Check is split child, if so check is parent in use (IR.Return for example)
                if (node.Result.IsSplitChild && node.Result.SplitParent.Uses.Count != 0)
                {
                    return;
                }

                if (trace.Active)
                {
                    trace.Log("REMOVED:\t" + node);
                }

                node.Empty();
                changed = true;
                instructionsRemovedCount++;
            }
        }
        /// <summary>
        /// Simple copy propagation.
        /// </summary>
        /// <param name="node">The node.</param>
        private void Move(InstructionNode node)
        {
            Debug.Assert(node.Instruction == X86.Mov32);

            var result = node.Result;
            var source = node.Operand1;

            if (!result.IsVirtualRegister)
            {
                return;
            }

            if (!source.IsVirtualRegister)
            {
                return;
            }

            if (result.Definitions.Count != 1)
            {
                return;
            }

            if (source.Definitions.Count != 1)
            {
                return;
            }

            if (source.IsResolvedConstant)
            {
                return;
            }

            Debug.Assert(result != source);

            changed = true;

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

                    if (result == operand)
                    {
                        if (trace.Active)
                        {
                            trace.Log("*** SimpleForwardCopyPropagation");
                        }
                        if (trace.Active)
                        {
                            trace.Log("BEFORE:\t" + useNode);
                        }
                        useNode.SetOperand(i, source);
                        if (trace.Active)
                        {
                            trace.Log("AFTER: \t" + useNode);
                        }
                    }
                }
            }

            Debug.Assert(result.Uses.Count == 0);

            if (trace.Active)
            {
                trace.Log("REMOVED:\t" + node);
            }
            node.Empty();
            IRInstructionRemovedCount++;
        }
        private void ProcessInstruction(InstructionNode node)
        {
            if (node.Instruction == IRInstruction.Load)
            {
                if (node.MosaType != null &&
                    TypeLayout.IsCompoundType(node.MosaType) && !node.MosaType.IsUI8 && !node.MosaType.IsR8)
                {
                    if (node.Result.IsVirtualRegister && !repl.ContainsKey(node.Result))
                    {
                        repl[node.Result] = MethodCompiler.StackLayout.AddStackLocal(node.MosaType);
                    }
                    node.ReplaceInstructionOnly(IRInstruction.CompoundLoad);
                }
            }
            else if (node.Instruction == IRInstruction.Store)
            {
                if (node.MosaType != null &&
                    TypeLayout.IsCompoundType(node.MosaType) && !node.MosaType.IsUI8 && !node.MosaType.IsR8)
                {
                    if (node.Operand3.IsVirtualRegister && !repl.ContainsKey(node.Operand3))
                    {
                        repl[node.Operand3] = MethodCompiler.StackLayout.AddStackLocal(node.MosaType);
                    }
                    node.ReplaceInstructionOnly(IRInstruction.CompoundStore);
                }
            }
            else if (node.Instruction == IRInstruction.Move)
            {
                if (node.Result.Type.Equals(node.Operand1.Type) &&
                    TypeLayout.IsCompoundType(node.Result.Type) && !node.Result.Type.IsUI8 && !node.Result.Type.IsR8)
                {
                    // If this move is proceded by a return then remove this instruction
                    // It is basically a double up caused by some instructions result in the same instruction output
                    if (node.Next.Instruction == IRInstruction.Return && node.Next.Operand1 == node.Result)
                    {
                        node.Next.Operand1 = node.Operand1;

                        var nopNode = new InstructionNode(IRInstruction.Nop);
                        node.Previous.Insert(nopNode);

                        node.Empty();
                        return;
                    }

                    // If this move is preceded by a compound move (which will turn into a compound move) remove this instruction
                    // It is basically a double up caused by some instructions result in the same IR output
                    if ((node.Previous.Instruction == IRInstruction.CompoundMove ||
                         node.Previous.Instruction == IRInstruction.CompoundLoad ||
                         node.Previous.Instruction == IRInstruction.Call) &&
                        node.Previous.Result == node.Operand1)
                    {
                        if (repl.ContainsKey(node.Previous.Result))
                        {
                            repl[node.Result] = repl[node.Previous.Result];
                            repl.Remove(node.Previous.Result);
                        }
                        node.Previous.Result = node.Result;

                        var nopNode = new InstructionNode(IRInstruction.Nop);
                        node.Previous.Insert(nopNode);

                        node.Empty();
                        return;
                    }

                    if (node.Result.IsVirtualRegister && !repl.ContainsKey(node.Result))
                    {
                        repl[node.Result] = MethodCompiler.StackLayout.AddStackLocal(node.Result.Type);
                    }
                    if (node.Operand1.IsVirtualRegister && !repl.ContainsKey(node.Operand1))
                    {
                        repl[node.Operand1] = MethodCompiler.StackLayout.AddStackLocal(node.Operand1.Type);
                    }
                    node.ReplaceInstructionOnly(IRInstruction.CompoundMove);
                }
            }
            else if (node.Instruction == IRInstruction.Call)
            {
                if (node.Result != null &&
                    TypeLayout.IsCompoundType(node.Result.Type) && !node.Result.Type.IsUI8 && !node.Result.Type.IsR8)
                {
                    if (node.Result.IsVirtualRegister && !repl.ContainsKey(node.Result))
                    {
                        repl[node.Result] = MethodCompiler.StackLayout.AddStackLocal(node.Result.Type);
                    }
                }
            }
        }
Example #11
0
 private static void Empty(InstructionNode node)
 {
     node.Empty();
 }
        private void ProcessInstruction(InstructionNode node)
        {
            if (node.Instruction == IRInstruction.Load)
            {
                if (node.MosaType != null && TypeLayout.IsCompoundType(node.MosaType))
                {
                    if (node.Result.IsVirtualRegister && !repl.ContainsKey(node.Result))
                    {
                        repl[node.Result] = MethodCompiler.StackLayout.AddStackLocal(node.MosaType);
                    }
                    node.ReplaceInstructionOnly(IRInstruction.CompoundLoad);
                }
            }
            else if (node.Instruction == IRInstruction.Store)
            {
                if (node.MosaType != null && TypeLayout.IsCompoundType(node.MosaType))
                {
                    if (node.Operand3.IsVirtualRegister && !repl.ContainsKey(node.Operand3))
                    {
                        repl[node.Operand3] = MethodCompiler.StackLayout.AddStackLocal(node.MosaType);
                    }
                    node.ReplaceInstructionOnly(IRInstruction.CompoundStore);
                }
            }
            else if (node.Instruction == IRInstruction.Move)
            {
                if (node.Result.Type.Equals(node.Operand1.Type) && TypeLayout.IsCompoundType(node.Result.Type))
                {
                    var prevNode = node.Previous;
                    var nextNode = node.Next;
                    while (prevNode.IsEmpty)
                        prevNode = prevNode.Previous;
                    while (nextNode.IsEmpty)
                        nextNode = nextNode.Next;

                    // If this move is proceeded by a return then remove this instruction
                    // It is basically a double up caused by some instructions result in the same instruction output
                    if (nextNode.Instruction == IRInstruction.Return && nextNode.Operand1 == node.Result)
                    {
                        nextNode.Operand1 = node.Operand1;

                        node.Empty();
                        return;
                    }

                    // If this move is preceded by a compound move (which will turn into a compound move) remove this instruction
                    // It is basically a double up caused by some instructions result in the same IR output
                    if ((prevNode.Instruction == IRInstruction.CompoundMove
                            || prevNode.Instruction == IRInstruction.CompoundLoad
                            || prevNode.Instruction == IRInstruction.Call)
                        && prevNode.Result == node.Operand1)
                    {
                        if (repl.ContainsKey(prevNode.Result))
                            repl[node.Result] = repl[prevNode.Result];
                        prevNode.Result = node.Result;

                        node.Empty();
                        return;
                    }

                    if (node.Result.IsVirtualRegister && !repl.ContainsKey(node.Result))
                    {
                        repl[node.Result] = MethodCompiler.StackLayout.AddStackLocal(node.Result.Type);
                    }
                    if (node.Operand1.IsVirtualRegister && !repl.ContainsKey(node.Operand1))
                    {
                        repl[node.Operand1] = MethodCompiler.StackLayout.AddStackLocal(node.Operand1.Type);
                    }
                    node.ReplaceInstructionOnly(IRInstruction.CompoundMove);
                }
                else if (node.Result.Type.Equals(node.Operand1.Type) && node.Result.IsStackLocal && node.Operand1.IsStackLocal)
                {
                    node.ReplaceInstructionOnly(IRInstruction.CompoundMove);
                }
            }
            else if (node.Instruction == IRInstruction.Call)
            {
                if (node.Result != null && TypeLayout.IsCompoundType(node.Result.Type))
                {
                    if (node.Result.IsVirtualRegister && !repl.ContainsKey(node.Result))
                    {
                        repl[node.Result] = MethodCompiler.StackLayout.AddStackLocal(node.Result.Type);
                    }
                }
            }
        }
Example #13
0
 private static void Empty(InstructionNode node)
 {
     node.Empty();
 }