From 7e1588c1a1ff1de7278ddafb29ac8333d5d976f1 Mon Sep 17 00:00:00 2001 From: Eric Liu Date: Wed, 24 Feb 2021 11:07:34 +0000 Subject: [PATCH 1/2] 8261008: Optimize Xor This patch canonicalizes 'Xor' to constant zero when both inputs are the same. It's not quite easy to measure the performance change between 'xor' and constant zero, the later is typically a single 'mov' in generated code. But given by this transformation, c2 may perform some other more powerful optimizations. This was tested with the micro benchmark below. Loop in this case is properly removed and the performance increases significantly. ``` public void xorTheSame(MyState s, Blackhole bh) { int x = s.in1; int y = s.in2; for (int i = 0; i < 5000; i++) { y = x ^ x; x = y ^ y; } bh.consume(x); } ``` [Test] All jtreg tests passed without new failure. Change-Id: I1334199868b07543c4fe004976c26bed9162a993 --- src/hotspot/share/opto/addnode.cpp | 23 +++++++++++++++++++++++ src/hotspot/share/opto/addnode.hpp | 4 +++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/opto/addnode.cpp b/src/hotspot/share/opto/addnode.cpp index 2a9e9434c1c1d..6ffcce5e9186b 100644 --- a/src/hotspot/share/opto/addnode.cpp +++ b/src/hotspot/share/opto/addnode.cpp @@ -913,6 +913,19 @@ const Type *OrLNode::add_ring( const Type *t0, const Type *t1 ) const { } //============================================================================= + +Node* XorINode::Ideal(PhaseGVN* phase, bool can_reshape) { + Node* in1 = in(1); + Node* in2 = in(2); + const Type* t1 = phase->type(in1); + const Type* t2 = phase->type(in2); + if (t1 != Type::TOP && t2 != Type::TOP && in1 == in2) { + return new ConINode(TypeInt::ZERO); + } + + return AddNode::Ideal(phase, can_reshape); +} + //------------------------------add_ring--------------------------------------- // Supplied function returns the sum of the inputs IN THE CURRENT RING. For // the logical operations the ring's ADD is really a logical OR function. @@ -948,6 +961,16 @@ const Type *XorLNode::add_ring( const Type *t0, const Type *t1 ) const { return TypeLong::make( r0->get_con() ^ r1->get_con() ); } +Node* XorLNode::Ideal(PhaseGVN* phase, bool can_reshape) { + Node* in1 = in(1); + Node* in2 = in(2); + const Type* t1 = phase->type(in1); + const Type* t2 = phase->type(in2); + if (t1 != Type::TOP && t2 != Type::TOP && in1 == in2) { + return new ConLNode(TypeLong::ZERO); + } + return AddNode::Ideal(phase, can_reshape); +} Node* MaxNode::build_min_max(Node* a, Node* b, bool is_max, bool is_unsigned, const Type* t, PhaseGVN& gvn) { bool is_int = gvn.type(a)->isa_int(); diff --git a/src/hotspot/share/opto/addnode.hpp b/src/hotspot/share/opto/addnode.hpp index 610bfffce39c8..8abdb917cb6fe 100644 --- a/src/hotspot/share/opto/addnode.hpp +++ b/src/hotspot/share/opto/addnode.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -213,6 +213,7 @@ class XorINode : public AddNode { virtual const Type *add_id() const { return TypeInt::ZERO; } virtual const Type *bottom_type() const { return TypeInt::INT; } virtual uint ideal_reg() const { return Op_RegI; } + virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); }; //------------------------------XorINode--------------------------------------- @@ -225,6 +226,7 @@ class XorLNode : public AddNode { virtual const Type *add_id() const { return TypeLong::ZERO; } virtual const Type *bottom_type() const { return TypeLong::LONG; } virtual uint ideal_reg() const { return Op_RegL; } + virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); }; //------------------------------MaxNode---------------------------------------- From fd25d5b418dd3fecac1b9010d610dec6dcfa7b82 Mon Sep 17 00:00:00 2001 From: Eric Liu Date: Tue, 2 Mar 2021 04:20:54 +0000 Subject: [PATCH 2/2] Implements Value() for XorNode. Change-Id: Ic9fc01375801adc82c0a0289d9a11a5367031eb4 --- src/hotspot/share/opto/addnode.cpp | 25 ++++++++++++++++--------- src/hotspot/share/opto/addnode.hpp | 4 ++-- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/hotspot/share/opto/addnode.cpp b/src/hotspot/share/opto/addnode.cpp index 6ffcce5e9186b..cfcf068242a5e 100644 --- a/src/hotspot/share/opto/addnode.cpp +++ b/src/hotspot/share/opto/addnode.cpp @@ -914,16 +914,19 @@ const Type *OrLNode::add_ring( const Type *t0, const Type *t1 ) const { //============================================================================= -Node* XorINode::Ideal(PhaseGVN* phase, bool can_reshape) { +const Type* XorINode::Value(PhaseGVN* phase) const { Node* in1 = in(1); Node* in2 = in(2); const Type* t1 = phase->type(in1); const Type* t2 = phase->type(in2); - if (t1 != Type::TOP && t2 != Type::TOP && in1 == in2) { - return new ConINode(TypeInt::ZERO); + if (t1 == Type::TOP || t2 == Type::TOP) { + return Type::TOP; } - - return AddNode::Ideal(phase, can_reshape); + // x ^ x ==> 0 + if (in1->eqv_uncast(in2)) { + return add_id(); + } + return AddNode::Value(phase); } //------------------------------add_ring--------------------------------------- @@ -961,15 +964,19 @@ const Type *XorLNode::add_ring( const Type *t0, const Type *t1 ) const { return TypeLong::make( r0->get_con() ^ r1->get_con() ); } -Node* XorLNode::Ideal(PhaseGVN* phase, bool can_reshape) { +const Type* XorLNode::Value(PhaseGVN* phase) const { Node* in1 = in(1); Node* in2 = in(2); const Type* t1 = phase->type(in1); const Type* t2 = phase->type(in2); - if (t1 != Type::TOP && t2 != Type::TOP && in1 == in2) { - return new ConLNode(TypeLong::ZERO); + if (t1 == Type::TOP || t2 == Type::TOP) { + return Type::TOP; } - return AddNode::Ideal(phase, can_reshape); + // x ^ x ==> 0 + if (in1->eqv_uncast(in2)) { + return add_id(); + } + return AddNode::Value(phase); } Node* MaxNode::build_min_max(Node* a, Node* b, bool is_max, bool is_unsigned, const Type* t, PhaseGVN& gvn) { diff --git a/src/hotspot/share/opto/addnode.hpp b/src/hotspot/share/opto/addnode.hpp index 8abdb917cb6fe..b23fc9b18779c 100644 --- a/src/hotspot/share/opto/addnode.hpp +++ b/src/hotspot/share/opto/addnode.hpp @@ -212,8 +212,8 @@ class XorINode : public AddNode { virtual const Type *add_ring( const Type *, const Type * ) const; virtual const Type *add_id() const { return TypeInt::ZERO; } virtual const Type *bottom_type() const { return TypeInt::INT; } + virtual const Type *Value(PhaseGVN *phase) const; virtual uint ideal_reg() const { return Op_RegI; } - virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); }; //------------------------------XorINode--------------------------------------- @@ -225,8 +225,8 @@ class XorLNode : public AddNode { virtual const Type *add_ring( const Type *, const Type * ) const; virtual const Type *add_id() const { return TypeLong::ZERO; } virtual const Type *bottom_type() const { return TypeLong::LONG; } + virtual const Type *Value(PhaseGVN *phase) const; virtual uint ideal_reg() const { return Op_RegL; } - virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); }; //------------------------------MaxNode----------------------------------------