Skip to content

Commit c59b3a0

Browse files
committed
Add constant propagation through methods with parameter or complex bodies
This change also - Adds simple inlining of method return values. - Fixes several shortcomings of existing implementation like ignoring methods called from unreachable blocks. This helps to reduce the size of all runtime assemblies. For example size of SPC for the default iOS project is reduced by 4% mostly due to metadata removal. The linker speed improves a little bit (~3%) for the same project.
1 parent 2999a6a commit c59b3a0

22 files changed

Lines changed: 1638 additions & 803 deletions

external/cecil

Submodule cecil updated from cdc0adc to 0780d4e

src/linker/Linker.Steps/UnreachableBlocksOptimizer.cs

Lines changed: 876 additions & 548 deletions
Large diffs are not rendered by default.

test/Mono.Linker.Tests.Cases/FeatureSettings/FeatureSubstitutions.cs

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,35 @@ namespace Mono.Linker.Tests.Cases.FeatureSettings
99
[SetupLinkerArgument ("--enable-opt", "ipconstprop")]
1010
public class FeatureSubstitutions
1111
{
12-
[Kept]
1312
static bool IsOptionalFeatureEnabled {
14-
[Kept]
15-
[ExpectedInstructionSequence (new[] {
16-
"ldc.i4.0",
17-
"ret",
18-
})]
1913
get;
2014
}
2115

16+
[ExpectedInstructionSequence (new[] {
17+
"nop",
18+
"call System.Void Mono.Linker.Tests.Cases.FeatureSettings.FeatureSubstitutions::TestOptionalFeature()",
19+
"nop",
20+
"ldc.i4.1",
21+
"pop",
22+
"ret",
23+
})]
2224
public static void Main ()
2325
{
2426
TestOptionalFeature ();
2527
_ = IsDefaultFeatureEnabled;
2628
}
2729

2830
[Kept]
29-
[ExpectBodyModified]
3031
[ExpectedInstructionSequence (new[] {
31-
"call",
32-
"brfalse",
33-
"call",
32+
"nop",
33+
"ldc.i4.0",
34+
"stloc.0",
35+
"ldloc.0",
36+
"brfalse.s il_6",
37+
"nop",
38+
"call System.Void Mono.Linker.Tests.Cases.FeatureSettings.FeatureSubstitutions::UseFallback()",
39+
"nop",
40+
"nop",
3441
"ret",
3542
})]
3643
static void TestOptionalFeature ()
@@ -51,13 +58,7 @@ static void UseFallback ()
5158
{
5259
}
5360

54-
[Kept]
5561
static bool IsDefaultFeatureEnabled {
56-
[Kept]
57-
[ExpectedInstructionSequence (new[] {
58-
"ldc.i4.1",
59-
"ret",
60-
})]
6162
get => throw new NotImplementedException ();
6263
}
6364
}

