Move cast elision from TreeNodeInfoInitCmp to LowerCompare
authorMike Danes <onemihaid@hotmail.com>
Sat, 17 Dec 2016 17:36:21 +0000 (19:36 +0200)
committerMike Danes <onemihaid@hotmail.com>
Tue, 17 Jan 2017 18:25:19 +0000 (20:25 +0200)
No FX diffs

src/jit/lower.cpp
src/jit/lowerxarch.cpp

index 41b94c6..5dbe74a 100644 (file)
@@ -2025,6 +2025,36 @@ void Lowering::LowerCompare(GenTree* cmp)
                 op2->gtType = op1Type;
             }
         }
+        else if ((op1->OperGet() == GT_CAST) && !op1->gtOverflow())
+        {
+            GenTreeCast* cast       = op1->AsCast();
+            var_types    castToType = cast->CastToType();
+            GenTree*     castOp     = cast->gtGetOp1();
+
+            if (((castToType == TYP_BOOL) || (castToType == TYP_UBYTE)) && FitsIn<UINT8>(op2Value))
+            {
+                bool canNarrow = ((castOp->OperGet() == GT_CNS_INT) || (castOp->OperGet() == GT_CALL) ||
+                                  (castOp->OperGet() == GT_LCL_VAR) || castOp->OperIsLogical() || castOp->isMemoryOp());
+
+                if (canNarrow)
+                {
+                    assert(!castOp->gtOverflowEx()); // Must not be an overflow checking operation
+
+                    castOp->gtType = castToType;
+
+                    if (castOp->IsIntegralConst())
+                    {
+                        castOp->AsIntCon()->SetIconValue(castOp->AsIntCon()->IconValue() & 255);
+                    }
+
+                    cmp->gtOp.gtOp1 = castOp;
+                    cmp->gtFlags |= GTF_UNSIGNED;
+                    op2->gtType = castToType;
+
+                    BlockRange().Remove(cast);
+                }
+            }
+        }
     }
 #endif // _TARGET_XARCH_
 
index b54e784..9281b1f 100644 (file)
@@ -3588,92 +3588,6 @@ void Lowering::TreeNodeInfoInitCmp(GenTreePtr tree)
                         }
                     }
                 }
-                else if (op1->OperGet() == GT_CAST)
-                {
-                    // If the op1 is a cast operation, and cast type is one byte sized unsigned type,
-                    // we can directly use the number in register, instead of doing an extra cast step.
-                    var_types  dstType       = op1->CastToType();
-                    bool       isUnsignedDst = varTypeIsUnsigned(dstType);
-                    emitAttr   castSize      = EA_ATTR(genTypeSize(dstType));
-                    GenTreePtr castOp1       = op1->gtOp.gtOp1;
-                    genTreeOps castOp1Oper   = castOp1->OperGet();
-                    bool       safeOper      = false;
-
-                    // It is not always safe to change the gtType of 'castOp1' to TYP_UBYTE.
-                    // For example when 'castOp1Oper' is a GT_RSZ or GT_RSH then we are shifting
-                    // bits from the left into the lower bits.  If we change the type to a TYP_UBYTE
-                    // we will instead generate a byte sized shift operation:  shr  al, 24
-                    // For the following ALU operations is it safe to change the gtType to the
-                    // smaller type:
-                    //
-                    if ((castOp1Oper == GT_CNS_INT) || (castOp1Oper == GT_CALL) || // the return value from a Call
-                        (castOp1Oper == GT_LCL_VAR) || castOp1->OperIsLogical() || // GT_AND, GT_OR, GT_XOR
-                        castOp1->isMemoryOp())                                     // isIndir() || isLclField();
-                    {
-                        safeOper = true;
-                    }
-
-                    if ((castSize == EA_1BYTE) && isUnsignedDst && // Unsigned cast to TYP_UBYTE
-                        safeOper &&                                // Must be a safe operation
-                        !op1->gtOverflow())                        // Must not be an overflow checking cast
-                    {
-                        // Currently all of the Oper accepted as 'safeOper' are
-                        // non-overflow checking operations.  If we were to add
-                        // an overflow checking operation then this assert needs
-                        // to be moved above to guard entry to this block.
-                        //
-                        assert(!castOp1->gtOverflowEx()); // Must not be an overflow checking operation
-
-                        // TODO-Cleanup: we're within "if (CheckImmedAndMakeContained(tree, op2))", so isn't
-                        // the following condition always true?
-                        if (op2->isContainedIntOrIImmed())
-                        {
-                            ssize_t val = (ssize_t)op2->AsIntConCommon()->IconValue();
-                            if (val >= 0 && val <= 255)
-                            {
-                                GenTreePtr removeTreeNode = op1;
-                                tree->gtOp.gtOp1          = castOp1;
-                                op1                       = castOp1;
-                                castOp1->gtType           = TYP_UBYTE;
-
-                                // trim down the value if castOp1 is an int constant since its type changed to UBYTE.
-                                if (castOp1Oper == GT_CNS_INT)
-                                {
-                                    castOp1->gtIntCon.gtIconVal = (UINT8)castOp1->gtIntCon.gtIconVal;
-                                }
-
-                                op2->gtType = TYP_UBYTE;
-                                tree->gtFlags |= GTF_UNSIGNED;
-
-                                // right now the op1's type is the same as op2's type.
-                                // if op1 is MemoryOp, we should make the op1 as contained node.
-                                if (castOp1->isMemoryOp())
-                                {
-                                    MakeSrcContained(tree, op1);
-                                    op1IsMadeContained = true;
-                                }
-
-                                BlockRange().Remove(removeTreeNode);
-
-                                // We've changed the type on op1 to TYP_UBYTE, but we already processed that node.
-                                // We need to go back and mark it byteable.
-                                // TODO-Cleanup: it might be better to move this out of the TreeNodeInfoInit pass to
-                                // the earlier "lower" pass, in which case the byteable check would just fall out.
-                                // But that is quite complex!
-                                TreeNodeInfoInitCheckByteable(op1);
-
-#ifdef DEBUG
-                                if (comp->verbose)
-                                {
-                                    printf("TreeNodeInfoInitCmp: Removing a GT_CAST to TYP_UBYTE and changing "
-                                           "castOp1->gtType to TYP_UBYTE\n");
-                                    comp->gtDispTreeRange(BlockRange(), tree);
-                                }
-#endif
-                            }
-                        }
-                    }
-                }
 
                 // If not made contained, op1 can be marked as reg-optional.
                 if (!op1IsMadeContained)