예제 #1
0
 public static bool MakeByRefCallsSimple(SsaForm ssaForm)
 {
     SimplifyByRefCalls instance = new SimplifyByRefCalls(ssaForm);
     foreach (SsaBlock block in ssaForm.Blocks) {
         for (int i = 0; i < block.Instructions.Count; i++) {
             SsaInstruction inst = block.Instructions[i];
             if (inst.Instruction != null) {
                 switch (inst.Instruction.OpCode.Code) {
                     case Code.Call:
                     case Code.Callvirt:
                         instance.MakeByRefCallSimple(block, ref i, (IMethodSignature)inst.Instruction.Operand);
                         break;
                     case Code.Initobj:
                         instance.MakeInitObjCallSimple(block, ref i);
                         break;
                     case Code.Ldfld:
                         instance.MakeLoadFieldCallSimple(block, ref i);
                         break;
                 }
             }
         }
     }
     instance.RemoveRedundantInstructions();
     if (instance.couldSimplifySomething)
         ssaForm.ComputeVariableUsage();
     return instance.couldSimplifySomething;
 }
예제 #2
0
        readonly bool[] addressTaken;                              // array index -> SsaVariable OriginalVariableIndex; value = whether ldloca instruction was used with variable

        private TransformToSsa(ControlFlowGraph cfg, SsaForm ssaForm)
        {
            this.cfg     = cfg;
            this.ssaForm = ssaForm;
            this.writeToOriginalVariables = new List <SsaInstruction> [ssaForm.OriginalVariables.Count];
            this.addressTaken             = new bool[ssaForm.OriginalVariables.Count];
        }
예제 #3
0
 private TransformToSsa(ControlFlowGraph cfg, SsaForm ssaForm)
 {
     this.cfg = cfg;
     this.ssaForm = ssaForm;
     this.writeToOriginalVariables = new List<SsaInstruction>[ssaForm.OriginalVariables.Count];
     this.addressTaken = new bool[ssaForm.OriginalVariables.Count];
 }
예제 #4
0
 internal SsaForm Build()
 {
     CreateGraphStructure();
     this.ssaForm = new SsaForm(blocks, parameters, locals, stackLocations, method.HasThis);
     CreateInstructions(cfg.EntryPoint.BlockIndex);
     CreateSpecialInstructions();
     return(ssaForm);
 }
예제 #5
0
 public static void Transform(ControlFlowGraph cfg, SsaForm ssa, bool optimize = true)
 {
     TransformToSsa transform = new TransformToSsa(cfg, ssa);
     transform.ConvertVariablesToSsa();
     SsaOptimization.RemoveDeadAssignments(ssa); // required so that 'MakeByRefCallsSimple' can detect more cases
     if (SimplifyByRefCalls.MakeByRefCallsSimple(ssa)) {
         transform.ConvertVariablesToSsa();
     }
     if (optimize)
         SsaOptimization.Optimize(ssa);
 }
예제 #6
0
        public static void RemoveDeadAssignments(SsaForm ssaForm)
        {
            HashSet <SsaVariable> liveVariables = new HashSet <SsaVariable>();

            // find variables that are used directly
            foreach (SsaBlock block in ssaForm.Blocks)
            {
                foreach (SsaInstruction inst in block.Instructions)
                {
                    if (!CanRemoveAsDeadCode(inst))
                    {
                        if (inst.Target != null)
                        {
                            liveVariables.Add(inst.Target);
                        }
                        foreach (SsaVariable op in inst.Operands)
                        {
                            liveVariables.Add(op);
                        }
                    }
                }
            }
            Queue <SsaVariable> queue = new Queue <SsaVariable>(liveVariables);

            // find variables that are used indirectly
            while (queue.Count > 0)
            {
                SsaVariable v = queue.Dequeue();
                if (v.IsSingleAssignment)
                {
                    foreach (SsaVariable op in v.Definition.Operands)
                    {
                        if (liveVariables.Add(op))
                        {
                            queue.Enqueue(op);
                        }
                    }
                }
            }
            // remove assignments to all unused variables
            foreach (SsaBlock block in ssaForm.Blocks)
            {
                block.Instructions.RemoveAll(
                    inst => {
                    if (inst.Target != null && !liveVariables.Contains(inst.Target))
                    {
                        Debug.Assert(inst.Target.IsSingleAssignment);
                        return(true);
                    }
                    return(false);
                });
            }
            ssaForm.ComputeVariableUsage();             // update usage after we modified stuff
        }
