8380475: C2: Improve AndNode::Identity with KnownBits

Reviewed-by: mchevalier, qamai
This commit is contained in:
Ashay Rane 2026-03-23 14:58:17 +00:00 committed by Quan Anh Mai
parent 890d62bb8c
commit 00ee63e99e
2 changed files with 256 additions and 239 deletions

View File

@ -651,31 +651,19 @@ Node* AndINode::Identity(PhaseGVN* phase) {
return in(1);
}
Node* in1 = in(1);
uint op = in1->Opcode();
const TypeInt* t2 = phase->type(in(2))->isa_int();
if (t2 && t2->is_con()) {
int con = t2->get_con();
// Masking off high bits which are always zero is useless.
const TypeInt* t1 = phase->type(in(1))->isa_int();
if (t1 != nullptr && t1->_lo >= 0) {
jint t1_support = right_n_bits(1 + log2i_graceful(t1->_hi));
if ((t1_support & con) == t1_support)
return in1;
}
// Masking off the high bits of a unsigned-shift-right is not
// needed either.
if (op == Op_URShiftI) {
const TypeInt* t12 = phase->type(in1->in(2))->isa_int();
if (t12 && t12->is_con()) { // Shift is by a constant
int shift = t12->get_con();
shift &= BitsPerJavaInteger - 1; // semantics of Java shifts
int mask = max_juint >> shift;
if ((mask & con) == mask) // If AND is useless, skip it
return in1;
}
}
const TypeInt* t1 = phase->type(in(1))->is_int();
const TypeInt* t2 = phase->type(in(2))->is_int();
if ((~t1->_bits._ones & ~t2->_bits._zeros) == 0) {
// All bits that might be 0 in in1 are known to be 0 in in2
return in(2);
}
if ((~t2->_bits._ones & ~t1->_bits._zeros) == 0) {
// All bits that might be 0 in in2 are known to be 0 in in1
return in(1);
}
return MulNode::Identity(phase);
}
@ -779,32 +767,19 @@ Node* AndLNode::Identity(PhaseGVN* phase) {
return in(1);
}
Node *usr = in(1);
const TypeLong *t2 = phase->type( in(2) )->isa_long();
if( t2 && t2->is_con() ) {
jlong con = t2->get_con();
// Masking off high bits which are always zero is useless.
const TypeLong* t1 = phase->type( in(1) )->isa_long();
if (t1 != nullptr && t1->_lo >= 0) {
int bit_count = log2i_graceful(t1->_hi) + 1;
jlong t1_support = jlong(max_julong >> (BitsPerJavaLong - bit_count));
if ((t1_support & con) == t1_support)
return usr;
}
uint lop = usr->Opcode();
// Masking off the high bits of a unsigned-shift-right is not
// needed either.
if( lop == Op_URShiftL ) {
const TypeInt *t12 = phase->type( usr->in(2) )->isa_int();
if( t12 && t12->is_con() ) { // Shift is by a constant
int shift = t12->get_con();
shift &= BitsPerJavaLong - 1; // semantics of Java shifts
jlong mask = max_julong >> shift;
if( (mask&con) == mask ) // If AND is useless, skip it
return usr;
}
}
const TypeLong* t1 = phase->type(in(1))->is_long();
const TypeLong* t2 = phase->type(in(2))->is_long();
if ((~t1->_bits._ones & ~t2->_bits._zeros) == 0) {
// All bits that might be 0 in in1 are known to be 0 in in2
return in(2);
}
if ((~t2->_bits._ones & ~t1->_bits._zeros) == 0) {
// All bits that might be 0 in in2 are known to be 0 in in1
return in(1);
}
return MulNode::Identity(phase);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2025, Red Hat, Inc. All rights reserved.
* Copyright (c) 2021, 2026, Red Hat, Inc. 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
@ -24,13 +24,14 @@
package compiler.c2.irTests;
import compiler.lib.ir_framework.*;
import jdk.test.lib.Utils;
import java.util.Random;
import static compiler.lib.generators.Generators.G;
import jdk.test.lib.Asserts;
import java.util.Objects;
/*
* @test
* @bug 8277850 8278949 8285793 8346664
* @bug 8277850 8278949 8285793 8346664 8380475
* @key randomness
* @summary C2: optimize mask checks in counted loops
* @library /test/lib /
@ -38,33 +39,31 @@ import java.util.Objects;
*/
public class TestShiftAndMask {
private static final Random RANDOM = Utils.getRandomInstance();
public static void main(String[] args) {
TestFramework.run();
}
// any X << INT_MASK_WIDTH is zero under any INT_MASK
static final int INT_MASK_WIDTH = 1 + RANDOM.nextInt(30);
static final int INT_MASK_WIDTH = G.ints().restricted(1, 30).next();
static final int INT_MAX_MASK = (1 << INT_MASK_WIDTH) - 1;
static final int INT_MASK = 1 + RANDOM.nextInt(INT_MAX_MASK);
static final int INT_MASK2 = 1 + RANDOM.nextInt(INT_MAX_MASK);
static final int INT_ZERO_CONST = RANDOM.nextInt() << INT_MASK_WIDTH;
static final int INT_MASK = G.ints().restricted(1, INT_MAX_MASK).next();
static final int INT_MASK2 = G.ints().restricted(1, INT_MAX_MASK).next();
static final int INT_ZERO_CONST = G.ints().next() << INT_MASK_WIDTH;
static final int INT_RANDOM_CONST = RANDOM.nextInt();
static final int INT_RANDOM_SHIFT = RANDOM.nextInt();
static final int INT_RANDOM_MASK = RANDOM.nextInt();
static final int INT_RANDOM_CONST = G.ints().next();
static final int INT_RANDOM_SHIFT = G.ints().next();
static final int INT_RANDOM_MASK = G.ints().next();
// any X << LONG_MASK_WIDTH is zero under any LONG_MASK
static final int LONG_MASK_WIDTH = 1 + RANDOM.nextInt(62);
static final int LONG_MASK_WIDTH = G.ints().restricted(1, 62).next();
static final long LONG_MAX_MASK = (1L << LONG_MASK_WIDTH) - 1;
static final long LONG_MASK = 1 + RANDOM.nextLong(LONG_MAX_MASK);
static final long LONG_MASK2 = 1 + RANDOM.nextLong(LONG_MAX_MASK);
static final long LONG_ZERO_CONST = RANDOM.nextLong() << LONG_MASK_WIDTH;
static final long LONG_MASK = G.longs().restricted(1L, LONG_MAX_MASK).next();
static final long LONG_MASK2 = G.longs().restricted(1L, LONG_MAX_MASK).next();
static final long LONG_ZERO_CONST = G.longs().next() << LONG_MASK_WIDTH;
static final long LONG_RANDOM_CONST = RANDOM.nextLong();
static final long LONG_RANDOM_SHIFT = RANDOM.nextLong();
static final long LONG_RANDOM_MASK = RANDOM.nextLong();
static final long LONG_RANDOM_CONST = G.longs().next();
static final long LONG_RANDOM_SHIFT = G.longs().next();
static final long LONG_RANDOM_MASK = G.longs().next();
@Test
public static int intSumAndMask(int i, int j) {
@ -73,12 +72,9 @@ public class TestShiftAndMask {
@Run(test = { "intSumAndMask" })
public static void checkIntSumAndMask() {
int j = RANDOM.nextInt();
int i = RANDOM.nextInt();
int res = intSumAndMask(i, j);
if (res != ((j + i << INT_RANDOM_SHIFT + INT_RANDOM_CONST) & INT_RANDOM_MASK)) {
throw new RuntimeException("incorrect result: " + res);
}
int j = G.ints().next();
int i = G.ints().next();
Asserts.assertEquals(intSumAndMask(i, j), (j + i << INT_RANDOM_SHIFT + INT_RANDOM_CONST) & INT_RANDOM_MASK);
}
@Test
@ -90,9 +86,7 @@ public class TestShiftAndMask {
@Check(test = "shiftMaskInt")
public static void checkShiftMaskInt(int res) {
if (res != 0) {
throw new RuntimeException("incorrect result: " + res);
}
Asserts.assertEquals(res, 0);
}
@Test
@ -102,12 +96,9 @@ public class TestShiftAndMask {
@Run(test = { "longSumAndMask" })
public static void checkLongSumAndMask() {
long j = RANDOM.nextLong();
long i = RANDOM.nextLong();
long res = longSumAndMask(i, j);
if (res != ((j + i << LONG_RANDOM_SHIFT + LONG_RANDOM_CONST) & LONG_RANDOM_MASK)) {
throw new RuntimeException("incorrect result: " + res);
}
long j = G.longs().next();
long i = G.longs().next();
Asserts.assertEquals(longSumAndMask(i, j), (j + i << LONG_RANDOM_SHIFT + LONG_RANDOM_CONST) & LONG_RANDOM_MASK);
}
@Test
@ -120,9 +111,7 @@ public class TestShiftAndMask {
@Check(test = "shiftMaskLong")
public static void checkShiftMaskLong(long res) {
if (res != 0) {
throw new RuntimeException("incorrect result: " + res);
}
Asserts.assertEquals(res, 0L);
}
static volatile int barrier;
@ -143,9 +132,7 @@ public class TestShiftAndMask {
@Check(test = "shiftNonConstMaskInt")
public static void checkShiftNonConstMaskInt(int res) {
if (res != 0) {
throw new RuntimeException("incorrect result: " + res);
}
Asserts.assertEquals(res, 0);
}
@Test
@ -164,9 +151,7 @@ public class TestShiftAndMask {
@Check(test = "shiftNonConstMaskLong")
public static void checkShiftNonConstMaskLong(long res) {
if (res != 0) {
throw new RuntimeException("incorrect result: " + res);
}
Asserts.assertEquals(res, 0L);
}
@Test
@ -178,12 +163,9 @@ public class TestShiftAndMask {
@Run(test = "addShiftMaskInt")
public static void addShiftMaskInt_runner() {
int i = RANDOM.nextInt();
int j = RANDOM.nextInt();
int res = addShiftMaskInt(i, j);
if (res != (j & INT_MASK)) {
throw new RuntimeException("incorrect result: " + res);
}
int i = G.ints().next();
int j = G.ints().next();
Asserts.assertEquals(addShiftMaskInt(i, j), j & INT_MASK);
}
@Test
@ -195,12 +177,9 @@ public class TestShiftAndMask {
@Run(test = "addShiftPlusConstMaskInt")
public static void addShiftPlusConstMaskInt_runner() {
int i = RANDOM.nextInt();
int j = RANDOM.nextInt();
int res = addShiftPlusConstMaskInt(i, j);
if (res != (j & INT_MASK)) {
throw new RuntimeException("incorrect result: " + res);
}
int i = G.ints().next();
int j = G.ints().next();
Asserts.assertEquals(addShiftPlusConstMaskInt(i, j), j & INT_MASK);
}
@Test
@ -233,16 +212,10 @@ public class TestShiftAndMask {
@Run(test = "addSshiftNonConstMaskInt")
public static void addSshiftNonConstMaskInt_runner() {
int i = RANDOM.nextInt();
int j = RANDOM.nextInt();
int res = addSshiftNonConstMaskInt(i, j, true);
if (res != (j & INT_MASK)) {
throw new RuntimeException("incorrect result: " + res);
}
res = addSshiftNonConstMaskInt(i, j, false);
if (res != (j & INT_MASK2)) {
throw new RuntimeException("incorrect result: " + res);
}
int i = G.ints().next();
int j = G.ints().next();
Asserts.assertEquals(addSshiftNonConstMaskInt(i, j, true), j & INT_MASK);
Asserts.assertEquals(addSshiftNonConstMaskInt(i, j, false), j & INT_MASK2);
}
@Test
@ -261,15 +234,9 @@ public class TestShiftAndMask {
@Run(test = "addConstNonConstMaskInt")
public static void addConstNonConstMaskInt_runner() {
int j = RANDOM.nextInt();
int res = addConstNonConstMaskInt(j, true);
if (res != (j & INT_MASK)) {
throw new RuntimeException("incorrect result: " + res);
}
res = addConstNonConstMaskInt(j, false);
if (res != (j & INT_MASK2)) {
throw new RuntimeException("incorrect result: " + res);
}
int j = G.ints().next();
Asserts.assertEquals(addConstNonConstMaskInt(j, true), j & INT_MASK);
Asserts.assertEquals(addConstNonConstMaskInt(j, false), j & INT_MASK2);
}
@Test
@ -281,12 +248,9 @@ public class TestShiftAndMask {
@Run(test = "addShiftMaskLong")
public static void addShiftMaskLong_runner() {
long i = RANDOM.nextLong();
long j = RANDOM.nextLong();
long res = addShiftMaskLong(i, j);
if (res != (j & LONG_MASK)) {
throw new RuntimeException("incorrect result: " + res);
}
long i = G.longs().next();
long j = G.longs().next();
Asserts.assertEquals(addShiftMaskLong(i, j), j & LONG_MASK);
}
@Test
@ -298,12 +262,9 @@ public class TestShiftAndMask {
@Run(test = "addShiftPlusConstMaskLong")
public static void addShiftPlusConstMaskLong_runner() {
long i = RANDOM.nextLong();
long j = RANDOM.nextLong();
long res = addShiftPlusConstMaskLong(i, j);
if (res != (j & LONG_MASK)) {
throw new RuntimeException("incorrect result: " + res);
}
long i = G.longs().next();
long j = G.longs().next();
Asserts.assertEquals(addShiftPlusConstMaskLong(i, j), j & LONG_MASK);
}
@Test
@ -322,16 +283,10 @@ public class TestShiftAndMask {
@Run(test = "addSshiftNonConstMaskLong")
public static void addSshiftNonConstMaskLong_runner() {
long i = RANDOM.nextLong();
long j = RANDOM.nextLong();
long res = addSshiftNonConstMaskLong(i, j, true);
if (res != (j & LONG_MASK)) {
throw new RuntimeException("incorrect result: " + res);
}
res = addSshiftNonConstMaskLong(i, j, false);
if (res != (j & LONG_MASK2)) {
throw new RuntimeException("incorrect result: " + res);
}
long i = G.longs().next();
long j = G.longs().next();
Asserts.assertEquals(addSshiftNonConstMaskLong(i, j, true), j & LONG_MASK);
Asserts.assertEquals(addSshiftNonConstMaskLong(i, j, false), j & LONG_MASK2);
}
@Test
@ -350,15 +305,9 @@ public class TestShiftAndMask {
@Run(test = "addConstNonConstMaskLong")
public static void addConstNonConstMaskLong_runner() {
long j = RANDOM.nextLong();
long res = addConstNonConstMaskLong(j, true);
if (res != (j & LONG_MASK)) {
throw new RuntimeException("incorrect result: " + res);
}
res = addConstNonConstMaskLong(j, false);
if (res != (j & LONG_MASK2)) {
throw new RuntimeException("incorrect result: " + res);
}
long j = G.longs().next();
Asserts.assertEquals(addConstNonConstMaskLong(j, true), j & LONG_MASK);
Asserts.assertEquals(addConstNonConstMaskLong(j, false), j & LONG_MASK2);
}
@Test
@ -370,9 +319,7 @@ public class TestShiftAndMask {
@Check(test = "addShiftMaskInt2")
public static void checkAddShiftMaskInt2(int res) {
if (res != 0) {
throw new RuntimeException("incorrect result: " + res);
}
Asserts.assertEquals(res, 0);
}
@Test
@ -384,9 +331,7 @@ public class TestShiftAndMask {
@Check(test = "addShiftMaskLong2")
public static void checkAddShiftMaskLong2(long res) {
if (res != 0) {
throw new RuntimeException("incorrect result: " + res);
}
Asserts.assertEquals(res, 0L);
}
// Try to get add inputs swapped compared to other tests
@ -401,12 +346,9 @@ public class TestShiftAndMask {
@Run(test = "addShiftMaskInt3")
public static void addShiftMaskInt3_runner() {
int i = RANDOM.nextInt();
int j = RANDOM.nextInt();
int res = addShiftMaskInt3(i, j);
if (res != (j & INT_MASK)) {
throw new RuntimeException("incorrect result: " + res);
}
int i = G.ints().next();
int j = G.ints().next();
Asserts.assertEquals(addShiftMaskInt3(i, j), j & INT_MASK);
}
@Test
@ -420,12 +362,9 @@ public class TestShiftAndMask {
@Run(test = "addShiftMaskLong3")
public static void addShiftMaskLong3_runner() {
long i = RANDOM.nextLong();
float j = RANDOM.nextFloat();
long res = addShiftMaskLong3(i, j);
if (res != (((long) j) & LONG_MASK)) {
throw new RuntimeException("incorrect result: " + res);
}
long i = G.longs().next();
float j = G.floats().next();
Asserts.assertEquals(addShiftMaskLong3(i, j), ((long) j) & LONG_MASK);
}
@Test
@ -437,9 +376,7 @@ public class TestShiftAndMask {
@Check(test = "shiftConvMask")
public static void checkShiftConvMask(long res) {
if (res != 0) {
throw new RuntimeException("incorrect result: " + res);
}
Asserts.assertEquals(res, 0L);
}
@Test
@ -458,9 +395,7 @@ public class TestShiftAndMask {
@Check(test = "shiftNotConstConvMask")
public static void checkShiftNotConstConvMask(long res) {
if (res != 0) {
throw new RuntimeException("incorrect result: " + res);
}
Asserts.assertEquals(res, 0L);
}
@Test
@ -472,12 +407,9 @@ public class TestShiftAndMask {
@Run(test = "addShiftConvMask")
public static void addShiftConvMask_runner() {
int i = RANDOM.nextInt();
long j = RANDOM.nextLong();
long res = addShiftConvMask(i, j);
if (res != (j & INT_MASK)) {
throw new RuntimeException("incorrect result: " + res);
}
int i = G.ints().next();
long j = G.longs().next();
Asserts.assertEquals(addShiftConvMask(i, j), j & INT_MASK);
}
@Test
@ -489,9 +421,7 @@ public class TestShiftAndMask {
@Check(test = "addShiftConvMask2")
public static void checkAddShiftConvMask2(long res) {
if (res != 0) {
throw new RuntimeException("incorrect result: " + res);
}
Asserts.assertEquals(res, 0L);
}
@Test
@ -502,11 +432,8 @@ public class TestShiftAndMask {
@Run(test = "shiftMaskIntCheckIndex")
public static void shiftMaskIntCheckIndex_runner() {
int i = RANDOM.nextInt((Integer.MAX_VALUE - 1) >> INT_MASK_WIDTH);
int res = shiftMaskIntCheckIndex(i, (i << INT_MASK_WIDTH) + 1);
if (res != 0) {
throw new RuntimeException("incorrect result: " + res);
}
int i = G.uniformInts(0, ((Integer.MAX_VALUE - 1) >> INT_MASK_WIDTH) - 1).next();
Asserts.assertEquals(shiftMaskIntCheckIndex(i, (i << INT_MASK_WIDTH) + 1), 0);
}
@Test
@ -517,11 +444,8 @@ public class TestShiftAndMask {
@Run(test = "shiftMaskLongCheckIndex")
public static void shiftMaskLongCheckIndex_runner() {
long i = RANDOM.nextLong((Long.MAX_VALUE - 1) >> LONG_MASK_WIDTH);
long res = shiftMaskLongCheckIndex(i, (i << LONG_MASK_WIDTH) + 1);
if (res != 0) {
throw new RuntimeException("incorrect result: " + res);
}
long i = G.uniformLongs(0L, ((Long.MAX_VALUE - 1) >> LONG_MASK_WIDTH) - 1).next();
Asserts.assertEquals(shiftMaskLongCheckIndex(i, (i << LONG_MASK_WIDTH) + 1), 0L);
}
@Test
@ -533,12 +457,9 @@ public class TestShiftAndMask {
@Run(test = "addShiftMaskIntCheckIndex")
public static void addShiftMaskIntCheckIndex_runner() {
int i = RANDOM.nextInt((Integer.MAX_VALUE - 1) >> INT_MASK_WIDTH);
int j = RANDOM.nextInt();
int res = addShiftMaskIntCheckIndex(i, j, (i << INT_MASK_WIDTH) + 1);
if (res != (j & INT_MASK)) {
throw new RuntimeException("incorrect result: " + res);
}
int i = G.uniformInts(0, ((Integer.MAX_VALUE - 1) >> INT_MASK_WIDTH) - 1).next();
int j = G.ints().next();
Asserts.assertEquals(addShiftMaskIntCheckIndex(i, j, (i << INT_MASK_WIDTH) + 1), j & INT_MASK);
}
@Test
@ -550,12 +471,9 @@ public class TestShiftAndMask {
@Run(test = "addShiftMaskLongCheckIndex")
public static void addShiftMaskLongCheckIndex_runner() {
long i = RANDOM.nextLong((Long.MAX_VALUE - 1) >> LONG_MASK_WIDTH);
long j = RANDOM.nextLong();
long res = addShiftMaskLongCheckIndex(i, j, (i << LONG_MASK_WIDTH) + 1);
if (res != (j & LONG_MASK)) {
throw new RuntimeException("incorrect result: " + res);
}
long i = G.uniformLongs(0L, ((Long.MAX_VALUE - 1) >> LONG_MASK_WIDTH) - 1).next();
long j = G.longs().next();
Asserts.assertEquals(addShiftMaskLongCheckIndex(i, j, (i << LONG_MASK_WIDTH) + 1), j & LONG_MASK);
}
@Test
@ -567,12 +485,9 @@ public class TestShiftAndMask {
@Run(test = "addShiftMaskIntCheckIndex2")
public static void addShiftMaskIntCheckIndex2_runner() {
int i = RANDOM.nextInt((Integer.MAX_VALUE - 1) >> INT_MASK_WIDTH);
int j = RANDOM.nextInt((Integer.MAX_VALUE - 1) >> INT_MASK_WIDTH);
int res = addShiftMaskIntCheckIndex2(i, j, (Integer.max(i, j) << INT_MASK_WIDTH) + 1);
if (res != 0) {
throw new RuntimeException("incorrect result: " + res);
}
int i = G.uniformInts(0, ((Integer.MAX_VALUE - 1) >> INT_MASK_WIDTH) - 1).next();
int j = G.uniformInts(0, ((Integer.MAX_VALUE - 1) >> INT_MASK_WIDTH) - 1).next();
Asserts.assertEquals(addShiftMaskIntCheckIndex2(i, j, (Integer.max(i, j) << INT_MASK_WIDTH) + 1), 0);
}
@Test
@ -583,12 +498,9 @@ public class TestShiftAndMask {
@Run(test = "addShiftMaskLongCheckIndex2")
public static void addShiftMaskLongCheckIndex2_runner() {
long i = RANDOM.nextLong((Long.MAX_VALUE - 1) >> LONG_MASK_WIDTH);
long j = RANDOM.nextLong((Long.MAX_VALUE - 1) >> LONG_MASK_WIDTH);
long res = addShiftMaskLongCheckIndex2(i, j, (Long.max(i, j) << LONG_MASK_WIDTH) + 1);
if (res != 0) {
throw new RuntimeException("incorrect result: " + res);
}
long i = G.uniformLongs(0L, ((Long.MAX_VALUE - 1) >> LONG_MASK_WIDTH) - 1).next();
long j = G.uniformLongs(0L, ((Long.MAX_VALUE - 1) >> LONG_MASK_WIDTH) - 1).next();
Asserts.assertEquals(addShiftMaskLongCheckIndex2(i, j, (Long.max(i, j) << LONG_MASK_WIDTH) + 1), 0L);
}
@Test
@ -599,11 +511,8 @@ public class TestShiftAndMask {
@Run(test = "shiftConvMaskCheckIndex")
public static void shiftConvMaskCheckIndex_runner() {
int i = RANDOM.nextInt((Integer.MAX_VALUE - 1) >> INT_MASK_WIDTH);
long res = shiftConvMaskCheckIndex(i, (i << INT_MASK_WIDTH) + 1);
if (res != 0) {
throw new RuntimeException("incorrect result: " + res);
}
int i = G.uniformInts(0, ((Integer.MAX_VALUE - 1) >> INT_MASK_WIDTH) - 1).next();
Asserts.assertEquals(shiftConvMaskCheckIndex(i, (i << INT_MASK_WIDTH) + 1), 0L);
}
@Test
@ -615,12 +524,9 @@ public class TestShiftAndMask {
@Run(test = "addShiftConvMaskCheckIndex")
public static void addShiftConvMaskCheckIndex_runner() {
int i = RANDOM.nextInt((Integer.MAX_VALUE - 1) >> INT_MASK_WIDTH);
long j = RANDOM.nextLong();
long res = addShiftConvMaskCheckIndex(i, j, (i << INT_MASK_WIDTH) + 1);
if (res != (j & INT_MASK)) {
throw new RuntimeException("incorrect result: " + res);
}
int i = G.uniformInts(0, ((Integer.MAX_VALUE - 1) >> INT_MASK_WIDTH) - 1).next();
long j = G.longs().next();
Asserts.assertEquals(addShiftConvMaskCheckIndex(i, j, (i << INT_MASK_WIDTH) + 1), j & INT_MASK);
}
@Test
@ -631,11 +537,147 @@ public class TestShiftAndMask {
@Run(test = "addShiftConvMaskCheckIndex2")
public static void addShiftConvMaskCheckIndex2_runner() {
int i = RANDOM.nextInt((Integer.MAX_VALUE - 1) >> INT_MASK_WIDTH);
int j = RANDOM.nextInt((Integer.MAX_VALUE - 1) >> INT_MASK_WIDTH);
long res = addShiftConvMaskCheckIndex2(i, j, (Integer.max(i, j) << INT_MASK_WIDTH) + 1);
if (res != 0) {
throw new RuntimeException("incorrect result: " + res);
}
int i = G.uniformInts(0, ((Integer.MAX_VALUE - 1) >> INT_MASK_WIDTH) - 1).next();
int j = G.uniformInts(0, ((Integer.MAX_VALUE - 1) >> INT_MASK_WIDTH) - 1).next();
Asserts.assertEquals(addShiftConvMaskCheckIndex2(i, j, (Integer.max(i, j) << INT_MASK_WIDTH) + 1), 0L);
}
@Test
@IR(failOn = {IRNode.AND_I})
@IR(counts = {IRNode.LSHIFT_I, "1"})
public int shiftLeftWithLowMaskInt(int x) {
return (x << INT_MASK_WIDTH) & (-1 << INT_MASK_WIDTH); // transformed to: return x << INT_MASK_WIDTH;
}
@Test
@IR(failOn = {IRNode.AND_L})
@IR(counts = {IRNode.LSHIFT_L, "1"})
public long shiftLeftWithLowMaskLong(long x) {
return (x << LONG_MASK_WIDTH) & (-1 << LONG_MASK_WIDTH); // transformed to: return x << LONG_MASK_WIDTH;
}
@Test
@IR(failOn = {IRNode.AND_I})
@IR(counts = {IRNode.LSHIFT_I, "1"})
public int shiftLeftWithLowMaskSmallInt(int x) {
return (x << INT_MASK_WIDTH) & (-1 << (INT_MASK_WIDTH - 1)); // transformed to: return x << INT_MASK_WIDTH;
}
@Test
@IR(failOn = {IRNode.AND_L})
@IR(counts = {IRNode.LSHIFT_L, "1"})
public long shiftLeftWithLowMaskSmallLong(long x) {
return (x << LONG_MASK_WIDTH) & (-1 << (LONG_MASK_WIDTH - 1)); // transformed to: return x << LONG_MASK_WIDTH;
}
@Test
@IR(failOn = {IRNode.AND_I})
@IR(counts = {IRNode.LSHIFT_I, "1"})
public static int shiftLeftWithLowMaskIntReversed(int x) {
return (-1 << INT_MASK_WIDTH) & (x << INT_MASK_WIDTH); // transformed to: return x << INT_MASK_WIDTH;
}
@Test
@IR(failOn = {IRNode.AND_L})
@IR(counts = {IRNode.LSHIFT_L, "1"})
public static long shiftLeftWithLowMaskLongReversed(long x) {
return (-1 << LONG_MASK_WIDTH) & (x << LONG_MASK_WIDTH); // transformed to: return x << LONG_MASK_WIDTH;
}
@Test
@IR(failOn = {IRNode.AND_I})
@IR(counts = {IRNode.LSHIFT_I, "1"})
public static int shiftLeftWithLowMaskSmallIntReversed(int x) {
return (-1 << (INT_MASK_WIDTH - 1)) & (x << INT_MASK_WIDTH); // transformed to: return x << INT_MASK_WIDTH;
}
@Test
@IR(failOn = {IRNode.AND_L})
@IR(counts = {IRNode.LSHIFT_L, "1"})
public static long shiftLeftWithLowMaskSmallLongReversed(long x) {
return (-1 << (LONG_MASK_WIDTH - 1)) & (x << LONG_MASK_WIDTH); // transformed to: return x << LONG_MASK_WIDTH;
}
@Test
@IR(counts = {IRNode.AND_I, "1"})
public int andMaskNonNegativeInt(int x) {
return (x & 0x7FFF) & 0xFFFF; // transformed to: return x & 0x7FFF;
}
@Test
@IR(counts = {IRNode.AND_L, "1"})
public long andMaskNonNegativeLong(long x) {
return (x & 0x7FFFL) & 0xFFFFL; // transformed to: return x & 0x7FFFL;
}
@Test
@IR(counts = {IRNode.AND_I, "1"})
public int andMaskNonNegativeIntReversed(int x) {
return 0xFFFF & (x & 0x7FFF); // transformed to: return x & 0x7FFF;
}
@Test
@IR(counts = {IRNode.AND_L, "1"})
public long andMaskNonNegativeLongReversed(long x) {
return 0xFFFFL & (x & 0x7FFFL); // transformed to: return x & 0x7FFFL;
}
@Test
@IR(failOn = {IRNode.AND_I})
@IR(counts = {IRNode.URSHIFT_I, "1"})
public int andAfterURShiftInt(int x) {
return (x >>> 8) & 0x00FFFFFF; // transformed to return x >>> 8;
}
@Test
@IR(failOn = {IRNode.AND_L})
@IR(counts = {IRNode.URSHIFT_L, "1"})
public long andAfterURShiftLong(long x) {
return (x >>> 16) & 0x0000FFFFFFFFFFFFL; // transformed to return x >>> 16;
}
@Test
@IR(failOn = {IRNode.AND_I})
@IR(counts = {IRNode.URSHIFT_I, "1"})
public int andAfterURShiftIntReversed(int x) {
return 0x00FFFFFF & (x >>> 8); // transformed to return x >>> 8;
}
@Test
@IR(failOn = {IRNode.AND_L})
@IR(counts = {IRNode.URSHIFT_L, "1"})
public long andAfterURShiftLongReversed(long x) {
return 0x0000FFFFFFFFFFFFL & (x >>> 16); // transformed to return x >>> 16;
}
@Run(test = {"shiftLeftWithLowMaskInt", "shiftLeftWithLowMaskLong",
"shiftLeftWithLowMaskSmallInt", "shiftLeftWithLowMaskSmallLong",
"shiftLeftWithLowMaskIntReversed", "shiftLeftWithLowMaskLongReversed",
"shiftLeftWithLowMaskSmallIntReversed", "shiftLeftWithLowMaskSmallLongReversed",
"andMaskNonNegativeInt", "andMaskNonNegativeLong",
"andMaskNonNegativeIntReversed", "andMaskNonNegativeLongReversed",
"andAfterURShiftInt", "andAfterURShiftLong",
"andAfterURShiftIntReversed", "andAfterURShiftLongReversed",
})
public void verifyShiftAndMaskTransforms() {
int xi = G.ints().next();
long xl = G.longs().next();
Asserts.assertEquals(shiftLeftWithLowMaskInt(xi), (xi << INT_MASK_WIDTH));
Asserts.assertEquals(shiftLeftWithLowMaskLong(xl), (xl << LONG_MASK_WIDTH));
Asserts.assertEquals(shiftLeftWithLowMaskSmallInt(xi), (xi << INT_MASK_WIDTH));
Asserts.assertEquals(shiftLeftWithLowMaskSmallLong(xl), (xl << LONG_MASK_WIDTH));
Asserts.assertEquals(shiftLeftWithLowMaskIntReversed(xi), (xi << INT_MASK_WIDTH));
Asserts.assertEquals(shiftLeftWithLowMaskLongReversed(xl), (xl << LONG_MASK_WIDTH));
Asserts.assertEquals(shiftLeftWithLowMaskSmallIntReversed(xi), (xi << INT_MASK_WIDTH));
Asserts.assertEquals(shiftLeftWithLowMaskSmallLongReversed(xl), (xl << LONG_MASK_WIDTH));
Asserts.assertEquals(andMaskNonNegativeInt(xi), (xi & 0x7FFF));
Asserts.assertEquals(andMaskNonNegativeLong(xl), (xl & 0x7FFFL));
Asserts.assertEquals(andMaskNonNegativeIntReversed(xi), (xi & 0x7FFF));
Asserts.assertEquals(andMaskNonNegativeLongReversed(xl), (xl & 0x7FFFL));
Asserts.assertEquals(andAfterURShiftInt(xi), (xi >>> 8));
Asserts.assertEquals(andAfterURShiftLong(xl), (xl >>> 16));
Asserts.assertEquals(andAfterURShiftIntReversed(xi), (xi >>> 8));
Asserts.assertEquals(andAfterURShiftLongReversed(xl), (xl >>> 16));
}
}