8267332: xor value should handle bounded values

Reviewed-by: thartmann, redestad
This commit is contained in:
Nils Eliasson 2021-05-21 14:06:18 +00:00
parent ee2651b9e5
commit 4ba761381c
2 changed files with 166 additions and 0 deletions

View File

@ -920,9 +920,23 @@ const Type* XorINode::Value(PhaseGVN* phase) const {
if (in1->eqv_uncast(in2)) {
return add_id();
}
// result of xor can only have bits sets where any of the
// inputs have bits set. lo can always become 0.
const TypeInt* t1i = t1->is_int();
const TypeInt* t2i = t2->is_int();
if ((t1i->_lo >= 0) &&
(t1i->_hi > 0) &&
(t2i->_lo >= 0) &&
(t2i->_hi > 0)) {
// hi - set all bits below the highest bit. Using round_down to avoid overflow.
const TypeInt* t1x = TypeInt::make(0, round_down_power_of_2(t1i->_hi) + (round_down_power_of_2(t1i->_hi) - 1), t1i->_widen);
const TypeInt* t2x = TypeInt::make(0, round_down_power_of_2(t2i->_hi) + (round_down_power_of_2(t2i->_hi) - 1), t2i->_widen);
return t1x->meet(t2x);
}
return AddNode::Value(phase);
}
//------------------------------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.
@ -970,6 +984,19 @@ const Type* XorLNode::Value(PhaseGVN* phase) const {
if (in1->eqv_uncast(in2)) {
return add_id();
}
// result of xor can only have bits sets where any of the
// inputs have bits set. lo can always become 0.
const TypeLong* t1l = t1->is_long();
const TypeLong* t2l = t2->is_long();
if ((t1l->_lo >= 0) &&
(t1l->_hi > 0) &&
(t2l->_lo >= 0) &&
(t2l->_hi > 0)) {
// hi - set all bits below the highest bit. Using round_down to avoid overflow.
const TypeLong* t1x = TypeLong::make(0, round_down_power_of_2(t1l->_hi) + (round_down_power_of_2(t1l->_hi) - 1), t1l->_widen);
const TypeLong* t2x = TypeLong::make(0, round_down_power_of_2(t2l->_hi) + (round_down_power_of_2(t2l->_hi) - 1), t2l->_widen);
return t1x->meet(t2x);
}
return AddNode::Value(phase);
}

View File

@ -0,0 +1,139 @@
/*
* Copyright (c) 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @key randomness
* @bug 8267332
* @summary Test meet on xor
* @library /test/lib /
* @run main/othervm compiler.types.TestMeetXor -Xbatch -XX::CompileCommand=dontinline,*::test*
*/
package compiler.types;
import java.util.Random;
import jdk.test.lib.Asserts;
public class TestMeetXor {
public static void main(String[] args) throws Exception {
for (int i = 0; i < 50_000; i++) {
testCase1E();
testCase2E();
testCase3E();
testCase4E();
testCaseS();
}
}
static int[] count = new int[256];
static Random r = jdk.test.lib.Utils.getRandomInstance();
public static void testCase1E() {
boolean aiobe = false;
try {
testBound1E(r.nextInt());
} catch (ArrayIndexOutOfBoundsException e) {
aiobe = true;
}
Asserts.assertTrue(aiobe);
}
public static void testBound1E(int i1) throws ArrayIndexOutOfBoundsException {
int index = (i1 >>> 24) ^ -1;
count[index]++;
}
public static void testCase2E() {
boolean aiobe = false;
try {
testBound2E(r.nextInt());
} catch (ArrayIndexOutOfBoundsException e) {
aiobe = true;
}
Asserts.assertTrue(aiobe);
}
public static void testBound2E(int i1) throws ArrayIndexOutOfBoundsException {
int index = (i1 >>> 24) ^ 0x100;
count[index]++;
}
public static void testCase3E() {
boolean aiobe = false;
try {
testBound3E(r.nextInt());
} catch (ArrayIndexOutOfBoundsException e) {
aiobe = true;
}
Asserts.assertTrue(aiobe);
}
public static void testBound3E(int i1) throws ArrayIndexOutOfBoundsException {
int index = (i1 >>> 24) ^ Integer.MIN_VALUE;
count[index]++;
}
public static void testCase4E() {
boolean aiobe = false;
try {
testBound4E(r.nextInt(), 0xf0f0ff);
} catch (ArrayIndexOutOfBoundsException e) {
aiobe = true;
}
Asserts.assertTrue(aiobe);
}
public static void testBound4E(int i1, int i2) throws ArrayIndexOutOfBoundsException {
int index = (i1 >>> 24) ^ i2;
count[index]++;
}
public static void testCaseS() {
testBound1S(r.nextInt());
testBound2S(r.nextInt());
testBound3S(r.nextInt(), r.nextInt());
testBound4S(r.nextInt());
}
public static void testBound1S(int i1) throws ArrayIndexOutOfBoundsException {
int index = (i1 >>> 24) ^ 0x80;
count[index]++;
}
public static void testBound2S(int i1) throws ArrayIndexOutOfBoundsException {
int index = (i1 >>> 24) ^ 0xff;
count[index]++;
}
public static void testBound3S(int i1, int i2) throws ArrayIndexOutOfBoundsException {
int index = (i1 >>> 24) ^ (i2 >>> 24);
count[index]++;
}
public static void testBound4S(int i1) throws ArrayIndexOutOfBoundsException {
int index = (i1 >>> 24) ^ 0;
count[index]++;
}
}