예제 #7
0
        public static void Transform(ControlFlowGraph cfg, SsaForm ssa, bool optimize = true)
        {
            TransformToSsa transform = new TransformToSsa(cfg, ssa);

            transform.ConvertVariablesToSsa();
            SsaOptimization.RemoveDeadAssignments(ssa);             // required so that 'MakeByRefCallsSimple' can detect more cases
            if (SimplifyByRefCalls.MakeByRefCallsSimple(ssa))
            {
                transform.ConvertVariablesToSsa();
            }
            if (optimize)
            {
                SsaOptimization.Optimize(ssa);
            }
        }
예제 #8
0
 /// <summary>
 /// When any instructions stores its result in a stack location that's used only once in a 'stloc' or 'starg' instruction,
 /// we optimize this to directly store in the target location.
 /// As optimization this is redundant (does the same as copy propagation), but it'll make us keep the variables named
 /// after locals instead of keeping the temps as using only the simple copy propagation would do.
 /// </summary>
 public static void DirectlyStoreToVariables(SsaForm ssaForm)
 {
     foreach (SsaBlock block in ssaForm.Blocks) {
         block.Instructions.RemoveAll(
             inst => {
                 if (inst.Instruction != null && (inst.Instruction.OpCode == OpCodes.Stloc || inst.Instruction.OpCode == OpCodes.Starg)) {
                     SsaVariable target = inst.Target;
                     SsaVariable temp = inst.Operands[0];
                     if (target.IsSingleAssignment && temp.IsSingleAssignment && temp.Usage.Count == 1 && temp.IsStackLocation) {
                         temp.Definition.Target = target;
                         return true;
                     }
                 }
                 return false;
             });
     }
     ssaForm.ComputeVariableUsage(); // update usage after we modified stuff
 }
예제 #9
0
 public static void SimpleCopyPropagation(SsaForm ssaForm, bool onlyForStackLocations = true)
 {
     foreach (SsaBlock block in ssaForm.Blocks)
     {
         foreach (SsaInstruction inst in block.Instructions)
         {
             if (inst.IsMoveInstruction && inst.Target.IsSingleAssignment && inst.Operands[0].IsSingleAssignment)
             {
                 if (inst.Target.IsStackLocation || !onlyForStackLocations)
                 {
                     // replace all uses of 'target' with 'operands[0]'.
                     foreach (SsaInstruction useInstruction in inst.Target.Usage)
                     {
                         useInstruction.ReplaceVariableInOperands(inst.Target, inst.Operands[0]);
                     }
                 }
             }
         }
     }
     ssaForm.ComputeVariableUsage();             // update usage after we modified stuff
 }
예제 #10
0
 /// <summary>
 /// When any instructions stores its result in a stack location that's used only once in a 'stloc' or 'starg' instruction,
 /// we optimize this to directly store in the target location.
 /// As optimization this is redundant (does the same as copy propagation), but it'll make us keep the variables named
 /// after locals instead of keeping the temps as using only the simple copy propagation would do.
 /// </summary>
 public static void DirectlyStoreToVariables(SsaForm ssaForm)
 {
     foreach (SsaBlock block in ssaForm.Blocks)
     {
         block.Instructions.RemoveAll(
             inst => {
             if (inst.Instruction != null && (inst.Instruction.OpCode == OpCodes.Stloc || inst.Instruction.OpCode == OpCodes.Starg))
             {
                 SsaVariable target = inst.Target;
                 SsaVariable temp   = inst.Operands[0];
                 if (target.IsSingleAssignment && temp.IsSingleAssignment && temp.Usage.Count == 1 && temp.IsStackLocation)
                 {
                     temp.Definition.Target = target;
                     return(true);
                 }
             }
             return(false);
         });
     }
     ssaForm.ComputeVariableUsage();             // update usage after we modified stuff
 }
