/// <summary>
        /// Simplifies sign/zero extended move
        /// </summary>
        /// <param name="node">The node.</param>
        private void SimplifyExtendedMove(InstructionNode node)
        {
            if (node.IsEmpty)
                return;

            if (!(node.Instruction == IRInstruction.ZeroExtendedMove || node.Instruction == IRInstruction.SignExtendedMove))
                return;

            if (!node.Result.IsVirtualRegister || !node.Operand1.IsVirtualRegister)
                return;

            if (!((NativePointerSize == 4 && node.Result.IsInt && (node.Operand1.IsInt || node.Operand1.IsU || node.Operand1.IsI)) ||
                (NativePointerSize == 4 && node.Operand1.IsInt && (node.Result.IsInt || node.Result.IsU || node.Result.IsI)) ||
                (NativePointerSize == 8 && node.Result.IsLong && (node.Operand1.IsLong || node.Operand1.IsU || node.Operand1.IsI)) ||
                (NativePointerSize == 8 && node.Operand1.IsLong && (node.Result.IsLong || node.Result.IsU || node.Result.IsI))))
                return;

            AddOperandUsageToWorkList(node);
            if (trace.Active) trace.Log("*** SimplifyExtendedMove");
            if (trace.Active) trace.Log("BEFORE:\t" + node.ToString());
            node.SetInstruction(IRInstruction.Move, node.Result, node.Operand1);
            simplifyExtendedMoveCount++;
            if (trace.Active) trace.Log("AFTER: \t" + node.ToString());
            changeCount++;
        }
Exemplo n.º 2
0
 private void Break(InstructionNode node)
 {
     node.SetInstruction(X86.Break);
 }
Exemplo n.º 3
0
        /// <summary>
        /// Strength reduction for division when one of the constants is zero or one
        /// </summary>
        /// <param name="node">The node.</param>
        private void ArithmeticSimplificationDivision(InstructionNode node)
        {
            if (!(node.Instruction == IRInstruction.DivSigned || node.Instruction == IRInstruction.DivUnsigned))
                return;

            if (!node.Result.IsVirtualRegister)
                return;

            Operand result = node.Result;
            Operand op1 = node.Operand1;
            Operand op2 = node.Operand2;

            if (!op2.IsResolvedConstant || op2.IsConstantZero)
            {
                // Possible divide by zero
                return;
            }

            if (op1.IsResolvedConstant && op1.IsConstantZero)
            {
                AddOperandUsageToWorkList(node);
                if (trace.Active) trace.Log("*** ArithmeticSimplificationDivision");
                if (trace.Active) trace.Log("BEFORE:\t" + node.ToString());
                node.SetInstruction(IRInstruction.MoveInteger, result, ConstantZero);
                arithmeticSimplificationDivisionCount++;
                changeCount++;
                if (trace.Active) trace.Log("AFTER: \t" + node.ToString());
                return;
            }

            if (op2.IsResolvedConstant && op2.IsConstantOne)
            {
                AddOperandUsageToWorkList(node);
                if (trace.Active) trace.Log("*** ArithmeticSimplificationDivision");
                if (trace.Active) trace.Log("BEFORE:\t" + node.ToString());
                node.SetInstruction(IRInstruction.MoveInteger, result, op1);
                arithmeticSimplificationDivisionCount++;
                changeCount++;
                if (trace.Active) trace.Log("AFTER: \t" + node.ToString());
                return;
            }

            if (node.Instruction == IRInstruction.DivUnsigned && IsPowerOfTwo(op2.ConstantUnsignedLongInteger))
            {
                int shift = GetPowerOfTwo(op2.ConstantUnsignedLongInteger);

                if (shift < 32)
                {
                    AddOperandUsageToWorkList(node);
                    if (trace.Active) trace.Log("*** ArithmeticSimplificationDivision");
                    if (trace.Active) trace.Log("BEFORE:\t" + node.ToString());
                    node.SetInstruction(IRInstruction.ShiftRight, result, op1, Operand.CreateConstant(TypeSystem, (int)shift));
                    arithmeticSimplificationDivisionCount++;
                    changeCount++;
                    if (trace.Active) trace.Log("AFTER: \t" + node.ToString());
                    return;
                }
            }
        }
 /// <summary>
 /// Decodes the specified instruction.
 /// </summary>
 /// <param name="ctx">The context.</param>
 /// <param name="decoder">The instruction decoder, which holds the code stream.</param>
 public virtual void Decode(InstructionNode ctx, IInstructionDecoder decoder)
 {
     ctx.SetInstruction(this, DefaultOperandCount, DefaultResultCount);
 }
 private void StoreFloatR8(InstructionNode node)
 {
     node.SetInstruction(X86.MovsdStore, null, node.Operand1, node.Operand2, node.Operand3);
 }
        /// <summary>
        /// Strength reduction shift operators.
        /// </summary>
        /// <param name="node">The node.</param>
        private void ArithmeticSimplificationShiftOperators(InstructionNode node)
        {
            if (node.IsEmpty)
                return;

            if (!(node.Instruction == IRInstruction.ShiftLeft || node.Instruction == IRInstruction.ShiftRight || node.Instruction == IRInstruction.ArithmeticShiftRight))
                return;

            if (!node.Result.IsVirtualRegister)
                return;

            if (!node.Operand2.IsConstant)
                return;

            Operand result = node.Result;
            Operand op1 = node.Operand1;
            Operand op2 = node.Operand2;

            if (op2.IsConstantZero || op1.IsConstantZero)
            {
                AddOperandUsageToWorkList(node);
                if (trace.Active) trace.Log("*** ArithmeticSimplificationShiftOperators");
                if (trace.Active) trace.Log("BEFORE:\t" + node.ToString());
                node.SetInstruction(IRInstruction.Move, result, op1);
                arithmeticSimplificationShiftOperators++;
                changeCount++;
                if (trace.Active) trace.Log("AFTER: \t" + node.ToString());
                return;
            }
        }
Exemplo n.º 7
0
        private void LoadParameterFloatR4(InstructionNode node)
        {
            Debug.Assert(node.Result.IsR4);

            node.SetInstruction(X86.MovssLoad, node.Size, node.Result, StackFrame, node.Operand1);
        }
Exemplo n.º 8
0
 private void LoadParamZeroExtend8x32(InstructionNode node)
 {
     node.SetInstruction(X86.MovzxLoad8, node.Result, StackFrame, node.Operand1);
 }
Exemplo n.º 9
0
 private void LogicalNot32(InstructionNode node)
 {
     node.SetInstruction(X86.Not32, node.Result, node.Operand1);
 }
Exemplo n.º 10
0
 private void BitCopyInt32ToFloatR4(InstructionNode node)
 {
     node.SetInstruction(X86.Movd, node.Result, node.Operand1);
 }
Exemplo n.º 11
0
 private void LoadParamSignExtend16x32(InstructionNode node)
 {
     node.SetInstruction(X86.MovsxLoad16, node.Result, StackFrame, node.Operand1);
 }
Exemplo n.º 12
0
 private void LogicalNot64(InstructionNode node)
 {
     node.SetInstruction(X64.Mov64, node.Result, node.Operand1);
 }
Exemplo n.º 13
0
        /// <summary>
        /// Arithmetics the simplification rem unsigned modulus.
        /// </summary>
        /// <param name="node">The node.</param>
        private void ArithmeticSimplificationRemUnsignedModulus(InstructionNode node)
        {
            if (node.IsEmpty)
                return;

            if (!(node.Instruction == IRInstruction.RemUnsigned))
                return;

            if (!node.Result.IsVirtualRegister)
                return;

            if (!node.Operand2.IsConstant)
                return;

            if (node.Operand2.ConstantUnsignedLongInteger == 0)
                return;

            if (!IsPowerOfTwo(node.Operand2.ConstantUnsignedLongInteger))
                return;

            Operand result = node.Result;
            Operand op1 = node.Operand1;
            Operand op2 = node.Operand2;

            if (op2.ConstantUnsignedLongInteger == 0)
            {
                AddOperandUsageToWorkList(node);
                if (trace.Active) trace.Log("*** ArithmeticSimplificationRemUnsignedModulus");
                if (trace.Active) trace.Log("BEFORE:\t" + node.ToString());
                node.SetInstruction(IRInstruction.Move, result, Operand.CreateConstant(TypeSystem, 0));
                arithmeticSimplificationModulus++;
                changeCount++;
                if (trace.Active) trace.Log("AFTER: \t" + node.ToString());
                return;
            }

            int power = GetPowerOfTwo(op2.ConstantUnsignedLongInteger);

            var mask = (1 << power) - 1;

            var constant = Operand.CreateConstant(TypeSystem, mask);

            AddOperandUsageToWorkList(node);
            if (trace.Active) trace.Log("*** ArithmeticSimplificationRemUnsignedModulus");
            if (trace.Active) trace.Log("BEFORE:\t" + node.ToString());
            node.SetInstruction(IRInstruction.LogicalAnd, result, op1, constant);
            arithmeticSimplificationModulus++;
            changeCount++;
            if (trace.Active) trace.Log("AFTER: \t" + node.ToString());
            return;
        }
