99
1010using  Debug  =  System . Diagnostics . Debug ; 
1111using  DependencyList  =  ILCompiler . DependencyAnalysisFramework . DependencyNodeCore < ILCompiler . DependencyAnalysis . NodeFactory > . DependencyList ; 
12+ using  CombinedDependencyList  =  System . Collections . Generic . List < ILCompiler . DependencyAnalysisFramework . DependencyNodeCore < ILCompiler . DependencyAnalysis . NodeFactory > . CombinedDependencyListEntry > ; 
13+ using  DependencyListEntry  =  ILCompiler . DependencyAnalysisFramework . DependencyNodeCore < ILCompiler . DependencyAnalysis . NodeFactory > . DependencyListEntry ; 
1214
1315#pragma warning disable IDE0060 
1416
@@ -28,7 +30,7 @@ internal partial class ILImporter
2830
2931        private  readonly  MethodDesc  _canonMethod ; 
3032
31-         private  DependencyList  _dependencies  =  new  DependencyList ( ) ; 
33+         private  DependencyList  _unconditionalDependencies  =  new  DependencyList ( ) ; 
3234
3335        private  readonly  byte [ ]  _ilBytes ; 
3436
@@ -51,11 +53,17 @@ public enum ImportState : byte
5153            public  bool  TryStart ; 
5254            public  bool  FilterStart ; 
5355            public  bool  HandlerStart ; 
56+ 
57+             public  object  Condition ; 
58+             public  DependencyList  Dependencies ; 
5459        } 
5560
5661        private  bool  _isReadOnly ; 
5762        private  TypeDesc  _constrained ; 
5863
64+         private  DependencyList  _dependencies ; 
65+         private  BasicBlock  _lateBasicBlocks ; 
66+ 
5967        private  sealed  class  ExceptionRegion 
6068        { 
6169            public  ILExceptionRegion  ILRegion ; 
@@ -107,9 +115,11 @@ public ILImporter(ILScanner compilation, MethodDesc method, MethodIL methodIL =
107115            { 
108116                _exceptionRegions [ i ]  =  new  ExceptionRegion ( )  {  ILRegion  =  ilExceptionRegions [ i ]  } ; 
109117            } 
118+ 
119+             _dependencies  =  _unconditionalDependencies ; 
110120        } 
111121
112-         public  DependencyList  Import ( ) 
122+         public  ( DependencyList ,   CombinedDependencyList )  Import ( ) 
113123        { 
114124            TypeDesc  owningType  =  _canonMethod . OwningType ; 
115125            if  ( _compilation . HasLazyStaticConstructor ( owningType ) ) 
@@ -172,9 +182,21 @@ public DependencyList Import()
172182            FindBasicBlocks ( ) ; 
173183            ImportBasicBlocks ( ) ; 
174184
175-             CodeBasedDependencyAlgorithm . AddDependenciesDueToMethodCodePresence ( ref  _dependencies ,  _factory ,  _canonMethod ,  _canonMethodIL ) ; 
185+             CombinedDependencyList  conditionalDependencies  =  null ; 
186+             foreach  ( BasicBlock  bb  in  _basicBlocks ) 
187+             { 
188+                 if  ( bb ? . Condition  ==  null ) 
189+                     continue ; 
190+ 
191+                 conditionalDependencies  ??=  new  CombinedDependencyList ( ) ; 
192+                 foreach  ( DependencyListEntry  dep  in  bb . Dependencies ) 
193+                     conditionalDependencies . Add ( new ( dep . Node ,  bb . Condition ,  dep . Reason ) ) ; 
194+             } 
195+ 
196+             CodeBasedDependencyAlgorithm . AddDependenciesDueToMethodCodePresence ( ref  _unconditionalDependencies ,  _factory ,  _canonMethod ,  _canonMethodIL ) ; 
197+             CodeBasedDependencyAlgorithm . AddConditionalDependenciesDueToMethodCodePresence ( ref  conditionalDependencies ,  _factory ,  _canonMethod ) ; 
176198
177-             return  _dependencies ; 
199+             return  ( _unconditionalDependencies ,   conditionalDependencies ) ; 
178200        } 
179201
180202        private  ISymbolNode  GetGenericLookupHelper ( ReadyToRunHelperId  helperId ,  object  helperArgument ) 
@@ -199,19 +221,29 @@ private ISymbolNode GetHelperEntrypoint(ReadyToRunHelper helper)
199221        } 
200222
201223        private  static void  MarkInstructionBoundary ( )  {  } 
202-         private  static void  EndImportingBasicBlock ( BasicBlock  basicBlock )  {  } 
224+ 
225+         private  void  EndImportingBasicBlock ( BasicBlock  basicBlock ) 
226+         { 
227+             if  ( _pendingBasicBlocks  ==  null ) 
228+             { 
229+                 _pendingBasicBlocks  =  _lateBasicBlocks ; 
230+                 _lateBasicBlocks  =  null ; 
231+             } 
232+         } 
203233
204234        private  void  StartImportingBasicBlock ( BasicBlock  basicBlock ) 
205235        { 
236+             _dependencies  =  basicBlock . Condition  !=  null  ?  basicBlock . Dependencies  :  _unconditionalDependencies ; 
237+ 
206238            // Import all associated EH regions 
207239            foreach  ( ExceptionRegion  ehRegion  in  _exceptionRegions ) 
208240            { 
209241                ILExceptionRegion  region  =  ehRegion . ILRegion ; 
210242                if  ( region . TryOffset  ==  basicBlock . StartOffset ) 
211243                { 
212-                     MarkBasicBlock ( _basicBlocks [ region . HandlerOffset ] ) ; 
244+                     ImportBasicBlockEdge ( basicBlock ,   _basicBlocks [ region . HandlerOffset ] ) ; 
213245                    if  ( region . Kind  ==  ILExceptionRegionKind . Filter ) 
214-                         MarkBasicBlock ( _basicBlocks [ region . FilterOffset ] ) ; 
246+                         ImportBasicBlockEdge ( basicBlock ,   _basicBlocks [ region . FilterOffset ] ) ; 
215247
216248                    if  ( region . Kind  ==  ILExceptionRegionKind . Catch ) 
217249                    { 
@@ -789,10 +821,26 @@ private void ImportCalli(int token)
789821
790822        private  void  ImportBranch ( ILOpcode  opcode ,  BasicBlock  target ,  BasicBlock  fallthrough ) 
791823        { 
824+             object  condition  =  null ; 
825+ 
826+             if  ( opcode  ==  ILOpcode . brfalse 
827+                 &&  _typeEqualityPatternAnalyzer . IsTypeEqualityBranch 
828+                 &&  ! _typeEqualityPatternAnalyzer . IsTwoTokens 
829+                 &&  ! _typeEqualityPatternAnalyzer . IsInequality ) 
830+             { 
831+                 TypeDesc  typeEqualityCheckType  =  ( TypeDesc ) _canonMethodIL . GetObject ( _typeEqualityPatternAnalyzer . Token1 ) ; 
832+                 if  ( ! typeEqualityCheckType . IsGenericDefinition 
833+                     &&  ConstructedEETypeNode . CreationAllowed ( typeEqualityCheckType ) 
834+                     &&  ! typeEqualityCheckType . ConvertToCanonForm ( CanonicalFormKind . Specific ) . IsCanonicalSubtype ( CanonicalFormKind . Any ) ) 
835+                 { 
836+                     condition  =  _factory . MaximallyConstructableType ( typeEqualityCheckType ) ; 
837+                 } 
838+             } 
839+ 
792840            ImportFallthrough ( target ) ; 
793841
794842            if  ( fallthrough  !=  null ) 
795-                 ImportFallthrough ( fallthrough ) ; 
843+                 ImportFallthrough ( fallthrough ,   condition ) ; 
796844        } 
797845
798846        private  void  ImportSwitchJump ( int  jmpBase ,  int [ ]  jmpDelta ,  BasicBlock  fallthrough ) 
@@ -1278,9 +1326,56 @@ private void ImportConvert(WellKnownType wellKnownType, bool checkOverflow, bool
12781326            } 
12791327        } 
12801328
1281-         private  void  ImportFallthrough ( BasicBlock  next ) 
1329+         private  void  ImportBasicBlockEdge ( BasicBlock  source ,  BasicBlock  next ,  object  condition  =  null ) 
1330+         { 
1331+             // We don't track multiple conditions; if the source basic block is only reachable under a condition, 
1332+             // this condition will be used for the next basic block, irrespective if we could make it more narrow. 
1333+             object  effectiveCondition  =  source . Condition  ??  condition ; 
1334+ 
1335+             // Did we already look at this basic block? 
1336+             if  ( next . State  !=  BasicBlock . ImportState . Unmarked ) 
1337+             { 
1338+                 // If next is not conditioned, it stays not conditioned. 
1339+                 // If it was conditioned on something else, it needs to become unconditional. 
1340+                 // If the conditions match, it stays conditioned on the same thing. 
1341+                 if  ( next . Condition  !=  null  &&  next . Condition  !=  effectiveCondition ) 
1342+                 { 
1343+                     // Now we need to make `next` not conditioned. We move all of its dependencies to 
1344+                     // unconditional dependencies, and do this for all basic blocks that are reachable 
1345+                     // from it. 
1346+                     // TODO-SIZE: below doesn't do it for all basic blocks reachable from `next`, but 
1347+                     // for all basic blocks with the same conditon. This is a shortcut. It likely 
1348+                     // doesn't matter in practice. 
1349+                     object  conditionToRemove  =  next . Condition ; 
1350+                     foreach  ( BasicBlock  bb  in  _basicBlocks ) 
1351+                     { 
1352+                         if  ( bb ? . Condition  ==  conditionToRemove ) 
1353+                         { 
1354+                             _unconditionalDependencies . AddRange ( bb . Dependencies ) ; 
1355+                             bb . Dependencies  =  null ; 
1356+                             bb . Condition  =  null ; 
1357+                         } 
1358+                     } 
1359+                 } 
1360+             } 
1361+             else 
1362+             { 
1363+                 if  ( effectiveCondition  !=  null ) 
1364+                 { 
1365+                     next . Condition  =  effectiveCondition ; 
1366+                     next . Dependencies  =  new  DependencyList ( ) ; 
1367+                     MarkBasicBlock ( next ,  ref  _lateBasicBlocks ) ; 
1368+                 } 
1369+                 else 
1370+                 { 
1371+                     MarkBasicBlock ( next ) ; 
1372+                 } 
1373+             } 
1374+         } 
1375+ 
1376+         private  void  ImportFallthrough ( BasicBlock  next ,  object  condition  =  null ) 
12821377        { 
1283-             MarkBasicBlock ( next ) ; 
1378+             ImportBasicBlockEdge ( _currentBasicBlock ,   next ,   condition ) ; 
12841379        } 
12851380
12861381        private  int  ReadILTokenAt ( int  ilOffset ) 
0 commit comments