public void RemoveStatementsFromExitBlock(SsaState ssa) { foreach (var stm in ssa.Procedure.ExitBlock.Statements.ToList()) { ssa.DeleteStatement(stm); } }
/// <summary> /// Remove any UseInstructions in the exit block of the procedure that /// can be proved to be dead out. /// </summary> /// <param name="ssa">SSA of the procedure whose exit block is to be examined.</param> /// <param name="wl">Worklist of SSA states.</param> /// <returns>True if any change was made to SSA.</returns> public bool RemoveUnusedDefinedValues(SsaState ssa, WorkList <SsaState> wl) { bool change = false; trace.Verbose("UVR: {0}", ssa.Procedure.Name); var(deadStms, deadStgs) = FindDeadStatementsInExitBlock(ssa, this.dataFlow[ssa.Procedure].BitsLiveOut); // Remove 'use' statements that are known to be dead from the exit block. foreach (var stm in deadStms) { trace.Verbose("UVR: {0}, deleting {1}", ssa.Procedure.Name, stm.Instruction); ssa.DeleteStatement(stm); change = true; } // If any instructions were removed, update the callers. if (!ssa.Procedure.Signature.ParametersValid && deadStms.Count > 0) { DeadCode.Eliminate(ssa); foreach (Statement stm in program.CallGraph.CallerStatements(ssa.Procedure)) { if (!(stm.Instruction is CallInstruction ci)) { continue; } var ssaCaller = this.procToSsa[stm.Block.Procedure]; if (RemoveDeadCallDefinitions(ssaCaller, ci, deadStgs)) { wl.Add(ssaCaller); } } } return(change); }
private void RemoveDefinition(Identifier id, Statement defStatement) { switch (defStatement.Instruction) { case CallInstruction ci: ci.Definitions.RemoveWhere(cb => cb.Expression == id); break; case PhiAssignment phi: ssa.DeleteStatement(defStatement); break; } }
private void ReplaceStores(SsaIdentifier sid, StoreOffset stoTail, StoreOffset stoHead) { if (Operator.Lt.ApplyConstants(stoTail.Offset, stoHead.Offset).ToBoolean()) { stoTail.Store.Dst.DataType = sid.Identifier.DataType; stoTail.Store.Src = sid.Identifier; ssa.DeleteStatement(stoHead.Statement); } else { throw new NotImplementedException(); } }
/// <summary> /// Remove any Use instruction that uses identifiers /// that are marked as preserved. /// </summary> /// <param name="ssa"></param> private void RemovePreservedUseInstructions(SsaState ssa) { var flow = this.flow[ssa.Procedure]; var deadStms = new List <Statement>(); foreach (var stm in ssa.Procedure.ExitBlock.Statements) { if (stm.Instruction is UseInstruction u && u.Expression is Identifier id && flow.Preserved.Contains(id.Storage)) { deadStms.Add(stm); } } foreach (var stm in deadStms) { ssa.DeleteStatement(stm); } }
/// <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); use.Instruction.Accept(new IdentifierReplacer(ssa.Identifiers, use, sid.Identifier, defExpr, false)); if (defsByStatement.TryGetValue(def, out var sids)) { foreach (SsaIdentifier s in sids) { if (s != sid) { s.DefStatement = use; SetDefStatement(use, s); } } } ssa.DeleteStatement(def); PostCoalesceDump(use); return(true); }
private void Eliminate() { liveIds = new WorkList <SsaIdentifier>(); HashSet <Statement> marks = new HashSet <Statement>(); // Initially, just mark those statements that contain critical statements. // These are calls to other functions, functions (which have side effects) and use statements. // Critical instructions must never be considered dead. foreach (var stm in proc.Statements) { if (critical.IsCritical(stm.Instruction)) { if (trace.TraceInfo) { Debug.WriteLineIf(trace.TraceInfo, string.Format("Critical: {0}", stm.Instruction)); } marks.Add(stm); stm.Instruction.Accept(this); // mark all used identifiers as live. } } // Each identifier is live, so its defining statement is also live. SsaIdentifier sid; while (liveIds.GetWorkItem(out sid)) { Statement def = sid.DefStatement; if (def != null) { if (!marks.Contains(def)) { if (trace.TraceInfo) { Debug.WriteLine(string.Format("Marked: {0}", def.Instruction)); } marks.Add(def); sid.DefStatement.Instruction.Accept(this); } } } // We have now marked all the useful instructions in the code. Any non-marked // instruction is now useless and should be deleted. foreach (Block b in proc.ControlGraph.Blocks) { for (int iStm = 0; iStm < b.Statements.Count; ++iStm) { Statement stm = b.Statements[iStm]; if (!marks.Contains(stm)) { if (trace.TraceInfo) { Debug.WriteLineIf(trace.TraceInfo, string.Format("Deleting: {0}", stm.Instruction)); } ssa.DeleteStatement(stm); --iStm; } } } AdjustApplicationsWithDeadReturnValues(); }
public void CreateLongInstruction(AddSubCandidate loCandidate, AddSubCandidate hiCandidate) { var totalSize = PrimitiveType.Create( Domain.SignedInt | Domain.UnsignedInt, loCandidate.Dst.DataType.BitSize + hiCandidate.Dst.DataType.BitSize); var left = CreateCandidate(loCandidate.Left, hiCandidate.Left, totalSize); var right = CreateCandidate(loCandidate.Right, hiCandidate.Right, totalSize); this.dst = CreateCandidate(loCandidate.Dst, hiCandidate.Dst, totalSize); var stmts = hiCandidate.Statement.Block.Statements; var linAddr = hiCandidate.Statement.LinearAddress; var iStm = FindInsertPosition(loCandidate, hiCandidate, stmts); Statement stmMkLeft = null; if (left is Identifier) { stmMkLeft = stmts.Insert( iStm++, linAddr, CreateMkSeq(left, hiCandidate.Left, loCandidate.Left)); left = ReplaceDstWithSsaIdentifier(left, null, stmMkLeft); } Statement stmMkRight = null; if (right is Identifier) { stmMkRight = stmts.Insert( iStm++, linAddr, CreateMkSeq(right, hiCandidate.Right, loCandidate.Right)); right = ReplaceDstWithSsaIdentifier(right, null, stmMkRight); } var expSum = new BinaryExpression(loCandidate.Op, left.DataType, left, right); Instruction instr = Assign(dst, expSum); var stmLong = stmts.Insert(iStm++, linAddr, instr); this.dst = ReplaceDstWithSsaIdentifier(this.dst, expSum, stmLong); var sidDst = GetSsaIdentifierOf(dst); var sidLeft = GetSsaIdentifierOf(left); var sidRight = GetSsaIdentifierOf(right); if (stmMkLeft != null && sidLeft != null) { GetSsaIdentifierOf(loCandidate.Left)?.Uses.Add(stmMkLeft); GetSsaIdentifierOf(hiCandidate.Left)?.Uses.Add(stmMkLeft); } if (stmMkRight != null && sidRight != null) { GetSsaIdentifierOf(loCandidate.Right)?.Uses.Add(stmMkRight); GetSsaIdentifierOf(hiCandidate.Right)?.Uses.Add(stmMkRight); } if (sidDst != null) { if (sidLeft != null) { sidLeft.Uses.Add(stmLong); } if (sidRight != null) { sidRight.Uses.Add(stmLong); } } var sidDstLo = GetSsaIdentifierOf(loCandidate.Dst); if (sidDstLo != null) { var cast = new Slice(loCandidate.Dst.DataType, dst, 0); var stmCastLo = stmts.Insert(iStm++, linAddr, new AliasAssignment( sidDstLo.Identifier, cast)); var stmDeadLo = sidDstLo.DefStatement; sidDstLo.DefExpression = cast; sidDstLo.DefStatement = stmCastLo; var sidDstHi = GetSsaIdentifierOf(hiCandidate.Dst); var slice = new Slice(hiCandidate.Dst.DataType, dst, loCandidate.Dst.DataType.BitSize); var stmSliceHi = stmts.Insert(iStm++, linAddr, new AliasAssignment( sidDstHi.Identifier, slice)); var stmDeadHi = sidDstHi.DefStatement; sidDstHi.DefExpression = slice; sidDstHi.DefStatement = stmSliceHi; if (sidDstLo != null) { sidDst.Uses.Add(stmCastLo); } if (sidDstHi != null) { sidDst.Uses.Add(stmSliceHi); } ssa.DeleteStatement(stmDeadLo); ssa.DeleteStatement(stmDeadHi); } }