Exemplo n.º 14
0
        /// <summary>
        /// Arithmetics the simplification rem signed modulus.
        /// </summary>
        /// <param name="node">The node.</param>
        private void ArithmeticSimplificationRemSignedModulus(InstructionNode node)
        {
            if (node.IsEmpty)
                return;

            if (!(node.Instruction == IRInstruction.RemSigned))
                return;

            if (!node.Result.IsVirtualRegister)
                return;

            if (!node.Operand2.IsConstant)
                return;

            if (node.Operand2.ConstantUnsignedLongInteger != 1)
                return;

            Operand result = node.Result;
            Operand op1 = node.Operand1;
            Operand op2 = node.Operand2;

            AddOperandUsageToWorkList(node);
            if (trace.Active) trace.Log("*** ArithmeticSimplificationRemSignedModulus");
            if (trace.Active) trace.Log("BEFORE:\t" + node.ToString());
            node.SetInstruction(IRInstruction.Move, result, Operand.CreateConstant(TypeSystem, 0));
            arithmeticSimplificationModulus++;
            changeCount++;
            if (trace.Active) trace.Log("AFTER: \t" + node.ToString());
            return;
        }
        /// <summary>
        /// Simplifies the phi.
        /// </summary>
        /// <param name="node">The node.</param>
        private void SimplifyPhi(InstructionNode node)
        {
            if (node.IsEmpty)
                return;

            if (node.Instruction != IRInstruction.Phi)
                return;

            if (node.OperandCount != 1)
                return;

            if (node.Result.Definitions.Count != 1)
                return;

            if (trace.Active) trace.Log("*** SimplifyPhiInstruction");
            if (trace.Active) trace.Log("BEFORE:\t" + node.ToString());
            AddOperandUsageToWorkList(node);
            node.SetInstruction(IRInstruction.Move, node.Result, node.Operand1);
            if (trace.Active) trace.Log("AFTER: \t" + node.ToString());
            simplifyPhiCount++;
            changeCount++;
        }
Exemplo n.º 16
0
        protected void Inline(InstructionNode callNode, BasicBlocks blocks)
        {
            var mapBlocks = new Dictionary<BasicBlock, BasicBlock>(blocks.Count);
            var map = new Dictionary<Operand, Operand>();

            var nextBlock = Split(callNode);

            // create basic blocks
            foreach (var block in blocks)
            {
                var newBlock = CreateNewBlock();
                mapBlocks.Add(block, newBlock);
            }

            // copy instructions
            foreach (var block in blocks)
            {
                var newBlock = mapBlocks[block];

                for (var node = block.First.Next; !node.IsBlockEndInstruction; node = node.Next)
                {
                    if (node.IsEmpty)
                        continue;

                    if (node.Instruction == IRInstruction.Prologue)
                        continue;

                    if (node.Instruction == IRInstruction.Epilogue)
                        continue;

                    if (node.Instruction == IRInstruction.Return)
                    {
                        if (callNode.Result != null)
                        {
                            var newOp = Map(node.Operand1, map, callNode);
                            newBlock.BeforeLast.Insert(new InstructionNode(IRInstruction.Move, callNode.Result, newOp));
                        }
                        newBlock.BeforeLast.Insert(new InstructionNode(IRInstruction.Jmp, nextBlock));

                        continue;
                    }

                    var newNode = new InstructionNode(node.Instruction, node.OperandCount, node.ResultCount);
                    newNode.Size = node.Size;
                    newNode.ConditionCode = node.ConditionCode;

                    if (node.BranchTargets != null)
                    {
                        // copy targets
                        foreach (var target in node.BranchTargets)
                        {
                            newNode.AddBranchTarget(mapBlocks[target]);
                        }
                    }

                    // copy results
                    for (int i = 0; i < node.ResultCount; i++)
                    {
                        var op = node.GetResult(i);

                        var newOp = Map(op, map, callNode);

                        newNode.SetResult(i, newOp);
                    }

                    // copy operands
                    for (int i = 0; i < node.OperandCount; i++)
                    {
                        var op = node.GetOperand(i);

                        var newOp = Map(op, map, callNode);

                        newNode.SetOperand(i, newOp);
                    }

                    // copy other
                    if (node.MosaType != null)
                        newNode.MosaType = node.MosaType;
                    if (node.MosaField != null)
                        newNode.MosaField = node.MosaField;
                    if (node.InvokeMethod != null)
                        newNode.InvokeMethod = node.InvokeMethod;

                    newBlock.BeforeLast.Insert(newNode);
                }
            }

            callNode.SetInstruction(IRInstruction.Jmp, mapBlocks[blocks.PrologueBlock]);
        }
        /// <summary>
        /// Strength reduction for logical operators
        /// </summary>
        /// <param name="node">The node.</param>
        private void ArithmeticSimplificationLogicalOperators(InstructionNode node)
        {
            if (node.IsEmpty)
                return;

            if (!(node.Instruction == IRInstruction.LogicalAnd || node.Instruction == IRInstruction.LogicalOr))
                return;

            if (!node.Result.IsVirtualRegister)
                return;

            if (!node.Operand2.IsConstant)
                return;

            Operand result = node.Result;
            Operand op1 = node.Operand1;
            Operand op2 = node.Operand2;

            if (node.Instruction == IRInstruction.LogicalOr)
            {
                if (op2.IsConstantZero)
                {
                    AddOperandUsageToWorkList(node);
                    if (trace.Active) trace.Log("*** ArithmeticSimplificationLogicalOperators");
                    if (trace.Active) trace.Log("BEFORE:\t" + node.ToString());
                    node.SetInstruction(IRInstruction.Move, result, op1);
                    arithmeticSimplificationLogicalOperatorsCount++;
                    changeCount++;
                    if (trace.Active) trace.Log("AFTER: \t" + node.ToString());
                    return;
                }
            }
            else if (node.Instruction == IRInstruction.LogicalAnd)
            {
                if (op2.IsConstantZero)
                {
                    AddOperandUsageToWorkList(node);
                    if (trace.Active) trace.Log("*** ArithmeticSimplificationLogicalOperators");
                    if (trace.Active) trace.Log("BEFORE:\t" + node.ToString());
                    node.SetInstruction(IRInstruction.Move, result, Operand.CreateConstant(node.Result.Type, 0));
                    arithmeticSimplificationLogicalOperatorsCount++;
                    changeCount++;
                    if (trace.Active) trace.Log("AFTER: \t" + node.ToString());
                    return;
                }

                if (((result.IsI4 || result.IsU4 || result.IsI || result.IsU) && op2.ConstantUnsignedInteger == 0xFFFFFFFF)
                    || ((result.IsI8 || result.IsU8) && op2.ConstantUnsignedLongInteger == 0xFFFFFFFFFFFFFFFF))
                {
                    AddOperandUsageToWorkList(node);
                    if (trace.Active) trace.Log("*** ArithmeticSimplificationLogicalOperators");
                    if (trace.Active) trace.Log("BEFORE:\t" + node.ToString());
                    node.SetInstruction(IRInstruction.Move, result, op1);
                    arithmeticSimplificationLogicalOperatorsCount++;
                    changeCount++;
                    if (trace.Active) trace.Log("AFTER: \t" + node.ToString());
                    return;
                }
            }

            // TODO: Add more strength reductions especially for AND w/ 0xFF, 0xFFFF, 0xFFFFFFFF, etc when source or destination are same or smaller
        }