예제 #11
0
 public static void RemoveDeadAssignments(SsaForm ssaForm)
 {
     HashSet<SsaVariable> liveVariables = new HashSet<SsaVariable>();
     // find variables that are used directly
     foreach (SsaBlock block in ssaForm.Blocks) {
         foreach (SsaInstruction inst in block.Instructions) {
             if (!CanRemoveAsDeadCode(inst)) {
                 if (inst.Target != null)
                     liveVariables.Add(inst.Target);
                 foreach (SsaVariable op in inst.Operands) {
                     liveVariables.Add(op);
                 }
             }
         }
     }
     Queue<SsaVariable> queue = new Queue<SsaVariable>(liveVariables);
     // find variables that are used indirectly
     while (queue.Count > 0) {
         SsaVariable v = queue.Dequeue();
         if (v.IsSingleAssignment) {
             foreach (SsaVariable op in v.Definition.Operands) {
                 if (liveVariables.Add(op))
                     queue.Enqueue(op);
             }
         }
     }
     // remove assignments to all unused variables
     foreach (SsaBlock block in ssaForm.Blocks) {
         block.Instructions.RemoveAll(
             inst => {
                 if (inst.Target != null && !liveVariables.Contains(inst.Target)) {
                     Debug.Assert(inst.Target.IsSingleAssignment);
                     return true;
                 }
                 return false;
             });
     }
     ssaForm.ComputeVariableUsage(); // update usage after we modified stuff
 }
예제 #12
0
        public static bool MakeByRefCallsSimple(SsaForm ssaForm)
        {
            SimplifyByRefCalls instance = new SimplifyByRefCalls(ssaForm);

            foreach (SsaBlock block in ssaForm.Blocks)
            {
                for (int i = 0; i < block.Instructions.Count; i++)
                {
                    SsaInstruction inst = block.Instructions[i];
                    if (inst.Instruction != null)
                    {
                        switch (inst.Instruction.OpCode.Code)
                        {
                        case Code.Call:
                        case Code.Callvirt:
                            instance.MakeByRefCallSimple(block, ref i, (IMethodSignature)inst.Instruction.Operand);
                            break;

                        case Code.Initobj:
                            instance.MakeInitObjCallSimple(block, ref i);
                            break;

                        case Code.Ldfld:
                            instance.MakeLoadFieldCallSimple(block, ref i);
                            break;
                        }
                    }
                }
            }
            instance.RemoveRedundantInstructions();
            if (instance.couldSimplifySomething)
            {
                ssaForm.ComputeVariableUsage();
            }
            return(instance.couldSimplifySomething);
        }
예제 #13
0
 internal SsaForm Build()
 {
     CreateGraphStructure();
     this.ssaForm = new SsaForm(blocks, parameters, locals, stackLocations, method.HasThis);
     CreateInstructions(cfg.EntryPoint.BlockIndex);
     CreateSpecialInstructions();
     return ssaForm;
 }
예제 #14
0
 public static void Optimize(SsaForm ssaForm)
 {
     DirectlyStoreToVariables(ssaForm);
     SimpleCopyPropagation(ssaForm);
     RemoveDeadAssignments(ssaForm);
 }
예제 #15
0
 public static void Optimize(SsaForm ssaForm)
 {
     DirectlyStoreToVariables(ssaForm);
     SimpleCopyPropagation(ssaForm);
     RemoveDeadAssignments(ssaForm);
 }
예제 #16
0
 public static void SimpleCopyPropagation(SsaForm ssaForm, bool onlyForStackLocations = true)
 {
     foreach (SsaBlock block in ssaForm.Blocks) {
         foreach (SsaInstruction inst in block.Instructions) {
             if (inst.IsMoveInstruction && inst.Target.IsSingleAssignment && inst.Operands[0].IsSingleAssignment) {
                 if (inst.Target.IsStackLocation || !onlyForStackLocations) {
                     // replace all uses of 'target' with 'operands[0]'.
                     foreach (SsaInstruction useInstruction in inst.Target.Usage) {
                         useInstruction.ReplaceVariableInOperands(inst.Target, inst.Operands[0]);
                     }
                 }
             }
         }
     }
     ssaForm.ComputeVariableUsage(); // update usage after we modified stuff
 }
예제 #17
0
 private SimplifyByRefCalls(SsaForm ssaForm)
 {
     this.ssaForm = ssaForm;
 }
예제 #18
0
 private SimplifyByRefCalls(SsaForm ssaForm)
 {
     this.ssaForm = ssaForm;
 }