-
Notifications
You must be signed in to change notification settings - Fork 128
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Only compute if method returns a constant when needed #1734
Only compute if method returns a constant when needed #1734
Conversation
Just store results for all methods (not just those with constant value). Will be needed once the const detection is done on-demand (to detect which methods were already processed).
Basically computation if method is constant is now always done on-demand.
For various reasons we can't propagate constant return values from many methods. Basically we only allow parameterless static methods - with some exceptions. There's no point asking about constant return value for methods which won't be able to propagate the value further.
@@ -17,81 +17,68 @@ namespace Mono.Linker.Steps | |||
public class RemoveUnreachableBlocksStep : BaseStep | |||
{ | |||
Dictionary<MethodDefinition, Instruction> constExprMethods; | |||
int constExprMethodsAdded; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cannot this be bool
value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM modulo the case we discussed where a constant-returning method has conflicting substitutions
If method returns a constant value but substitutions overrides it to a different value - in some cases the constant propagation might end up using the value from the method body and not from the substitution. This change fixes that
This change also "fixes" a bug - if the IPConstantPropagation feature was disabled, substitutions would still work for the first level of propagation. After this change, even the first level propagation requires the IPContantPropagation to be turned on. Note that this has nothing to do with the replacement of the method bodies in substitutions, those work regardless of the options. |
In dotnet#1734 a change was made that substitutions are only considered for methods which are not instrinsic or no-inline. That is not how it should work, even intrinsic or no-inline methods should still allow substitutions and constant propagation from those. What instrinsic and no-inline methods should not do is participate in constant propagation as intermediate methods (so methods which become constant because they're calling other constant methods). In short substitutions effectively override the intrinsic/no-inline. Added test cases.
In #1734 a change was made that substitutions are only considered for methods which are not intrinsic or no-inline. That is not how it should work, even intrinsic or no-inline methods should still allow substitutions and constant propagation from those. What intrinsic and no-inline methods should not do is participate in constant propagation as intermediate methods (so methods which become constant because they're calling other constant methods). In short substitutions effectively override the intrinsic/no-inline. Added test cases. Fixes #1747
…1734) This changes how the `RemoveUnreachableBlocksStep` computes if a method returns a constant or not. Previously we would go over all methods and detect those which return constants (and store only those in a dictionary). Then we would proceed with branch removal relying on this dictionary. For a hello world console app this means we ran the detection of constants on almost 50K methods. On the other hand the dictionary stored only about 1.5K records (actually constant methods). With this change the constant detection only runs on methods we need the result for later on. This means the dictionary stores records for all methods asked about (`null` value represents "We checked, and it's not constant"). For the same hello world console app we now run the detection only on ~5K methods (10x less). On the other hand we have records for all (5K -> 3x increase). So this trades CPU for memory. The purpose of this change is not the CPU/memory tradeoff, it's to prepare the constant propagation to make it possible to call it on-demand per-method from `MarkStep` which will be needed once we switch over to the current lazy-loading of assemblies. Commit migrated from dotnet/linker@17db5ef
In dotnet/linker#1734 a change was made that substitutions are only considered for methods which are not intrinsic or no-inline. That is not how it should work, even intrinsic or no-inline methods should still allow substitutions and constant propagation from those. What intrinsic and no-inline methods should not do is participate in constant propagation as intermediate methods (so methods which become constant because they're calling other constant methods). In short substitutions effectively override the intrinsic/no-inline. Added test cases. Fixes dotnet/linker#1747 Commit migrated from dotnet/linker@fc8abef
This changes how the
RemoveUnreachableBlocksStep
computes if a method returns a constant or not. Previously we would go over all methods and detect those which return constants (and store only those in a dictionary). Then we would proceed with branch removal relying on this dictionary.For a hello world console app this means we ran the detection of constants on almost 50K methods. On the other hand the dictionary stored only about 1.5K records (actually constant methods).
With this change the constant detection only runs on methods we need the result for later on. This means the dictionary stores records for all methods asked about (
null
value represents "We checked, and it's not constant").For the same hello world console app we now run the detection only on ~5K methods (10x less). On the other hand we have records for all (5K -> 3x increase). So this trades CPU for memory.
The purpose of this change is not the CPU/memory tradeoff, it's to prepare the constant propagation to make it possible to call it on-demand per-method from
MarkStep
which will be needed once we switch over to the current lazy-loading of assemblies.This is a just a first step in this process described by #1733.