Exemplo n.º 18
0
        protected override void Run()
        {
            if (IsMethodPlugged)
            {
                var plugMethod = MethodCompiler.Compiler.PlugSystem.GetReplacement(MethodCompiler.Method);

                Debug.Assert(plugMethod != null);

                var plugSymbol = Operand.CreateSymbolFromMethod(plugMethod, TypeSystem);
                var context    = CreateNewBlockContext(-1, -1);
                context.AppendInstruction(IRInstruction.Jmp, null, plugSymbol);
                BasicBlocks.AddHeadBlock(context.Block);
                return;
            }

            // No CIL decoding if this is a linker generated method
            if (MethodCompiler.Method.IsLinkerGenerated)
            {
                return;
            }

            if (MethodCompiler.Method.Code.Count == 0)
            {
                if (DelegatePatcher.PatchDelegate(MethodCompiler))
                {
                    return;
                }

                MethodCompiler.Stop();
                return;
            }

            if (CompilerOptions.EnableStatistics)
            {
                counts = new int[CILInstruction.MaxOpCodeValue];
            }

            MethodCompiler.SetLocalVariables(MethodCompiler.Method.LocalVariables);

            // Create the prologue block
            var prologue = CreateNewBlock(BasicBlock.PrologueLabel);

            BasicBlocks.AddHeadBlock(prologue);

            var jmpNode = new InstructionNode()
            {
                Label = BasicBlock.PrologueLabel,
                Block = prologue
            };

            prologue.First.Insert(jmpNode);

            // Create starting block
            var startBlock = CreateNewBlock(0);

            jmpNode.SetInstruction(IRInstruction.Jmp, startBlock);

            DecodeInstructionTargets();

            DecodeProtectedRegionTargets();

            /* Decode the instructions */
            DecodeInstructions();

            foreach (var block in BasicBlocks)
            {
                if (!block.HasPreviousBlocks && !block.IsHeadBlock)
                {
                    // block was targeted (probably by an leave instruction within a protected region)
                    BasicBlocks.AddHeadBlock(block);
                }
            }

            // This makes it easier to review --- it's not necessary
            BasicBlocks.OrderByLabel();
        }
        /// <summary>
        /// Folds the integer compare on constants
        /// </summary>
        /// <param name="node">The node.</param>
        private void ConstantFoldingIntegerCompare(InstructionNode node)
        {
            if (node.IsEmpty)
                return;

            if (node.Instruction != IRInstruction.IntegerCompare)
                return;

            if (!node.Result.IsVirtualRegister)
                return;

            Operand result = node.Result;
            Operand op1 = node.Operand1;
            Operand op2 = node.Operand2;

            if (!op1.IsConstant || !op2.IsConstant)
                return;

            if (!op1.IsValueType || !op2.IsValueType)
                return;

            bool compareResult = true;

            switch (node.ConditionCode)
            {
                case ConditionCode.Equal: compareResult = (op1.ConstantUnsignedLongInteger == op2.ConstantUnsignedLongInteger); break;
                case ConditionCode.NotEqual: compareResult = (op1.ConstantUnsignedLongInteger != op2.ConstantUnsignedLongInteger); break;
                case ConditionCode.GreaterOrEqual: compareResult = (op1.ConstantUnsignedLongInteger >= op2.ConstantUnsignedLongInteger); break;
                case ConditionCode.GreaterThan: compareResult = (op1.ConstantUnsignedLongInteger > op2.ConstantUnsignedLongInteger); break;
                case ConditionCode.LessOrEqual: compareResult = (op1.ConstantUnsignedLongInteger <= op2.ConstantUnsignedLongInteger); break;
                case ConditionCode.LessThan: compareResult = (op1.ConstantUnsignedLongInteger < op2.ConstantUnsignedLongInteger); break;

                // TODO: Add more
                default: return;
            }

            AddOperandUsageToWorkList(node);
            if (trace.Active) trace.Log("*** ConstantFoldingIntegerCompare");
            if (trace.Active) trace.Log("BEFORE:\t" + node.ToString());
            node.SetInstruction(IRInstruction.Move, result, Operand.CreateConstant(result.Type, compareResult ? 1 : 0));
            constantFoldingIntegerCompareCount++;
            changeCount++;
            if (trace.Active) trace.Log("AFTER: \t" + node.ToString());
        }
Exemplo n.º 20
0
        private static void UpdateParameterInstructions(InstructionNode newNode)
        {
            var instruction = newNode.Instruction;

            if (instruction == IRInstruction.LoadParamR4)
            {
                newNode.Instruction = IRInstruction.MoveR4;
            }
            else if (instruction == IRInstruction.LoadParamR8)
            {
                newNode.Instruction = IRInstruction.MoveR8;
            }
            else if (instruction == IRInstruction.LoadParam32 ||
                     instruction == IRInstruction.LoadParamSignExtend8x32 ||
                     instruction == IRInstruction.LoadParamSignExtend16x32 ||
                     instruction == IRInstruction.LoadParamZeroExtend8x32 ||
                     instruction == IRInstruction.LoadParamZeroExtend16x32)
            {
                newNode.Instruction = IRInstruction.Move32;
            }
            else if (instruction == IRInstruction.LoadParamObject)
            {
                newNode.Instruction = IRInstruction.MoveObject;
            }
            else if (instruction == IRInstruction.LoadParam64 ||
                     instruction == IRInstruction.LoadParamSignExtend8x64 ||
                     instruction == IRInstruction.LoadParamSignExtend16x64 ||
                     instruction == IRInstruction.LoadParamSignExtend32x64 ||
                     instruction == IRInstruction.LoadParamZeroExtend8x64 ||
                     instruction == IRInstruction.LoadParamZeroExtend16x64 ||
                     instruction == IRInstruction.LoadParamZeroExtend32x64)
            {
                newNode.Instruction = IRInstruction.Move64;
            }
            else if (instruction == IRInstruction.StoreParam8 ||
                     instruction == IRInstruction.StoreParam16 ||
                     instruction == IRInstruction.StoreParam32)
            {
                newNode.SetInstruction(IRInstruction.Move32, newNode.Operand1, newNode.Operand2);
            }
            else if (instruction == IRInstruction.StoreParamObject)
            {
                newNode.SetInstruction(IRInstruction.MoveObject, newNode.Operand1, newNode.Operand2);
            }
            else if (instruction == IRInstruction.StoreParam64)
            {
                newNode.SetInstruction(IRInstruction.Move64, newNode.Operand1, newNode.Operand2);
            }
            else if (instruction == IRInstruction.StoreParamR4)
            {
                newNode.SetInstruction(IRInstruction.MoveR4, newNode.Operand1, newNode.Operand2);
            }
            else if (instruction == IRInstruction.StoreParamR8)
            {
                newNode.SetInstruction(IRInstruction.MoveR8, newNode.Operand1, newNode.Operand2);
            }
            else if (instruction == IRInstruction.StoreParamCompound)
            {
                newNode.Instruction = IRInstruction.MoveCompound;
            }
            else if (instruction == IRInstruction.LoadParamCompound)
            {
                newNode.Instruction = IRInstruction.MoveCompound;
            }
        }
Exemplo n.º 21
0
        /// <summary>
        /// Visitation function for Return.
        /// </summary>
        /// <param name="node">The node.</param>
        private void GotoEpilogue(InstructionNode node)
        {
            Debug.Assert(node.Operand1 == null);

            node.SetInstruction(X86.Jmp, BasicBlocks.EpilogueBlock);
        }
