@@ -5328,89 +5328,152 @@ GenTree* Compiler::impOptimizeCastClassOrIsInst(GenTree* op1, CORINFO_RESOLVED_T
5328
5328
int Compiler::impIsInstPatternMatch(
5329
5329
GenTree* op1, GenTree* op2, const BYTE* codeAddr, const BYTE* codeEndp)
5330
5330
{
5331
- if (( impGetNonPrefixOpcode(codeAddr, codeEndp) == CEE_LDNULL ))
5331
+ switch ( impGetNonPrefixOpcode(codeAddr, codeEndp))
5332
5332
{
5333
- switch (impGetNonPrefixOpcode(codeAddr + 1, codeEndp))
5334
- {
5335
- case CEE_CGT_UN:
5336
- // isinst + ldnull + cgt.un
5337
- // convert to op1 == null ? false : *op1 == op2
5338
- {
5339
- GenTree* condNull;
5340
- //
5341
- // expand the null check:
5342
- //
5343
- // condNull ==> GT_NE
5344
- // / \.
5345
- // op1Copy CNS_INT
5346
- // null
5347
- //
5348
- condNull = gtNewOperNode(GT_NE, TYP_INT, gtClone(op1), gtNewNull());
5333
+ case CEE_LDNULL:
5334
+ switch (impGetNonPrefixOpcode(codeAddr + 1, codeEndp))
5335
+ {
5336
+ case CEE_CGT_UN:
5337
+ // isinst + ldnull + cgt.un
5338
+ // convert to op1 == null ? false : *op1 == op2
5339
+ {
5340
+ GenTree* condNull;
5341
+ //
5342
+ // expand the null check:
5343
+ //
5344
+ // condNull ==> GT_NE
5345
+ // / \.
5346
+ // op1Copy CNS_INT
5347
+ // null
5348
+ //
5349
+ condNull = gtNewOperNode(GT_NE, TYP_INT, gtClone(op1), gtNewNull());
5349
5350
5350
- GenTree* temp;
5351
- GenTree* condMT;
5352
- //
5353
- // expand the methodtable match:
5354
- //
5355
- // condMT ==> GT_EQ
5356
- // / \.
5357
- // GT_IND op2 (typically CNS_INT)
5358
- // |
5359
- // op1Copy
5360
- //
5351
+ GenTree* temp;
5352
+ GenTree* condMT;
5353
+ //
5354
+ // expand the methodtable match:
5355
+ //
5356
+ // condMT ==> GT_EQ
5357
+ // / \.
5358
+ // GT_IND op2 (typically CNS_INT)
5359
+ // |
5360
+ // op1Copy
5361
+ //
5361
5362
5362
- // This can replace op1 with a GT_COMMA that evaluates op1 into a local
5363
- //
5364
- op1 = impCloneExpr(op1, &temp, CHECK_SPILL_ALL, nullptr DEBUGARG("CASTCLASS eval op1"));
5365
- //
5366
- // op1 is now known to be a non-complex tree
5367
- // thus we can use gtClone(op1) from now on
5368
- //
5363
+ // This can replace op1 with a GT_COMMA that evaluates op1 into a local
5364
+ //
5365
+ op1 = impCloneExpr(op1, &temp, CHECK_SPILL_ALL, nullptr DEBUGARG("CASTCLASS eval op1"));
5366
+ //
5367
+ // op1 is now known to be a non-complex tree
5368
+ // thus we can use gtClone(op1) from now on
5369
+ //
5369
5370
5370
- GenTree* op2Var = op2;
5371
- temp = gtNewMethodTableLookup(temp);
5372
- condMT = gtNewOperNode(GT_EQ, TYP_INT, temp, op2);
5371
+ GenTree* op2Var = op2;
5372
+ temp = gtNewMethodTableLookup(temp);
5373
+ condMT = gtNewOperNode(GT_EQ, TYP_INT, temp, op2);
5373
5374
5374
- GenTree* qmarkNull;
5375
- //
5376
- // Generate QMARK - COLON tree
5377
- //
5378
- // qmarkNull ==> GT_QMARK
5379
- // / \.
5380
- // condNull GT_COLON
5381
- // / \.
5382
- // condMT CNS_INT
5383
- // false
5384
- //
5385
- temp = new (this, GT_COLON) GenTreeColon(TYP_INT, condMT, gtNewFalse());
5386
- qmarkNull = gtNewQmarkNode(TYP_INT, condNull, temp->AsColon());
5375
+ GenTree* qmarkNull;
5376
+ //
5377
+ // Generate QMARK - COLON tree
5378
+ //
5379
+ // qmarkNull ==> GT_QMARK
5380
+ // / \.
5381
+ // condNull GT_COLON
5382
+ // / \.
5383
+ // condMT CNS_INT
5384
+ // false
5385
+ //
5386
+ temp = new (this, GT_COLON) GenTreeColon(TYP_INT, condMT, gtNewFalse());
5387
+ qmarkNull = gtNewQmarkNode(TYP_INT, condNull, temp->AsColon());
5387
5388
5388
- // Make QMark node a top level node by spilling it.
5389
- unsigned tmp = lvaGrabTemp(true DEBUGARG("spilling QMark"));
5390
- impStoreTemp(tmp, qmarkNull, CHECK_SPILL_NONE);
5389
+ // Make QMark node a top level node by spilling it.
5390
+ unsigned tmp = lvaGrabTemp(true DEBUGARG("spilling QMark"));
5391
+ impStoreTemp(tmp, qmarkNull, CHECK_SPILL_NONE);
5391
5392
5392
- GenTree* lclVar = gtNewLclvNode(tmp, TYP_INT);
5393
- impPushOnStack(lclVar, TYP_INT);
5394
- return 3;
5395
- }
5393
+ GenTree* lclVar = gtNewLclvNode(tmp, TYP_INT);
5394
+ impPushOnStack(lclVar, TYP_INT);
5395
+ return 3;
5396
+ }
5396
5397
5397
- case CEE_CEQ:
5398
- // isinst + ldnull + ceq
5399
- // convert to op1 == null ? true : *op1 != op2
5398
+ case CEE_CEQ:
5399
+ // isinst + ldnull + ceq
5400
+ // convert to op1 == null ? true : *op1 != op2
5400
5401
5401
- break;
5402
+ break;
5403
+ default:
5404
+ return -1;
5405
+ }
5406
+ break;
5402
5407
5403
- case CEE_BRTRUE:
5404
- case CEE_BRTRUE_S:
5405
- break;
5408
+ case CEE_BRTRUE:
5409
+ case CEE_BRTRUE_S:
5410
+ // isinst + brtrue
5411
+ // convert isinst to op1 == null ? false : *op1 == op2, leave the branch IL
5412
+ {
5413
+ GenTree* condNull;
5414
+ //
5415
+ // expand the null check:
5416
+ //
5417
+ // condNull ==> GT_NE
5418
+ // / \.
5419
+ // op1Copy CNS_INT
5420
+ // null
5421
+ //
5422
+ condNull = gtNewOperNode(GT_NE, TYP_INT, gtClone(op1), gtNewNull());
5406
5423
5407
- case CEE_BRFALSE:
5408
- case CEE_BRFALSE_S:
5424
+ GenTree* temp;
5425
+ GenTree* condMT;
5426
+ //
5427
+ // expand the methodtable match:
5428
+ //
5429
+ // condMT ==> GT_EQ
5430
+ // / \.
5431
+ // GT_IND op2 (typically CNS_INT)
5432
+ // |
5433
+ // op1Copy
5434
+ //
5409
5435
5410
- break;
5411
- default:
5412
- return -1;
5413
- }
5436
+ // This can replace op1 with a GT_COMMA that evaluates op1 into a local
5437
+ //
5438
+ op1 = impCloneExpr(op1, &temp, CHECK_SPILL_ALL, nullptr DEBUGARG("CASTCLASS eval op1"));
5439
+ //
5440
+ // op1 is now known to be a non-complex tree
5441
+ // thus we can use gtClone(op1) from now on
5442
+ //
5443
+
5444
+ GenTree* op2Var = op2;
5445
+ temp = gtNewMethodTableLookup(temp);
5446
+ condMT = gtNewOperNode(GT_EQ, TYP_INT, temp, op2);
5447
+
5448
+ GenTree* qmarkNull;
5449
+ //
5450
+ // Generate QMARK - COLON tree
5451
+ //
5452
+ // qmarkNull ==> GT_QMARK
5453
+ // / \.
5454
+ // condNull GT_COLON
5455
+ // / \.
5456
+ // condMT CNS_INT
5457
+ // false
5458
+ //
5459
+ temp = new (this, GT_COLON) GenTreeColon(TYP_INT, condMT, gtNewFalse());
5460
+ qmarkNull = gtNewQmarkNode(TYP_INT, condNull, temp->AsColon());
5461
+
5462
+ // Make QMark node a top level node by spilling it.
5463
+ unsigned tmp = lvaGrabTemp(true DEBUGARG("spilling QMark"));
5464
+ impStoreTemp(tmp, qmarkNull, CHECK_SPILL_NONE);
5465
+
5466
+ GenTree* lclVar = gtNewLclvNode(tmp, TYP_INT);
5467
+ impPushOnStack(lclVar, TYP_INT);
5468
+ return 0;
5469
+ }
5470
+
5471
+ case CEE_BRFALSE:
5472
+ case CEE_BRFALSE_S:
5473
+
5474
+ break;
5475
+ default:
5476
+ return -1;
5414
5477
}
5415
5478
5416
5479
return -1;
0 commit comments