/// <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++; }
private void Break(InstructionNode node) { node.SetInstruction(X86.Break); }
/// <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; } }
private void LoadParameterFloatR4(InstructionNode node) { Debug.Assert(node.Result.IsR4); node.SetInstruction(X86.MovssLoad, node.Size, node.Result, StackFrame, node.Operand1); }
private void LoadParamZeroExtend8x32(InstructionNode node) { node.SetInstruction(X86.MovzxLoad8, node.Result, StackFrame, node.Operand1); }
private void LogicalNot32(InstructionNode node) { node.SetInstruction(X86.Not32, node.Result, node.Operand1); }
private void BitCopyInt32ToFloatR4(InstructionNode node) { node.SetInstruction(X86.Movd, node.Result, node.Operand1); }
private void LoadParamSignExtend16x32(InstructionNode node) { node.SetInstruction(X86.MovsxLoad16, node.Result, StackFrame, node.Operand1); }
private void LogicalNot64(InstructionNode node) { node.SetInstruction(X64.Mov64, node.Result, node.Operand1); }
/// <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; }
/// <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++; }
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 }
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()); }
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; } }
/// <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); }
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); }
/// <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); }
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; } }
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; } } }
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++; }
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()); }
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]); }
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++; }
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; }
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++; }
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++; }
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); }