Exemplo n.º 22
0
        protected override void Run()
        {
            if (!MethodCompiler.IsCILDecodeRequired)
            {
                return;
            }

            // No CIL decoding if this is a linker generated method
            Debug.Assert(!Method.IsCompilerGenerated);

            if (!Method.HasImplementation)
            {
                //if (DelegatePatcher.PatchDelegate(MethodCompiler))
                //	return;

                MethodCompiler.Stop();
                return;
            }

            if (CompilerOptions.EnableStatistics)
            {
                counts = new int[CILInstruction.MaxOpCodeValue];
            }

            MethodCompiler.SetLocalVariables(Method.LocalVariables);

            // Create the prologue block
            var prologue = CreateNewBlock(BasicBlock.PrologueLabel);

            BasicBlocks.AddHeadBlock(prologue);

            var jmpNode = new InstructionNode()
            {
                Label = BasicBlock.PrologueLabel,
                Block = prologue
            };

            prologue.First.Insert(jmpNode);

            // Create starting block
            var startBlock = CreateNewBlock(0);

            jmpNode.SetInstruction(IRInstruction.Jmp, startBlock);

            DecodeInstructionTargets();

            DecodeProtectedRegionTargets();

            /* Decode the instructions */
            DecodeInstructions();

            foreach (var block in BasicBlocks)
            {
                if (!block.HasPreviousBlocks && !block.IsHeadBlock)
                {
                    // block was targeted (probably by an leave instruction within a protected region)
                    BasicBlocks.AddHeadBlock(block);
                }
            }

            // This makes it easier to review --- it's not necessary
            BasicBlocks.OrderByLabel();
        }
        private void LoadZeroExtend16x32(InstructionNode node)
        {
            LoadStore.OrderLoadOperands(node, MethodCompiler);

            node.SetInstruction(X86.MovzxLoad16, node.Result, node.Operand1, node.Operand2);
        }
Exemplo n.º 24
0
 /// <summary>
 /// Decodes the specified instruction.
 /// </summary>
 /// <param name="node">The context.</param>
 /// <param name="decoder">The instruction decoder, which holds the code stream.</param>
 public virtual void Decode(InstructionNode node, IInstructionDecoder decoder)
 {
     node.SetInstruction(this, DefaultOperandCount, DefaultResultCount);
 }
 private void StoreParamFloatR8(InstructionNode node)
 {
     node.SetInstruction(X86.MovsdStore, null, StackFrame, node.Operand1, node.Operand2);
 }
        private void LoadFloatR4(InstructionNode node)
        {
            Debug.Assert(node.Result.IsR4);

            node.SetInstruction(X64.MovssLoad, node.Result, node.Operand1, node.Operand2);
        }
Exemplo n.º 27
0
        private void LoadParamFloatR8(InstructionNode node)
        {
            Debug.Assert(node.Result.IsR8);

            node.SetInstruction(X86.MovsdLoad, node.Result, StackFrame, node.Operand1);
        }
 private void LoadParamInt64(InstructionNode node)
 {
     node.SetInstruction(X64.MovLoad64, node.Result, StackFrame, node.Operand1);
 }
        /// <summary>
        /// Simple copy propagation.
        /// </summary>
        /// <param name="node">The node.</param>
        private void SimpleForwardCopyPropagation(InstructionNode node)
        {
            if (node.IsEmpty)
                return;

            if (node.Instruction != IRInstruction.Move)
                return;

            if (!node.Result.IsVirtualRegister)
                return;

            if (node.Result.Definitions.Count != 1)
                return;

            if (node.Operand1.Definitions.Count != 1)
                return;

            if (node.Operand1.IsConstant)
                return;

            if (!node.Operand1.IsVirtualRegister)
                return;

            // If the pointer or reference types are different, we can not copy propagation because type information would be lost.
            // Also if the operand sign is different, we cannot do it as it requires a signed/unsigned extended move, not a normal move
            if (!CanCopyPropagation(node.Result, node.Operand1))
                return;

            Operand destination = node.Result;
            Operand source = node.Operand1;

            if (ContainsAddressOf(destination))
                return;

            // for each statement T that uses operand, substituted c in statement T
            AddOperandUsageToWorkList(node);

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

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

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

            if (trace.Active) trace.Log("REMOVED:\t" + node.ToString());
            AddOperandUsageToWorkList(node);
            node.SetInstruction(IRInstruction.Nop);
            instructionsRemovedCount++;
            changeCount++;
        }
        private void LoadSignExtend16x64(InstructionNode node)
        {
            LoadStore.OrderLoadOperands(node, MethodCompiler);

            node.SetInstruction(X64.MovsxLoad16, node.Result, node.Operand1, node.Operand2);
        }
        /// <summary>
        /// Simplifies extended moves with a constant
        /// </summary>
        /// <param name="node">The node.</param>
        private void SimplifyExtendedMoveWithConstant(InstructionNode node)
        {
            if (node.IsEmpty)
                return;

            if (!(node.Instruction == IRInstruction.ZeroExtendedMove || node.Instruction == IRInstruction.SignExtendedMove))
                return;

            if (!node.Result.IsVirtualRegister)
                return;

            if (node.Result.Definitions.Count != 1)
                return;

            if (!node.Operand1.IsConstant)
                return;

            Operand result = node.Result;
            Operand op1 = node.Operand1;

            Operand newOperand;

            if (node.Instruction == IRInstruction.ZeroExtendedMove && result.IsUnsigned && op1.IsSigned)
            {
                var newConstant = Unsign(op1.Type, op1.ConstantSignedLongInteger);
                newOperand = Operand.CreateConstant(node.Result.Type, newConstant);
            }
            else
            {
                newOperand = Operand.CreateConstant(node.Result.Type, op1.ConstantUnsignedLongInteger);
            }

            AddOperandUsageToWorkList(node);
            if (trace.Active) trace.Log("*** SimplifyExtendedMoveWithConstant");
            if (trace.Active) trace.Log("BEFORE:\t" + node.ToString());
            node.SetInstruction(IRInstruction.Move, result, newOperand);
            simplifyExtendedMoveWithConstantCount++;
            changeCount++;
            if (trace.Active) trace.Log("AFTER: \t" + node.ToString());
        }
 private void StoreParamInt32(InstructionNode node)
 {
     node.SetInstruction(X64.MovStore32, null, StackFrame, node.Operand1, node.Operand2);
 }
        /// <summary>
        /// Strength reduction for integer addition when one of the constants is zero
        /// </summary>
        /// <param name="node">The node.</param>
        private void ArithmeticSimplificationAdditionAndSubstraction(InstructionNode node)
        {
            if (node.IsEmpty)
                return;

            if (!(node.Instruction == IRInstruction.AddSigned || node.Instruction == IRInstruction.AddUnsigned
                || node.Instruction == IRInstruction.SubSigned || node.Instruction == IRInstruction.SubUnsigned))
                return;

            if (!node.Result.IsVirtualRegister)
                return;

            Operand result = node.Result;
            Operand op1 = node.Operand1;
            Operand op2 = node.Operand2;

            if (op2.IsConstant && !op1.IsConstant && op2.IsConstantZero)
            {
                AddOperandUsageToWorkList(node);
                if (trace.Active) trace.Log("*** ArithmeticSimplificationAdditionAndSubstraction");
                if (trace.Active) trace.Log("BEFORE:\t" + node.ToString());
                node.SetInstruction(IRInstruction.Move, result, op1);
                if (trace.Active) trace.Log("AFTER: \t" + node.ToString());
                arithmeticSimplificationAdditionAndSubstractionCount++;
                changeCount++;
                return;
            }
        }
