private void OptimizationInBlock(TacExpr expr, ThreeAddressCode block, string tmpName) { var taCode = block.TACodeLines.First; while (taCode != null) { var node = taCode.Value; if (node is TacAssignmentNode assign) { TacExpr nodeExpr = new TacExpr(assign.FirstOperand, assign.Operation, assign.SecondOperand); string id = assign.LeftPartIdentifier; if (id == expr.FirstOperand || id == expr.SecondOperand) { block.TACodeLines.AddAfter(block.TACodeLines.Find(node), expr.CreateAssignNode(tmpName)); } if (nodeExpr.Equals(expr) && id != tmpName) { assign.FirstOperand = tmpName; assign.Operation = null; assign.SecondOperand = null; } } taCode = taCode.Next; } }
// public bool Optimize(AvailableExpressionsITA ita) public bool Optimize(IterationAlgorithm <TacNode> ita) { bool isUsed = false; var bb = ita.controlFlowGraph.SourceBasicBlocks; Dictionary <ThreeAddressCode, HashSet <TacNode> > IN = ita.InOut.In; Dictionary <ThreeAddressCode, HashSet <TacNode> > OUT = ita.InOut.Out; // переделываем IN OUT в нужный формат var IN_EXPR = new Dictionary <ThreeAddressCode, HashSet <TacExpr> >(); var OUT_EXPR = new Dictionary <ThreeAddressCode, HashSet <TacExpr> >(); foreach (var block in bb.BasicBlockItems) { HashSet <TacExpr> inNode = TransformHashSetNodeToExpr(IN[block]); IN_EXPR.Add(block, inNode); HashSet <TacExpr> outNode = TransformHashSetNodeToExpr(OUT[block]); OUT_EXPR.Add(block, outNode); } Dictionary <TacExpr, int> tacExprCount = new Dictionary <TacExpr, int>(); Dictionary <TacExpr, bool> varsExprChange = new Dictionary <TacExpr, bool>(); // ищем какие выражения нужно оптимизировать foreach (var block in bb.BasicBlockItems) { foreach (TacNode node in block.TACodeLines) { if (node is TacAssignmentNode assign) { if (assign.Operation != null && assign.SecondOperand != null) { TacExpr expr = new TacExpr(assign); if (!tacExprCount.Keys.Contains(expr)) { tacExprCount.Add(expr, 1); } else { tacExprCount[expr] += 1; } } } } } // проводим оптимизацию for (int blockInd = 0; blockInd < bb.BasicBlockItems.Count(); blockInd++) { var block = bb.BasicBlockItems[blockInd]; var codeLine = block.TACodeLines.First; foreach (var _expr in varsExprChange.Keys.ToArray()) { varsExprChange[_expr] = !IN_EXPR[block].Contains(_expr); } while (codeLine != null) { var node = codeLine.Value; if (node is TacAssignmentNode assign) { string assignId = assign.LeftPartIdentifier; TacExpr expr = new TacExpr(assign); bool isCommonExpr = false; if (idsForExprDic.Keys.Contains(expr) && idsForExprDic[expr] == assignId) { isCommonExpr = true; } // если выражений больше 1 делаем оптимизацию if (!isCommonExpr && tacExprCount.Keys.Contains(expr) && tacExprCount[expr] > 1) { isUsed = true; if (!varsExprChange.Keys.Contains(expr)) { varsExprChange.Add(expr, !IN_EXPR[block].Contains(expr)); } // если это первая замена общего выражения if (!idsForExprDic.Keys.Contains(expr)) { // создаём переменную для общего выражения string idName = TmpNameManager.Instance.GenerateTmpVariableName(); idsForExprDic.Add(expr, idName); block.TACodeLines.AddBefore(block.TACodeLines.Find(node), expr.CreateAssignNode(idName)); AssignRightPartVarReplace(assign, idName); varsExprChange[expr] = false; } else { string idName = idsForExprDic[expr]; // если это не замена общего выражения if (assignId != idName) { AssignRightPartVarReplace(assign, idName); } // если выражение недоступно на входе if (varsExprChange[expr]) { block.TACodeLines.AddBefore(block.TACodeLines.Find(node), expr.CreateAssignNode(idName)); varsExprChange[expr] = false; } } } // для всех оптимизируемых выражений foreach (var _expr in varsExprChange.Keys.ToArray()) { // если выражение недоступно на выходе и присваивание его изменяет if (_expr.FirstOperand == assignId || _expr.SecondOperand == assignId) { varsExprChange[_expr] = true; } } } codeLine = codeLine.Next; } } return(isUsed); }
public bool Optimize(ControlFlowGraph cfg) { bool isUsed = false; var bb = cfg.SourceBasicBlocks; for (int source = 0; source < bb.BasicBlockItems.Count(); source++) { var sourceBlock = bb.BasicBlockItems[source]; var sourceCodeLine = sourceBlock.TACodeLines.First; while (sourceCodeLine != null) { var sourceNode = sourceCodeLine.Value; if (sourceNode is TacAssignmentNode sourceAssign) { if (sourceAssign.SecondOperand == null) { break; } TacExpr sourceExpr = new TacExpr(sourceAssign.FirstOperand, sourceAssign.Operation, sourceAssign.SecondOperand); for (int target = 0; target < bb.BasicBlockItems.Count(); target++) { var targetBlock = bb.BasicBlockItems[target]; var targetCodeLine = targetBlock.TACodeLines.First; while (targetCodeLine != null) { var targetNode = targetCodeLine.Value; if (targetNode == sourceNode) { break; } if (targetNode is TacAssignmentNode targetAssign) { string targetAssignId = targetAssign.LeftPartIdentifier; bool isNeedAdditionaly = targetAssignId == sourceExpr.FirstOperand || targetAssignId == sourceExpr.SecondOperand; TacExpr targetExpr = new TacExpr(targetAssign.FirstOperand, targetAssign.Operation, targetAssign.SecondOperand); if (targetExpr.Equals(sourceExpr) || isNeedAdditionaly) { string tmpName = null; HashSet <ThreeAddressCode> hashSet = null; bool isIdVar = infoDictionary.ContainsKey(sourceExpr); if (!isIdVar) { tmpName = TmpNameManager.Instance.GenerateTmpVariableName(); sourceBlock.TACodeLines.AddBefore(sourceBlock.TACodeLines.Find(sourceNode), sourceExpr.CreateAssignNode(tmpName)); OptimizationInBlock(sourceExpr, sourceBlock, tmpName); hashSet = new HashSet <ThreeAddressCode>(); hashSet.Add(sourceBlock); infoDictionary.Add(sourceExpr, new Tuple <string, HashSet <ThreeAddressCode> >(tmpName, hashSet)); } else { if (!infoDictionary.ContainsKey(sourceExpr)) { break; } var info = infoDictionary[sourceExpr]; tmpName = info.Item1; hashSet = info.Item2; } if (sourceBlock == targetBlock) { break; } bool isOptim = hashSet.Contains(targetBlock); if (!isOptim) { isUsed = true; hashSet.Add(targetBlock); OptimizationInBlock(sourceExpr, targetBlock, tmpName); break; } } } targetCodeLine = targetCodeLine.Next; } } } sourceCodeLine = sourceCodeLine.Next; } } return(isUsed); }