private void OutputDiagram() { var trace = CreateTraceLog("Diagram"); var sb = new StringBuilder(); trace.Log("digraph blocks {"); foreach (var headBlock in BasicBlocks.HeadBlocks) { var dominance = new SimpleFastDominance(BasicBlocks, headBlock); for (int i = 0; i < BasicBlocks.Count; i++) { var block = BasicBlocks[i]; var children = dominance.GetChildren(block); if (children != null && children.Count != 0) { foreach (var child in children) { trace.Log("\t" + block + " -> " + child); } } } } trace.Log("}"); }
/// <summary> /// Renames the variables. /// </summary> /// <param name="headBlock">The head block.</param> /// <param name="dominanceAnalysis">The dominance analysis.</param> private void RenameVariables(BasicBlock headBlock, SimpleFastDominance dominanceAnalysis) { var worklist = new Stack <BasicBlock>(); worklist.Push(headBlock); while (worklist.Count != 0) { var block = worklist.Pop(); if (block != null) { if (trace.Active) { trace.Log("Processing: " + block); } UpdateOperands(block); UpdatePHIs(block); worklist.Push(block); worklist.Push(null); if (trace.Active) { trace.Log(" >Pushed: " + block + " (Return)"); } // Repeat for all children of the dominance block, if any var children = dominanceAnalysis.GetChildren(block); if (children != null && children.Count > 0) { foreach (var s in children) { worklist.Push(s); if (trace.Active) { trace.Log(" >Pushed: " + s); } } } } else { block = worklist.Pop(); if (trace.Active) { trace.Log("Processing: " + block + " (Back)"); } UpdateResultOperands(block); } } }
/// <summary> /// Renames the variables. /// </summary> /// <param name="block">The block.</param> /// <param name="dominanceAnalysis">The dominance analysis.</param> private void RenameVariables2(BasicBlock block, SimpleFastDominance dominanceAnalysis) { trace?.Log($"Processing: {block}"); UpdateOperands(block); UpdatePHIs(block); // Repeat for all children of the dominance block, if any var children = dominanceAnalysis.GetChildren(block); if (children != null && children.Count != 0) { foreach (var s in children) { RenameVariables2(s, dominanceAnalysis); } } UpdateResultOperands(block); }
private void OutputList() { var trace = CreateTraceLog("List"); var sb = new StringBuilder(); foreach (var headBlock in BasicBlocks.HeadBlocks) { trace.Log("Head: " + headBlock); var dominance = new SimpleFastDominance(BasicBlocks, headBlock); for (int i = 0; i < BasicBlocks.Count; i++) { var block = BasicBlocks[i]; sb.Clear(); sb.Append(" Block "); sb.Append(block); sb.Append(" : "); var children = dominance.GetChildren(block); if (children != null && children.Count != 0) { foreach (var child in children) { sb.Append(child); sb.Append(", "); } sb.Length -= 2; } trace.Log(sb.ToString()); } trace.Log(); } }
private void ValueNumber(BasicBlock block, out List <BasicBlock> nextblocks, out List <Expression> newExpressions) { trace?.Log($"Processing Block: {block}"); //Debug.Assert(!Processed.Get(block.Sequence)); newExpressions = null; nextblocks = null; // Mark the beginning of the new scope by keeping a list bool successorValidated = false; bool successorProcessed = true; Processed.Set(block.Sequence, true); for (var node = block.AfterFirst; !node.IsBlockEndInstruction; node = node.Next) { if (node.IsEmptyOrNop) { continue; } if (IsPhiInstruction(node.Instruction)) { // Validate all successor are already processed // and if not, just set the value number if (!successorValidated) { successorValidated = true; foreach (var processed in block.PreviousBlocks) { if (!Processed.Get(block.Sequence)) { successorProcessed = false; break; } } } if (successorValidated && !successorProcessed) { SetValueNumber(node.Result, node.Result); continue; } // check for useless if (IsPhiUseless(node)) { var w = GetValueNumber(node.Operand1); SetValueNumber(node.Result, w); trace?.Log($"Removed Unless PHI: {node}"); node.SetInstruction(IRInstruction.Nop); InstructionRemovalCount++; continue; } // check for redundant var redundant = CheckRedundant(node); if (redundant != null) { var w = GetValueNumber(redundant); SetValueNumber(node.Result, w); trace?.Log($"Removed Redundant PHI: {node}"); node.SetInstruction(IRInstruction.Nop); InstructionRemovalCount++; continue; } SetValueNumber(node.Result, node.Result); continue; } UpdateNodeWithValueNumbers(node); // move constant to right for commutative operations - helpful later if (node.Instruction.IsCommutative && node.Operand1.IsResolvedConstant && node.Operand2.IsVirtualRegister) { var operand1 = node.Operand1; node.Operand1 = node.Operand2; node.Operand2 = operand1; } if (node.Instruction == IRInstruction.Move32 || node.Instruction == IRInstruction.Move64 || node.Instruction == IRInstruction.MoveR4 || node.Instruction == IRInstruction.MoveR8) { if (node.Result.IsCPURegister || node.Operand1.IsCPURegister) { SetValueNumber(node.Result, node.Result); continue; } // FUTURE: The check for IsSymbol (unresolved constant) should not be necessary if (node.Operand1.IsStackLocal || node.Operand1.IsOnStack || node.Operand1.IsSymbol) { SetValueNumber(node.Result, node.Result); continue; } SetValueNumber(node.Result, node.Operand1); node.SetInstruction(IRInstruction.Nop); InstructionRemovalCount++; continue; } if (!CanAssignValueNumberToExpression(node)) { if (node.ResultCount == 1) { SetValueNumber(node.Result, node.Result); } else if (node.ResultCount == 2) { SetValueNumber(node.Result, node.Result); SetValueNumber(node.Result2, node.Result2); } continue; } var hash = ComputeExpressionHash(node); var list = GetExpressionsByHash(hash); var match = FindMatch(list, node); if (match != null) { var w = GetValueNumber(match.ValueNumber); trace?.Log($"Found Expression Match: {node}"); SetValueNumber(node.Result, w); if (node.Instruction.IsParameterLoad) { ParameterLoadEliminationCount++; } node.SetInstruction(IRInstruction.Nop); InstructionRemovalCount++; SubexpressionEliminationCount++; continue; } else { trace?.Log($"No Expression Found: {node}"); } var newExpression = new Expression() { Hash = hash, Instruction = node.Instruction, Operand1 = node.Operand1, Operand2 = node.Operand2, ValueNumber = node.Result }; AddExpressionToHashTable(newExpression); Debug.Assert(FindMatch(GetExpressionsByHash(ComputeExpressionHash(node)), node) == newExpression); (newExpressions ?? (newExpressions = new List <Expression>())).Add(newExpression); if (node.Instruction.IsCommutative && node.Operand1 != node.Operand2) { var newExpression2 = new Expression() { Hash = hash, Instruction = node.Instruction, Operand1 = node.Operand2, Operand2 = node.Operand1, ValueNumber = node.Result }; AddExpressionToHashTable(newExpression2); newExpressions.Add(newExpression2); } SetValueNumber(node.Result, node.Result); } // For each successor of the block, adjust the φ-function inputs UpdatePhiSuccesors(block); var children = AnalysisDominance.GetChildren(block); if (children != null || children.Count == 0) { nextblocks = new List <BasicBlock>(children.Capacity); if (children.Count == 1) { // Efficient! nextblocks.Add(children[0]); //trace?.Log("Queue Block:" + children[0]); } else if (ReversePostOrder.Count < 32) { // Efficient for small sets foreach (var child in ReversePostOrder) { if (children.Contains(child)) { nextblocks.Add(child); //trace?.Log("Queue Block:" + child); } } } else { // Scalable for large sets var bitArray = new BitArray(BasicBlocks.Count, false); foreach (var child in children) { bitArray.Set(child.Sequence, true); } foreach (var child in ReversePostOrder) { if (bitArray.Get(child.Sequence)) { nextblocks.Add(child); //trace?.Log("Queue Block:" + child); } } } } }