예제 #1
0
파일: DeadCode.cs 프로젝트: tgiphil/reko
        private void Eliminate()
        {
            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 ssa.Procedure.Statements)
            {
                if (CriticalInstruction.IsCritical(stm.Instruction))
                {
                    trace.Inform("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.

            while (liveIds.GetWorkItem(out SsaIdentifier sid))
            {
                Statement?def = sid.DefStatement;
                if (def != null)
                {
                    if (!marks.Contains(def))
                    {
                        trace.Inform("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. Now remove all uses;
            // we just proved that no-one uses the non-marked instructions.
            foreach (var sid in ssa.Identifiers)
            {
                sid.Uses.RemoveAll(u => !marks.Contains(u));
                if (sid.DefStatement != null && !marks.Contains(sid.DefStatement))
                {
                    sid.DefStatement = null;
                }
            }
            foreach (Block b in ssa.Procedure.ControlGraph.Blocks)
            {
                int iTo = 0;
                for (int iStm = 0; iStm < b.Statements.Count; ++iStm)
                {
                    Statement stm = b.Statements[iStm];
                    if (stm.Instruction is CallInstruction call)
                    {
                        AdjustCallWithDeadDefinitions(call);
                    }
                    if (marks.Contains(stm))
                    {
                        b.Statements[iTo] = stm;
                        ++iTo;
                    }
                    else
                    {
                        trace.Inform("Deleting: {0}", stm.Instruction);
                    }
                }
                b.Statements.RemoveRange(iTo, b.Statements.Count - iTo);
            }

            AdjustApplicationsWithDeadReturnValues();
        }
예제 #2
0
        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();
        }