@@ -14322,15 +14322,12 @@ GenTree* Compiler::gtFoldExprSpecial(GenTree* tree)
14322
14322
14323
14323
val = cons->AsIntConCommon()->IconValue();
14324
14324
14325
- // Transforms that would drop op cannot be performed if op has side effects
14326
- bool opHasSideEffects = (op->gtFlags & GTF_SIDE_EFFECT) != 0;
14327
-
14328
14325
// Helper function that creates a new IntCon node and morphs it, if required
14329
14326
auto NewMorphedIntConNode = [&](int value) -> GenTreeIntCon* {
14330
14327
GenTreeIntCon* icon = gtNewIconNode(value);
14331
14328
if (fgGlobalMorph)
14332
14329
{
14333
- fgMorphTreeDone (icon);
14330
+ INDEBUG (icon->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED );
14334
14331
}
14335
14332
return icon;
14336
14333
};
@@ -14365,43 +14362,52 @@ GenTree* Compiler::gtFoldExprSpecial(GenTree* tree)
14365
14362
switch (oper)
14366
14363
{
14367
14364
case GT_LE:
14368
- if (tree->IsUnsigned() && (val == 0) && (op1 == cons) && !opHasSideEffects)
14365
+ {
14366
+ if (tree->IsUnsigned() && (val == 0) && (op1 == cons))
14369
14367
{
14370
14368
// unsigned (0 <= x) is always true
14371
- op = NewMorphedIntConNode(1);
14369
+ op = gtWrapWithSideEffects( NewMorphedIntConNode(1), op, GTF_ALL_EFFECT );
14372
14370
goto DONE_FOLD;
14373
14371
}
14374
14372
break;
14373
+ }
14375
14374
14376
14375
case GT_GE:
14377
- if (tree->IsUnsigned() && (val == 0) && (op2 == cons) && !opHasSideEffects)
14376
+ {
14377
+ if (tree->IsUnsigned() && (val == 0) && (op2 == cons))
14378
14378
{
14379
14379
// unsigned (x >= 0) is always true
14380
- op = NewMorphedIntConNode(1);
14380
+ op = gtWrapWithSideEffects( NewMorphedIntConNode(1), op, GTF_ALL_EFFECT );
14381
14381
goto DONE_FOLD;
14382
14382
}
14383
14383
break;
14384
+ }
14384
14385
14385
14386
case GT_LT:
14386
- if (tree->IsUnsigned() && (val == 0) && (op2 == cons) && !opHasSideEffects)
14387
+ {
14388
+ if (tree->IsUnsigned() && (val == 0) && (op2 == cons))
14387
14389
{
14388
14390
// unsigned (x < 0) is always false
14389
- op = NewMorphedIntConNode(0);
14391
+ op = gtWrapWithSideEffects( NewMorphedIntConNode(0), op, GTF_ALL_EFFECT );
14390
14392
goto DONE_FOLD;
14391
14393
}
14392
14394
break;
14395
+ }
14393
14396
14394
14397
case GT_GT:
14395
- if (tree->IsUnsigned() && (val == 0) && (op1 == cons) && !opHasSideEffects)
14398
+ {
14399
+ if (tree->IsUnsigned() && (val == 0) && (op1 == cons))
14396
14400
{
14397
14401
// unsigned (0 > x) is always false
14398
- op = NewMorphedIntConNode(0);
14402
+ op = gtWrapWithSideEffects( NewMorphedIntConNode(0), op, GTF_ALL_EFFECT );
14399
14403
goto DONE_FOLD;
14400
14404
}
14405
+ }
14401
14406
FALLTHROUGH;
14407
+
14402
14408
case GT_EQ:
14403
14409
case GT_NE:
14404
-
14410
+ {
14405
14411
// Optimize boxed value classes; these are always false. This IL is
14406
14412
// generated when a generic value is tested against null:
14407
14413
// <T> ... foo(T x) { ... if ((object)x == null) ...
@@ -14463,57 +14469,60 @@ GenTree* Compiler::gtFoldExprSpecial(GenTree* tree)
14463
14469
{
14464
14470
return gtFoldBoxNullable(tree);
14465
14471
}
14466
-
14467
14472
break;
14473
+ }
14468
14474
14469
14475
case GT_ADD:
14476
+ {
14470
14477
if (val == 0)
14471
14478
{
14472
14479
goto DONE_FOLD;
14473
14480
}
14474
14481
break;
14482
+ }
14475
14483
14476
14484
case GT_MUL:
14485
+ {
14477
14486
if (val == 1)
14478
14487
{
14479
14488
goto DONE_FOLD;
14480
14489
}
14481
14490
else if (val == 0)
14482
14491
{
14483
- /* Multiply by zero - return the 'zero' node, but not if side effects */
14484
- if (!opHasSideEffects)
14485
- {
14486
- op = cons;
14487
- goto DONE_FOLD;
14488
- }
14492
+ // Multiply by zero - return the 'zero' node
14493
+ op = gtWrapWithSideEffects(cons, op, GTF_ALL_EFFECT);
14494
+ goto DONE_FOLD;
14489
14495
}
14490
14496
break;
14497
+ }
14491
14498
14492
14499
case GT_DIV:
14493
14500
case GT_UDIV:
14501
+ {
14494
14502
if ((op2 == cons) && (val == 1) && !op1->OperIsConst())
14495
14503
{
14496
14504
goto DONE_FOLD;
14497
14505
}
14498
14506
break;
14507
+ }
14499
14508
14500
14509
case GT_SUB:
14510
+ {
14501
14511
if ((op2 == cons) && (val == 0) && !op1->OperIsConst())
14502
14512
{
14503
14513
goto DONE_FOLD;
14504
14514
}
14505
14515
break;
14516
+ }
14506
14517
14507
14518
case GT_AND:
14519
+ {
14508
14520
if (val == 0)
14509
14521
{
14510
- /* AND with zero - return the 'zero' node, but not if side effects */
14511
-
14512
- if (!opHasSideEffects)
14513
- {
14514
- op = cons;
14515
- goto DONE_FOLD;
14516
- }
14522
+ // AND with zero - return the 'zero' node
14523
+ op = gtWrapWithSideEffects(cons, op, GTF_ALL_EFFECT);
14524
+ ;
14525
+ goto DONE_FOLD;
14517
14526
}
14518
14527
else if (val == 0xFF)
14519
14528
{
@@ -14546,8 +14555,10 @@ GenTree* Compiler::gtFoldExprSpecial(GenTree* tree)
14546
14555
}
14547
14556
}
14548
14557
break;
14558
+ }
14549
14559
14550
14560
case GT_OR:
14561
+ {
14551
14562
if (val == 0)
14552
14563
{
14553
14564
goto DONE_FOLD;
@@ -14558,34 +14569,33 @@ GenTree* Compiler::gtFoldExprSpecial(GenTree* tree)
14558
14569
14559
14570
assert(val == 1);
14560
14571
14561
- /* OR with one - return the 'one' node, but not if side effects */
14562
-
14563
- if (!opHasSideEffects)
14564
- {
14565
- op = cons;
14566
- goto DONE_FOLD;
14567
- }
14572
+ // OR with one - return the 'one' node
14573
+ op = gtWrapWithSideEffects(cons, op, GTF_ALL_EFFECT);
14574
+ goto DONE_FOLD;
14568
14575
}
14569
14576
break;
14577
+ }
14570
14578
14571
14579
case GT_LSH:
14572
14580
case GT_RSH:
14573
14581
case GT_RSZ:
14574
14582
case GT_ROL:
14575
14583
case GT_ROR:
14584
+ {
14576
14585
if (val == 0)
14577
14586
{
14578
14587
if (op2 == cons)
14579
14588
{
14580
14589
goto DONE_FOLD;
14581
14590
}
14582
- else if (!opHasSideEffects)
14591
+ else
14583
14592
{
14584
- op = cons;
14593
+ op = gtWrapWithSideEffects( cons, op, GTF_ALL_EFFECT) ;
14585
14594
goto DONE_FOLD;
14586
14595
}
14587
14596
}
14588
14597
break;
14598
+ }
14589
14599
14590
14600
case GT_QMARK:
14591
14601
{
@@ -14608,9 +14618,8 @@ GenTree* Compiler::gtFoldExprSpecial(GenTree* tree)
14608
14618
{
14609
14619
fgWalkTreePre(&op, gtClearColonCond);
14610
14620
}
14611
- }
14612
-
14613
14621
goto DONE_FOLD;
14622
+ }
14614
14623
14615
14624
default:
14616
14625
break;
@@ -14627,6 +14636,13 @@ GenTree* Compiler::gtFoldExprSpecial(GenTree* tree)
14627
14636
JITDUMP("Transformed into:\n");
14628
14637
DISPTREE(op);
14629
14638
14639
+ if (fgGlobalMorph)
14640
+ {
14641
+ // We can sometimes produce a comma over the constant if the original op
14642
+ // had a side effect, so just ensure we set the flag (which will be already
14643
+ // set for the operands otherwise).
14644
+ INDEBUG(op->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED);
14645
+ }
14630
14646
return op;
14631
14647
}
14632
14648
0 commit comments