Exemplo n.º 34
0
        private void RemoveUselessPhi(InstructionNode node)
        {
            if (node.IsEmpty)
                return;

            if (node.Instruction != IRInstruction.Phi)
                return;

            if (node.Result.Definitions.Count != 1)
                return;

            var result = node.Result;

            foreach (var use in node.Result.Uses)
            {
                if (use != node)
                    return;
            }

            AddOperandUsageToWorkList(node);
            if (trace.Active) trace.Log("REMOVED:\t" + node.ToString());
            node.SetInstruction(IRInstruction.Nop);
            removeUselessPhiCount++;
        }
        /// <summary>
        /// Strength reduction for multiplication when one of the constants is zero or one
        /// </summary>
        /// <param name="node">The node.</param>
        private void ArithmeticSimplificationMultiplication(InstructionNode node)
        {
            if (node.IsEmpty)
                return;

            if (!(node.Instruction == IRInstruction.MulSigned || node.Instruction == IRInstruction.MulUnsigned))
                return;

            if (!node.Result.IsVirtualRegister)
                return;

            if (!node.Operand2.IsConstant)
                return;

            Operand result = node.Result;
            Operand op1 = node.Operand1;
            Operand op2 = node.Operand2;

            if (op2.IsConstantZero)
            {
                AddOperandUsageToWorkList(node);
                if (trace.Active) trace.Log("*** ArithmeticSimplificationMultiplication");
                if (trace.Active) trace.Log("BEFORE:\t" + node.ToString());
                node.SetInstruction(IRInstruction.Move, result, Operand.CreateConstant(node.Result.Type, 0));
                arithmeticSimplificationMultiplicationCount++;
                if (trace.Active) trace.Log("AFTER: \t" + node.ToString());
                changeCount++;
                return;
            }

            if (op2.IsConstantOne)
            {
                AddOperandUsageToWorkList(node);
                if (trace.Active) trace.Log("*** ArithmeticSimplificationMultiplication");
                if (trace.Active) trace.Log("BEFORE:\t" + node.ToString());
                node.SetInstruction(IRInstruction.Move, result, op1);
                arithmeticSimplificationMultiplicationCount++;
                if (trace.Active) trace.Log("AFTER: \t" + node.ToString());
                changeCount++;
                return;
            }

            if (IsPowerOfTwo(op2.ConstantUnsignedLongInteger))
            {
                uint shift = GetPowerOfTwo(op2.ConstantUnsignedLongInteger);

                if (shift < 32)
                {
                    AddOperandUsageToWorkList(node);
                    if (trace.Active) trace.Log("*** ArithmeticSimplificationMultiplication");
                    if (trace.Active) trace.Log("BEFORE:\t" + node.ToString());
                    node.SetInstruction(IRInstruction.ShiftLeft, result, op1, Operand.CreateConstant(TypeSystem, (int)shift));
                    arithmeticSimplificationMultiplicationCount++;
                    if (trace.Active) trace.Log("AFTER: \t" + node.ToString());
                    changeCount++;
                    return;
                }
            }
        }
Exemplo n.º 36
0
        protected void Inline(InstructionNode callSiteNode, BasicBlocks blocks)
        {
            var mapBlocks = new Dictionary <BasicBlock, BasicBlock>(blocks.Count);
            var map       = new Dictionary <Operand, Operand>();

            var nextBlock = Split(callSiteNode);

            // create basic blocks
            foreach (var block in blocks)
            {
                var newBlock = CreateNewBlock();
                mapBlocks.Add(block, newBlock);
            }

            // copy instructions
            foreach (var block in blocks)
            {
                var newBlock = mapBlocks[block];

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

                    if (node.Instruction == IRInstruction.Prologue)
                    {
                        continue;
                    }

                    if (node.Instruction == IRInstruction.Epilogue)
                    {
                        newBlock.BeforeLast.Insert(new InstructionNode(IRInstruction.Jmp, nextBlock));
                        continue;
                    }

                    if (node.Instruction == IRInstruction.SetReturn32 ||
                        node.Instruction == IRInstruction.SetReturn64 ||
                        node.Instruction == IRInstruction.SetReturnR4 ||
                        node.Instruction == IRInstruction.SetReturnR8 ||
                        node.Instruction == IRInstruction.SetReturnCompound)
                    {
                        if (callSiteNode.Result != null)
                        {
                            var newOperand = Map(node.Operand1, map, callSiteNode);

                            BaseInstruction moveInstruction = null;

                            if (node.Instruction == IRInstruction.SetReturn32)
                            {
                                moveInstruction = IRInstruction.MoveInt32;
                            }
                            else if (node.Instruction == IRInstruction.SetReturn64)
                            {
                                moveInstruction = IRInstruction.MoveInt64;
                            }
                            else if (node.Instruction == IRInstruction.SetReturnR4)
                            {
                                moveInstruction = IRInstruction.MoveFloatR4;
                            }
                            else if (node.Instruction == IRInstruction.SetReturnR8)
                            {
                                moveInstruction = IRInstruction.MoveFloatR8;
                            }
                            else if (node.Instruction == IRInstruction.SetReturnCompound)
                            {
                                moveInstruction = IRInstruction.MoveCompound;
                            }

                            Debug.Assert(moveInstruction != null);

                            var moveNode = new InstructionNode(moveInstruction, callSiteNode.Result, newOperand);

                            newBlock.BeforeLast.Insert(moveNode);
                        }

                        continue;
                    }

                    var newNode = new InstructionNode(node.Instruction, node.OperandCount, node.ResultCount)
                    {
                        ConditionCode = node.ConditionCode,
                        Label         = callSiteNode.Label
                    };

                    if (node.BranchTargets != null)
                    {
                        // copy targets
                        foreach (var target in node.BranchTargets)
                        {
                            newNode.AddBranchTarget(mapBlocks[target]);
                        }
                    }

                    // copy results
                    for (int i = 0; i < node.ResultCount; i++)
                    {
                        var op = node.GetResult(i);

                        var newOp = Map(op, map, callSiteNode);

                        newNode.SetResult(i, newOp);
                    }

                    // copy operands
                    for (int i = 0; i < node.OperandCount; i++)
                    {
                        var op = node.GetOperand(i);

                        var newOp = Map(op, map, callSiteNode);

                        newNode.SetOperand(i, newOp);
                    }

                    // copy other
                    if (node.MosaType != null)
                    {
                        newNode.MosaType = node.MosaType;
                    }
                    if (node.MosaField != null)
                    {
                        newNode.MosaField = node.MosaField;
                    }

                    UpdateParameterInstructions(newNode);

                    newBlock.BeforeLast.Insert(newNode);
                }
            }

            var prologue = mapBlocks[blocks.PrologueBlock];

            var callSiteOperands = callSiteNode.GetOperands();

            if (callSiteOperands.Count > 1)
            {
                var context = new Context(prologue);

                for (int i = 1; i < callSiteOperands.Count; i++)
                {
                    var operand = callSiteOperands[i];

                    if (!operand.IsVirtualRegister || operand.Low == null)
                    {
                        continue;
                    }

                    context.AppendInstruction(IRInstruction.GetLow64, operand.Low, operand);
                    context.AppendInstruction(IRInstruction.GetHigh64, operand.High, operand);
                }
            }

            callSiteNode.SetInstruction(IRInstruction.Jmp, prologue);
        }
        /// <summary>
        /// Simplifies subtraction where both operands are the same
        /// </summary>
        /// <param name="node">The node.</param>
        private void ArithmeticSimplificationSubtraction(InstructionNode node)
        {
            if (node.IsEmpty)
                return;

            if (!(node.Instruction == IRInstruction.SubSigned || node.Instruction == IRInstruction.SubUnsigned))
                return;

            if (!node.Result.IsVirtualRegister)
                return;

            Operand result = node.Result;
            Operand op1 = node.Operand1;
            Operand op2 = node.Operand2;

            if (op1 != op2)
                return;

            AddOperandUsageToWorkList(node);
            if (trace.Active) trace.Log("*** ArithmeticSimplificationSubtraction");
            if (trace.Active) trace.Log("BEFORE:\t" + node.ToString());
            node.SetInstruction(IRInstruction.Move, result, Operand.CreateConstant(node.Result.Type, 0));
            arithmeticSimplificationSubtractionCount++;
            changeCount++;
        }
