Beispiel #1
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];
 }
Beispiel #2
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;
 }
        readonly bool[] addressTaken;                              // array index -> SsaVariable OriginalVariableIndex; value = whether ldloca instruction was used with variable

        TransformToSsa(ControlFlowGraph cfg, SsaForm ssaForm)
        {
            this.cfg                 = cfg;
            this.ssaForm             = ssaForm;
            writeToOriginalVariables = new List <SsaInstruction> [ssaForm.OriginalVariables.Count];
            addressTaken             = new bool[ssaForm.OriginalVariables.Count];
        }
Beispiel #4
0
 internal SsaForm Build()
 {
     CreateGraphStructure();
     this.ssaForm = new SsaForm(blocks, parameters, locals, stackLocations, method.HasThis);
     CreateInstructions(cfg.EntryPoint.BlockIndex);
     CreateSpecialInstructions();
     return(ssaForm);
 }
Beispiel #5
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
        }
Beispiel #6
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);
 }
        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);
            }
        }
		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
		}
		/// <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
		}
 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
 }
 /// <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
 }
		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
		}
        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);
        }
Beispiel #14
0
		internal SsaForm Build()
		{
			CreateGraphStructure();
			this.ssaForm = new SsaForm(blocks, parameters, locals, stackLocations, method.HasThis);
			CreateInstructions(cfg.EntryPoint.BlockIndex);
			CreateSpecialInstructions();
			return ssaForm;
		}
 public static void Optimize(SsaForm ssaForm)
 {
     DirectlyStoreToVariables(ssaForm);
     SimpleCopyPropagation(ssaForm);
     RemoveDeadAssignments(ssaForm);
 }
 private SimplifyByRefCalls(SsaForm ssaForm)
 {
     this.ssaForm = ssaForm;
 }
Beispiel #17
0
 private SimplifyByRefCalls(SsaForm ssaForm)
 {
     this.ssaForm = ssaForm;
 }
		public static void Optimize(SsaForm ssaForm)
		{
			DirectlyStoreToVariables(ssaForm);
			SimpleCopyPropagation(ssaForm);
			RemoveDeadAssignments(ssaForm);
		}