public void LiveOutAtBlock(Block b, SsaIdentifier v) { Set(records[b].LiveOut, v); if (!visited.Contains(b)) { visited.Add(b); var s = (b.Statements.Count > 0) ? b.Statements[^ 1] : null;
/// <summary> /// Computes the closure 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">The SSA identifier whose use-closure we're calculating</param> /// <param name="uses">Uses we've seen so far.</param> /// <param name="aliases">Aliases of sid we've seen so far.</param> public HashSet <Statement> ClosureOfUsingStatements( SsaIdentifier sid, HashSet <Statement> uses, HashSet <Identifier> aliases) { foreach (var use in sid.Uses) { if (uses.Contains(use)) { continue; } uses.Add(use); if (IsCopyWithOptionalCast(sid.Identifier, use)) { // Bypass copies (C_4 = C_3) and casts // (C_4 = SLICE(SZC_3, bool, 0) var ass = (Assignment)use.Instruction; var sidAlias = ssaIds[ass.Dst]; aliases.Add(sidAlias.Identifier); ClosureOfUsingStatements(sidAlias, uses, aliases); } if (use.Instruction is PhiAssignment phiAss) { // Bypass PHI nodes. var sidPhi = ssaIds[phiAss.Dst]; aliases.Add(sidPhi.Identifier); ClosureOfUsingStatements(sidPhi, uses, aliases); } } return(uses); }
private void Set(List <SsaIdentifier> s, SsaIdentifier v) { if (!s.Contains(v)) { s.Add(v); } }
public LinearInductionVariable CreateInductionVariable() { if (ctx.PhiStatement == null) { return(null); } if (ctx.PhiIdentifier == null) { return(null); } if (ctx.DeltaValue == null) { return(null); } SsaIdentifier sidPhi = ssaIds[ctx.PhiIdentifier]; if (ctx.TestStatement == null && ctx.InitialValue == null) { return(new LinearInductionVariable(null, ctx.DeltaValue, null, false)); } if (ctx.InitialValue != null) { if (IsIdUsedOnlyBy(ctx.PhiIdentifier, ctx.TestStatement, ctx.DeltaStatement)) { // The only use inside the loop is the increment, so we never see the initial value. ctx.InitialValue = Operator.IAdd.ApplyConstants(ctx.InitialValue, ctx.DeltaValue); } } ctx.TestValue = AdjustTestValue(ctx.TestValue); return(ctx.CreateInductionVariable()); }
/// <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); } if (use.Instruction is PhiAssignment phiAss) { var sidPhi = ssaIds[phiAss.Dst]; aliases.Add(sidPhi); ClosureOfUsingStatements(sidPhi, expr, uses, aliases); } } return(uses); }
public void Transform() { foreach (var s in ssaIds.ToList()) { 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)); } } } }
private static void GeneratePhiFunction(SsaIdentifier phi, PhiArgument[] args) { ((PhiAssignment)phi.DefStatement !.Instruction).Src = new PhiFunction( phi.Identifier.DataType, args); }
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 void ProcessAdjacentStores(SsaIdentifier sid, StoreOffset[] storeOffset) { for (int i = 0; i < storeOffset.Length; ++i) { if (storeOffset[i] == null) { continue; } var cast1 = GetCastRhs(storeOffset[i].Store); var slice1 = GetSliceRhs(storeOffset[i].Store); if (cast1 != null || slice1 != null) { for (int j = i + 1; j < storeOffset.Length; ++j) { var cast2 = GetCastRhs(storeOffset[j].Store); var slice2 = GetSliceRhs(storeOffset[j].Store); if (cast1 != null && slice2 != null) { ReplaceStores(sid, storeOffset[i], storeOffset[j]); storeOffset[i] = null !; storeOffset[j] = null !; } else if (slice1 != null && cast2 != null) { throw new NotImplementedException(); } } } } }
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); }
/// <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); }
/// <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)); }
public void Transform() { foreach (var s in ssaIds.ToList()) { sidGrf = s; if (!IsLocallyDefinedFlagGroup(sidGrf)) { continue; } if (sidGrf.DefStatement.Instruction is AliasAssignment) { continue; } var uses = new HashSet <Statement>(); this.aliases = new HashSet <Identifier>(); ClosureOfUsingStatements(sidGrf, uses, aliases); trace.Inform("Tracing {0}", sidGrf.DefStatement.Instruction); foreach (var u in uses) { useStm = u; trace.Inform(" used {0}", useStm.Instruction); useStm.Instruction.Accept(this); trace.Inform(" now {0}", useStm.Instruction); } } }
private Identifier Reg8(string name) { var mr = new RegisterStorage(name, ssaIds.Count, 0, 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; }
public void ReplaceAssigment(SsaIdentifier sid, Assignment ass) { var stm = sid.DefStatement !; ssa.RemoveUses(stm); sid.DefStatement !.Instruction = ass; ssa.AddUses(stm); }
private void LiveOutAtBlock(Block n, SsaIdentifier sid) { if (!visitedBlocks.ContainsKey(n)) { visitedBlocks[n] = n; LiveOutAtStatement(n, n.Statements.Count - 1, sid); } }
/// <summary> /// Ensure that identifier is alive. Simplify phi function until /// identifier is not in the list of removed phi identifiers /// </summary> /// <param name="sid">SSA identifier of phi function</param> /// <returns> /// Returns original SSA identifier or result of phi function /// simplification /// </returns> private SsaIdentifier EnsureLiveIdentifier(SsaIdentifier sid) { while (this.outer.sidsToRemove.Contains(sid)) { sid = SamePhiArgument(sid); } return(sid); }
private bool IsLocallyDefinedFlagGroup(SsaIdentifier sid) { var stg = sid.OriginalIdentifier.Storage; return((stg is FlagGroupStorage || stg is FlagRegister) && sid.DefStatement != null); }
public override void VisitIdentifier(Identifier id) { SsaIdentifier sid = ssa.Identifiers[id]; if (sid.DefStatement != null) { liveIds.Add(sid); } }
public IEnumerable <SsaIdentifier> GetSuccessors(SsaIdentifier sid) { this.operands = new List <SsaIdentifier>(); if (sid.DefStatement != null) { sid.DefStatement.Instruction.Accept(this); } return(operands); }
private SsaIdentifier AddPhiOperands(Identifier id, SsaIdentifier phi) { // Determine operands from predecessors. ((PhiAssignment)phi.DefStatement.Instruction).Src = new PhiFunction( id.DataType, phi.DefStatement.Block.Pred.Select(p => ReadVariable(id, p).Identifier).ToArray()); return(TryRemoveTrivial(phi)); }
public Identifier InsertAssignmentNewId(Identifier idOld, Block b, int i) { Statement stm = new Statement(0, null, b); SsaIdentifier sidNew = ssaIds.Add((Identifier)ssaIds[idOld].OriginalIdentifier, stm, idOld, false); stm.Instruction = new Assignment(sidNew.Identifier, idOld); b.Statements.Insert(i, stm); return(sidNew.Identifier); }
private void UsePhiArguments(SsaIdentifier phi) { var phiFunc = ((PhiAssignment)phi.DefStatement.Instruction).Src; foreach (var de in phiFunc.Arguments) { var id = (Identifier)de.Value; ssaIds[id].Uses.Add(phi.DefStatement); } }
public override Expression VisitTestCondition(TestCondition tc) { SsaIdentifier sid = ssaIds[(Identifier)tc.Expression]; sid.Uses.Remove(useStm !); Expression c = UseGrfConditionally(sid, tc.ConditionCode); Use(c, useStm !); return(c); }
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(); } }
private void DefineUninitializedIdentifier( Statement stm, SsaIdentifier sid) { var value = Constant.Invalid; var ass = new Assignment(sid.Identifier, value); var newStm = InsertStatementAfter(ass, stm); sid.DefExpression = value; sid.DefStatement = newStm; }
private Identifier Use(Identifier idOld) { SsaIdentifier sid; if (!ssa.Identifiers.TryGetValue(idOld, out sid)) { sid = new SsaIdentifier(idOld, idOld, stmCur, null, false); ssa.Identifiers.Add(idOld, sid); } ssa.Identifiers[idOld].Uses.Add(stmCur); return(idOld); }
public override void VisitIdentifier(Identifier id) { SsaIdentifier sid = ssaIds[id]; for (int i = 0; i < sid.Uses.Count; ++i) { if (sid.Uses[i] == def) { sid.Uses[i] = use; } } }
public Identifier InsertAssignmentNewId(Identifier idOld, Block b, int i) { var stm = new Statement( (b.Address ?? b.Procedure.EntryAddress).ToLinear(), null, b); SsaIdentifier sidNew = ssaIds.Add((Identifier)ssaIds[idOld].OriginalIdentifier, stm, idOld, false); stm.Instruction = new Assignment(sidNew.Identifier, idOld); b.Statements.Insert(i, stm); return(sidNew.Identifier); }
private Expression ReplaceMkSequence(MkSequence seq, Statement stmCur, SsaIdentifier sidHead, SsaIdentifier sidTail) { var idSeq = ssa.Procedure.Frame.EnsureSequence( seq.DataType, sidHead.OriginalIdentifier.Storage, sidTail.OriginalIdentifier.Storage); SsaIdentifier sidSeq = EnsureSequenceArgument(idSeq); sidSeq.Uses.Add(stmCur); RemoveUse(sidHead); RemoveUse(sidTail); return(sidSeq.Identifier); }
public bool IsIdUsedOnlyBy(Identifier id, Statement?stm1, Statement?stm2) { SsaIdentifier sid = ssa.Identifiers[id]; foreach (Statement u in sid.Uses) { if (u != stm1 && u != stm2) { return(false); } } return(true); }
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); } } }
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(); 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 Add(SsaIdentifier sid) { if (Members.Contains(sid)) // should be a set! return; Members.Add(sid); if (this.Identifier == null) { this.Identifier = sid.Identifier; } else { if (string.Compare(sid.Identifier.Name, this.Identifier.Name) < 0) { this.Identifier = sid.Identifier; } if (iv == null) { iv = sid.InductionVariable; } else if (sid.InductionVariable == null) { sid.InductionVariable = iv; } else { iv = LinearInductionVariable.Merge(sid.InductionVariable, iv); if (iv == null) { // Warning(string.Format("{0} and {1} are conflicting induction variables: {2} {3}", } sid.InductionVariable = iv; } } Definitions.Add(sid.DefStatement); foreach (Statement u in sid.Uses) Uses.Add(u); }
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)); } } }
public override void VisitIdentifier(Identifier id) { sid = ssaIds[id]; stm = sid.DefStatement; }
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); }
private void LiveOutAtBlock(Block n, SsaIdentifier sid) { if (!visitedBlocks.ContainsKey(n)) { visitedBlocks[n] = n; LiveOutAtStatement(n, n.Statements.Count-1, sid); } }
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); } }
// 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); }
private void Set(List<SsaIdentifier> s, SsaIdentifier v) { if (!s.Contains(v)) s.Add(v); }
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()); }
public void RenameDominatedIdentifiers(SsaIdentifier sidOld, SsaIdentifier sidNew) { DominatedUseRenamer dur = new DominatedUseRenamer(doms); dur.Transform(sidOld, sidNew); }
private bool IsLocallyDefinedFlagGroup(SsaIdentifier sid) { return sid.OriginalIdentifier.Storage is FlagGroupStorage && sid.DefStatement != null; }
/// <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; }
/// <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> /// 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); }
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 bool IsDefinedAtStatement(SsaIdentifier v, Statement stm) { return (v.DefStatement == stm); }
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 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); } }
/// <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 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); } } }
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 bool IsLocallyDefinedFlagGroup(SsaIdentifier sid) { var stg = sid.OriginalIdentifier.Storage; return (stg is FlagGroupStorage || stg is FlagRegister) && sid.DefStatement != null; }