Exemplo n.º 38
0
        protected override void Run()
        {
            // No CIL decoding if this is a linker generated method
            if (MethodCompiler.Method.IsLinkerGenerated)
                return;

            if (IsPlugged)
            {
                var plugMethod = MethodCompiler.Compiler.PlugSystem.GetPlugMethod(MethodCompiler.Method);

                Debug.Assert(plugMethod != null);

                var plugSymbol = Operand.CreateSymbolFromMethod(TypeSystem, plugMethod);
                var context = CreateNewBlockContext(-1);
                context.AppendInstruction(IRInstruction.Jmp, null, plugSymbol);
                BasicBlocks.AddHeadBlock(context.Block);
                return;
            }

            if (MethodCompiler.Method.Code.Count == 0)
            {
                if (DelegatePatcher.PatchDelegate(MethodCompiler))
                    return;

                MethodCompiler.Stop();
                return;
            }

            if (MethodCompiler.Compiler.CompilerOptions.EnableStatistics)
            {
                counts = new int[CILInstruction.MaxOpCodeValue];
            }

            MethodCompiler.SetLocalVariables(MethodCompiler.Method.LocalVariables);

            // Create the prologue block
            var prologue = CreateNewBlock(BasicBlock.PrologueLabel);
            BasicBlocks.AddHeadBlock(prologue);

            var jmpNode = new InstructionNode();
            jmpNode.Label = BasicBlock.PrologueLabel;
            jmpNode.Block = prologue;
            prologue.First.Insert(jmpNode);

            // Create starting block
            var startBlock = CreateNewBlock(0);

            jmpNode.SetInstruction(IRInstruction.Jmp, startBlock);

            DecodeInstructionTargets();

            DecodeProtectedRegionTargets();

            /* Decode the instructions */
            DecodeInstructions();

            foreach (var block in BasicBlocks)
            {
                if (!block.HasPreviousBlocks && !BasicBlocks.HeadBlocks.Contains(block))
                {
                    // block was targeted (probably by an leave instruction within a protected region)
                    BasicBlocks.AddHeadBlock(block);
                }
            }

            // This makes it easier to review --- it's not necessary
            BasicBlocks.OrderByLabel();
        }
        /// <summary>
        /// Folds an integer operation on constants
        /// </summary>
        /// <param name="node">The node.</param>
        private void ConstantFoldingIntegerOperations(InstructionNode node)
        {
            if (node.IsEmpty)
                return;

            if (!(node.Instruction == IRInstruction.AddSigned || node.Instruction == IRInstruction.AddUnsigned ||
                  node.Instruction == IRInstruction.SubSigned || node.Instruction == IRInstruction.SubUnsigned ||
                  node.Instruction == IRInstruction.LogicalAnd || node.Instruction == IRInstruction.LogicalOr ||
                  node.Instruction == IRInstruction.LogicalXor ||
                  node.Instruction == IRInstruction.MulSigned || node.Instruction == IRInstruction.MulUnsigned ||
                  node.Instruction == IRInstruction.DivSigned || node.Instruction == IRInstruction.DivUnsigned ||
                  node.Instruction == IRInstruction.ArithmeticShiftRight ||
                  node.Instruction == IRInstruction.ShiftLeft || node.Instruction == IRInstruction.ShiftRight))
                return;

            if (!node.Result.IsVirtualRegister)
                return;

            Operand result = node.Result;
            Operand op1 = node.Operand1;
            Operand op2 = node.Operand2;

            if (!op1.IsConstant || !op2.IsConstant)
                return;

            // Divide by zero!
            if ((node.Instruction == IRInstruction.DivSigned || node.Instruction == IRInstruction.DivUnsigned) && op2.IsConstant && op2.IsConstantZero)
                return;

            Operand constant = null;

            if (node.Instruction == IRInstruction.AddSigned || node.Instruction == IRInstruction.AddUnsigned)
            {
                constant = Operand.CreateConstant(result.Type, op1.ConstantUnsignedLongInteger + op2.ConstantUnsignedLongInteger);
            }
            else if (node.Instruction == IRInstruction.SubSigned || node.Instruction == IRInstruction.SubUnsigned)
            {
                constant = Operand.CreateConstant(result.Type, op1.ConstantUnsignedLongInteger - op2.ConstantUnsignedLongInteger);
            }
            else if (node.Instruction == IRInstruction.LogicalAnd)
            {
                constant = Operand.CreateConstant(result.Type, op1.ConstantUnsignedLongInteger & op2.ConstantUnsignedLongInteger);
            }
            else if (node.Instruction == IRInstruction.LogicalOr)
            {
                constant = Operand.CreateConstant(result.Type, op1.ConstantUnsignedLongInteger | op2.ConstantUnsignedLongInteger);
            }
            else if (node.Instruction == IRInstruction.LogicalXor)
            {
                constant = Operand.CreateConstant(result.Type, op1.ConstantUnsignedLongInteger ^ op2.ConstantUnsignedLongInteger);
            }
            else if (node.Instruction == IRInstruction.MulSigned || node.Instruction == IRInstruction.MulUnsigned)
            {
                constant = Operand.CreateConstant(result.Type, op1.ConstantUnsignedLongInteger * op2.ConstantUnsignedLongInteger);
            }
            else if (node.Instruction == IRInstruction.DivUnsigned)
            {
                constant = Operand.CreateConstant(result.Type, op1.ConstantUnsignedLongInteger / op2.ConstantUnsignedLongInteger);
            }
            else if (node.Instruction == IRInstruction.DivSigned)
            {
                constant = Operand.CreateConstant(result.Type, op1.ConstantSignedLongInteger / op2.ConstantSignedLongInteger);
            }
            else if (node.Instruction == IRInstruction.ArithmeticShiftRight)
            {
                constant = Operand.CreateConstant(result.Type, ((long)op1.ConstantUnsignedLongInteger) >> (int)op2.ConstantUnsignedLongInteger);
            }
            else if (node.Instruction == IRInstruction.ShiftRight)
            {
                constant = Operand.CreateConstant(result.Type, op1.ConstantUnsignedLongInteger >> (int)op2.ConstantUnsignedLongInteger);
            }
            else if (node.Instruction == IRInstruction.ShiftLeft)
            {
                constant = Operand.CreateConstant(result.Type, op1.ConstantUnsignedLongInteger << (int)op2.ConstantUnsignedLongInteger);
            }

            if (constant == null)
                return;

            AddOperandUsageToWorkList(node);
            if (trace.Active) trace.Log("*** ConstantFoldingIntegerOperations");
            if (trace.Active) trace.Log("BEFORE:\t" + node.ToString());
            node.SetInstruction(IRInstruction.Move, node.Result, constant);
            constantFoldingIntegerOperationsCount++;
            changeCount++;
            if (trace.Active) trace.Log("AFTER: \t" + node.ToString());
        }
Exemplo n.º 40
0
        protected void Inline(InstructionNode callNode, BasicBlocks blocks)
        {
            var mapBlocks = new Dictionary <BasicBlock, BasicBlock>(blocks.Count);
            var map       = new Dictionary <Operand, Operand>();

            var nextBlock = Split(callNode);

            // create basic blocks
            foreach (var block in blocks)
            {
                var newBlock = CreateNewBlock();
                mapBlocks.Add(block, newBlock);
            }

            // copy instructions
            foreach (var block in blocks)
            {
                var newBlock = mapBlocks[block];

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

                    if (node.Instruction == IRInstruction.Prologue)
                    {
                        continue;
                    }

                    if (node.Instruction == IRInstruction.Epilogue)
                    {
                        continue;
                    }

                    if (node.Instruction == IRInstruction.Return)
                    {
                        if (callNode.Result != null)
                        {
                            var newOp           = Map(node.Operand1, map, callNode);
                            var moveInsturction = GetMoveInstruction(callNode.Result.Type);

                            var moveNode = new InstructionNode(moveInsturction, callNode.Result, newOp);

                            newBlock.BeforeLast.Insert(moveNode);
                        }
                        newBlock.BeforeLast.Insert(new InstructionNode(IRInstruction.Jmp, nextBlock));

                        continue;
                    }

                    var newNode = new InstructionNode(node.Instruction, node.OperandCount, node.ResultCount);
                    newNode.Size          = node.Size;
                    newNode.ConditionCode = node.ConditionCode;

                    if (node.BranchTargets != null)
                    {
                        // copy targets
                        foreach (var target in node.BranchTargets)
                        {
                            newNode.AddBranchTarget(mapBlocks[target]);
                        }
                    }

                    // copy results
                    for (int i = 0; i < node.ResultCount; i++)
                    {
                        var op = node.GetResult(i);

                        var newOp = Map(op, map, callNode);

                        newNode.SetResult(i, newOp);
                    }

                    // copy operands
                    for (int i = 0; i < node.OperandCount; i++)
                    {
                        var op = node.GetOperand(i);

                        var newOp = Map(op, map, callNode);

                        newNode.SetOperand(i, newOp);
                    }

                    // copy other
                    if (node.MosaType != null)
                    {
                        newNode.MosaType = node.MosaType;
                    }
                    if (node.MosaField != null)
                    {
                        newNode.MosaField = node.MosaField;
                    }
                    if (node.InvokeMethod != null)
                    {
                        newNode.InvokeMethod = node.InvokeMethod;
                    }

                    UpdateParameterInstructions(newNode);

                    newBlock.BeforeLast.Insert(newNode);
                }
            }

            callNode.SetInstruction(IRInstruction.Jmp, mapBlocks[blocks.PrologueBlock]);
        }
