# HG changeset patch # User roland # Date 1536244027 -7200 # Node ID 7e6b86eb7914778027d3ccdbd8cb8cf00860b3fb # Parent cda49f297cb13cdd5c236908b5cad45faf9e0673 8209544: AES encrypt performance regression in jdk11b11 Reviewed-by: kvn, vlivanov diff -r cda49f297cb1 -r 7e6b86eb7914 src/hotspot/share/opto/subnode.cpp --- a/src/hotspot/share/opto/subnode.cpp Thu Sep 06 17:45:15 2018 -0700 +++ b/src/hotspot/share/opto/subnode.cpp Thu Sep 06 16:27:07 2018 +0200 @@ -1348,6 +1348,15 @@ return NULL; } +static bool is_counted_loop_cmp(Node *cmp) { + Node *n = cmp->in(1)->in(1); + return n != NULL && + n->is_Phi() && + n->in(0) != NULL && + n->in(0)->is_CountedLoop() && + n->in(0)->as_CountedLoop()->phi() == n; +} + //------------------------------Ideal------------------------------------------ Node *BoolNode::Ideal(PhaseGVN *phase, bool can_reshape) { // Change "bool tst (cmp con x)" into "bool ~tst (cmp x con)". @@ -1406,7 +1415,7 @@ // Change ((x & m) u<= m) or ((m & x) u<= m) to always true // Same with ((x & m) u< m+1) and ((m & x) u< m+1) if (cop == Op_CmpU && - cmp1->Opcode() == Op_AndI) { + cmp1_op == Op_AndI) { Node* bound = NULL; if (_test._test == BoolTest::le) { bound = cmp2; @@ -1424,7 +1433,7 @@ // This is the off-by-one variant of the above if (cop == Op_CmpU && _test._test == BoolTest::lt && - cmp1->Opcode() == Op_AndI) { + cmp1_op == Op_AndI) { Node* l = cmp1->in(1); Node* r = cmp1->in(2); for (int repeat = 0; repeat < 2; repeat++) { @@ -1445,13 +1454,24 @@ } } + // Change x u< 1 or x u<= 0 to x == 0 + if (cop == Op_CmpU && + cmp1_op != Op_LoadRange && + ((_test._test == BoolTest::lt && + cmp2->find_int_con(-1) == 1) || + (_test._test == BoolTest::le && + cmp2->find_int_con(-1) == 0))) { + Node* ncmp = phase->transform(new CmpINode(cmp1, phase->intcon(0))); + return new BoolNode(ncmp, BoolTest::eq); + } + // Change (arraylength <= 0) or (arraylength == 0) // into (arraylength u<= 0) // Also change (arraylength != 0) into (arraylength u> 0) // The latter version matches the code pattern generated for // array range checks, which will more likely be optimized later. if (cop == Op_CmpI && - cmp1->Opcode() == Op_LoadRange && + cmp1_op == Op_LoadRange && cmp2->find_int_con(-1) == 0) { if (_test._test == BoolTest::le || _test._test == BoolTest::eq) { Node* ncmp = phase->transform(new CmpUNode(cmp1, cmp2)); @@ -1481,17 +1501,32 @@ // due to possible integer overflow. if ((_test._test == BoolTest::eq || _test._test == BoolTest::ne) && (cop == Op_CmpI) && - (cmp1->Opcode() == Op_SubI) && + (cmp1_op == Op_SubI) && ( cmp2_type == TypeInt::ZERO ) ) { Node *ncmp = phase->transform( new CmpINode(cmp1->in(1),cmp1->in(2))); return new BoolNode( ncmp, _test._test ); } + // Same as above but with and AddI of a constant + if ((_test._test == BoolTest::eq || _test._test == BoolTest::ne) && + cop == Op_CmpI && + cmp1_op == Op_AddI && + cmp1->in(2) != NULL && + phase->type(cmp1->in(2))->isa_int() && + phase->type(cmp1->in(2))->is_int()->is_con() && + cmp2_type == TypeInt::ZERO && + !is_counted_loop_cmp(cmp) // modifying the exit test of a counted loop messes the counted loop shape + ) { + const TypeInt* cmp1_in2 = phase->type(cmp1->in(2))->is_int(); + Node *ncmp = phase->transform( new CmpINode(cmp1->in(1),phase->intcon(-cmp1_in2->_hi))); + return new BoolNode( ncmp, _test._test ); + } + // Change (-A vs 0) into (A vs 0) by commuting the test. Disallow in the // most general case because negating 0x80000000 does nothing. Needed for // the CmpF3/SubI/CmpI idiom. if( cop == Op_CmpI && - cmp1->Opcode() == Op_SubI && + cmp1_op == Op_SubI && cmp2_type == TypeInt::ZERO && phase->type( cmp1->in(1) ) == TypeInt::ZERO && phase->type( cmp1->in(2) )->higher_equal(TypeInt::SYMINT) ) {