This helps clean up the mess left behind when stack slots are not eliminated by the normal transforms.
We previously didn't do this because aggressive copy propagation could confuse the normal transforms; but this is no longer an issue with the new pass ordering.
Unreachable code is not part of the dominator tree, which most of our transforms are based on.
In particular, dominance-based loop detection runs into the problem where unreachable code might have jumps into two independent loops. In that case, it's impossible to place the unreachable code in a way that avoids assertions / generating invalid C#.
We establish the invariant that all blocks in a BlockContainer must be statically reachable from the entry point (-> every block is part of the dominator tree). This means transforms no longer have to deal with special cases for unreachable code.
The "Remove dead and side effect free code" option still has an effect on dead stores, but unreachable code is now always removed (previously this also was dependent on this option).
Also, assume that unknown inputs to ldfld are temporaries, not unmanaged pointers.
This avoids emitting weird pointer casts when accessing fields on unresolved value types.
Roslyn re-uses the same "this.Finally(); return v;" block for both "yield break;" instructions, so the yield break pattern needs to support multiple stores to the helper variable.
For user-defined increments, there were problems with Roslyn was optimizing out one of the stores.
The new transform FixRemainingIncrements now takes increments/decrements that were not detected by TransformAssignment and introduces a temporary variable that can be incremented.
This sometimes requires un-inlining via the new ILInstruction.Extract() operation.
Extract() is not supported in all possible contexts, so it is possible but unlikely that some op_Increment calls remain.
For decimals, the situation is different: legacy csc actually was optimizing "d + 1m" to "op_Increment(d)", so we can get rid of any left-over increments by undoing this optimization. This now happens in ReplaceMethodCallsWithOperators.
This was left-over from earlier versions; but ILSpy stopped caring so much about variable vs. stack slot since Roslyn started to optimize more aggressively.
The change of variable type caused problems for debug information and could even cause an assertion.
Closes#1456, closes#1562.
This means we can get rid of the special case in TransformDisplayClassUsage, as compound.assign can now also be used with the address of a local variable.