Exemplo n.º 41
0
        private void LoadParameterZeroExtended(InstructionNode node)
        {
            Debug.Assert(node.Size == InstructionSize.Size8 || node.Size == InstructionSize.Size16);

            node.SetInstruction(X86.MovzxLoad, node.Size, node.Result, StackFrame, node.Operand1);
        }
        /// <summary>
        /// Folds the constant phi instruction.
        /// </summary>
        /// <param name="node">The node.</param>
        private void ConstantFoldingPhi(InstructionNode node)
        {
            if (node.IsEmpty)
                return;

            if (node.Instruction != IRInstruction.Phi)
                return;

            if (node.Result.Definitions.Count != 1)
                return;

            if (!node.Result.IsInteger)
                return;

            Operand operand1 = node.Operand1;
            Operand result = node.Result;

            foreach (var operand in node.Operands)
            {
                if (!operand.IsConstant)
                    return;

                if (operand.ConstantUnsignedLongInteger != operand1.ConstantUnsignedLongInteger)
                    return;
            }

            if (trace.Active) trace.Log("*** FoldConstantPhiInstruction");
            if (trace.Active) trace.Log("BEFORE:\t" + node.ToString());
            AddOperandUsageToWorkList(node);
            node.SetInstruction(IRInstruction.Move, result, operand1);
            if (trace.Active) trace.Log("AFTER: \t" + node.ToString());
            constantFoldingPhiCount++;
            changeCount++;
        }
Exemplo n.º 43
0
 private void StoreParameterInteger(InstructionNode node)
 {
     node.SetInstruction(X86.MovStore, node.Size, null, StackFrame, node.Operand1, node.Operand2);
 }
        /// <summary>
        /// Removes the useless move and dead code
        /// </summary>
        /// <param name="node">The node.</param>
        private void DeadCodeElimination(InstructionNode node)
        {
            if (node.IsEmpty)
                return;

            if (node.ResultCount != 1)
                return;

            if (!node.Result.IsVirtualRegister)
                return;

            if (node.Result.Definitions.Count != 1)
                return;

            if (node.Instruction == IRInstruction.Call || node.Instruction == IRInstruction.IntrinsicMethodCall)
                return;

            if (node.Instruction == IRInstruction.Move && node.Operand1.IsVirtualRegister && node.Operand1 == node.Result)
            {
                if (trace.Active) trace.Log("*** DeadCodeElimination");
                if (trace.Active) trace.Log("REMOVED:\t" + node.ToString());
                AddOperandUsageToWorkList(node);
                node.SetInstruction(IRInstruction.Nop);
                instructionsRemovedCount++;
                deadCodeEliminationCount++;
                changeCount++;
                return;
            }

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

            if (trace.Active) trace.Log("*** DeadCodeElimination");
            if (trace.Active) trace.Log("REMOVED:\t" + node.ToString());
            AddOperandUsageToWorkList(node);
            node.SetInstruction(IRInstruction.Nop);
            instructionsRemovedCount++;
            deadCodeEliminationCount++;
            changeCount++;
            return;
        }
Exemplo n.º 45
0
 private void Promote(InstructionNode node, Operand virtualRegister)
 {
     if (node.Instruction == IRInstruction.MoveInt32 || node.Instruction == IRInstruction.MoveInt64)
     {
         foreach (var node2 in node.Result.Uses.ToArray())
         {
             Promote(node2, virtualRegister);
         }
     }
     else if (node.Instruction == IRInstruction.StoreInt32)
     {
         if (trace.Active)
         {
             trace.Log("BEFORE:\t" + node);
         }
         node.SetInstruction(IRInstruction.MoveInt32, virtualRegister, node.Operand3);
         if (trace.Active)
         {
             trace.Log("AFTER: \t" + node);
         }
     }
     else if (node.Instruction == IRInstruction.StoreInt64)
     {
         if (trace.Active)
         {
             trace.Log("BEFORE:\t" + node);
         }
         node.SetInstruction(IRInstruction.MoveInt64, virtualRegister, node.Operand3);
         if (trace.Active)
         {
             trace.Log("AFTER: \t" + node);
         }
     }
     else if (node.Instruction == IRInstruction.MemorySet)
     {
         if (node.Operand3.ConstantUnsignedLongInteger == 4)
         {
             if (trace.Active)
             {
                 trace.Log("BEFORE:\t" + node);
             }
             node.SetInstruction(IRInstruction.MoveInt32, virtualRegister, node.Operand2);
             if (trace.Active)
             {
                 trace.Log("AFTER: \t" + node);
             }
         }
         else if (node.Operand3.ConstantUnsignedLongInteger == 8)
         {
             if (trace.Active)
             {
                 trace.Log("BEFORE:\t" + node);
             }
             node.SetInstruction(IRInstruction.MoveInt64, virtualRegister, node.Operand2);
             if (trace.Active)
             {
                 trace.Log("AFTER: \t" + node);
             }
         }
     }
     else if (node.Instruction == IRInstruction.LoadInt32)
     {
         if (trace.Active)
         {
             trace.Log("BEFORE:\t" + node);
         }
         node.SetInstruction(IRInstruction.MoveInt32, node.Result, virtualRegister);
         if (trace.Active)
         {
             trace.Log("AFTER: \t" + node);
         }
     }
     else if (node.Instruction == IRInstruction.LoadInt64)
     {
         if (trace.Active)
         {
             trace.Log("BEFORE:\t" + node);
         }
         node.SetInstruction(IRInstruction.MoveInt64, node.Result, virtualRegister);
         if (trace.Active)
         {
             trace.Log("AFTER: \t" + node);
         }
     }
 }
        private void DeadCodeEliminationPhi(InstructionNode node)
        {
            if (node.IsEmpty)
                return;

            if (node.Instruction != IRInstruction.Phi)
                return;

            if (node.Result.Definitions.Count != 1)
                return;

            var result = node.Result;

            foreach (var use in result.Uses)
            {
                if (use != node)
                    return;
            }

            AddOperandUsageToWorkList(node);
            if (trace.Active) trace.Log("*** DeadCodeEliminationPhi");
            if (trace.Active) trace.Log("REMOVED:\t" + node.ToString());
            node.SetInstruction(IRInstruction.Nop);
            deadCodeEliminationPhi++;
            changeCount++;
        }
 private void Nop(InstructionNode node)
 {
     node.SetInstruction(X86.Nop);
 }
        /// <summary>
        /// Folds integer compare branch.
        /// </summary>
        /// <param name="node">The node.</param>
        private void FoldIntegerCompareBranch(InstructionNode node)
        {
            if (node.IsEmpty)
                return;

            if (node.Instruction != IRInstruction.IntegerCompareBranch)
                return;

            Debug.Assert(node.OperandCount == 2);

            Operand op1 = node.Operand1;
            Operand op2 = node.Operand2;

            if (!op1.IsConstant || !op2.IsConstant)
                return;

            Operand result = node.Result;
            InstructionNode nextNode = node.Next;

            if (nextNode.Instruction != IRInstruction.Jmp)
                return;

            if (node.BranchTargets[0] == nextNode.BranchTargets[0])
            {
                if (trace.Active) trace.Log("*** FoldIntegerCompareBranch-Useless");
                if (trace.Active) trace.Log("REMOVED:\t" + node.ToString());
                AddOperandUsageToWorkList(node);
                node.SetInstruction(IRInstruction.Nop);
                instructionsRemovedCount++;
                foldIntegerCompareBranchCount++;
                changeCount++;
                return;
            }

            bool compareResult = true;

            switch (node.ConditionCode)
            {
                case ConditionCode.Equal: compareResult = (op1.ConstantUnsignedLongInteger == op2.ConstantUnsignedLongInteger); break;
                case ConditionCode.NotEqual: compareResult = (op1.ConstantUnsignedLongInteger != op2.ConstantUnsignedLongInteger); break;
                case ConditionCode.GreaterOrEqual: compareResult = (op1.ConstantUnsignedLongInteger >= op2.ConstantUnsignedLongInteger); break;
                case ConditionCode.GreaterThan: compareResult = (op1.ConstantUnsignedLongInteger > op2.ConstantUnsignedLongInteger); break;
                case ConditionCode.LessOrEqual: compareResult = (op1.ConstantUnsignedLongInteger <= op2.ConstantUnsignedLongInteger); break;
                case ConditionCode.LessThan: compareResult = (op1.ConstantUnsignedLongInteger < op2.ConstantUnsignedLongInteger); break;

                // TODO: Add more
                default: return;
            }

            BasicBlock notTaken;
            InstructionNode notUsed;

            if (trace.Active) trace.Log("*** FoldIntegerCompareBranch");

            if (compareResult)
            {
                notTaken = nextNode.BranchTargets[0];
                if (trace.Active) trace.Log("BEFORE:\t" + node.ToString());
                node.SetInstruction(IRInstruction.Jmp, node.BranchTargets[0]);
                if (trace.Active) trace.Log("AFTER:\t" + node.ToString());

                notUsed = nextNode;
            }
            else
            {
                notTaken = node.BranchTargets[0];
                notUsed = node;
            }

            if (trace.Active) trace.Log("REMOVED:\t" + node.ToString());
            AddOperandUsageToWorkList(notUsed);
            notUsed.SetInstruction(IRInstruction.Nop);
            instructionsRemovedCount++;
            foldIntegerCompareBranchCount++;
            changeCount++;

            // if target block no longer has any predecessors (or the only predecessor is itself), remove all instructions from it.
            CheckAndClearEmptyBlock(notTaken);
        }
        private void StoreInt8(InstructionNode node)
        {
            LoadStore.OrderStoreOperands(node, MethodCompiler);

            node.SetInstruction(X86.MovStore8, null, node.Operand1, node.Operand2, node.Operand3);
        }
        private void ReduceTruncationAndExpansion(InstructionNode node)
        {
            if (node.IsEmpty)
                return;

            if (node.Instruction != IRInstruction.ZeroExtendedMove)
                return;

            if (!node.Operand1.IsVirtualRegister)
                return;

            if (!node.Result.IsVirtualRegister)
                return;

            if (node.Result.Uses.Count != 1)
                return;

            if (node.Result.Definitions.Count != 1)
                return;

            if (node.Operand1.Uses.Count != 1 || node.Operand1.Definitions.Count != 1)
                return;

            var node2 = node.Operand1.Definitions[0];

            if (node2.Instruction != IRInstruction.Move)
                return;

            if (node2.Result.Uses.Count != 1)
                return;

            Debug.Assert(node2.Result.Definitions.Count == 1);

            if (node2.Operand1.Type != node.Result.Type)
                return;

            if (trace.Active) trace.Log("*** ReduceTruncationAndExpansion");
            AddOperandUsageToWorkList(node2);
            AddOperandUsageToWorkList(node);
            if (trace.Active) trace.Log("BEFORE:\t" + node2.ToString());
            node2.Result = node.Result;
            if (trace.Active) trace.Log("AFTER: \t" + node2.ToString());
            if (trace.Active) trace.Log("REMOVED:\t" + node2.ToString());
            node.SetInstruction(IRInstruction.Nop);
            reduceTruncationAndExpansionCount++;
            instructionsRemovedCount++;
            changeCount++;
        }
 private void StoreParamInt8(InstructionNode node)
 {
     node.SetInstruction(X86.MovStore8, null, StackFrame, node.Operand1, node.Operand2);
 }
        private void ReduceZeroExtendedMove(InstructionNode node)
        {
            if (node.IsEmpty)
                return;

            if (node.Instruction != IRInstruction.ZeroExtendedMove)
                return;

            if (!node.Operand1.IsVirtualRegister)
                return;

            if (!node.Result.IsVirtualRegister)
                return;

            if (trace.Active) trace.Log("*** ReduceZeroExtendedMove");
            AddOperandUsageToWorkList(node);
            if (trace.Active) trace.Log("BEFORE:\t" + node.ToString());
            node.SetInstruction(IRInstruction.Move, node.Result, node.Operand1);
            if (trace.Active) trace.Log("AFTER: \t" + node.ToString());
            reduceZeroExtendedMoveCount++;
            changeCount++;
        }
