src/share/vm/opto/subnode.cpp

Print this page

        

@@ -1205,10 +1205,44 @@
       phase->type( cmp1->in(2) )->higher_equal(TypeInt::SYMINT) ) {
     Node *ncmp = phase->transform( new (phase->C) CmpINode(cmp1->in(2),cmp2));
     return new (phase->C) BoolNode( ncmp, _test.commute() );
   }
 
+  // Change ((x & m) <= m) into (m >= 0)
+  // Integer expressions which perform bitwise and can be proven to
+  // be less than or equal to either operand, as long as the compared
+  // operand is non-negative.
+  if ( cop == Op_CmpI &&
+       _test._test == BoolTest::le &&
+       cmp1->Opcode() == Op_AndI &&
+       cmp1->in(2) == cmp2) {
+    Node* ncmp = phase->transform( new (phase->C) CmpINode(cmp2, phase->intcon(0))); 
+    return new (phase->C) BoolNode(ncmp, BoolTest::ge);
+  }
+  
+  // Change ((x & m) u<= m) to always true
+  if ( cop == Op_CmpU &&
+       _test._test == BoolTest::le &&
+       cmp1->Opcode() == Op_AndI &&
+       cmp1->in(2) == cmp2) {
+    return ConINode::make(phase->C, 1);
+  }
+
+  // Change ((x & m - 1) < m) or ((x & m - 1) u< m) into (m > 0)
+  // This is the off-by-one variant of the two patterns above
+  if ((cop == Op_CmpU || cop == Op_CmpI) &&
+       _test._test == BoolTest::lt &&
+       cmp1->Opcode() == Op_AndI &&
+       (cmp1->in(2)->Opcode() == Op_AddI && cmp1->in(2)->in(2)->find_int_con(0) == -1 ||
+        cmp1->in(2)->Opcode() == Op_SubI && cmp1->in(2)->in(2)->find_int_con(0) == 1) &&
+       cmp1->in(2)->in(1) == cmp2) {
+    Node* ncmp = phase->transform( new (phase->C) CmpINode(cmp2, phase->intcon(0))); 
+    return cmp2->Opcode() == Op_LoadRange
+           ? new (phase->C) BoolNode(ncmp, BoolTest::ne)  // arraylength known to be non-negative
+           : new (phase->C) BoolNode(ncmp, BoolTest::gt);
+  }
+
   //  The transformation below is not valid for either signed or unsigned
   //  comparisons due to wraparound concerns at MAX_VALUE and MIN_VALUE.
   //  This transformation can be resurrected when we are able to
   //  make inferences about the range of values being subtracted from
   //  (or added to) relative to the wraparound point.