test/Mono.Linker.Tests.Cases/FeatureSettings/FeatureSubstitutionsNested.cs

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,20 @@ namespace Mono.Linker.Tests.Cases.FeatureSettings
1919
[KeptResource ("ResourceFileRemoveWhenFalse.txt")]
2020
public class FeatureSubstitutionsNested
2121
{
22+
[ExpectedInstructionSequence (new[] {
23+
"nop",
24+
"ldc.i4.1",
25+
"pop",
26+
"ldc.i4.0",
27+
"pop",
28+
"ldc.i4.1",
29+
"pop",
30+
"ldc.i4.0",
31+
"pop",
32+
"ldsfld System.Boolean Mono.Linker.Tests.Cases.FeatureSettings.FeatureSubstitutionsNested::FieldConditionField",
33+
"pop",
34+
"ret",
35+
})]
2236
public static void Main ()
2337
{
2438
GlobalConditionMethod ();
@@ -28,41 +42,21 @@ public static void Main ()
2842
_ = FieldConditionField;
2943
}
3044

31-
[Kept]
32-
[ExpectedInstructionSequence (new[] {
33-
"ldc.i4.1",
34-
"ret",
35-
})]
3645
static bool GlobalConditionMethod ()
3746
{
3847
throw new NotImplementedException ();
3948
}
4049

41-
[Kept]
42-
[ExpectedInstructionSequence (new[] {
43-
"ldc.i4.0",
44-
"ret",
45-
})]
4650
static bool AssemblyConditionMethod ()
4751
{
4852
throw new NotImplementedException ();
4953
}
5054

51-
[Kept]
52-
[ExpectedInstructionSequence (new[] {
53-
"ldc.i4.1",
54-
"ret",
55-
})]
5655
static bool TypeConditionMethod ()
5756
{
5857
throw new NotImplementedException ();
5958
}
6059

61-
[Kept]
62-
[ExpectedInstructionSequence (new[] {
63-
"ldc.i4.0",
64-
"ret",
65-
})]
6660
static bool MethodConditionMethod ()
6761
{
6862
throw new NotImplementedException ();

test/Mono.Linker.Tests.Cases/Libraries/RootLibrary.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,7 @@ public void NotUsed ()
137137
[Kept]
138138
public class SubstitutionsTest
139139
{
140-
[Kept]
141-
private static bool FalseProp { [Kept] get { return false; } }
140+
private static bool FalseProp { get { return false; } }
142141

143142
[Kept]
144143
[ExpectBodyModified]

test/Mono.Linker.Tests.Cases/Substitutions/StubBody.cs

Lines changed: 36 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,42 @@ namespace Mono.Linker.Tests.Cases.Substitutions
77
[SetupLinkerSubstitutionFile ("StubBody.xml")]
88
public class StubBody
99
{
10+
[ExpectedInstructionSequence (new[] {
11+
"nop",
12+
"newobj System.Void Mono.Linker.Tests.Cases.Substitutions.StubBody::.ctor()",
13+
"pop",
14+
"ldc.i4.5",
15+
"newobj System.Void Mono.Linker.Tests.Cases.Substitutions.StubBody/NestedType::.ctor(System.Int32)",
16+
"pop",
17+
"ldnull",
18+
"pop",
19+
"ldc.i4.0",
20+
"pop",
21+
"ldc.i4.0",
22+
"pop",
23+
"call System.Decimal Mono.Linker.Tests.Cases.Substitutions.StubBody::TestMethod_4()",
24+
"pop",
25+
"ldc.i4.0",
26+
"pop",
27+
"call System.Void Mono.Linker.Tests.Cases.Substitutions.StubBody::TestMethod_6()",
28+
"nop",
29+
"ldc.r8 0",
30+
"pop",
31+
"ldc.i4.5",
32+
"call T Mono.Linker.Tests.Cases.Substitutions.StubBody::TestMethod_8<System.Int32>(T)",
33+
"pop",
34+
"ldc.r4 0",
35+
"pop",
36+
"ldc.i8 0x0",
37+
"pop",
38+
"ldnull",
39+
"pop",
40+
"ldnull",
41+
"pop",
42+
"ldnull",
43+
"pop",
44+
"ret",
45+
})]
1046
public static void Main ()
1147
{
1248
new StubBody ();
@@ -50,31 +86,16 @@ public StubBody ()
5086
throw new NotImplementedException ();
5187
}
5288

53-
[Kept]
54-
[ExpectedInstructionSequence (new[] {
55-
"ldnull",
56-
"ret",
57-
})]
5889
static string TestMethod_1 ()
5990
{
6091
throw new NotImplementedException ();
6192
}
6293

63-
[Kept]
64-
[ExpectedInstructionSequence (new[] {
65-
"ldc.i4.0",
66-
"ret",
67-
})]
6894
static byte TestMethod_2 ()
6995
{
7096
throw new NotImplementedException ();
7197
}
7298

73-
[Kept]
74-
[ExpectedInstructionSequence (new[] {
75-
"ldc.i4.0",
76-
"ret",
77-
})]
7899
static char TestMethod_3 ()
79100
{
80101
throw new NotImplementedException ();
@@ -93,11 +114,6 @@ static decimal TestMethod_4 ()
93114
throw new NotImplementedException ();
94115
}
95116

96-
[Kept]
97-
[ExpectedInstructionSequence (new[] {
98-
"ldc.i4.0",
99-
"ret",
100-
})]
101117
static bool TestMethod_5 ()
102118
{
103119
throw new NotImplementedException ();
@@ -112,12 +128,6 @@ static void TestMethod_6 ()
112128
TestMethod_5 ();
113129
}
114130

115-
[Kept]
116-
[ExpectedInstructionSequence (new[] {
117-
"ldc.r8 0",
118-
"ret",
119-
})]
120-
[ExpectLocalsModified]
121131
static double TestMethod_7 ()
122132
{
123133
double d = 1.1;
@@ -137,53 +147,27 @@ static T TestMethod_8<T> (T t)
137147
throw new NotImplementedException ();
138148
}
139149

140-
[Kept]
141-
[ExpectedInstructionSequence (new[] {
142-
"ldc.r4 0",
143-
"ret",
144-
})]
145-
[ExpectLocalsModified]
146150
static float TestMethod_9 ()
147151
{
148152
float f = 1.1f;
149153
return f;
150154
}
151155

152-
[Kept]
153-
[ExpectedInstructionSequence (new[] {
154-
"ldc.i8 0x0",
155-
"ret",
156-
})]
157156
static ulong TestMethod_10 ()
158157
{
159158
throw new NotImplementedException ();
160159
}
161160

162-
[Kept]
163-
[ExpectedInstructionSequence (new[] {
164-
"ldnull",
165-
"ret",
166-
})]
167161
static long[] TestMethod_11 ()
168162
{
169163
throw new NotImplementedException ();
170164
}
171165

172-
[Kept]
173-
[ExpectedInstructionSequence (new[] {
174-
"ldnull",
175-
"ret",
176-
})]
177166
static object TestMethod_12 ()
178167
{
179168
throw new NotImplementedException ();
180169
}
181170

182-
[Kept]
183-
[ExpectedInstructionSequence (new[] {
184-
"ldnull",
185-
"ret",
186-
})]
187171
static System.Collections.Generic.List<int> TestMethod_13 ()
188172
{
189173
throw new NotImplementedException ();

test/Mono.Linker.Tests.Cases/Substitutions/StubBodyWithValue.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Runtime.CompilerServices;
23
using Mono.Linker.Tests.Cases.Expectations.Assertions;
34
using Mono.Linker.Tests.Cases.Expectations.Metadata;
45

@@ -28,6 +29,7 @@ public static void Main ()
2829
"ldstr 'abcd'",
2930
"ret",
3031
})]
32+
[MethodImplAttribute (MethodImplOptions.NoInlining)]
3133
static string TestMethod_1 ()
3234
{
3335
throw new NotImplementedException ();
@@ -38,6 +40,7 @@ static string TestMethod_1 ()
3840
"ldc.i4 0x4",
3941
"ret",
4042
})]
43+
[MethodImplAttribute (MethodImplOptions.NoInlining)]
4144
static byte TestMethod_2 ()
4245
{
4346
throw new NotImplementedException ();
@@ -48,6 +51,7 @@ static byte TestMethod_2 ()
4851
"ldc.i4 0x78",
4952
"ret",
5053
})]
54+
[MethodImplAttribute (MethodImplOptions.NoInlining)]
5155
static char TestMethod_3 ()
5256
{
5357
throw new NotImplementedException ();
@@ -58,6 +62,7 @@ static char TestMethod_3 ()
5862
"ldc.i4 0x3",
5963
"ret"
6064
})]
65+
[MethodImplAttribute (MethodImplOptions.NoInlining)]
6166
static sbyte TestMethod_4 ()
6267
{
6368
throw new NotImplementedException ();
@@ -68,6 +73,7 @@ static sbyte TestMethod_4 ()
6873
"ldc.i4.1",
6974
"ret",
7075
})]
76+
[MethodImplAttribute (MethodImplOptions.NoInlining)]
7177
static bool TestMethod_5 ()
7278
{
7379
throw new NotImplementedException ();
@@ -78,6 +84,7 @@ static bool TestMethod_5 ()
7884
"ldc.i4.1",
7985
"ret",
8086
})]
87+
[MethodImplAttribute (MethodImplOptions.NoInlining)]
8188
static bool TestMethod_6 ()
8289
{
8390
throw new NotImplementedException ();
@@ -88,6 +95,7 @@ static bool TestMethod_6 ()
8895
"ldc.r8 2.5",
8996
"ret",
9097
})]
98+
[MethodImplAttribute (MethodImplOptions.NoInlining)]
9199
static double TestMethod_7 ()
92100
{
93101
throw new NotImplementedException ();
@@ -98,6 +106,7 @@ static double TestMethod_7 ()
98106
"ldc.i4 0xfffffffd",
99107
"ret"
100108
})]
109+
[MethodImplAttribute (MethodImplOptions.NoInlining)]
101110
static int TestMethod_8 ()
102111
{
103112
throw new NotImplementedException ();
@@ -108,6 +117,7 @@ static int TestMethod_8 ()
108117
"ldc.r4 6",
109118
"ret",
110119
})]
120+
[MethodImplAttribute (MethodImplOptions.NoInlining)]
111121
static float TestMethod_9 ()
112122
{
113123
throw new NotImplementedException ();
@@ -118,6 +128,7 @@ static float TestMethod_9 ()
118128
"ldc.i8 0x1e240",
119129
"ret",
120130
})]
131+
[MethodImplAttribute (MethodImplOptions.NoInlining)]
121132
static ulong TestMethod_10 ()
122133
{
123134
throw new NotImplementedException ();
@@ -128,6 +139,7 @@ static ulong TestMethod_10 ()
128139
"ldc.i8 0xfffffffffffffc18",
129140
"ret",
130141
})]
142+
[MethodImplAttribute (MethodImplOptions.NoInlining)]
131143
static long TestMethod_11 ()
132144
{
133145
throw new NotImplementedException ();
@@ -138,6 +150,7 @@ static long TestMethod_11 ()
138150
"ldc.i4 0xffffffff",
139151
"ret",
140152
})]
153+
[MethodImplAttribute (MethodImplOptions.NoInlining)]
141154
static uint TestMethod_12 ()
142155
{
143156
throw new NotImplementedException ();

0 commit comments

Comments
 (0)