protected void RemoveUseless(InstructionNode node) { if (node.StatusRegister == StatusRegister.Set) { return; } if (node.ResultCount != 1) { return; } if (node.Result.IsCPURegister) /// same as if (!node.Result.IsVirtualRegister) { return; } if (node.Result.Uses.Count != 0) { return; } // Check is split child, if so check is parent in use (Manual.Return for example) if (node.Result.HasLongParent && node.Result.LongParent.Uses.Count != 0) { return; } trace?.Log($"REMOVED:\t{node}"); node.Empty(); changed = true; IRInstructionRemovedCount++; }
public void CallReg(InstructionNode node) { Debug.Assert(node.Operand1 != null); Debug.Assert(node.Operand1.IsCPURegister); var before = node.Previous; while (before.IsEmpty && !before.IsBlockStartInstruction) { before = before.Previous; } if (before == null || before.IsBlockStartInstruction) { return; } if (before.Instruction != X86.Mov32) { return; } if (!before.Result.IsCPURegister) { return; } if (node.Operand1.Register != before.Result.Register) { return; } before.SetInstruction(X86.Call, null, before.Operand1); node.Empty(); }
/// <summary> /// Replaces the intrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="methodCompiler">The method compiler.</param> void IIntrinsicInternalMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler) { var result = context.Result; var operand1 = context.Operand1; if (operand1.IsValueType) { InstructionNode def = operand1.Definitions[0]; var replacements = new List <Tuple <InstructionNode, int> >(); foreach (var use in operand1.Uses) { for (int i = 0; i < use.OperandCount; i++) { if (use.GetOperand(i) == operand1) { replacements.Add(new Tuple <InstructionNode, int>(use, i)); } } } foreach (var replace in replacements) { replace.Item1.SetOperand(replace.Item2, def.Operand1); } operand1 = def.Operand1; def.Empty(); } context.SetInstruction(IRInstruction.MoveInteger, result, operand1); }
/// <summary> /// Simple copy propagation. /// </summary> /// <param name="node">The node.</param> protected void Move(InstructionNode node) { var result = node.Result; var source = node.Operand1; if (!result.IsVirtualRegister) { return; } if (!source.IsVirtualRegister) { return; } if (result.Definitions.Count != 1) { return; } if (source.Definitions.Count != 1) { return; } if (source.IsResolvedConstant) { return; } Debug.Assert(result != source); changed = true; //ReplaceOperand(result, source); foreach (var useNode in result.Uses.ToArray()) { for (int i = 0; i < useNode.OperandCount; i++) { var operand = useNode.GetOperand(i); if (result == operand) { trace?.Log("*** SimpleForwardCopyPropagation"); trace?.Log($"BEFORE:\t{useNode}"); useNode.SetOperand(i, source); trace?.Log($"AFTER: \t{useNode}"); } } } Debug.Assert(result.Uses.Count == 0); trace?.Log($"REMOVED:\t{node}"); node.Empty(); IRInstructionRemovedCount++; }
private bool SimplePhiUpdate(InstructionNode node) { // Experiment var result = node.Result; if (result.Definitions.Count != 1) { return(false); } for (int i = 0; i < node.OperandCount; i++) { var operand = node.GetOperand(i); if (operand.IsConstant) { continue; } if (operand.Definitions.Count != 1) { return(false); } if (!operand.IsVirtualRegister) { return(false); } if (operand.Definitions[0].Block != node.PhiBlocks[i]) { return(false); } } for (int i = 0; i < node.OperandCount; i++) { var operand = node.GetOperand(i); if (operand.IsVirtualRegister) { operand.Definitions[0].Result = result; ReplaceOperand(operand, result); } else { InsertCopyStatement(node.PhiBlocks[i], result, operand); } } node.Empty(); return(true); }
/// <summary> /// Processes the phi instruction. /// </summary> /// <param name="node">The context.</param> private void ProcessPhiInstruction(InstructionNode node) { var sourceBlocks = node.PhiBlocks; for (var index = 0; index < node.Block.PreviousBlocks.Count; index++) { var operand = node.GetOperand(index); var predecessor = sourceBlocks[index]; InsertCopyStatement(predecessor, node.Result, operand); } node.Empty(); }
protected void RemoveUseless(InstructionNode node) { // Remove instruction, if useless if (node.ResultCount == 1 && node.Result.Uses.Count == 0 && node.Result.IsVirtualRegister) { // Check is split child, if so check is parent in use (IR.Return for example) if (node.Result.HasLongParent && node.Result.LongParent.Uses.Count != 0) { return; } trace?.Log($"REMOVED:\t{node}"); node.Empty(); changed = true; IRInstructionRemovedCount++; } }
private void RemoveUseless(InstructionNode node) { // Remove useless instructions if (node.ResultCount == 1 && node.Result.Uses.Count == 0 && node.Result.IsVirtualRegister) { // Check is split child, if so check is parent in use (IR.Return for example) if (node.Result.IsSplitChild && node.Result.SplitParent.Uses.Count != 0) { return; } if (trace.Active) { trace.Log("REMOVED:\t" + node); } node.Empty(); changed = true; instructionsRemovedCount++; } }
/// <summary> /// Simple copy propagation. /// </summary> /// <param name="node">The node.</param> private void Move(InstructionNode node) { Debug.Assert(node.Instruction == X86.Mov32); var result = node.Result; var source = node.Operand1; if (!result.IsVirtualRegister) { return; } if (!source.IsVirtualRegister) { return; } if (result.Definitions.Count != 1) { return; } if (source.Definitions.Count != 1) { return; } if (source.IsResolvedConstant) { return; } Debug.Assert(result != source); changed = true; foreach (var useNode in result.Uses.ToArray()) { for (int i = 0; i < useNode.OperandCount; i++) { var operand = useNode.GetOperand(i); if (result == operand) { if (trace.Active) { trace.Log("*** SimpleForwardCopyPropagation"); } if (trace.Active) { trace.Log("BEFORE:\t" + useNode); } useNode.SetOperand(i, source); if (trace.Active) { trace.Log("AFTER: \t" + useNode); } } } } Debug.Assert(result.Uses.Count == 0); if (trace.Active) { trace.Log("REMOVED:\t" + node); } node.Empty(); IRInstructionRemovedCount++; }
private void ProcessInstruction(InstructionNode node) { if (node.Instruction == IRInstruction.Load) { if (node.MosaType != null && TypeLayout.IsCompoundType(node.MosaType) && !node.MosaType.IsUI8 && !node.MosaType.IsR8) { if (node.Result.IsVirtualRegister && !repl.ContainsKey(node.Result)) { repl[node.Result] = MethodCompiler.StackLayout.AddStackLocal(node.MosaType); } node.ReplaceInstructionOnly(IRInstruction.CompoundLoad); } } else if (node.Instruction == IRInstruction.Store) { if (node.MosaType != null && TypeLayout.IsCompoundType(node.MosaType) && !node.MosaType.IsUI8 && !node.MosaType.IsR8) { if (node.Operand3.IsVirtualRegister && !repl.ContainsKey(node.Operand3)) { repl[node.Operand3] = MethodCompiler.StackLayout.AddStackLocal(node.MosaType); } node.ReplaceInstructionOnly(IRInstruction.CompoundStore); } } else if (node.Instruction == IRInstruction.Move) { if (node.Result.Type.Equals(node.Operand1.Type) && TypeLayout.IsCompoundType(node.Result.Type) && !node.Result.Type.IsUI8 && !node.Result.Type.IsR8) { // If this move is proceded by a return then remove this instruction // It is basically a double up caused by some instructions result in the same instruction output if (node.Next.Instruction == IRInstruction.Return && node.Next.Operand1 == node.Result) { node.Next.Operand1 = node.Operand1; var nopNode = new InstructionNode(IRInstruction.Nop); node.Previous.Insert(nopNode); node.Empty(); return; } // If this move is preceded by a compound move (which will turn into a compound move) remove this instruction // It is basically a double up caused by some instructions result in the same IR output if ((node.Previous.Instruction == IRInstruction.CompoundMove || node.Previous.Instruction == IRInstruction.CompoundLoad || node.Previous.Instruction == IRInstruction.Call) && node.Previous.Result == node.Operand1) { if (repl.ContainsKey(node.Previous.Result)) { repl[node.Result] = repl[node.Previous.Result]; repl.Remove(node.Previous.Result); } node.Previous.Result = node.Result; var nopNode = new InstructionNode(IRInstruction.Nop); node.Previous.Insert(nopNode); node.Empty(); return; } if (node.Result.IsVirtualRegister && !repl.ContainsKey(node.Result)) { repl[node.Result] = MethodCompiler.StackLayout.AddStackLocal(node.Result.Type); } if (node.Operand1.IsVirtualRegister && !repl.ContainsKey(node.Operand1)) { repl[node.Operand1] = MethodCompiler.StackLayout.AddStackLocal(node.Operand1.Type); } node.ReplaceInstructionOnly(IRInstruction.CompoundMove); } } else if (node.Instruction == IRInstruction.Call) { if (node.Result != null && TypeLayout.IsCompoundType(node.Result.Type) && !node.Result.Type.IsUI8 && !node.Result.Type.IsR8) { if (node.Result.IsVirtualRegister && !repl.ContainsKey(node.Result)) { repl[node.Result] = MethodCompiler.StackLayout.AddStackLocal(node.Result.Type); } } } }
private static void Empty(InstructionNode node) { node.Empty(); }
private void ProcessInstruction(InstructionNode node) { if (node.Instruction == IRInstruction.Load) { if (node.MosaType != null && TypeLayout.IsCompoundType(node.MosaType)) { if (node.Result.IsVirtualRegister && !repl.ContainsKey(node.Result)) { repl[node.Result] = MethodCompiler.StackLayout.AddStackLocal(node.MosaType); } node.ReplaceInstructionOnly(IRInstruction.CompoundLoad); } } else if (node.Instruction == IRInstruction.Store) { if (node.MosaType != null && TypeLayout.IsCompoundType(node.MosaType)) { if (node.Operand3.IsVirtualRegister && !repl.ContainsKey(node.Operand3)) { repl[node.Operand3] = MethodCompiler.StackLayout.AddStackLocal(node.MosaType); } node.ReplaceInstructionOnly(IRInstruction.CompoundStore); } } else if (node.Instruction == IRInstruction.Move) { if (node.Result.Type.Equals(node.Operand1.Type) && TypeLayout.IsCompoundType(node.Result.Type)) { var prevNode = node.Previous; var nextNode = node.Next; while (prevNode.IsEmpty) prevNode = prevNode.Previous; while (nextNode.IsEmpty) nextNode = nextNode.Next; // If this move is proceeded by a return then remove this instruction // It is basically a double up caused by some instructions result in the same instruction output if (nextNode.Instruction == IRInstruction.Return && nextNode.Operand1 == node.Result) { nextNode.Operand1 = node.Operand1; node.Empty(); return; } // If this move is preceded by a compound move (which will turn into a compound move) remove this instruction // It is basically a double up caused by some instructions result in the same IR output if ((prevNode.Instruction == IRInstruction.CompoundMove || prevNode.Instruction == IRInstruction.CompoundLoad || prevNode.Instruction == IRInstruction.Call) && prevNode.Result == node.Operand1) { if (repl.ContainsKey(prevNode.Result)) repl[node.Result] = repl[prevNode.Result]; prevNode.Result = node.Result; node.Empty(); return; } if (node.Result.IsVirtualRegister && !repl.ContainsKey(node.Result)) { repl[node.Result] = MethodCompiler.StackLayout.AddStackLocal(node.Result.Type); } if (node.Operand1.IsVirtualRegister && !repl.ContainsKey(node.Operand1)) { repl[node.Operand1] = MethodCompiler.StackLayout.AddStackLocal(node.Operand1.Type); } node.ReplaceInstructionOnly(IRInstruction.CompoundMove); } else if (node.Result.Type.Equals(node.Operand1.Type) && node.Result.IsStackLocal && node.Operand1.IsStackLocal) { node.ReplaceInstructionOnly(IRInstruction.CompoundMove); } } else if (node.Instruction == IRInstruction.Call) { if (node.Result != null && TypeLayout.IsCompoundType(node.Result.Type)) { if (node.Result.IsVirtualRegister && !repl.ContainsKey(node.Result)) { repl[node.Result] = MethodCompiler.StackLayout.AddStackLocal(node.Result.Type); } } } }