private void CategorizeIdentifier(SsaIdentifier sid) { if (sid.DefStatement.Instruction is DefInstruction && sid.DefStatement.Block == proc.EntryBlock) { // Reaching definition was a DefInstruction; flow.Preserved.Add(sid.OriginalIdentifier.Storage); return; } Assignment ass; if (sid.DefStatement.Instruction.As<Assignment>(out ass)) { if ((ass.Src == sid.OriginalIdentifier) || (sid.OriginalIdentifier.Storage == arch.StackRegister && ass.Src == proc.Frame.FramePointer)) { flow.Preserved.Add(sid.OriginalIdentifier.Storage); return; } Constant c; if (ass.Src.As<Constant>(out c)) { flow.Constants.Add(sid.OriginalIdentifier.Storage, c); // Fall through to Trashed below --v } } flow.Trashed.Add(sid.OriginalIdentifier.Storage); }
private Identifier Reg8(string name) { var mr = new RegisterStorage(name, ssaIds.Count, PrimitiveType.Byte); Identifier id = new Identifier(mr.Name, mr.DataType, mr); SsaIdentifier sid = new SsaIdentifier(id, id, null, null, false); ssaIds.Add(id, sid); return sid.Identifier; }
private void SetDefStatement(Statement stm, SsaIdentifier sid) { List<SsaIdentifier> sids; if (defsByStatement.TryGetValue(sid.DefStatement, out sids)) { sids.Remove(sid); } if (!defsByStatement.TryGetValue(stm, out sids)) { sids = new List<SsaIdentifier>(); defsByStatement.Add(stm, sids); } sids.Add(sid); }
public void OutpReplaceSimple() { var m = new ProcedureBuilder(); var block = m.Label("block"); var foo = new Identifier("foo", PrimitiveType.Word32, null); var pfoo = new Identifier("pfoo", PrimitiveType.Pointer32, null); m.Assign(foo, 3); var sid = new SsaIdentifier(foo, foo, m.Block.Statements.Last, null, false); var ssaIds = new SsaIdentifierCollection { { foo, sid } }; var opt = new OutParameterTransformer(null, ssaIds); opt.ReplaceDefinitionsWithOutParameter(foo, pfoo); Assert.AreEqual("*pfoo = 0x00000003", m.Block.Statements[0].ToString()); }
/// <summary> /// Chases a chain statements to locate the expression that /// defines the value of a condition code. /// </summary> /// <param name="sid"></param> /// <returns></returns> public void FindDefiningExpression(SsaIdentifier sid) { this.sid = sid; negated = false; stm = sid.DefStatement; if (stm != null) { Statement stmOld = null; defExpr = null; while (stm != null && defExpr == null) { stmOld = stm; stm = null; stmOld.Instruction.Accept(this); } } }
public void ReplaceDefinitionsWithOutParameter(Identifier id, Identifier idOut) { this.idOut = idOut; wl = new WorkList<Identifier>(); wl.Add(id); var visited = new HashSet<Statement>(); while (wl.GetWorkItem(out id)) { ssa = ssaIds[id]; stmDef = ssa.DefStatement; if (stmDef != null && !visited.Contains(stmDef)) { visited.Add(stmDef); iStmDef = stmDef.Block.Statements.IndexOf(stmDef); stmDef.Instruction = stmDef.Instruction.Accept(this); } } }
public void Transform() { foreach (var s in ssaIds) { sidGrf = s; if (!IsLocallyDefinedFlagGroup(sidGrf)) continue; var uses = new HashSet<Statement>(); aliases = new HashSet<SsaIdentifier>(); ClosureOfUsingStatements(sidGrf, sidGrf.DefExpression, uses, aliases); if (trace.TraceInfo) Debug.WriteLine(string.Format("Tracing {0}", sidGrf.DefStatement.Instruction)); foreach (var u in uses) { useStm = u; if (trace.TraceInfo) Debug.WriteLine(string.Format(" used {0}", useStm.Instruction)); useStm.Instruction.Accept(this); if (trace.TraceInfo) Debug.WriteLine(string.Format(" now {0}", useStm.Instruction)); } } }
// Returns true if v is also live in before executing s. public bool LiveOutAtStatement(Statement s, SsaIdentifier v) { // v is live-out at s. List<Identifier> ids = this.IdentifiersDefinedAtStatement(s); if (ids != null) { foreach (Identifier id in ids) { if (id != v.Identifier) interference.Add(id, v.Identifier); } } return (v.DefStatement != s); }
public void LiveInAtStatement(Block b, int i, SsaIdentifier v) { // v is live-in at s. while (i > 0) { --i; Statement s = b.Statements[i]; if (IsDefinedAtStatement(v, s)) return; } // v is live-in at the header of this block! Set(records[b].LiveIn, v); foreach (Block p in b.Pred) { LiveOutAtBlock(p, v); } }
public void LiveOutAtBlock(Block b, SsaIdentifier v) { Set(records[b].LiveOut, v); if (!visited.Contains(b)) { visited.Add(b); Statement s = b.Statements.Last; if (!IsDefinedAtStatement(v, s)) LiveInAtStatement(b, b.Statements.Count - 1, v); } }
public bool IsDefinedAtStatement(SsaIdentifier v, Statement stm) { return (v.DefStatement == stm); }
public void RenameDominatedIdentifiers(SsaIdentifier sidOld, SsaIdentifier sidNew) { DominatedUseRenamer dur = new DominatedUseRenamer(doms); dur.Transform(sidOld, sidNew); }
public void OutpReplaceManyUses() { ProcedureBuilder m = new ProcedureBuilder(); Identifier foo = new Identifier("foo", PrimitiveType.Word32, null); Identifier bar = new Identifier("bar", PrimitiveType.Word32, null); Identifier pfoo = new Identifier("pfoo", PrimitiveType.Pointer32, null); Block block = m.Label("block"); m.Assign(foo, 1); Statement stmFoo = m.Block.Statements.Last; m.Assign(bar, foo); Statement stmBar = m.Block.Statements.Last; SsaIdentifier ssaFoo = new SsaIdentifier(foo, foo, stmFoo, ((Assignment) stmFoo.Instruction).Src, false); ssaFoo.Uses.Add(stmBar); SsaIdentifier ssaBar = new SsaIdentifier(bar, bar, stmBar, ((Assignment) stmBar.Instruction).Src, false); SsaIdentifierCollection ssaIds = new SsaIdentifierCollection(); ssaIds.Add(foo, ssaFoo); ssaIds.Add(bar, ssaBar); OutParameterTransformer opt = new OutParameterTransformer(m.Procedure, ssaIds); opt.ReplaceDefinitionsWithOutParameter(foo, pfoo); Assert.AreEqual(3, block.Statements.Count); Assert.AreEqual("foo = 0x00000001", block.Statements[0].Instruction.ToString()); Assert.AreEqual("*pfoo = foo", block.Statements[1].Instruction.ToString()); Assert.AreEqual("bar = foo", block.Statements[2].Instruction.ToString()); }
private void LiveInAtStatement(Block block, int iStm, SsaIdentifier sid) { if (iStm <= 0) { foreach (Block p in block.Pred) { LiveOutAtBlock(p, sid); } } else { LiveOutAtStatement(block, --iStm, sid); } }
public override void VisitIdentifier(Identifier id) { sid = ssaIds[id]; stm = sid.DefStatement; }
/// <summary> /// Coalesces the single use and the single definition of an identifier. /// </summary> /// <param name="sid"></param> /// <param name="defExpr"></param> /// <param name="def"></param> /// <param name="use"></param> /// <returns></returns> public bool CoalesceStatements(SsaIdentifier sid, Expression defExpr, Statement def, Statement use) { PreCoalesceDump(sid, def, use); def.Instruction.Accept(new UsedIdentifierAdjuster(def, ssa.Identifiers, use)); use.Instruction.Accept(new IdentifierReplacer(ssa, use, sid.Identifier, defExpr)); List<SsaIdentifier> sids; if (defsByStatement.TryGetValue(def, out sids)) { foreach (SsaIdentifier s in sids) { if (s != sid) { s.DefStatement = use; SetDefStatement(use, s); } } } ssa.DeleteStatement(def); PostCoalesceDump(use); return true; }
/// <summary> /// Computes the close of a web of using statements. The <paramref name="uses"/> hash set /// will contain all non-trivial uses of the expression. /// </summary> /// <param name="sid"></param> /// <param name="expr"></param> /// <param name="uses"></param> public HashSet<Statement> ClosureOfUsingStatements( SsaIdentifier sid, Expression expr, HashSet<Statement> uses, HashSet<SsaIdentifier> aliases) { foreach (var use in sid.Uses) { if (uses.Contains(use)) continue; uses.Add(use); if (IsCopyWithOptionalCast(sid.Identifier, use)) { var ass = (Assignment)use.Instruction; var sidAlias = ssaIds[ass.Dst]; aliases.Add(sidAlias); ClosureOfUsingStatements(sidAlias, expr, uses, aliases); } } return uses; }
public Expression UseGrfConditionally(SsaIdentifier sid, ConditionCode cc) { GrfDefinitionFinder gf = new GrfDefinitionFinder(ssaIds); gf.FindDefiningExpression(sid); Expression e = gf.DefiningExpression; if (e == null) { return sid.Identifier; } BinaryExpression binDef = e as BinaryExpression; if (binDef != null) { if (gf.IsNegated) e = new UnaryExpression(Operator.Not, PrimitiveType.Bool, e); return e; } ConditionOf cof = e as ConditionOf; if (cof != null) { binDef = cof.Expression as BinaryExpression; if (binDef == null) binDef = CmpExpressionToZero(cof.Expression); return ComparisonFromConditionCode(cc, binDef, gf.IsNegated); } Application app = e as Application; if (app != null) { return sid.Identifier; } PhiFunction phi = e as PhiFunction; if (phi != null) { return sid.Identifier; } throw new NotImplementedException("NYI: e: " + e.ToString()); }
private bool IsLocallyDefinedFlagGroup(SsaIdentifier sid) { return sid.OriginalIdentifier.Storage is FlagGroupStorage && sid.DefStatement != null; }
private void Set(List<SsaIdentifier> s, SsaIdentifier v) { if (!s.Contains(v)) s.Add(v); }
/// <summary> /// Tries to move the assigment as far down the block as is possible. /// </summary> /// <param name="ass"></param> /// <param name="block"></param> /// <param name="i"></param> /// <returns>true if a change was made</returns> public bool TryMoveAssignment(Statement stmDef, SsaIdentifier sidDef, Expression defExpr, Block block, int initialPosition) { SideEffectFlags flagsDef = sef.FindSideEffect(stmDef.Instruction); for (int i = initialPosition + 1; i < block.Statements.Count; ++i) { Statement stm = block.Statements[i]; if (sidDef.Uses.Contains(stm)) { if (CanCoalesce(sidDef, stmDef, stm)) { Coalesced = true; return CoalesceStatements(sidDef, defExpr, stmDef, stm); } else { return MoveAssignment(initialPosition, i, block); } } if (stm.Instruction.IsControlFlow) { return MoveAssignment(initialPosition, i, block); } SideEffectFlags flagsStm = sef.FindSideEffect(stm.Instruction); if (sef.Conflict(flagsDef, flagsStm)) { return MoveAssignment(initialPosition, i, block); } } return MoveAssignment(initialPosition, block.Statements.Count, block); }
private void LiveOutAtBlock(Block n, SsaIdentifier sid) { if (!visitedBlocks.ContainsKey(n)) { visitedBlocks[n] = n; LiveOutAtStatement(n, n.Statements.Count-1, sid); } }
public Node(SsaIdentifier info) { this.info = info; if (info.DefStatement != null) { Assignment ass = info.DefStatement.Instruction as Assignment; if (ass != null) { this.lvalue = ass.Dst; return; } PhiAssignment phi = info.DefStatement.Instruction as PhiAssignment; if (phi != null) { this.lvalue = phi.Dst; return; } } this.lvalue = info.Identifier; }
public void LiveOutAtStatement(Block block, int iStm, SsaIdentifier sid) { Dictionary<SsaIdentifier, SsaIdentifier> W = iStm >= 0 ? VariablesDefinedByStatement(block.Statements[iStm]) : new Dictionary<SsaIdentifier,SsaIdentifier>(); foreach (SsaIdentifier w in W.Values) { if (w != sid) interference.Add(w.Identifier, sid.Identifier); } if (!W.ContainsKey(sid)) LiveInAtStatement(block, iStm, sid); }
/// <summary> /// Returns true if the identifer <paramref name="sid"/>, which is defined in <paramref name="def"/>, can safely /// be coalesced into <paramref name="use"/>. /// </summary> /// <param name="sid">identifier common to <paramref name="def"/> and <paramref name="use"/>.</param> /// <param name="def">Statement that defines <paramref name="sid"/>. </param> /// <param name="use">Statement that uses <paramref name="sid"/>. </param> /// <returns></returns> public bool CanCoalesce(SsaIdentifier sid, Statement def, Statement use) { if (sid.Uses.Count != 1) return false; System.Diagnostics.Debug.Assert(sid.Uses[0] == use); if (use.Instruction is PhiAssignment) return false; if (use.Instruction is UseInstruction) return false; //$PERFORMANCE: this loop might be slow and should be improved if possible. List<SsaIdentifier> sids; if (defsByStatement.TryGetValue(def, out sids)) { foreach (SsaIdentifier sidOther in sids) { if (sidOther != sid && sidOther.IsSideEffect) { if (sidOther.Uses.Contains(use)) return false; } } } return true; }
private static void PreCoalesceDump(SsaIdentifier sid, Statement def, Statement use) { if (trace.TraceInfo) { Debug.WriteLineIf(trace.TraceInfo, "Coalescing on " + sid.Identifier.ToString()); Debug.Indent(); Debug.WriteLineIf(trace.TraceInfo, def.Instruction.ToString()); Debug.WriteLineIf(trace.TraceInfo, use.Instruction.ToString()); Debug.Unindent(); } }
public void Transform(SsaIdentifier sidOld, SsaIdentifier sidNew) { this.sidOld = sidOld; this.sidNew = sidNew; foreach (Statement stm in sidOld.Uses) { stmCur = stm; if (domGraph.DominatesStrictly(sidOld.DefStatement, stm)) { stm.Instruction = stm.Instruction.Accept(this); } } }