@@ -448,14 +448,15 @@ bool Lowering::IsContainableUnaryOrBinaryOp(GenTree* parentNode, GenTree* childN
448
448
return false ;
449
449
}
450
450
451
+ if (!IsInvariantInRange (childNode, parentNode))
452
+ {
453
+ return false ;
454
+ }
455
+
451
456
if (parentNode->OperIs (GT_ADD, GT_SUB))
452
457
{
453
458
// These operations can still report flags
454
-
455
- if (IsInvariantInRange (childNode, parentNode))
456
- {
457
- return true ;
458
- }
459
+ return true ;
459
460
}
460
461
461
462
if ((parentNode->gtFlags & GTF_SET_FLAGS) != 0 )
@@ -466,10 +467,27 @@ bool Lowering::IsContainableUnaryOrBinaryOp(GenTree* parentNode, GenTree* childN
466
467
467
468
if (parentNode->OperIs (GT_CMP))
468
469
{
469
- if (IsInvariantInRange (childNode, parentNode))
470
+ return true ;
471
+ }
472
+
473
+ if (parentNode->OperIsCmpCompare ())
474
+ {
475
+ if (castOp->isContained ())
470
476
{
471
- return true ;
477
+ return false ;
472
478
}
479
+
480
+ if (IsContainableMemoryOp (castOp))
481
+ {
482
+ // The cast node will contain a memory operation which will perform
483
+ // the cast on load/store, so we don't need to contain it here.
484
+ // This check won't catch spills, so if register pressure is high
485
+ // this can result in cmp (extended-register) taking higher priority
486
+ // over a load/store with extension.
487
+ return false ;
488
+ }
489
+
490
+ return true ;
473
491
}
474
492
475
493
return false ;
@@ -2846,25 +2864,24 @@ void Lowering::ContainCheckBinary(GenTreeOp* node)
2846
2864
{
2847
2865
if (IsContainableUnaryOrBinaryOp (node, op2))
2848
2866
{
2849
- if (op2->OperIs (GT_CAST))
2867
+ if (node-> OperIs (GT_ADD, GT_SUB, GT_CMP) && op2->OperIs (GT_CAST))
2850
2868
{
2851
2869
// We want to prefer the combined op here over containment of the cast op
2852
2870
op2->AsCast ()->CastOp ()->ClearContained ();
2853
2871
}
2854
- MakeSrcContained (node, op2);
2855
2872
2873
+ MakeSrcContained (node, op2);
2856
2874
return ;
2857
2875
}
2858
-
2859
2876
if (node->OperIsCommutative () && IsContainableUnaryOrBinaryOp (node, op1))
2860
2877
{
2861
- if (op1->OperIs (GT_CAST))
2878
+ if (node-> OperIs (GT_ADD, GT_SUB, GT_CMP) && op1->OperIs (GT_CAST))
2862
2879
{
2863
2880
// We want to prefer the combined op here over containment of the cast op
2864
2881
op1->AsCast ()->CastOp ()->ClearContained ();
2865
2882
}
2866
- MakeSrcContained (node, op1);
2867
2883
2884
+ MakeSrcContained (node, op1);
2868
2885
std::swap (node->gtOp1 , node->gtOp2 );
2869
2886
return ;
2870
2887
}
@@ -3080,12 +3097,22 @@ void Lowering::ContainCheckCompare(GenTreeOp* cmp)
3080
3097
{
3081
3098
if (IsContainableUnaryOrBinaryOp (cmp, op2))
3082
3099
{
3100
+ if (cmp->OperIsCmpCompare () && op2->OperIs (GT_CAST))
3101
+ {
3102
+ op2->AsCast ()->CastOp ()->ClearRegOptional ();
3103
+ }
3104
+
3083
3105
MakeSrcContained (cmp, op2);
3084
3106
return ;
3085
3107
}
3086
3108
3087
3109
if (IsContainableUnaryOrBinaryOp (cmp, op1))
3088
3110
{
3111
+ if (cmp->OperIsCmpCompare () && op1->OperIs (GT_CAST))
3112
+ {
3113
+ op1->AsCast ()->CastOp ()->ClearRegOptional ();
3114
+ }
3115
+
3089
3116
MakeSrcContained (cmp, op1);
3090
3117
std::swap (cmp->gtOp1 , cmp->gtOp2 );
3091
3118
if (cmp->OperIsCompare ())
0 commit comments