Exemplo n.º 53
0
        private void LoadFloatR8(InstructionNode node)
        {
            Debug.Assert(node.Result.IsR8);

            node.SetInstruction(X86.MovsdLoad, node.Result, node.Operand1, node.Operand2);
        }
        /// <summary>
        /// Removes the unless integer compare branch.
        /// </summary>
        /// <param name="node">The node.</param>
        private void RemoveUselessIntegerCompareBranch(InstructionNode node)
        {
            if (node.IsEmpty)
                return;

            if (node.Instruction != IRInstruction.IntegerCompareBranch)
                return;

            if (node.Block.NextBlocks.Count != 1)
                return;

            if (trace.Active) trace.Log("REMOVED:\t" + node.ToString());
            AddOperandUsageToWorkList(node);
            node.SetInstruction(IRInstruction.Nop);
            instructionsRemovedCount++;
            removeUselessIntegerCompareBranch++;
            changeCount++;
        }
Exemplo n.º 55
0
 private void LoadParamInt32(InstructionNode node)
 {
     node.SetInstruction(X86.MovLoad32, node.Result, StackFrame, node.Operand1);
 }
        private void PerformStaticAllocationOf(InstructionNode allocation, InstructionNode assignment)
        {
            var allocatedType = (allocation.InvokeMethod != null) ? allocation.InvokeMethod.DeclaringType : allocation.Result.Type;
            var assignmentField = assignment.MosaField;

            // Get size of type
            int typeSize = TypeLayout.GetTypeSize(allocatedType);

            // If instruction is newarr then get the size of the element, multiply it by array size, and add array header size
            // Also need to align to a 4-byte boundary
            if (allocation.Instruction is NewarrInstruction)
            {
                int elements = GetConstant(allocation.Operand1);
                typeSize = (TypeLayout.GetTypeSize(allocatedType.ElementType) * elements) + (TypeLayout.NativePointerSize * 3);
            }

            // Allocate a linker symbol to refer to this allocation. Use the destination field name as the linker symbol name.
            var symbolName = MethodCompiler.Linker.CreateSymbol(assignmentField.FullName + @"<<$cctor", SectionKind.ROData, Architecture.NativeAlignment, typeSize);

            // Try to get typeDefinitionSymbol if allocatedType isn't a value type
            string typeDefinitionSymbol = GetTypeDefinition(allocatedType);

            if (typeDefinitionSymbol != null)
            {
                MethodCompiler.Linker.Link(LinkType.AbsoluteAddress, PatchType.I4, symbolName, 0, 0, typeDefinitionSymbol, SectionKind.ROData, 0);
            }

            Operand staticAddress = Operand.CreateManagedSymbol(assignmentField.FieldType, symbolName.Name);
            Operand result1 = MethodCompiler.CreateVirtualRegister(assignmentField.FieldType);

            //Operand result2 = MethodCompiler.CreateVirtualRegister(assignmentField.FieldType);

            // Issue a load request before the newobj and before the assignment.
            new Context(allocation).InsertBefore().SetInstruction(CILInstruction.Get(OpCode.Ldc_i4), result1, staticAddress);
            assignment.Operand1 = result1;

            // If the instruction is a newarr
            if (allocation.Instruction is NewarrInstruction)
            {
                allocation.SetInstruction(CILInstruction.Get(OpCode.Ldc_i4), allocation.Result, result1);
                return;
            }

            //new Context(allocation).InsertBefore().SetInstruction(CILInstruction.Get(OpCode.Ldc_i4), result2, staticAddress);

            // Change the newobj to a call and increase the operand count to include the this ptr.
            // If the instruction is a newarr, then just replace with a nop instead
            allocation.Result = null;
            allocation.ResultCount = 0;
            allocation.OperandCount++;

            for (int i = allocation.OperandCount; i > 0; i--)
            {
                var op = allocation.GetOperand(i - 1);
                allocation.SetOperand(i, op);
            }

            allocation.Operand1 = result1;
            allocation.Instruction = CILInstruction.Get(OpCode.Call);
        }