Move and-cmp-nonzero transform from TreeNodeInfoInitCmp to LowerCompare
authorMike Danes <onemihaid@hotmail.com>
Sat, 17 Dec 2016 18:26:13 +0000 (20:26 +0200)
committerMike Danes <onemihaid@hotmail.com>
Tue, 17 Jan 2017 18:25:19 +0000 (20:25 +0200)
FX diff shows a 34 byte improvement without any regressions. In the original code this transform was unnecessarily blocked by an uncontainable GT_AND bit mask:

mov      rax, 0x80000000
and      rax, qword ptr [rsp+08H]
mov      rdx, 0x80000000
cmp      rax, rdx
sete    al

now generates

mov      rax, 0x8000000000000000
and      rax, qword ptr [rsp+08H]
setne    al

Commit migrated from https://github.com/dotnet/coreclr/commit/e74c08ecdde10a84af4fa555efbd925f2cc08547

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

index 5dbe74a..3c9fd90 100644 (file)
@@ -2055,6 +2055,26 @@ void Lowering::LowerCompare(GenTree* cmp)
                 }
             }
         }
+        else if (op1->OperGet() == GT_AND && ((cmp->OperGet() == GT_EQ) || (cmp->OperGet() == GT_NE)))
+        {
+            GenTree* andOp1 = op1->gtGetOp1();
+            GenTree* andOp2 = op1->gtGetOp2();
+
+            if (op2Value != 0)
+            {
+                //
+                // If we don't have a 0 compare we can get one by transforming ((x AND mask) EQ|NE mask)
+                // into ((x AND mask) NE|EQ 0) when mask is a single bit.
+                //
+
+                if (isPow2(static_cast<size_t>(op2Value)) && andOp2->IsIntegralConst(op2Value))
+                {
+                    op2Value = 0;
+                    op2->SetIconValue(0);
+                    cmp->SetOperRaw(GenTree::ReverseRelop(cmp->OperGet()));
+                }
+            }
+        }
     }
 #endif // _TARGET_XARCH_
 
index 9281b1f..c7d8a09 100644 (file)
@@ -3487,20 +3487,6 @@ void Lowering::TreeNodeInfoInitCmp(GenTreePtr tree)
                         ssize_t andOp2CnsVal = andOp2->AsIntConCommon()->IconValue();
                         ssize_t relOp2CnsVal = op2->AsIntConCommon()->IconValue();
 
-                        if ((relOp2CnsVal == andOp2CnsVal) && isPow2(andOp2CnsVal))
-                        {
-                            // We have a single bit test, so now we can change the
-                            // tree into the alternative form,
-                            // so that we can generate a test instruction.
-
-                            // Reverse the equality comparison
-                            tree->SetOperRaw((tree->gtOper == GT_EQ) ? GT_NE : GT_EQ);
-
-                            // Change the relOp2CnsVal to zero
-                            relOp2CnsVal = 0;
-                            op2->AsIntConCommon()->SetIconValue(0);
-                        }
-
                         // Now do we have a equality compare with zero?
                         //
                         if (relOp2CnsVal == 0)