private static bool GetUsedVersions(SSAUConstructorSparseEx ssa, VarVersionPair var, List <VarVersionNode> res) { VarVersionsGraph ssuversions = ssa.GetSsuversions(); VarVersionNode varnode = ssuversions.nodes.GetWithKey(var); HashSet <VarVersionNode> setVisited = new HashSet <VarVersionNode>(); HashSet <VarVersionNode> setNotDoms = new HashSet <VarVersionNode>(); LinkedList <VarVersionNode> stack = new LinkedList <VarVersionNode>(); stack.AddLast(varnode); while (!(stack.Count == 0)) { VarVersionNode nd = stack.RemoveAtReturningValue(0); setVisited.Add(nd); if (nd != varnode && (nd.flags & VarVersionNode.Flag_Phantom_Finexit) == 0) { res.Add(nd); } foreach (VarVersionEdge edge in nd.succs) { VarVersionNode succ = edge.dest; if (!setVisited.Contains(edge.dest)) { bool isDominated = true; foreach (VarVersionEdge prededge in succ.preds) { if (!setVisited.Contains(prededge.source)) { isDominated = false; break; } } if (isDominated) { stack.AddLast(succ); } else { setNotDoms.Add(succ); } } } } setNotDoms.RemoveAll(setVisited); return(!(setNotDoms.Count == 0)); }
private static void ReplaceSingleVar(Exprent parent, VarExprent var, Exprent dest , SSAUConstructorSparseEx ssau) { parent.ReplaceExprent(var, dest); // live sets SFormsFastMapDirect livemap = ssau.GetLiveVarVersionsMap(new VarVersionPair(var)); HashSet <VarVersionPair> setVars = GetAllVersions(dest); foreach (VarVersionPair varpaar in setVars) { VarVersionNode node = ssau.GetSsuversions().nodes.GetWithKey(varpaar); var toRemove = new List <KeyValuePair <int, FastSparseSetFactory <int> .FastSparseSet <int> > >(); var entryList = node.live.EntryList(); for (var index = 0; index < entryList.Count; index++) { var itent = entryList[index]; KeyValuePair <int, FastSparseSetFactory <int> .FastSparseSet <int> > ent = entryList.ElementAtOrDefault(index + 1); if (ent.Value == null) { break; } int key = ent.Key; if (!livemap.ContainsKey(key)) { toRemove.Add(itent); } else { FastSparseSetFactory <int> .FastSparseSet <int> set = ent.Value; set.Complement(livemap.Get(key)); if (set.IsEmpty()) { toRemove.Add(itent); } } } foreach (var keyValuePair in toRemove) { node.live.PutInternal(keyValuePair.Key, keyValuePair.Value, true); // entryList.RemoveAll(c => c.Key == keyValuePair.Key); } } }
public virtual void SimplifyStackVars(RootStatement root, StructMethod mt, StructClass cl) { HashSet <int> setReorderedIfs = new HashSet <int>(); SSAUConstructorSparseEx ssau = null; while (true) { bool found = false; SSAConstructorSparseEx ssa = new SSAConstructorSparseEx(); ssa.SplitVariables(root, mt); SimplifyExprentsHelper sehelper = new SimplifyExprentsHelper(ssau == null); while (sehelper.SimplifyStackVarsStatement(root, setReorderedIfs, ssa, cl)) { found = true; } SetVersionsToNull(root); SequenceHelper.CondenseSequences(root); ssau = new SSAUConstructorSparseEx(); ssau.SplitVariables(root, mt); if (IterateStatements(root, ssau)) { found = true; } SetVersionsToNull(root); if (!found) { break; } } // remove unused assignments ssau = new SSAUConstructorSparseEx(); ssau.SplitVariables(root, mt); IterateStatements(root, ssau); SetVersionsToNull(root); }
private bool IterateStatements(RootStatement root, SSAUConstructorSparseEx ssa) { FlattenStatementsHelper flatthelper = new FlattenStatementsHelper(); DirectGraph dgraph = flatthelper.BuildDirectGraph(root); bool res = false; HashSet <DirectNode> setVisited = new HashSet <DirectNode>(); LinkedList <DirectNode> stack = new LinkedList <DirectNode>(); LinkedList <Dictionary <VarVersionPair, Exprent> > stackMaps = new LinkedList <Dictionary <VarVersionPair, Exprent> >(); stack.AddLast(dgraph.first); stackMaps.AddLast(new Dictionary <VarVersionPair, Exprent>()); while (!(stack.Count == 0)) { DirectNode nd = Sharpen.Collections.RemoveFirst(stack); Dictionary <VarVersionPair, Exprent> mapVarValues = Sharpen.Collections.RemoveFirst (stackMaps); if (setVisited.Contains(nd)) { continue; } setVisited.Add(nd); List <List <Exprent> > lstLists = new List <List <Exprent> >(); if (!(nd.exprents.Count == 0)) { lstLists.Add(nd.exprents); } if (nd.succs.Count == 1) { DirectNode ndsucc = nd.succs[0]; if (ndsucc.type == DirectNode.Node_Tail && !(ndsucc.exprents.Count == 0)) { lstLists.Add(nd.succs[0].exprents); nd = ndsucc; } } for (int i = 0; i < lstLists.Count; i++) { List <Exprent> lst = lstLists[i]; int index = 0; while (index < lst.Count) { Exprent next = null; if (index == lst.Count - 1) { if (i < lstLists.Count - 1) { next = lstLists[i + 1][0]; } } else { next = lst[index + 1]; } int[] ret = IterateExprent(lst, index, next, mapVarValues, ssa); if (ret[0] >= 0) { index = ret[0]; } else { index++; } res |= (ret[1] == 1); } } foreach (DirectNode ndx in nd.succs) { stack.AddLast(ndx); stackMaps.AddLast(new Dictionary <VarVersionPair, Exprent>(mapVarValues)); } // make sure the 3 special exprent lists in a loop (init, condition, increment) are not empty // change loop type if necessary if ((nd.exprents.Count == 0) && (nd.type == DirectNode.Node_Init || nd.type == DirectNode .Node_Condition || nd.type == DirectNode.Node_Increment)) { nd.exprents.Add(null); if (nd.statement.type == Statement.Type_Do) { DoStatement loop = (DoStatement)nd.statement; if (loop.GetLooptype() == DoStatement.Loop_For && loop.GetInitExprent() == null && loop.GetIncExprent() == null) { // "downgrade" loop to 'while' loop.SetLooptype(DoStatement.Loop_While); } } } } return(res); }
private static Dictionary <int, HashSet <VarVersionPair> > GetAllVarVersions(VarVersionPair leftvar, Exprent exprent, SSAUConstructorSparseEx ssau) { Dictionary <int, HashSet <VarVersionPair> > map = new Dictionary <int, HashSet <VarVersionPair > >(); SFormsFastMapDirect mapLiveVars = ssau.GetLiveVarVersionsMap(leftvar); List <Exprent> lst = exprent.GetAllExprents(true); lst.Add(exprent); foreach (Exprent expr in lst) { if (expr.type == Exprent.Exprent_Var) { int varindex = ((VarExprent)expr).GetIndex(); if (leftvar.var != varindex) { if (mapLiveVars.ContainsKey(varindex)) { HashSet <VarVersionPair> verset = new HashSet <VarVersionPair>(); foreach (int vers in mapLiveVars.Get(varindex)) { verset.Add(new VarVersionPair(varindex, vers)); } Sharpen.Collections.Put(map, varindex, verset); } else { throw new Exception("inkonsistent live map!"); } } else { Sharpen.Collections.Put(map, varindex, null); } } else if (expr.type == Exprent.Exprent_Field) { if (ssau.GetMapFieldVars().ContainsKey(expr.id)) { int?varindex = ssau.GetMapFieldVars().GetOrNullable(expr.id); if (mapLiveVars.ContainsKey(varindex.Value)) { HashSet <VarVersionPair> verset = new HashSet <VarVersionPair>(); foreach (int vers in mapLiveVars.Get(varindex.Value)) { verset.Add(new VarVersionPair(varindex.Value, vers)); } Sharpen.Collections.Put(map, varindex.Value, verset); } } } } return(map); }
private static bool IsVersionToBeReplaced(VarVersionPair usedvar, Dictionary <int , HashSet <VarVersionPair> > mapVars, SSAUConstructorSparseEx ssau, VarVersionPair leftpaar) { VarVersionsGraph ssuversions = ssau.GetSsuversions(); SFormsFastMapDirect mapLiveVars = ssau.GetLiveVarVersionsMap(usedvar); if (mapLiveVars == null) { // dummy version, predecessor of a phi node return(false); } // compare protected ranges if (!InterpreterUtil.EqualObjects(ssau.GetMapVersionFirstRange().GetOrNullable(leftpaar ), ssau.GetMapVersionFirstRange().GetOrNullable(usedvar))) { return(false); } foreach (KeyValuePair <int, HashSet <VarVersionPair> > ent in mapVars) { FastSparseSetFactory <int> .FastSparseSet <int> liveverset = mapLiveVars.Get(ent.Key); if (liveverset == null) { return(false); } HashSet <VarVersionNode> domset = new HashSet <VarVersionNode>(); foreach (VarVersionPair verpaar in ent.Value) { domset.Add(ssuversions.nodes.GetWithKey(verpaar)); } bool isdom = false; foreach (int livever in liveverset) { VarVersionNode node = ssuversions.nodes.GetWithKey(new VarVersionPair(ent.Key, livever )); if (ssuversions.IsDominatorSet(node, domset)) { isdom = true; break; } } if (!isdom) { return(false); } } return(true); }
private static object[] IterateChildExprent(Exprent exprent, Exprent parent, Exprent next, Dictionary <VarVersionPair, Exprent> mapVarValues, SSAUConstructorSparseEx ssau) { bool changed = false; foreach (Exprent expr in exprent.GetAllExprents()) { var oldExpr = expr; while (true) { object[] arr = IterateChildExprent(oldExpr, parent, next, mapVarValues, ssau); Exprent retexpr = (Exprent)arr[0]; changed |= (bool)arr[1]; bool isReplaceable = (bool)arr[2]; if (retexpr != null) { if (isReplaceable) { ReplaceSingleVar(exprent, (VarExprent)oldExpr, retexpr, ssau); oldExpr = retexpr; } else { exprent.ReplaceExprent(oldExpr, retexpr); } changed = true; } if (!isReplaceable) { break; } } } Exprent dest = IsReplaceableVar(exprent, mapVarValues); if (dest != null) { return(new object[] { dest, true, true }); } VarExprent left = null; Exprent right = null; if (exprent.type == Exprent.Exprent_Assignment) { AssignmentExprent @as = (AssignmentExprent)exprent; if (@as.GetLeft().type == Exprent.Exprent_Var) { left = (VarExprent)@as.GetLeft(); right = @as.GetRight(); } } if (left == null) { return(new object[] { null, changed, false }); } bool isHeadSynchronized = false; if (next == null && parent.type == Exprent.Exprent_Monitor) { MonitorExprent monexpr = (MonitorExprent)parent; if (monexpr.GetMonType() == MonitorExprent.Monitor_Enter && exprent.Equals(monexpr .GetValue())) { isHeadSynchronized = true; } } // stack variable or synchronized head exprent if (!left.IsStack() && !isHeadSynchronized) { return(new object[] { null, changed, false }); } VarVersionPair leftpaar = new VarVersionPair(left); List <VarVersionNode> usedVers = new List <VarVersionNode>(); bool notdom = GetUsedVersions(ssau, leftpaar, usedVers); if (!notdom && (usedVers.Count == 0)) { return(new object[] { right, changed, false }); } // stack variables only if (!left.IsStack()) { return(new object[] { null, changed, false }); } int useflags = right.GetExprentUse(); if ((useflags & Exprent.Both_Flags) != Exprent.Both_Flags) { return(new object[] { null, changed, false }); } Dictionary <int, HashSet <VarVersionPair> > mapVars = GetAllVarVersions(leftpaar, right , ssau); if (mapVars.ContainsKey(leftpaar.var) && notdom) { return(new object[] { null, changed, false }); } Sharpen.Collections.Remove(mapVars, leftpaar.var); HashSet <VarVersionPair> setAllowedVars = GetAllVersions(parent); if (next != null) { Sharpen.Collections.AddAll(setAllowedVars, GetAllVersions(next)); } bool vernotreplaced = false; HashSet <VarVersionPair> setTempUsedVers = new HashSet <VarVersionPair>(); foreach (VarVersionNode usedvar in usedVers) { VarVersionPair usedver = new VarVersionPair(usedvar.var, usedvar.version); if (IsVersionToBeReplaced(usedver, mapVars, ssau, leftpaar) && (right.type == Exprent .Exprent_Var || setAllowedVars.Contains(usedver))) { setTempUsedVers.Add(usedver); } else { vernotreplaced = true; } } if (!notdom && !vernotreplaced) { foreach (VarVersionPair usedver in setTempUsedVers) { Exprent copy = right.Copy(); if (right.type == Exprent.Exprent_Field && ssau.GetMapFieldVars().ContainsKey(right .id)) { Sharpen.Collections.Put(ssau.GetMapFieldVars(), copy.id, ssau.GetMapFieldVars().GetOrNullable (right.id)); } Sharpen.Collections.Put(mapVarValues, usedver, copy); } // remove assignment return(new object[] { right, changed, false }); } return(new object[] { null, changed, false }); }
private int[] IterateExprent(List <Exprent> lstExprents, int index, Exprent next, Dictionary <VarVersionPair, Exprent> mapVarValues, SSAUConstructorSparseEx ssau) { Exprent exprent = lstExprents[index]; int changed = 0; foreach (Exprent expr in exprent.GetAllExprents()) { var oldExpr = expr; while (true) { object[] arr = IterateChildExprent(oldExpr, exprent, next, mapVarValues, ssau); Exprent retexpr = (Exprent)arr[0]; changed |= (bool)arr[1] ? 1 : 0; bool isReplaceable = (bool)arr[2]; if (retexpr != null) { if (isReplaceable) { ReplaceSingleVar(exprent, (VarExprent)oldExpr, retexpr, ssau); oldExpr = retexpr; } else { exprent.ReplaceExprent(oldExpr, retexpr); } changed = 1; } if (!isReplaceable) { break; } } } // no var on the highest level, so no replacing VarExprent left = null; Exprent right = null; if (exprent.type == Exprent.Exprent_Assignment) { AssignmentExprent @as = (AssignmentExprent)exprent; if (@as.GetLeft().type == Exprent.Exprent_Var) { left = (VarExprent)@as.GetLeft(); right = @as.GetRight(); } } if (left == null) { return(new int[] { -1, changed }); } VarVersionPair leftpaar = new VarVersionPair(left); List <VarVersionNode> usedVers = new List <VarVersionNode>(); bool notdom = GetUsedVersions(ssau, leftpaar, usedVers); if (!notdom && (usedVers.Count == 0)) { if (left.IsStack() && (right.type == Exprent.Exprent_Invocation || right.type == Exprent.Exprent_Assignment || right.type == Exprent.Exprent_New)) { if (right.type == Exprent.Exprent_New) { // new Object(); permitted NewExprent nexpr = (NewExprent)right; if (nexpr.IsAnonymous() || nexpr.GetNewType().arrayDim > 0 || nexpr.GetNewType(). type != ICodeConstants.Type_Object) { return(new int[] { -1, changed }); } } lstExprents[index] = right; return(new int[] { index + 1, 1 }); } else if (right.type == Exprent.Exprent_Var) { lstExprents.RemoveAtReturningValue(index); return(new int[] { index, 1 }); } else { return(new int[] { -1, changed }); } } int useflags = right.GetExprentUse(); // stack variables only if (!left.IsStack() && (right.type != Exprent.Exprent_Var || ((VarExprent)right). IsStack())) { // special case catch(... ex) return(new int[] { -1, changed }); } if ((useflags & Exprent.Multiple_Uses) == 0 && (notdom || usedVers.Count > 1)) { return(new int[] { -1, changed }); } Dictionary <int, HashSet <VarVersionPair> > mapVars = GetAllVarVersions(leftpaar, right , ssau); bool isSelfReference = mapVars.ContainsKey(leftpaar.var); if (isSelfReference && notdom) { return(new int[] { -1, changed }); } HashSet <VarVersionPair> setNextVars = next == null ? null : GetAllVersions(next); // FIXME: fix the entire method! if (right.type != Exprent.Exprent_Const && right.type != Exprent.Exprent_Var && setNextVars != null && mapVars.ContainsKey(leftpaar.var)) { foreach (VarVersionNode usedvar in usedVers) { if (!setNextVars.Contains(new VarVersionPair(usedvar.var, usedvar.version))) { return(new int[] { -1, changed }); } } } Sharpen.Collections.Remove(mapVars, leftpaar.var); bool vernotreplaced = false; bool verreplaced = false; HashSet <VarVersionPair> setTempUsedVers = new HashSet <VarVersionPair>(); foreach (VarVersionNode usedvar in usedVers) { VarVersionPair usedver = new VarVersionPair(usedvar.var, usedvar.version); if (IsVersionToBeReplaced(usedver, mapVars, ssau, leftpaar) && (right.type == Exprent .Exprent_Const || right.type == Exprent.Exprent_Var || right.type == Exprent.Exprent_Field || setNextVars == null || setNextVars.Contains(usedver))) { setTempUsedVers.Add(usedver); verreplaced = true; } else { vernotreplaced = true; } } if (isSelfReference && vernotreplaced) { return(new int[] { -1, changed }); } else { foreach (VarVersionPair usedver in setTempUsedVers) { Exprent copy = right.Copy(); if (right.type == Exprent.Exprent_Field && ssau.GetMapFieldVars().ContainsKey(right .id)) { Sharpen.Collections.Put(ssau.GetMapFieldVars(), copy.id, ssau.GetMapFieldVars().GetOrNullable (right.id)); } Sharpen.Collections.Put(mapVarValues, usedver, copy); } } if (!notdom && !vernotreplaced) { // remove assignment lstExprents.RemoveAtReturningValue(index); return(new int[] { index, 1 }); } else if (verreplaced) { return(new int[] { index + 1, changed }); } else { return(new int[] { -1, changed }); } }