@@ -5711,34 +5711,76 @@ bool Compiler::optNarrowTree(GenTree* tree, var_types srct, var_types dstt, Valu
5711
5711
switch (tree->gtOper )
5712
5712
{
5713
5713
case GT_AND:
5714
+ noway_assert (genActualType (tree->gtType ) == genActualType (op1->gtType ));
5714
5715
noway_assert (genActualType (tree->gtType ) == genActualType (op2->gtType ));
5715
5716
5716
- // Is op2 a small constant than can be narrowed into dstt?
5717
- // if so the result of the GT_AND will also fit into 'dstt' and can be narrowed
5718
- if ((op2->gtOper == GT_CNS_INT) && optNarrowTree (op2, srct, dstt, NoVNPair, false ))
5717
+ GenTree* opToNarrow;
5718
+ opToNarrow = nullptr ;
5719
+ GenTree** otherOpPtr;
5720
+ otherOpPtr = nullptr ;
5721
+ bool canNotNarrowOperand;
5722
+ canNotNarrowOperand = false ;
5723
+
5724
+ // If 'dstt' is unsigned and one of the operands can be narrowed into 'dsst',
5725
+ // the result of the GT_AND will also fit into 'dstt' and can be narrowed.
5726
+ // The same is true if one of the operands is an int const and can be narrowed into 'dsst'.
5727
+ if (!gtIsActiveCSE_Candidate (op2) && ((op2->gtOper == GT_CNS_INT) || varTypeIsUnsigned (dstt)))
5719
5728
{
5720
- // We will change the type of the tree and narrow op2
5729
+ if (optNarrowTree (op2, srct, dstt, NoVNPair, false ))
5730
+ {
5731
+ opToNarrow = op2;
5732
+ otherOpPtr = &tree->gtOp .gtOp1 ;
5733
+ }
5734
+ else
5735
+ {
5736
+ canNotNarrowOperand = true ;
5737
+ }
5738
+ }
5739
+
5740
+ if ((opToNarrow == nullptr ) && !gtIsActiveCSE_Candidate (op1) &&
5741
+ ((op1->gtOper == GT_CNS_INT) || varTypeIsUnsigned (dstt)))
5742
+ {
5743
+ if (optNarrowTree (op1, srct, dstt, NoVNPair, false ))
5744
+ {
5745
+ opToNarrow = op1;
5746
+ otherOpPtr = &tree->gtOp .gtOp2 ;
5747
+ }
5748
+ else
5749
+ {
5750
+ canNotNarrowOperand = true ;
5751
+ }
5752
+ }
5753
+
5754
+ if (opToNarrow != nullptr )
5755
+ {
5756
+ // We will change the type of the tree and narrow opToNarrow
5721
5757
//
5722
5758
if (doit)
5723
5759
{
5724
5760
tree->gtType = genActualType (dstt);
5725
5761
tree->SetVNs (vnpNarrow);
5726
5762
5727
- optNarrowTree (op2 , srct, dstt, NoVNPair, true );
5728
- // We may also need to cast away the upper bits of op1
5763
+ optNarrowTree (opToNarrow , srct, dstt, NoVNPair, true );
5764
+ // We may also need to cast away the upper bits of *otherOpPtr
5729
5765
if (srcSize == 8 )
5730
5766
{
5731
5767
assert (tree->gtType == TYP_INT);
5732
- op1 = gtNewCastNode (TYP_INT, op1, false , TYP_INT);
5768
+ GenTree* castOp = gtNewCastNode (TYP_INT, op1, false , TYP_INT);
5733
5769
#ifdef DEBUG
5734
- op1 ->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED;
5770
+ castOp ->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED;
5735
5771
#endif
5736
- tree-> gtOp . gtOp1 = op1 ;
5772
+ *otherOpPtr = castOp ;
5737
5773
}
5738
5774
}
5739
5775
return true ;
5740
5776
}
5741
5777
5778
+ if (canNotNarrowOperand)
5779
+ {
5780
+ noway_assert (doit == false );
5781
+ return false ;
5782
+ }
5783
+
5742
5784
goto COMMON_BINOP;
5743
5785
5744
5786
case GT_ADD:
@@ -5753,10 +5795,9 @@ bool Compiler::optNarrowTree(GenTree* tree, var_types srct, var_types dstt, Valu
5753
5795
5754
5796
case GT_OR:
5755
5797
case GT_XOR:
5756
- COMMON_BINOP:
5757
5798
noway_assert (genActualType (tree->gtType ) == genActualType (op1->gtType ));
5758
5799
noway_assert (genActualType (tree->gtType ) == genActualType (op2->gtType ));
5759
-
5800
+ COMMON_BINOP:
5760
5801
if (gtIsActiveCSE_Candidate (op1) || gtIsActiveCSE_Candidate (op2) ||
5761
5802
!optNarrowTree (op1, srct, dstt, NoVNPair, doit) || !optNarrowTree (op2, srct, dstt, NoVNPair, doit))
5762
5803
{
0 commit comments