8278949: Cleanups for 8277850
Co-authored-by: John R Rose <jrose@openjdk.org> Reviewed-by: kvn, jrose
This commit is contained in:
parent
31fbb8723e
commit
06206c7199
src/hotspot/share/opto
test/hotspot/jtreg/compiler/c2/irTests
@ -507,7 +507,7 @@ const Type *AndINode::mul_ring( const Type *t0, const Type *t1 ) const {
|
||||
|
||||
const Type* AndINode::Value(PhaseGVN* phase) const {
|
||||
// patterns similar to (v << 2) & 3
|
||||
if (AndIL_shift_and_mask(phase, in(2), in(1), T_INT)) {
|
||||
if (AndIL_shift_and_mask_is_always_zero(phase, in(1), in(2), T_INT, true)) {
|
||||
return TypeInt::ZERO;
|
||||
}
|
||||
|
||||
@ -553,6 +553,12 @@ Node* AndINode::Identity(PhaseGVN* phase) {
|
||||
|
||||
//------------------------------Ideal------------------------------------------
|
||||
Node *AndINode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
// pattern similar to (v1 + (v2 << 2)) & 3 transformed to v1 & 3
|
||||
Node* progress = AndIL_add_shift_and_mask(phase, T_INT);
|
||||
if (progress != NULL) {
|
||||
return progress;
|
||||
}
|
||||
|
||||
// Special case constant AND mask
|
||||
const TypeInt *t2 = phase->type( in(2) )->isa_int();
|
||||
if( !t2 || !t2->is_con() ) return MulNode::Ideal(phase, can_reshape);
|
||||
@ -607,12 +613,6 @@ Node *AndINode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
phase->type(load->in(1)) == TypeInt::ZERO )
|
||||
return new AndINode( load->in(2), in(2) );
|
||||
|
||||
// pattern similar to (v1 + (v2 << 2)) & 3 transformed to v1 & 3
|
||||
Node* progress = AndIL_add_shift_and_mask(phase, T_INT);
|
||||
if (progress != NULL) {
|
||||
return progress;
|
||||
}
|
||||
|
||||
return MulNode::Ideal(phase, can_reshape);
|
||||
}
|
||||
|
||||
@ -646,7 +646,7 @@ const Type *AndLNode::mul_ring( const Type *t0, const Type *t1 ) const {
|
||||
|
||||
const Type* AndLNode::Value(PhaseGVN* phase) const {
|
||||
// patterns similar to (v << 2) & 3
|
||||
if (AndIL_shift_and_mask(phase, in(2), in(1), T_LONG)) {
|
||||
if (AndIL_shift_and_mask_is_always_zero(phase, in(1), in(2), T_LONG, true)) {
|
||||
return TypeLong::ZERO;
|
||||
}
|
||||
|
||||
@ -693,6 +693,12 @@ Node* AndLNode::Identity(PhaseGVN* phase) {
|
||||
|
||||
//------------------------------Ideal------------------------------------------
|
||||
Node *AndLNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
// pattern similar to (v1 + (v2 << 2)) & 3 transformed to v1 & 3
|
||||
Node* progress = AndIL_add_shift_and_mask(phase, T_LONG);
|
||||
if (progress != NULL) {
|
||||
return progress;
|
||||
}
|
||||
|
||||
// Special case constant AND mask
|
||||
const TypeLong *t2 = phase->type( in(2) )->isa_long();
|
||||
if( !t2 || !t2->is_con() ) return MulNode::Ideal(phase, can_reshape);
|
||||
@ -729,12 +735,6 @@ Node *AndLNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
}
|
||||
}
|
||||
|
||||
// pattern similar to (v1 + (v2 << 2)) & 3 transformed to v1 & 3
|
||||
Node* progress = AndIL_add_shift_and_mask(phase, T_LONG);
|
||||
if (progress != NULL) {
|
||||
return progress;
|
||||
}
|
||||
|
||||
return MulNode::Ideal(phase, can_reshape);
|
||||
}
|
||||
|
||||
@ -1714,11 +1714,20 @@ const Type* RotateRightNode::Value(PhaseGVN* phase) const {
|
||||
}
|
||||
}
|
||||
|
||||
// Helper method to transform:
|
||||
// patterns similar to (v << 2) & 3 to 0
|
||||
// and
|
||||
// patterns similar to (v1 + (v2 << 2)) & 3 transformed to v1 & 3
|
||||
bool MulNode::AndIL_shift_and_mask(PhaseGVN* phase, Node* mask, Node* shift, BasicType bt) {
|
||||
// Given an expression (AndX shift mask) or (AndX mask shift),
|
||||
// determine if the AndX must always produce zero, because the
|
||||
// the shift (x<<N) is bitwise disjoint from the mask #M.
|
||||
// The X in AndX must be I or L, depending on bt.
|
||||
// Specifically, the following cases fold to zero,
|
||||
// when the shift value N is large enough to zero out
|
||||
// all the set positions of the and-mask M.
|
||||
// (AndI (LShiftI _ #N) #M) => #0
|
||||
// (AndL (LShiftL _ #N) #M) => #0
|
||||
// (AndL (ConvI2L (LShiftI _ #N)) #M) => #0
|
||||
// The M and N values must satisfy ((-1 << N) & M) == 0.
|
||||
// Because the optimization might work for a non-constant
|
||||
// mask M, we check the AndX for both operand orders.
|
||||
bool MulNode::AndIL_shift_and_mask_is_always_zero(PhaseGVN* phase, Node* shift, Node* mask, BasicType bt, bool check_reverse) {
|
||||
if (mask == NULL || shift == NULL) {
|
||||
return false;
|
||||
}
|
||||
@ -1727,14 +1736,25 @@ bool MulNode::AndIL_shift_and_mask(PhaseGVN* phase, Node* mask, Node* shift, Bas
|
||||
if (mask_t == NULL || shift_t == NULL) {
|
||||
return false;
|
||||
}
|
||||
if (bt == T_LONG && shift != NULL && shift->Opcode() == Op_ConvI2L) {
|
||||
BasicType shift_bt = bt;
|
||||
if (bt == T_LONG && shift->Opcode() == Op_ConvI2L) {
|
||||
bt = T_INT;
|
||||
shift = shift->in(1);
|
||||
if (shift == NULL) {
|
||||
Node* val = shift->in(1);
|
||||
if (val == NULL) {
|
||||
return false;
|
||||
}
|
||||
if (val->Opcode() == Op_LShiftI) {
|
||||
shift_bt = T_INT;
|
||||
shift = val;
|
||||
}
|
||||
}
|
||||
if (shift->Opcode() != Op_LShift(bt)) {
|
||||
if (shift->Opcode() != Op_LShift(shift_bt)) {
|
||||
if (check_reverse &&
|
||||
(mask->Opcode() == Op_LShift(bt) ||
|
||||
(bt == T_LONG && mask->Opcode() == Op_ConvI2L))) {
|
||||
// try it the other way around
|
||||
return AndIL_shift_and_mask_is_always_zero(phase, mask, shift, bt, false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Node* shift2 = shift->in(2);
|
||||
@ -1746,7 +1766,7 @@ bool MulNode::AndIL_shift_and_mask(PhaseGVN* phase, Node* mask, Node* shift, Bas
|
||||
return false;
|
||||
}
|
||||
|
||||
jint shift_con = shift2_t->is_int()->get_con() & ((bt == T_INT ? BitsPerJavaInteger : BitsPerJavaLong) - 1);
|
||||
jint shift_con = shift2_t->is_int()->get_con() & ((shift_bt == T_INT ? BitsPerJavaInteger : BitsPerJavaLong) - 1);
|
||||
if ((((jlong)1) << shift_con) > mask_t->hi_as_long() && mask_t->lo_as_long() >= 0) {
|
||||
return true;
|
||||
}
|
||||
@ -1754,20 +1774,43 @@ bool MulNode::AndIL_shift_and_mask(PhaseGVN* phase, Node* mask, Node* shift, Bas
|
||||
return false;
|
||||
}
|
||||
|
||||
// Helper method to transform:
|
||||
// patterns similar to (v1 + (v2 << 2)) & 3 to v1 & 3
|
||||
// Given an expression (AndX (AddX v1 (LShiftX v2 #N)) #M)
|
||||
// determine if the AndX must always produce (AndX v1 #M),
|
||||
// because the shift (v2<<N) is bitwise disjoint from the mask #M.
|
||||
// The X in AndX will be I or L, depending on bt.
|
||||
// Specifically, the following cases fold,
|
||||
// when the shift value N is large enough to zero out
|
||||
// all the set positions of the and-mask M.
|
||||
// (AndI (AddI v1 (LShiftI _ #N)) #M) => (AndI v1 #M)
|
||||
// (AndL (AddI v1 (LShiftL _ #N)) #M) => (AndL v1 #M)
|
||||
// (AndL (AddL v1 (ConvI2L (LShiftI _ #N))) #M) => (AndL v1 #M)
|
||||
// The M and N values must satisfy ((-1 << N) & M) == 0.
|
||||
// Because the optimization might work for a non-constant
|
||||
// mask M, and because the AddX operands can come in either
|
||||
// order, we check for every operand order.
|
||||
Node* MulNode::AndIL_add_shift_and_mask(PhaseGVN* phase, BasicType bt) {
|
||||
Node* in1 = in(1);
|
||||
Node* in2 = in(2);
|
||||
if (in1 != NULL && in2 != NULL && in1->Opcode() == Op_Add(bt)) {
|
||||
Node* add1 = in1->in(1);
|
||||
Node* add2 = in1->in(2);
|
||||
Node* add = in(1);
|
||||
Node* mask = in(2);
|
||||
if (add == NULL || mask == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
int addidx = 0;
|
||||
if (add->Opcode() == Op_Add(bt)) {
|
||||
addidx = 1;
|
||||
} else if (mask->Opcode() == Op_Add(bt)) {
|
||||
mask = add;
|
||||
addidx = 2;
|
||||
add = in(addidx);
|
||||
}
|
||||
if (addidx > 0) {
|
||||
Node* add1 = add->in(1);
|
||||
Node* add2 = add->in(2);
|
||||
if (add1 != NULL && add2 != NULL) {
|
||||
if (AndIL_shift_and_mask(phase, in2, add1, bt)) {
|
||||
set_req_X(1, add2, phase);
|
||||
if (AndIL_shift_and_mask_is_always_zero(phase, add1, mask, bt, false)) {
|
||||
set_req_X(addidx, add2, phase);
|
||||
return this;
|
||||
} else if (AndIL_shift_and_mask(phase, in2, add2, bt)) {
|
||||
set_req_X(1, add1, phase);
|
||||
} else if (AndIL_shift_and_mask_is_always_zero(phase, add2, mask, bt, false)) {
|
||||
set_req_X(addidx, add1, phase);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ public:
|
||||
|
||||
static MulNode* make(Node* in1, Node* in2, BasicType bt);
|
||||
|
||||
static bool AndIL_shift_and_mask(PhaseGVN* phase, Node* mask, Node* shift, BasicType bt);
|
||||
static bool AndIL_shift_and_mask_is_always_zero(PhaseGVN* phase, Node* shift, Node* mask, BasicType bt, bool check_reverse);
|
||||
Node* AndIL_add_shift_and_mask(PhaseGVN* phase, BasicType bt);
|
||||
};
|
||||
|
||||
|
@ -24,16 +24,20 @@
|
||||
package compiler.c2.irTests;
|
||||
|
||||
import compiler.lib.ir_framework.*;
|
||||
import jdk.test.lib.Utils;
|
||||
import java.util.Random;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8277850
|
||||
* @bug 8277850 8278949
|
||||
* @summary C2: optimize mask checks in counted loops
|
||||
* @library /test/lib /
|
||||
* @run driver compiler.c2.irTests.TestShiftAndMask
|
||||
*/
|
||||
|
||||
public class TestShiftAndMask {
|
||||
private static final Random RANDOM = Utils.getRandomInstance();
|
||||
|
||||
public static void main(String[] args) {
|
||||
TestFramework.run();
|
||||
}
|
||||
@ -45,6 +49,13 @@ public class TestShiftAndMask {
|
||||
return (i << 2) & 3; // transformed to: return 0;
|
||||
}
|
||||
|
||||
@Check(test = "shiftMaskInt")
|
||||
public static void checkShiftMaskInt(int res) {
|
||||
if (res != 0) {
|
||||
throw new RuntimeException("incorrect result: " + res);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Arguments(Argument.RANDOM_EACH)
|
||||
@IR(failOn = { IRNode.AND_L, IRNode.LSHIFT_L })
|
||||
@ -52,22 +63,148 @@ public class TestShiftAndMask {
|
||||
return (i << 2) & 3; // transformed to: return 0;
|
||||
}
|
||||
|
||||
|
||||
@Check(test = "shiftMaskLong")
|
||||
public static void checkShiftMaskLong(long res) {
|
||||
if (res != 0) {
|
||||
throw new RuntimeException("incorrect result: " + res);
|
||||
}
|
||||
}
|
||||
|
||||
static volatile int barrier;
|
||||
|
||||
@Test
|
||||
@Arguments({Argument.RANDOM_EACH, Argument.BOOLEAN_TOGGLE_FIRST_TRUE})
|
||||
@IR(failOn = { IRNode.AND_I, IRNode.LSHIFT_I })
|
||||
public static int shiftNonConstMaskInt(int i, boolean flag) {
|
||||
int mask;
|
||||
if (flag) {
|
||||
barrier = 42;
|
||||
mask = 3;
|
||||
} else {
|
||||
mask = 1;
|
||||
}
|
||||
return mask & (i << 2); // transformed to: return 0;
|
||||
}
|
||||
|
||||
@Check(test = "shiftNonConstMaskInt")
|
||||
public static void checkShiftNonConstMaskInt(int res) {
|
||||
if (res != 0) {
|
||||
throw new RuntimeException("incorrect result: " + res);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Arguments({Argument.RANDOM_EACH, Argument.BOOLEAN_TOGGLE_FIRST_TRUE})
|
||||
@IR(failOn = { IRNode.AND_L, IRNode.LSHIFT_L })
|
||||
public static long shiftNonConstMaskLong(long i, boolean flag) {
|
||||
long mask;
|
||||
if (flag) {
|
||||
barrier = 42;
|
||||
mask = 3;
|
||||
} else {
|
||||
mask = 1;
|
||||
}
|
||||
return mask & (i << 2); // transformed to: return 0;
|
||||
}
|
||||
|
||||
@Check(test = "shiftNonConstMaskLong")
|
||||
public static void checkShiftNonConstMaskLong(long res) {
|
||||
if (res != 0) {
|
||||
throw new RuntimeException("incorrect result: " + res);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH})
|
||||
@IR(counts = { IRNode.AND_I, "1" })
|
||||
@IR(failOn = { IRNode.ADD_I, IRNode.LSHIFT_I })
|
||||
public static int addShiftMaskInt(int i, int j) {
|
||||
return (j + (i << 2)) & 3; // transformed to: return j & 3;
|
||||
}
|
||||
|
||||
@Run(test = "addShiftMaskInt")
|
||||
public static void addShiftMaskInt_runner() {
|
||||
int i = RANDOM.nextInt();
|
||||
int j = RANDOM.nextInt();
|
||||
int res = addShiftMaskInt(i, j);
|
||||
if (res != (j & 3)) {
|
||||
throw new RuntimeException("incorrect result: " + res);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@IR(counts = { IRNode.AND_I, "1" })
|
||||
@IR(failOn = { IRNode.ADD_I, IRNode.LSHIFT_I })
|
||||
public static int addSshiftNonConstMaskInt(int i, int j, boolean flag) {
|
||||
int mask;
|
||||
if (flag) {
|
||||
barrier = 42;
|
||||
mask = 3;
|
||||
} else {
|
||||
mask = 1;
|
||||
}
|
||||
return mask & (j + (i << 2)); // transformed to: return j & mask;
|
||||
}
|
||||
|
||||
@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 & 3)) {
|
||||
throw new RuntimeException("incorrect result: " + res);
|
||||
}
|
||||
res = addSshiftNonConstMaskInt(i, j, false);
|
||||
if (res != (j & 1)) {
|
||||
throw new RuntimeException("incorrect result: " + res);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH})
|
||||
@IR(counts = { IRNode.AND_L, "1" })
|
||||
@IR(failOn = { IRNode.ADD_L, IRNode.LSHIFT_L })
|
||||
public static long addShiftMaskLong(long i, long j) {
|
||||
return (j + (i << 2)) & 3; // transformed to: return j & 3;
|
||||
}
|
||||
|
||||
@Run(test = "addShiftMaskLong")
|
||||
public static void addShiftMaskLong_runner() {
|
||||
long i = RANDOM.nextLong();
|
||||
long j = RANDOM.nextLong();
|
||||
long res = addShiftMaskLong(i, j);
|
||||
if (res != (j & 3)) {
|
||||
throw new RuntimeException("incorrect result: " + res);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@IR(counts = { IRNode.AND_L, "1" })
|
||||
@IR(failOn = { IRNode.ADD_L, IRNode.LSHIFT_L })
|
||||
public static long addSshiftNonConstMaskLong(long i, long j, boolean flag) {
|
||||
int mask;
|
||||
if (flag) {
|
||||
barrier = 42;
|
||||
mask = 3;
|
||||
} else {
|
||||
mask = 1;
|
||||
}
|
||||
return mask & (j + (i << 2)); // transformed to: return j & mask;
|
||||
}
|
||||
|
||||
@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 & 3)) {
|
||||
throw new RuntimeException("incorrect result: " + res);
|
||||
}
|
||||
res = addSshiftNonConstMaskLong(i, j, false);
|
||||
if (res != (j & 1)) {
|
||||
throw new RuntimeException("incorrect result: " + res);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH})
|
||||
@IR(failOn = { IRNode.AND_I, IRNode.ADD_I, IRNode.LSHIFT_I })
|
||||
@ -75,6 +212,13 @@ public class TestShiftAndMask {
|
||||
return ((j << 2) + (i << 2)) & 3; // transformed to: return 0;
|
||||
}
|
||||
|
||||
@Check(test = "addShiftMaskInt2")
|
||||
public static void checkAddShiftMaskInt2(int res) {
|
||||
if (res != 0) {
|
||||
throw new RuntimeException("incorrect result: " + res);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH})
|
||||
@IR(failOn = { IRNode.AND_L, IRNode.ADD_L, IRNode.LSHIFT_L })
|
||||
@ -82,21 +226,104 @@ public class TestShiftAndMask {
|
||||
return ((j << 2) + (i << 2)) & 3; // transformed to: return 0;
|
||||
}
|
||||
|
||||
@Check(test = "addShiftMaskLong2")
|
||||
public static void checkAddShiftMaskLong2(long res) {
|
||||
if (res != 0) {
|
||||
throw new RuntimeException("incorrect result: " + res);
|
||||
}
|
||||
}
|
||||
|
||||
// Try to get add inputs swapped compared to other tests
|
||||
@Test
|
||||
@Arguments(Argument.RANDOM_EACH)
|
||||
@IR(counts = { IRNode.AND_I, "1" })
|
||||
@IR(failOn = { IRNode.ADD_I, IRNode.LSHIFT_I })
|
||||
public static int addShiftMaskInt3(int i, long j) {
|
||||
int add1 = (i << 2);
|
||||
int add2 = (int)j;
|
||||
return (add1 + add2) & 3; // transformed to: return j & 3;
|
||||
}
|
||||
|
||||
@Run(test = "addShiftMaskInt3")
|
||||
public static void addShiftMaskInt3_runner() {
|
||||
int i = RANDOM.nextInt();
|
||||
int j = RANDOM.nextInt();
|
||||
int res = addShiftMaskInt3(i, j);
|
||||
if (res != (j & 3)) {
|
||||
throw new RuntimeException("incorrect result: " + res);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@IR(counts = { IRNode.AND_L, "1" })
|
||||
@IR(failOn = { IRNode.ADD_L, IRNode.LSHIFT_L })
|
||||
public static long addShiftMaskLong3(long i, float j) {
|
||||
long add1 = (i << 2);
|
||||
long add2 = (long)j;
|
||||
return (add1 + add2) & 3; // transformed to: return j & 3;
|
||||
}
|
||||
|
||||
@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) & 3)) {
|
||||
throw new RuntimeException("incorrect result: " + res);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Arguments({Argument.RANDOM_EACH})
|
||||
@IR(failOn = { IRNode.AND_L, IRNode.LSHIFT_I })
|
||||
public static long shiftConvMask(int i) {
|
||||
return ((long)(i << 2)) & 3; // transformed to: return 0;
|
||||
}
|
||||
|
||||
@Check(test = "shiftConvMask")
|
||||
public static void checkShiftConvMask(long res) {
|
||||
if (res != 0) {
|
||||
throw new RuntimeException("incorrect result: " + res);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Arguments({Argument.RANDOM_EACH, Argument.BOOLEAN_TOGGLE_FIRST_TRUE})
|
||||
@IR(failOn = { IRNode.AND_L, IRNode.LSHIFT_L })
|
||||
public static long shiftNotConstConvMask(int i, boolean flag) {
|
||||
long mask;
|
||||
if (flag) {
|
||||
barrier = 42;
|
||||
mask = 3;
|
||||
} else {
|
||||
mask = 1;
|
||||
}
|
||||
return mask & ((long)(i << 2)); // transformed to: return 0;
|
||||
}
|
||||
|
||||
@Check(test = "shiftNotConstConvMask")
|
||||
public static void checkShiftNotConstConvMask(long res) {
|
||||
if (res != 0) {
|
||||
throw new RuntimeException("incorrect result: " + res);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH})
|
||||
@IR(counts = { IRNode.AND_L, "1" })
|
||||
@IR(failOn = { IRNode.ADD_L, IRNode.LSHIFT_I, IRNode.CONV_I2L })
|
||||
public static long addShiftConvMask(int i, long j) {
|
||||
return (j + (i << 2)) & 3; // transformed to: return j & 3;
|
||||
}
|
||||
|
||||
@Run(test = "addShiftConvMask")
|
||||
public static void addShiftConvMask_runner() {
|
||||
int i = RANDOM.nextInt();
|
||||
long j = RANDOM.nextLong();
|
||||
long res = addShiftConvMask(i, j);
|
||||
if (res != (j & 3)) {
|
||||
throw new RuntimeException("incorrect result: " + res);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH})
|
||||
@IR(failOn = { IRNode.AND_L, IRNode.ADD_L, IRNode.LSHIFT_L })
|
||||
@ -104,5 +331,10 @@ public class TestShiftAndMask {
|
||||
return (((long)(j << 2)) + ((long)(i << 2))) & 3; // transformed to: return 0;
|
||||
}
|
||||
|
||||
@Check(test = "addShiftConvMask2")
|
||||
public static void checkAddShiftConvMask2(long res) {
|
||||
if (res != 0) {
|
||||
throw new RuntimeException("incorrect result: " + res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user