use of org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand in project JikesRVM by JikesRVM.
the class ExpressionFolding method transform.
/**
* Perform the transformation on the instruction
*
* @param s
* the instruction to transform of the form y = x op c1
* @param def
* the definition of x, the defining instruction is of the form x = a
* op c2
* @return the new instruction to replace s;
*/
private static Instruction transform(Instruction s, Instruction def) {
// x = a op1 c1 <-- def
// y = x op2 c2 <-- s
final RegisterOperand a = getUseFromCandidate(def);
final RegisterOperand x = getDefFromCandidate(def, true);
if (x == null) {
return null;
}
final RegisterOperand y = getDefFromCandidate(s, false);
if (y == null) {
return null;
}
if (VM.VerifyAssertions) {
RegisterOperand x2;
x2 = getUseFromCandidate(s);
boolean similar = x.similar(x2);
if (!similar) {
String msg = "x not similar to x2 " + x + " : " + x2;
VM._assert(VM.NOT_REACHED, msg);
}
}
switch(s.getOpcode()) {
// Foldable operators
case INT_ADD_opcode:
{
if (FOLD_INTS && FOLD_ADDS) {
int c2 = getIntValue(Binary.getVal2(s));
if (def.operator() == INT_ADD) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a + c1; y = x + c2
return Binary.create(INT_ADD, y.copyRO(), a.copyRO(), IC(c1 + c2));
} else if (def.operator() == INT_SUB) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a - c1; y = x + c2
return Binary.create(INT_ADD, y.copyRO(), a.copyRO(), IC(c2 - c1));
} else if (def.operator() == INT_NEG && FOLD_CONSTANTS_TO_LHS) {
// x = -a; y = x + c2;
return Binary.create(INT_SUB, y.copyRO(), IC(c2), a.copyRO());
}
}
return null;
}
case REF_ADD_opcode:
{
if (FOLD_REFS && FOLD_ADDS) {
Address c2 = getAddressValue(Binary.getVal2(s));
if (def.operator() == REF_ADD) {
Address c1 = getAddressValue(Binary.getVal2(def));
// x = a + c1; y = x + c2
return Binary.create(REF_ADD, y.copyRO(), a.copyRO(), AC(c1.toWord().plus(c2.toWord()).toAddress()));
} else if (def.operator() == REF_SUB) {
Address c1 = getAddressValue(Binary.getVal2(def));
// x = a - c1; y = x + c2
return Binary.create(REF_ADD, y.copyRO(), a.copyRO(), AC(c2.toWord().minus(c1.toWord()).toAddress()));
} else if (def.operator() == REF_NEG && FOLD_CONSTANTS_TO_LHS) {
// x = -a; y = x + c2;
return Binary.create(REF_SUB, y.copyRO(), AC(c2), a.copyRO());
}
}
return null;
}
case LONG_ADD_opcode:
{
if (FOLD_LONGS && FOLD_ADDS) {
long c2 = getLongValue(Binary.getVal2(s));
if (def.operator() == LONG_ADD) {
long c1 = getLongValue(Binary.getVal2(def));
// x = a + c1; y = x + c2
return Binary.create(LONG_ADD, y.copyRO(), a.copyRO(), LC(c1 + c2));
} else if (def.operator() == LONG_SUB) {
long c1 = getLongValue(Binary.getVal2(def));
// x = a - c1; y = x + c2
return Binary.create(LONG_ADD, y.copyRO(), a.copyRO(), LC(c2 - c1));
} else if (def.operator() == LONG_NEG && FOLD_CONSTANTS_TO_LHS) {
// x = -a; y = x + c2;
return Binary.create(LONG_SUB, y.copyRO(), LC(c2), a.copyRO());
}
}
return null;
}
case FLOAT_ADD_opcode:
{
if (FOLD_FLOATS && FOLD_ADDS) {
float c2 = getFloatValue(Binary.getVal2(s));
if (def.operator() == FLOAT_ADD) {
float c1 = getFloatValue(Binary.getVal2(def));
// x = a + c1; y = x + c2
return Binary.create(FLOAT_ADD, y.copyRO(), a.copyRO(), FC(c1 + c2));
} else if (def.operator() == FLOAT_SUB) {
float c1 = getFloatValue(Binary.getVal2(def));
// x = a - c1; y = x + c2
return Binary.create(FLOAT_ADD, y.copyRO(), a.copyRO(), FC(c2 - c1));
} else if (def.operator() == FLOAT_NEG && FOLD_CONSTANTS_TO_LHS) {
// x = -a; y = x + c2;
return Binary.create(FLOAT_SUB, y.copyRO(), FC(c2), a.copyRO());
}
}
return null;
}
case DOUBLE_ADD_opcode:
{
if (FOLD_DOUBLES && FOLD_ADDS) {
double c2 = getDoubleValue(Binary.getVal2(s));
if (def.operator() == DOUBLE_ADD) {
double c1 = getDoubleValue(Binary.getVal2(def));
// x = a + c1; y = x + c2
return Binary.create(DOUBLE_ADD, y.copyRO(), a.copyRO(), DC(c1 + c2));
} else if (def.operator() == DOUBLE_SUB) {
double c1 = getDoubleValue(Binary.getVal2(def));
// x = a - c1; y = x + c2
return Binary.create(DOUBLE_ADD, y.copyRO(), a.copyRO(), DC(c2 - c1));
} else if (def.operator() == DOUBLE_NEG && FOLD_CONSTANTS_TO_LHS) {
// x = -a; y = x + c2;
return Binary.create(DOUBLE_SUB, y.copyRO(), DC(c2), a.copyRO());
}
}
return null;
}
case INT_SUB_opcode:
{
if (FOLD_INTS && FOLD_SUBS) {
int c2 = getIntValue(Binary.getVal2(s));
if (def.operator() == INT_ADD) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a + c1; y = x - c2
return Binary.create(INT_ADD, y.copyRO(), a.copyRO(), IC(c1 - c2));
} else if (def.operator() == INT_SUB) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a - c1; y = x - c2
return Binary.create(INT_ADD, y.copyRO(), a.copyRO(), IC(-c1 - c2));
} else if (def.operator() == INT_NEG && FOLD_CONSTANTS_TO_LHS) {
// x = -a; y = x - c2;
return Binary.create(INT_SUB, y.copyRO(), IC(-c2), a.copyRO());
}
}
return null;
}
case REF_SUB_opcode:
{
if (FOLD_REFS && FOLD_SUBS) {
Address c2 = getAddressValue(Binary.getVal2(s));
if (def.operator() == REF_ADD) {
Address c1 = getAddressValue(Binary.getVal2(def));
// x = a + c1; y = x - c2
return Binary.create(REF_ADD, y.copyRO(), a.copyRO(), AC(c1.toWord().minus(c2.toWord()).toAddress()));
} else if (def.operator() == REF_SUB) {
Address c1 = getAddressValue(Binary.getVal2(def));
// x = a - c1; y = x - c2
return Binary.create(REF_ADD, y.copyRO(), a.copyRO(), AC(Word.zero().minus(c1.toWord()).minus(c2.toWord()).toAddress()));
} else if (def.operator() == REF_NEG && FOLD_CONSTANTS_TO_LHS) {
// x = -a; y = x - c2;
return Binary.create(REF_SUB, y.copyRO(), AC(Word.zero().minus(c2.toWord()).toAddress()), a.copyRO());
}
}
return null;
}
case LONG_SUB_opcode:
{
if (FOLD_LONGS && FOLD_SUBS) {
long c2 = getLongValue(Binary.getVal2(s));
if (def.operator() == LONG_ADD) {
long c1 = getLongValue(Binary.getVal2(def));
// x = a + c1; y = x - c2
return Binary.create(LONG_ADD, y.copyRO(), a.copyRO(), LC(c1 - c2));
} else if (def.operator() == LONG_SUB) {
long c1 = getLongValue(Binary.getVal2(def));
// x = a - c1; y = x - c2
return Binary.create(LONG_ADD, y.copyRO(), a.copyRO(), LC(-c1 - c2));
} else if (def.operator() == LONG_NEG && FOLD_CONSTANTS_TO_LHS) {
// x = -a; y = x - c2;
return Binary.create(LONG_SUB, y.copyRO(), LC(-c2), a.copyRO());
}
}
return null;
}
case FLOAT_SUB_opcode:
{
if (FOLD_FLOATS && FOLD_SUBS) {
float c2 = getFloatValue(Binary.getVal2(s));
if (def.operator() == FLOAT_ADD) {
float c1 = getFloatValue(Binary.getVal2(def));
// x = a + c1; y = x - c2
return Binary.create(FLOAT_ADD, y.copyRO(), a.copyRO(), FC(c1 - c2));
} else if (def.operator() == FLOAT_SUB) {
float c1 = getFloatValue(Binary.getVal2(def));
// x = a - c1; y = x - c2
return Binary.create(FLOAT_ADD, y.copyRO(), a.copyRO(), FC(-c1 - c2));
} else if (def.operator() == FLOAT_NEG && FOLD_CONSTANTS_TO_LHS) {
// x = -a; y = x - c2;
return Binary.create(FLOAT_SUB, y.copyRO(), FC(-c2), a.copyRO());
}
}
return null;
}
case DOUBLE_SUB_opcode:
{
if (FOLD_DOUBLES && FOLD_SUBS) {
double c2 = getDoubleValue(Binary.getVal2(s));
if (def.operator() == FLOAT_ADD) {
double c1 = getDoubleValue(Binary.getVal2(def));
// x = a + c1; y = x - c2
return Binary.create(DOUBLE_ADD, y.copyRO(), a.copyRO(), DC(c1 - c2));
} else if (def.operator() == DOUBLE_SUB) {
double c1 = getDoubleValue(Binary.getVal2(def));
// x = a - c1; y = x + c2
return Binary.create(DOUBLE_ADD, y.copyRO(), a.copyRO(), DC(-c1 - c2));
} else if (def.operator() == DOUBLE_NEG && FOLD_CONSTANTS_TO_LHS) {
// x = -a; y = x - c2;
return Binary.create(DOUBLE_SUB, y.copyRO(), DC(-c2), a.copyRO());
}
}
return null;
}
case INT_MUL_opcode:
{
if (FOLD_INTS && FOLD_MULTS) {
int c2 = getIntValue(Binary.getVal2(s));
if (def.operator() == INT_MUL) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a * c1; y = x * c2
return Binary.create(INT_MUL, y.copyRO(), a.copyRO(), IC(c1 * c2));
} else if (def.operator() == INT_NEG) {
// x = -a; y = x * c2;
return Binary.create(INT_MUL, y.copyRO(), a.copyRO(), IC(-c2));
}
}
return null;
}
case LONG_MUL_opcode:
{
if (FOLD_LONGS && FOLD_MULTS) {
long c2 = getLongValue(Binary.getVal2(s));
if (def.operator() == LONG_MUL) {
long c1 = getLongValue(Binary.getVal2(def));
// x = a * c1; y = x * c2
return Binary.create(LONG_MUL, y.copyRO(), a.copyRO(), LC(c1 * c2));
} else if (def.operator() == LONG_NEG) {
// x = -a; y = x * c2;
return Binary.create(LONG_MUL, y.copyRO(), a.copyRO(), LC(-c2));
}
}
return null;
}
case FLOAT_MUL_opcode:
{
if (FOLD_FLOATS && FOLD_MULTS) {
float c2 = getFloatValue(Binary.getVal2(s));
if (def.operator() == FLOAT_MUL) {
float c1 = getFloatValue(Binary.getVal2(def));
// x = a * c1; y = x * c2
return Binary.create(FLOAT_MUL, y.copyRO(), a.copyRO(), FC(c1 * c2));
} else if (def.operator() == FLOAT_NEG) {
// x = -a; y = x * c2;
return Binary.create(FLOAT_MUL, y.copyRO(), a.copyRO(), FC(-c2));
}
}
return null;
}
case DOUBLE_MUL_opcode:
{
if (FOLD_DOUBLES && FOLD_MULTS) {
double c2 = getDoubleValue(Binary.getVal2(s));
if (def.operator() == DOUBLE_MUL) {
double c1 = getDoubleValue(Binary.getVal2(def));
// x = a * c1; y = x * c2
return Binary.create(DOUBLE_MUL, y.copyRO(), a.copyRO(), DC(c1 * c2));
} else if (def.operator() == DOUBLE_NEG) {
// x = -a; y = x * c2;
return Binary.create(DOUBLE_MUL, y.copyRO(), a.copyRO(), DC(-c2));
}
}
return null;
}
case INT_DIV_opcode:
{
if (FOLD_INTS && FOLD_DIVS) {
int c2 = getIntValue(GuardedBinary.getVal2(s));
if (def.operator() == INT_DIV) {
int c1 = getIntValue(GuardedBinary.getVal2(def));
Operand guard = GuardedBinary.getGuard(def);
// x = a / c1; y = x / c2
return GuardedBinary.create(INT_DIV, y.copyRO(), a.copyRO(), IC(c1 * c2), guard);
} else if (def.operator() == INT_NEG) {
Operand guard = GuardedBinary.getGuard(s);
// x = -a; y = x / c2;
return GuardedBinary.create(INT_DIV, y.copyRO(), a.copyRO(), IC(-c2), guard);
}
}
return null;
}
case LONG_DIV_opcode:
{
if (FOLD_LONGS && FOLD_DIVS) {
long c2 = getLongValue(GuardedBinary.getVal2(s));
if (def.operator() == LONG_DIV) {
long c1 = getLongValue(GuardedBinary.getVal2(def));
Operand guard = GuardedBinary.getGuard(def);
// x = a / c1; y = x / c2
return GuardedBinary.create(LONG_DIV, y.copyRO(), a.copyRO(), LC(c1 * c2), guard);
} else if (def.operator() == LONG_NEG) {
Operand guard = GuardedBinary.getGuard(s);
// x = -a; y = x / c2;
return GuardedBinary.create(LONG_DIV, y.copyRO(), a.copyRO(), LC(-c2), guard);
}
}
return null;
}
case FLOAT_DIV_opcode:
{
if (FOLD_FLOATS && FOLD_DIVS) {
float c2 = getFloatValue(Binary.getVal2(s));
if (def.operator() == FLOAT_DIV) {
float c1 = getFloatValue(Binary.getVal2(def));
// x = a / c1; y = x / c2
return Binary.create(FLOAT_DIV, y.copyRO(), a.copyRO(), FC(c1 * c2));
} else if (def.operator() == FLOAT_NEG) {
// x = -a; y = x / c2;
return Binary.create(FLOAT_DIV, y.copyRO(), a.copyRO(), FC(-c2));
}
}
return null;
}
case DOUBLE_DIV_opcode:
{
if (FOLD_DOUBLES && FOLD_DIVS) {
double c2 = getDoubleValue(Binary.getVal2(s));
if (def.operator() == DOUBLE_DIV) {
double c1 = getDoubleValue(Binary.getVal2(def));
// x = a / c1; y = x / c2
return Binary.create(DOUBLE_DIV, y.copyRO(), a.copyRO(), DC(c1 * c2));
} else if (def.operator() == DOUBLE_NEG) {
// x = -a; y = x / c2;
return Binary.create(DOUBLE_DIV, y.copyRO(), a.copyRO(), DC(-c2));
}
}
return null;
}
case INT_SHL_opcode:
{
if (FOLD_INTS && FOLD_SHIFTLS) {
int c2 = getIntValue(Binary.getVal2(s));
if (def.operator() == INT_SHL) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a << c1; y = x << c2
return Binary.create(INT_SHL, y.copyRO(), a.copyRO(), IC(c1 + c2));
} else if ((def.operator() == INT_SHR) || (def.operator() == INT_USHR)) {
int c1 = getIntValue(Binary.getVal2(def));
if (c1 == c2) {
// x = a >> c1; y = x << c1
return Binary.create(INT_AND, y.copyRO(), a.copyRO(), IC(-1 << c1));
}
} else if (def.operator() == INT_AND) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a & c1; y = << c2
if ((c1 << c2) == (-1 << c2)) {
// the first mask is redundant
return Binary.create(INT_SHL, y.copyRO(), a.copyRO(), IC(c2));
}
} else if ((def.operator() == INT_OR) || (def.operator() == INT_XOR)) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a | c1; y = << c2
if ((c1 << c2) == 0) {
// the first mask is redundant
return Binary.create(INT_SHL, y.copyRO(), a.copyRO(), IC(c2));
}
}
}
return null;
}
case REF_SHL_opcode:
{
if (FOLD_REFS && FOLD_SHIFTLS) {
int c2 = getIntValue(Binary.getVal2(s));
if (def.operator() == REF_SHL) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a << c1; y = x << c2
return Binary.create(REF_SHL, y.copyRO(), a.copyRO(), IC(c1 + c2));
} else if ((def.operator() == REF_SHR) || (def.operator() == REF_USHR)) {
int c1 = getIntValue(Binary.getVal2(def));
if (c1 == c2) {
// x = a >> c1; y = x << c1
return Binary.create(REF_AND, y.copyRO(), a.copyRO(), AC(Word.zero().minus(Word.one()).lsh(c1).toAddress()));
}
} else if (def.operator() == REF_AND) {
Address c1 = getAddressValue(Binary.getVal2(def));
// x = a & c1; y = x << c2
if (c1.toWord().lsh(c2).EQ(Word.fromIntSignExtend(-1).lsh(c2))) {
// the first mask is redundant
return Binary.create(REF_SHL, y.copyRO(), a.copyRO(), IC(c2));
}
} else if ((def.operator() == REF_OR) || (def.operator() == REF_XOR)) {
Address c1 = getAddressValue(Binary.getVal2(def));
// x = a | c1; y = x << c2
if (c1.toWord().lsh(c2).EQ(Word.zero())) {
// the first mask is redundant
return Binary.create(REF_SHL, y.copyRO(), a.copyRO(), IC(c2));
}
}
}
return null;
}
case LONG_SHL_opcode:
{
if (FOLD_LONGS && FOLD_SHIFTLS) {
int c2 = getIntValue(Binary.getVal2(s));
if (def.operator() == LONG_SHL) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a << c1; y = x << c2
return Binary.create(LONG_SHL, y.copyRO(), a.copyRO(), IC(c1 + c2));
} else if ((def.operator() == LONG_SHR) || (def.operator() == LONG_USHR)) {
int c1 = getIntValue(Binary.getVal2(def));
if (c1 == c2) {
// x = a >> c1; y = x << c1
return Binary.create(LONG_AND, y.copyRO(), a.copyRO(), LC(-1L << c1));
}
} else if (def.operator() == LONG_AND) {
long c1 = getLongValue(Binary.getVal2(def));
// x = a & c1; y = << c2
if ((c1 << c2) == (-1L << c2)) {
// the first mask is redundant
return Binary.create(LONG_SHL, y.copyRO(), a.copyRO(), IC(c2));
}
} else if ((def.operator() == LONG_OR) || (def.operator() == LONG_XOR)) {
long c1 = getLongValue(Binary.getVal2(def));
// x = a | c1; y = << c2
if ((c1 << c2) == 0L) {
// the first mask is redundant
return Binary.create(LONG_SHL, y.copyRO(), a.copyRO(), IC(c2));
}
}
}
return null;
}
case INT_SHR_opcode:
{
if (FOLD_INTS && FOLD_SHIFTRS) {
int c2 = getIntValue(Binary.getVal2(s));
if (def.operator() == INT_SHR) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a >> c1; y = x >> c2
return Binary.create(INT_SHR, y.copyRO(), a.copyRO(), IC(c1 + c2));
} else if (def.operator() == INT_SHL) {
int c1 = getIntValue(Binary.getVal2(def));
if (c1 == c2) {
if (c1 == 24) {
// x = a << 24; y = x >> 24
return Unary.create(INT_2BYTE, y.copyRO(), a.copyRO());
} else if (c1 == 16) {
// x = a << 16; y = x >> 16
return Unary.create(INT_2SHORT, y.copyRO(), a.copyRO());
}
}
} else if (def.operator() == INT_AND) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a & c1; y = >> c2
if ((c1 >> c2) == -1) {
// the first mask is redundant
return Binary.create(INT_SHR, y.copyRO(), a.copyRO(), IC(c2));
}
} else if ((def.operator() == INT_OR) || (def.operator() == INT_XOR)) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a | c1; y = >> c2
if ((c1 >>> c2) == 0) {
// the first mask is redundant
return Binary.create(INT_SHR, y.copyRO(), a.copyRO(), IC(c2));
}
}
}
return null;
}
case REF_SHR_opcode:
{
if (FOLD_REFS && FOLD_SHIFTRS) {
int c2 = getIntValue(Binary.getVal2(s));
if (def.operator() == REF_SHR) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a >> c1; y = x >> c2
return Binary.create(REF_SHR, y.copyRO(), a.copyRO(), IC(c1 + c2));
} else if (def.operator() == REF_AND) {
Address c1 = getAddressValue(Binary.getVal2(def));
// x = a & c1; y = x >> c2
if (c1.toWord().rsha(c2).EQ(Word.zero().minus(Word.one()))) {
// the first mask is redundant
return Binary.create(REF_SHR, y.copyRO(), a.copyRO(), IC(c2));
}
} else if ((def.operator() == REF_OR) || (def.operator() == REF_XOR)) {
Address c1 = getAddressValue(Binary.getVal2(def));
// x = a | c1; y = x >> c2
if (c1.toWord().rshl(c2).EQ(Word.zero())) {
// the first mask is redundant
return Binary.create(REF_SHR, y.copyRO(), a.copyRO(), IC(c2));
}
}
}
return null;
}
case LONG_SHR_opcode:
{
if (FOLD_LONGS && FOLD_SHIFTRS) {
int c2 = getIntValue(Binary.getVal2(s));
if (def.operator() == LONG_SHR) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a >> c1; y = x >> c2
return Binary.create(LONG_SHR, y.copyRO(), a.copyRO(), IC(c1 + c2));
} else if (def.operator() == LONG_AND) {
long c1 = getLongValue(Binary.getVal2(def));
// x = a & c1; y = >> c2
if ((c1 >> c2) == -1L) {
// the first mask is redundant
return Binary.create(LONG_SHR, y.copyRO(), a.copyRO(), IC(c2));
}
} else if ((def.operator() == LONG_OR) || (def.operator() == LONG_XOR)) {
long c1 = getLongValue(Binary.getVal2(def));
// x = a & c1; y = >> c2
if ((c1 >>> c2) == 0L) {
// the first mask is redundant
return Binary.create(LONG_SHR, y.copyRO(), a.copyRO(), IC(c2));
}
}
}
return null;
}
case INT_USHR_opcode:
{
if (FOLD_INTS && FOLD_SHIFTRS) {
int c2 = getIntValue(Binary.getVal2(s));
if (def.operator() == INT_USHR) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a >>> c1; y = x >>> c2
return Binary.create(INT_USHR, y.copyRO(), a.copyRO(), IC(c1 + c2));
} else if (def.operator() == INT_SHL) {
int c1 = getIntValue(Binary.getVal2(def));
if (c1 == c2) {
// x = a << c1; y = x >>> c1
return Binary.create(INT_AND, y.copyRO(), a.copyRO(), IC(-1 >>> c1));
}
} else if (def.operator() == INT_AND) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a & c1; y = >>> c2
if ((c1 >> c2) == -1L) {
// the first mask is redundant
return Binary.create(INT_USHR, y.copyRO(), a.copyRO(), IC(c2));
}
} else if ((def.operator() == INT_OR) || (def.operator() == INT_XOR)) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a | c1; y = >>> c2
if ((c1 >>> c2) == 0) {
// the first mask is redundant
return Binary.create(INT_USHR, y.copyRO(), a.copyRO(), IC(c2));
}
}
}
return null;
}
case REF_USHR_opcode:
{
if (FOLD_REFS && FOLD_SHIFTRS) {
int c2 = getIntValue(Binary.getVal2(s));
if (def.operator() == REF_USHR) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a >>> c1; y = x >>> c2
return Binary.create(REF_USHR, y.copyRO(), a.copyRO(), IC(c1 + c2));
} else if (def.operator() == REF_SHL) {
int c1 = getIntValue(Binary.getVal2(def));
if (c1 == c2) {
// x = a << c1; y = x >>> c1
return Binary.create(REF_AND, y.copyRO(), a.copyRO(), AC(Word.zero().minus(Word.one()).rshl(c1).toAddress()));
}
} else if (def.operator() == REF_AND) {
// IAN!!!
Address c1 = getAddressValue(Binary.getVal2(def));
// x = a & c1; y = x >>> c2
if (c1.toWord().rsha(c2).EQ(Word.zero().minus(Word.one()))) {
// the first mask is redundant
return Binary.create(REF_USHR, y.copyRO(), a.copyRO(), IC(c2));
}
} else if (false) {
// (def.operator() == REF_OR) || (def.operator() == REF_XOR)) {
Address c1 = getAddressValue(Binary.getVal2(def));
// x = a | c1; y = x >>> c2
if (c1.toWord().rshl(c2).EQ(Word.zero())) {
// the first mask is redundant
return Binary.create(REF_USHR, y.copyRO(), a.copyRO(), IC(c2));
}
}
}
return null;
}
case LONG_USHR_opcode:
{
if (FOLD_LONGS && FOLD_SHIFTRS) {
int c2 = getIntValue(Binary.getVal2(s));
if (def.operator() == LONG_USHR) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a >>> c1; y = x >>> c2
return Binary.create(LONG_USHR, y.copyRO(), a.copyRO(), IC(c1 + c2));
} else if (def.operator() == LONG_SHL) {
int c1 = getIntValue(Binary.getVal2(def));
if (c1 == c2) {
// x = a << c1; y = x >>> c1
return Binary.create(LONG_AND, y.copyRO(), a.copyRO(), LC(-1L >>> c1));
}
} else if (def.operator() == LONG_AND) {
long c1 = getLongValue(Binary.getVal2(def));
// x = a & c1; y = >>> c2
if ((c1 >> c2) == -1L) {
// the first mask is redundant
return Binary.create(LONG_USHR, y.copyRO(), a.copyRO(), IC(c2));
}
} else if ((def.operator() == LONG_OR) || (def.operator() == LONG_XOR)) {
long c1 = getLongValue(Binary.getVal2(def));
// x = a & c1; y = >>> c2
if ((c1 >>> c2) == 0L) {
// the first mask is redundant
return Binary.create(LONG_USHR, y.copyRO(), a.copyRO(), IC(c2));
}
}
}
return null;
}
case INT_AND_opcode:
{
if (FOLD_INTS && FOLD_ANDS) {
int c2 = getIntValue(Binary.getVal2(s));
if (def.operator() == INT_AND) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a & c1; y = x & c2
return Binary.create(INT_AND, y.copyRO(), a.copyRO(), IC(c1 & c2));
} else if (def.operator() == INT_OR) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a | c1; y = x & c2
if ((c1 & c2) == 0) {
return Binary.create(INT_AND, y.copyRO(), a.copyRO(), IC(c2));
}
} else if (def.operator() == INT_XOR) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a ^ c1; y = x & c2
if ((c1 & c2) == 0) {
return Binary.create(INT_AND, y.copyRO(), a.copyRO(), IC(c2));
}
} else if (def.operator() == INT_SHR) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a >> c1; y = x & c2
if ((-1 >>> c1) == c2) {
// turn arithmetic shifts into logical shifts if possible
return Binary.create(INT_USHR, y.copyRO(), a.copyRO(), IC(c1));
}
} else if (def.operator() == INT_SHL) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a << c1; y = x & c2
if (((-1 << c1) & c2) == (-1 << c1)) {
// does the mask zero bits already cleared by the shift?
return Binary.create(INT_SHL, y.copyRO(), a.copyRO(), IC(c1));
}
} else if (def.operator() == INT_USHR) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a >>> c1; y = x & c2
if (((-1 >>> c1) & c2) == (-1 >>> c1)) {
// does the mask zero bits already cleared by the shift?
return Binary.create(INT_USHR, y.copyRO(), a.copyRO(), IC(c1));
}
}
}
return null;
}
case REF_AND_opcode:
{
if (FOLD_REFS && FOLD_ANDS) {
Address c2 = getAddressValue(Binary.getVal2(s));
if (def.operator() == REF_AND) {
Address c1 = getAddressValue(Binary.getVal2(def));
// x = a & c1; y = x & c2
return Binary.create(REF_AND, y.copyRO(), a.copyRO(), AC(c1.toWord().and(c2.toWord()).toAddress()));
} else if (def.operator() == REF_OR) {
Address c1 = getAddressValue(Binary.getVal2(def));
// x = a | c1; y = x & c2
if (c1.toWord().and(c2.toWord()).EQ(Word.zero())) {
return Binary.create(REF_AND, y.copyRO(), a.copyRO(), AC(c2));
}
} else if (def.operator() == REF_XOR) {
Address c1 = getAddressValue(Binary.getVal2(def));
// x = a ^ c1; y = x & c2
if (c1.toWord().and(c2.toWord()).EQ(Word.zero())) {
return Binary.create(REF_AND, y.copyRO(), a.copyRO(), AC(c2));
}
} else if (def.operator() == REF_SHR) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a >> c1; y = x & c2
if (Word.zero().minus(Word.one()).rshl(c1).toAddress().EQ(c2)) {
// turn arithmetic shifts into logical ones if possible
return Binary.create(REF_USHR, y.copyRO(), a.copyRO(), IC(c1));
}
} else if (def.operator() == REF_SHL) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a << c1; y = x & c2
if (Word.zero().minus(Word.one()).lsh(c1).and(c2.toWord()).EQ(Word.zero().minus(Word.one()).lsh(c1))) {
// does the mask zero bits already cleared by the shift?
return Binary.create(REF_SHL, y.copyRO(), a.copyRO(), IC(c1));
}
} else if (def.operator() == REF_USHR) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a >>> c1; y = x & c2
if (Word.zero().minus(Word.one()).rshl(c1).and(c2.toWord()).EQ(Word.zero().minus(Word.one()).rshl(c1))) {
// does the mask zero bits already cleared by the shift?
return Binary.create(REF_USHR, y.copyRO(), a.copyRO(), IC(c1));
}
}
}
return null;
}
case LONG_AND_opcode:
{
if (FOLD_LONGS && FOLD_ANDS) {
long c2 = getLongValue(Binary.getVal2(s));
if (def.operator() == LONG_AND) {
long c1 = getLongValue(Binary.getVal2(def));
// x = a & c1; y = x & c2
return Binary.create(LONG_AND, y.copyRO(), a.copyRO(), LC(c1 & c2));
} else if (def.operator() == LONG_OR) {
long c1 = getLongValue(Binary.getVal2(def));
// x = a | c1; y = x & c2
if ((c1 & c2) == 0) {
return Binary.create(LONG_AND, y.copyRO(), a.copyRO(), LC(c2));
}
} else if (def.operator() == LONG_XOR) {
long c1 = getLongValue(Binary.getVal2(def));
// x = a ^ c1; y = x & c2
if ((c1 & c2) == 0) {
return Binary.create(LONG_AND, y.copyRO(), a.copyRO(), LC(c2));
}
} else if (def.operator() == LONG_SHR) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a >> c1; y = x & c2
if ((-1L >>> c1) == c2) {
// turn arithmetic shifts into logical ones if possible
return Binary.create(LONG_USHR, y.copyRO(), a.copyRO(), IC(c1));
}
} else if (def.operator() == LONG_SHL) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a << c1; y = x & c2
if (((-1L << c1) & c2) == (-1L << c1)) {
// does the mask zero bits already cleared by the shift?
return Binary.create(LONG_SHL, y.copyRO(), a.copyRO(), IC(c1));
}
} else if (def.operator() == LONG_USHR) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a >>> c1; y = x & c2
if (((-1L >>> c1) & c2) == (-1L >>> c1)) {
// does the mask zero bits already cleared by the shift?
return Binary.create(LONG_USHR, y.copyRO(), a.copyRO(), IC(c1));
}
}
}
return null;
}
case INT_OR_opcode:
{
if (FOLD_INTS && FOLD_ORS) {
int c2 = getIntValue(Binary.getVal2(s));
if (def.operator() == INT_OR) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a | c1; y = x | c2
return Binary.create(INT_OR, y.copyRO(), a.copyRO(), IC(c1 | c2));
} else if (def.operator() == INT_AND) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a & c1; y = x | c2
if ((~c1 | c2) == c2) {
return Binary.create(INT_OR, y.copyRO(), a.copyRO(), IC(c2));
}
} else if (def.operator() == INT_XOR) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a ^ c1; y = x | c2
if ((c1 | c2) == c2) {
return Binary.create(INT_OR, y.copyRO(), a.copyRO(), IC(c2));
}
}
}
return null;
}
case REF_OR_opcode:
{
if (FOLD_REFS && FOLD_ORS) {
Address c2 = getAddressValue(Binary.getVal2(s));
if (def.operator() == REF_OR) {
Address c1 = getAddressValue(Binary.getVal2(def));
// x = a | c1; y = x | c2
return Binary.create(REF_OR, y.copyRO(), a.copyRO(), AC(c1.toWord().or(c2.toWord()).toAddress()));
} else if (def.operator() == REF_AND) {
Address c1 = getAddressValue(Binary.getVal2(def));
// x = a & c1; y = x | c2
if (c1.toWord().not().or(c2.toWord()).EQ(c2.toWord())) {
return Binary.create(REF_OR, y.copyRO(), a.copyRO(), AC(c2));
}
} else if (def.operator() == REF_XOR) {
Address c1 = getAddressValue(Binary.getVal2(def));
// x = a ^ c1; y = x | c2
if (c1.toWord().or(c2.toWord()).EQ(c2.toWord())) {
return Binary.create(REF_OR, y.copyRO(), a.copyRO(), AC(c2));
}
}
}
return null;
}
case LONG_OR_opcode:
{
if (FOLD_LONGS && FOLD_ORS) {
long c2 = getLongValue(Binary.getVal2(s));
if (def.operator() == LONG_OR) {
long c1 = getLongValue(Binary.getVal2(def));
// x = a | c1; y = x | c2
return Binary.create(LONG_OR, y.copyRO(), a.copyRO(), LC(c1 | c2));
} else if (def.operator() == LONG_AND) {
long c1 = getLongValue(Binary.getVal2(def));
// x = a & c1; y = x | c2
if ((~c1 | c2) == c2) {
return Binary.create(LONG_OR, y.copyRO(), a.copyRO(), LC(c2));
}
} else if (def.operator() == LONG_XOR) {
long c1 = getLongValue(Binary.getVal2(def));
// x = a ^ c1; y = x | c2
if ((c1 | c2) == c2) {
return Binary.create(LONG_OR, y.copyRO(), a.copyRO(), LC(c2));
}
}
}
return null;
}
case INT_XOR_opcode:
{
if (FOLD_INTS && FOLD_XORS) {
int c2 = getIntValue(Binary.getVal2(s));
if (def.operator() == INT_XOR) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a ^ c1; y = x ^ c2
return Binary.create(INT_XOR, y.copyRO(), a.copyRO(), IC(c1 ^ c2));
} else if (def.operator() == INT_NOT) {
// x = ~a; y = x ^ c2
return Binary.create(INT_XOR, y.copyRO(), a.copyRO(), IC(~c2));
} else if (def.operator() == BOOLEAN_NOT) {
// x = !a; y = x ^ c2
return Binary.create(INT_XOR, y.copyRO(), a.copyRO(), IC(c2 ^ 1));
}
}
return null;
}
case REF_XOR_opcode:
{
if (FOLD_REFS && FOLD_XORS) {
Address c2 = getAddressValue(Binary.getVal2(s));
if (def.operator() == REF_XOR) {
Address c1 = getAddressValue(Binary.getVal2(def));
// x = a ^ c1; y = x ^ c2
return Binary.create(REF_XOR, y.copyRO(), a.copyRO(), AC(c1.toWord().xor(c2.toWord()).toAddress()));
} else if (def.operator() == REF_NOT) {
// x = ~a; y = x ^ c2
return Binary.create(REF_XOR, y.copyRO(), a.copyRO(), AC(c2.toWord().not().toAddress()));
}
}
return null;
}
case LONG_XOR_opcode:
{
if (FOLD_LONGS && FOLD_XORS) {
long c2 = getLongValue(Binary.getVal2(s));
if (def.operator() == LONG_XOR) {
long c1 = getLongValue(Binary.getVal2(def));
// x = a ^ c1; y = x ^ c2
return Binary.create(LONG_XOR, y.copyRO(), a.copyRO(), LC(c1 ^ c2));
} else if (def.operator() == LONG_NOT) {
// x = ~a; y = x ^ c2
return Binary.create(LONG_XOR, y.copyRO(), a.copyRO(), LC(~c2));
}
}
return null;
}
case LONG_CMP_opcode:
{
if (FOLD_LONGS && FOLD_CMPS) {
long c2 = getLongValue(Binary.getVal2(s));
if (def.operator() == LONG_NEG) {
// x = -a; y = x cmp c2
return Binary.create(LONG_CMP, y.copyRO(), LC(-c2), a.copyRO());
}
}
return null;
}
case FLOAT_CMPL_opcode:
case FLOAT_CMPG_opcode:
{
if (FOLD_FLOATS && FOLD_CMPS) {
float c2 = getFloatValue(Binary.getVal2(s));
if (def.operator() == FLOAT_ADD) {
float c1 = getFloatValue(Binary.getVal2(def));
// x = a + c1; y = x cmp c2
return Binary.create(s.operator(), y.copyRO(), a.copyRO(), FC(c2 - c1));
} else if (def.operator() == FLOAT_SUB) {
float c1 = getFloatValue(Binary.getVal2(def));
// x = a - c1; y = x cmp c2
return Binary.create(s.operator(), y.copyRO(), a.copyRO(), FC(c1 + c2));
} else if (def.operator() == FLOAT_NEG) {
// x = -a; y = x cmp c2
return Binary.create(s.operator(), y.copyRO(), FC(-c2), a.copyRO());
}
}
return null;
}
case DOUBLE_CMPL_opcode:
case DOUBLE_CMPG_opcode:
{
if (FOLD_DOUBLES && FOLD_CMPS) {
double c2 = getDoubleValue(Binary.getVal2(s));
if (def.operator() == DOUBLE_ADD) {
double c1 = getDoubleValue(Binary.getVal2(def));
// x = a + c1; y = x cmp c2
return Binary.create(s.operator(), y.copyRO(), a.copyRO(), DC(c2 - c1));
} else if (def.operator() == DOUBLE_SUB) {
double c1 = getDoubleValue(Binary.getVal2(def));
// x = a - c1; y = x cmp c2
return Binary.create(s.operator(), y.copyRO(), a.copyRO(), DC(c1 + c2));
} else if (def.operator() == DOUBLE_NEG) {
// x = -a; y = x cmp c2
return Binary.create(s.operator(), y.copyRO(), DC(-c2), a.copyRO());
}
}
return null;
}
case BOOLEAN_CMP_INT_opcode:
{
if (FOLD_INTS && FOLD_CMPS) {
int c2 = getIntValue(BooleanCmp.getVal2(s));
ConditionOperand cond = (ConditionOperand) BooleanCmp.getCond(s).copy();
BranchProfileOperand prof = (BranchProfileOperand) BooleanCmp.getBranchProfile(s).copy();
if (cond.isEQUAL() || cond.isNOT_EQUAL()) {
if (def.operator() == INT_ADD) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a + c1; y = x cmp c2
return BooleanCmp.create(BOOLEAN_CMP_INT, y.copyRO(), a.copyRO(), IC(c2 - c1), cond, prof);
} else if (def.operator() == INT_SUB) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a - c1; y = x cmp c2
return BooleanCmp.create(BOOLEAN_CMP_INT, y.copyRO(), a.copyRO(), IC(c1 + c2), cond, prof);
} else if (def.operator() == INT_NEG) {
// x = -a; y = x cmp c2
return BooleanCmp.create(BOOLEAN_CMP_INT, y.copyRO(), a.copyRO(), IC(-c2), cond.flipOperands(), prof);
} else if (def.operator() == BOOLEAN_CMP_INT) {
int c1 = getIntValue(BooleanCmp.getVal2(def));
ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition();
// x = a cmp c1 ? true : false; y = x cmp c2 ? true : false
if ((cond.isEQUAL() && c2 == 1) || (cond.isNOT_EQUAL() && c2 == 0)) {
// Fold away redundancy boolean_cmp
return BooleanCmp.create(BOOLEAN_CMP_INT, y.copyRO(), a.copyRO(), IC(c1), cond2, prof);
} else if ((cond.isEQUAL() && c2 == 0) || (cond.isNOT_EQUAL() && c2 == 1)) {
// Fold away redundancy boolean_cmp
return BooleanCmp.create(BOOLEAN_CMP_INT, y.copyRO(), a.copyRO(), IC(c1), cond2.flipCode(), prof);
}
} else if (def.operator() == BOOLEAN_CMP_LONG) {
long c1 = getLongValue(BooleanCmp.getVal2(def));
ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition();
// x = a cmp c1 ? true : false; y = x cmp c2 ? true : false
if ((cond.isEQUAL() && c2 == 1) || (cond.isNOT_EQUAL() && c2 == 0)) {
// Fold away redundancy boolean_cmp
return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1), cond2, prof);
} else if ((cond.isEQUAL() && c2 == 0) || (cond.isNOT_EQUAL() && c2 == 1)) {
// Fold away redundancy boolean_cmp
return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1), cond2.flipCode(), prof);
}
} else if (def.operator() == BOOLEAN_CMP_ADDR) {
Address c1 = getAddressValue(BooleanCmp.getVal2(def));
ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition();
// x = a cmp c1 ? true : false; y = x cmp c2 ? true : false
if ((cond.isEQUAL() && c2 == 1) || (cond.isNOT_EQUAL() && c2 == 0)) {
// Fold away redundancy boolean_cmp
return BooleanCmp.create(BOOLEAN_CMP_ADDR, y.copyRO(), a.copyRO(), AC(c1), cond2, prof);
} else if ((cond.isEQUAL() && c2 == 0) || (cond.isNOT_EQUAL() && c2 == 1)) {
// Fold away redundancy boolean_cmp
return BooleanCmp.create(BOOLEAN_CMP_ADDR, y.copyRO(), a.copyRO(), AC(c1), cond2.flipCode(), prof);
}
} else if (def.operator() == BOOLEAN_CMP_FLOAT) {
float c1 = getFloatValue(BooleanCmp.getVal2(def));
ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition();
// x = a cmp c1 ? true : false; y = x cmp c2 ? true : false
if ((cond.isEQUAL() && c2 == 1) || (cond.isNOT_EQUAL() && c2 == 0)) {
// Fold away redundancy boolean_cmp
return BooleanCmp.create(BOOLEAN_CMP_FLOAT, y.copyRO(), a.copyRO(), FC(c1), cond2, prof);
} else if ((cond.isEQUAL() && c2 == 0) || (cond.isNOT_EQUAL() && c2 == 1)) {
// Fold away redundancy boolean_cmp
return BooleanCmp.create(BOOLEAN_CMP_FLOAT, y.copyRO(), a.copyRO(), FC(c1), cond2.flipCode(), prof);
}
} else if (def.operator() == BOOLEAN_CMP_DOUBLE) {
double c1 = getDoubleValue(BooleanCmp.getVal2(def));
ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition();
// x = a cmp c1 ? true : false; y = x cmp c2 ? true : false
if ((cond.isEQUAL() && c2 == 1) || (cond.isNOT_EQUAL() && c2 == 0)) {
// Fold away redundancy boolean_cmp
return BooleanCmp.create(BOOLEAN_CMP_DOUBLE, y.copyRO(), a.copyRO(), DC(c1), cond2, prof);
} else if ((cond.isEQUAL() && c2 == 0) || (cond.isNOT_EQUAL() && c2 == 1)) {
// Fold away redundancy boolean_cmp
return BooleanCmp.create(BOOLEAN_CMP_DOUBLE, y.copyRO(), a.copyRO(), DC(c1), cond2.flipCode(), prof);
}
} else if (def.operator() == LONG_CMP) {
long c1 = getLongValue(Binary.getVal2(def));
// x = a lcmp c1; y = y = x cmp c2 ? true : false
if (cond.isEQUAL() && c2 == 0) {
return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.EQUAL(), prof);
} else if (cond.isNOT_EQUAL() && c2 == 0) {
return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.NOT_EQUAL(), prof);
} else if ((cond.isEQUAL() && c2 == 1) || (cond.isGREATER() && c2 == 0)) {
return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.GREATER(), prof);
} else if (cond.isGREATER_EQUAL() && c2 == 0) {
return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.GREATER_EQUAL(), prof);
} else if ((cond.isEQUAL() && c2 == -1) || (cond.isLESS() && c2 == 0)) {
return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.LESS(), prof);
} else if (cond.isLESS_EQUAL() && c2 == 0) {
return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.LESS_EQUAL(), prof);
}
}
}
}
return null;
}
case BOOLEAN_CMP_LONG_opcode:
{
if (FOLD_LONGS && FOLD_CMPS) {
long c2 = getLongValue(BooleanCmp.getVal2(s));
ConditionOperand cond = (ConditionOperand) BooleanCmp.getCond(s).copy();
BranchProfileOperand prof = (BranchProfileOperand) BooleanCmp.getBranchProfile(s).copy();
if (cond.isEQUAL() || cond.isNOT_EQUAL()) {
if (def.operator() == LONG_ADD) {
long c1 = getLongValue(Binary.getVal2(def));
// x = a + c1; y = x cmp c2
return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c2 - c1), cond, prof);
} else if (def.operator() == LONG_SUB) {
long c1 = getLongValue(Binary.getVal2(def));
// x = a - c1; y = x cmp c2
return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1 + c2), cond, prof);
} else if (def.operator() == LONG_NEG) {
// x = -a; y = x cmp c2
return BooleanCmp.create(BOOLEAN_CMP_INT, y.copyRO(), a.copyRO(), LC(-c2), cond.flipOperands(), prof);
}
}
}
return null;
}
case BOOLEAN_CMP_ADDR_opcode:
{
if (FOLD_REFS && FOLD_CMPS) {
Address c2 = getAddressValue(BooleanCmp.getVal2(s));
ConditionOperand cond = (ConditionOperand) BooleanCmp.getCond(s).copy();
BranchProfileOperand prof = (BranchProfileOperand) BooleanCmp.getBranchProfile(s).copy();
if (cond.isEQUAL() || cond.isNOT_EQUAL()) {
if (def.operator() == REF_ADD) {
Address c1 = getAddressValue(Binary.getVal2(def));
// x = a + c1; y = x cmp c2
return BooleanCmp.create(BOOLEAN_CMP_ADDR, y.copyRO(), a.copyRO(), AC(c2.toWord().minus(c1.toWord()).toAddress()), cond, prof);
} else if (def.operator() == REF_SUB) {
Address c1 = getAddressValue(Binary.getVal2(def));
// x = a - c1; y = x cmp c2
return BooleanCmp.create(BOOLEAN_CMP_ADDR, y.copyRO(), a.copyRO(), AC(c1.toWord().plus(c2.toWord()).toAddress()), cond, prof);
} else if (def.operator() == REF_NEG) {
// x = -a; y = x cmp c2
return BooleanCmp.create(BOOLEAN_CMP_ADDR, y.copyRO(), a.copyRO(), AC(Word.zero().minus(c2.toWord()).toAddress()), cond.flipOperands(), prof);
}
}
}
return null;
}
case INT_IFCMP_opcode:
{
if (FOLD_INTS && FOLD_IFCMPS) {
int c2 = getIntValue(IfCmp.getVal2(s));
ConditionOperand cond = (ConditionOperand) IfCmp.getCond(s).copy();
BranchOperand target = (BranchOperand) IfCmp.getTarget(s).copy();
BranchProfileOperand prof = (BranchProfileOperand) IfCmp.getBranchProfile(s).copy();
if (cond.isEQUAL() || cond.isNOT_EQUAL()) {
if (def.operator() == INT_ADD) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a + c1; y = x cmp c2
return IfCmp.create(INT_IFCMP, y.copyRO(), a.copyRO(), IC(c2 - c1), cond, target, prof);
} else if (def.operator() == INT_SUB) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a - c1; y = x cmp c2
return IfCmp.create(INT_IFCMP, y.copyRO(), a.copyRO(), IC(c1 + c2), cond, target, prof);
} else if (def.operator() == INT_NEG) {
// x = -a; y = x cmp c2
return IfCmp.create(INT_IFCMP, y.copyRO(), a.copyRO(), IC(-c2), cond.flipOperands(), target, prof);
} else if (def.operator() == BOOLEAN_CMP_INT) {
int c1 = getIntValue(BooleanCmp.getVal2(def));
ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition();
// x = a cmp<cond2> c1 ? true : false; y = x cmp<cond> c2
if ((cond.isEQUAL() && c2 == 1) || (cond.isNOT_EQUAL() && c2 == 0)) {
// x = a cmp<cond2> c1; y = x == 1 ==> y = a cmp<cond2> c1
return IfCmp.create(INT_IFCMP, y.copyRO(), a.copyRO(), IC(c1), cond2, target, prof);
} else if ((cond.isEQUAL() && c2 == 0) || (cond.isNOT_EQUAL() && c2 == 1)) {
// x = a cmp<cond2> c1; y = x == 0 ==> y = a cmp<!cond2> c1
return IfCmp.create(INT_IFCMP, y.copyRO(), a.copyRO(), IC(c1), cond2.flipCode(), target, prof);
}
} else if (def.operator() == BOOLEAN_CMP_LONG) {
long c1 = getLongValue(BooleanCmp.getVal2(def));
ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition();
// x = a cmp c1 ? true : false; y = x cmp c2
if ((cond.isEQUAL() && c2 == 1) || (cond.isNOT_EQUAL() && c2 == 0)) {
// Fold away redundant boolean_cmp
return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1), cond2, target, prof);
} else if ((cond.isEQUAL() && c2 == 0) || (cond.isNOT_EQUAL() && c2 == 1)) {
// Fold away redundant boolean_cmp
return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1), cond2.flipCode(), target, prof);
}
} else if (def.operator() == BOOLEAN_CMP_ADDR) {
Address c1 = getAddressValue(BooleanCmp.getVal2(def));
ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition();
// x = a cmp c1 ? true : false; y = x cmp c2
if ((cond.isEQUAL() && c2 == 1) || (cond.isNOT_EQUAL() && c2 == 0)) {
// Fold away redundant boolean_cmp
return IfCmp.create(REF_IFCMP, y.copyRO(), a.copyRO(), AC(c1), cond2, target, prof);
} else if ((cond.isEQUAL() && c2 == 0) || (cond.isNOT_EQUAL() && c2 == 1)) {
// Fold away redundant boolean_cmp
return IfCmp.create(REF_IFCMP, y.copyRO(), a.copyRO(), AC(c1), cond2.flipCode(), target, prof);
}
} else if (def.operator() == BOOLEAN_CMP_FLOAT) {
float c1 = getFloatValue(BooleanCmp.getVal2(def));
ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition();
// x = a cmp c1 ? true : false; y = x cmp c2
if ((cond.isEQUAL() && c2 == 1) || (cond.isNOT_EQUAL() && c2 == 0)) {
// Fold away redundant boolean_cmp
return IfCmp.create(FLOAT_IFCMP, y.copyRO(), a.copyRO(), FC(c1), cond2, target, prof);
} else if ((cond.isEQUAL() && c2 == 0) || (cond.isNOT_EQUAL() && c2 == 1)) {
// Fold away redundant boolean_cmp
return IfCmp.create(FLOAT_IFCMP, y.copyRO(), a.copyRO(), FC(c1), cond2.flipCode(), target, prof);
}
} else if (def.operator() == BOOLEAN_CMP_DOUBLE) {
double c1 = getDoubleValue(BooleanCmp.getVal2(def));
ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition();
// x = a cmp c1 ? true : false; y = x cmp c2
if ((cond.isEQUAL() && c2 == 1) || (cond.isNOT_EQUAL() && c2 == 0)) {
// Fold away redundant boolean_cmp
return IfCmp.create(DOUBLE_IFCMP, y.copyRO(), a.copyRO(), DC(c1), cond2, target, prof);
} else if ((cond.isEQUAL() && c2 == 0) || (cond.isNOT_EQUAL() && c2 == 1)) {
// Fold away redundant boolean_cmp
return IfCmp.create(DOUBLE_IFCMP, y.copyRO(), a.copyRO(), DC(c1), cond2.flipCode(), target, prof);
}
} else if (def.operator() == LONG_CMP) {
long c1 = getLongValue(Binary.getVal2(def));
// x = a lcmp c1; y = y = x cmp c2
if (cond.isEQUAL() && c2 == 0) {
return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.EQUAL(), target, prof);
} else if (cond.isNOT_EQUAL() && c2 == 0) {
return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.NOT_EQUAL(), target, prof);
} else if ((cond.isEQUAL() && c2 == 1) || (cond.isGREATER() && c2 == 0)) {
return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.GREATER(), target, prof);
} else if (cond.isGREATER_EQUAL() && c2 == 0) {
return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.GREATER_EQUAL(), target, prof);
} else if ((cond.isEQUAL() && c2 == -1) || (cond.isLESS() && c2 == 0)) {
return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.LESS(), target, prof);
} else if (cond.isLESS_EQUAL() && c2 == 0) {
return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.LESS_EQUAL(), target, prof);
}
}
}
}
return null;
}
case LONG_IFCMP_opcode:
{
if (FOLD_LONGS && FOLD_IFCMPS) {
long c2 = getLongValue(IfCmp.getVal2(s));
ConditionOperand cond = (ConditionOperand) IfCmp.getCond(s).copy();
BranchOperand target = (BranchOperand) IfCmp.getTarget(s).copy();
BranchProfileOperand prof = (BranchProfileOperand) IfCmp.getBranchProfile(s).copy();
if (cond.isEQUAL() || cond.isNOT_EQUAL()) {
if (def.operator() == LONG_ADD) {
long c1 = getLongValue(Binary.getVal2(def));
// x = a + c1; y = x cmp c2
return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c2 - c1), cond, target, prof);
} else if (def.operator() == LONG_SUB) {
long c1 = getLongValue(Binary.getVal2(def));
// x = a - c1; y = x cmp c2
return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1 + c2), cond, target, prof);
} else if (def.operator() == LONG_NEG) {
// x = -a; y = x cmp c2
return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(-c2), cond.flipOperands(), target, prof);
}
}
}
return null;
}
case FLOAT_IFCMP_opcode:
{
if (FOLD_FLOATS && FOLD_IFCMPS) {
float c2 = getFloatValue(IfCmp.getVal2(s));
ConditionOperand cond = (ConditionOperand) IfCmp.getCond(s).copy();
BranchOperand target = (BranchOperand) IfCmp.getTarget(s).copy();
BranchProfileOperand prof = (BranchProfileOperand) IfCmp.getBranchProfile(s).copy();
if (def.operator() == FLOAT_ADD) {
float c1 = getFloatValue(Binary.getVal2(def));
// x = a + c1; y = x cmp c2
return IfCmp.create(FLOAT_IFCMP, y.copyRO(), a.copyRO(), FC(c2 - c1), cond, target, prof);
} else if (def.operator() == FLOAT_SUB) {
float c1 = getFloatValue(Binary.getVal2(def));
// x = a - c1; y = x cmp c2
return IfCmp.create(FLOAT_IFCMP, y.copyRO(), a.copyRO(), FC(c1 + c2), cond, target, prof);
} else if (def.operator() == FLOAT_NEG) {
// x = -a; y = x cmp c2
return IfCmp.create(FLOAT_IFCMP, y.copyRO(), a.copyRO(), FC(-c2), cond.flipOperands(), target, prof);
}
}
return null;
}
case DOUBLE_IFCMP_opcode:
{
if (FOLD_DOUBLES && FOLD_IFCMPS) {
double c2 = getDoubleValue(IfCmp.getVal2(s));
ConditionOperand cond = (ConditionOperand) IfCmp.getCond(s).copy();
BranchOperand target = (BranchOperand) IfCmp.getTarget(s).copy();
BranchProfileOperand prof = (BranchProfileOperand) IfCmp.getBranchProfile(s).copy();
if (def.operator() == DOUBLE_ADD) {
double c1 = getDoubleValue(Binary.getVal2(def));
// x = a + c1; y = x cmp c2
return IfCmp.create(DOUBLE_IFCMP, y.copyRO(), a.copyRO(), DC(c2 - c1), cond, target, prof);
} else if (def.operator() == DOUBLE_SUB) {
double c1 = getDoubleValue(Binary.getVal2(def));
// x = a - c1; y = x cmp c2
return IfCmp.create(DOUBLE_IFCMP, y.copyRO(), a.copyRO(), DC(c1 + c2), cond, target, prof);
} else if (def.operator() == DOUBLE_NEG) {
// x = -a; y = x cmp c2
return IfCmp.create(DOUBLE_IFCMP, y.copyRO(), a.copyRO(), DC(-c2), cond.flipOperands(), target, prof);
}
}
return null;
}
case REF_IFCMP_opcode:
{
if (FOLD_REFS && FOLD_IFCMPS) {
Address c2 = getAddressValue(IfCmp.getVal2(s));
ConditionOperand cond = (ConditionOperand) IfCmp.getCond(s).copy();
BranchOperand target = (BranchOperand) IfCmp.getTarget(s).copy();
BranchProfileOperand prof = (BranchProfileOperand) IfCmp.getBranchProfile(s).copy();
if (cond.isEQUAL() || cond.isNOT_EQUAL()) {
if ((def.operator() == NEW || def.operator() == NEWARRAY) && c2.EQ(Address.zero())) {
// x = new ... ; y = x cmp null
return IfCmp.create(REF_IFCMP, y.copyRO(), AC(Address.zero()), AC(Address.zero()), cond.flipCode(), target, prof);
} else if (def.operator() == REF_ADD) {
Address c1 = getAddressValue(Binary.getVal2(def));
// x = a + c1; y = x cmp c2
return IfCmp.create(REF_IFCMP, y.copyRO(), a.copyRO(), AC(c2.toWord().minus(c1.toWord()).toAddress()), cond, target, prof);
} else if (def.operator() == REF_SUB) {
Address c1 = getAddressValue(Binary.getVal2(def));
// x = a - c1; y = x cmp c2
return IfCmp.create(REF_IFCMP, y.copyRO(), a.copyRO(), AC(c1.toWord().plus(c2.toWord()).toAddress()), cond, target, prof);
} else if (def.operator() == REF_NEG) {
// x = -a; y = x cmp c2
return IfCmp.create(REF_IFCMP, y.copyRO(), a.copyRO(), AC(Word.zero().minus(c2.toWord()).toAddress()), cond.flipOperands(), target, prof);
}
}
}
return null;
}
case INT_IFCMP2_opcode:
{
if (FOLD_INTS && FOLD_IFCMPS) {
int c2 = getIntValue(IfCmp2.getVal2(s));
ConditionOperand cond1 = (ConditionOperand) IfCmp2.getCond1(s).copy();
ConditionOperand cond2 = (ConditionOperand) IfCmp2.getCond2(s).copy();
BranchOperand target1 = (BranchOperand) IfCmp2.getTarget1(s).copy();
BranchOperand target2 = (BranchOperand) IfCmp2.getTarget2(s).copy();
BranchProfileOperand prof1 = (BranchProfileOperand) IfCmp2.getBranchProfile1(s).copy();
BranchProfileOperand prof2 = (BranchProfileOperand) IfCmp2.getBranchProfile2(s).copy();
if ((cond1.isEQUAL() || cond1.isNOT_EQUAL()) && (cond2.isEQUAL() || cond2.isNOT_EQUAL())) {
if (def.operator() == INT_ADD) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a + c1; y = x cmp c2
return IfCmp2.create(INT_IFCMP2, y.copyRO(), a.copyRO(), IC(c2 - c1), cond1, target1, prof1, cond2, target2, prof2);
} else if (def.operator() == INT_SUB) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a - c1; y = x cmp c2
return IfCmp2.create(INT_IFCMP2, y.copyRO(), a.copyRO(), IC(c1 + c2), cond1, target1, prof1, cond2, target2, prof2);
} else if (def.operator() == INT_NEG) {
// x = -a; y = x cmp c2
return IfCmp2.create(INT_IFCMP2, y.copyRO(), a.copyRO(), IC(-c2), cond1.flipOperands(), target1, prof1, cond2.flipOperands(), target2, prof2);
}
}
}
return null;
}
case INT_COND_MOVE_opcode:
case LONG_COND_MOVE_opcode:
case REF_COND_MOVE_opcode:
case FLOAT_COND_MOVE_opcode:
case DOUBLE_COND_MOVE_opcode:
case GUARD_COND_MOVE_opcode:
{
if (FOLD_INTS && FOLD_CONDMOVES) {
Operand trueValue = CondMove.getTrueValue(s);
Operand falseValue = CondMove.getFalseValue(s);
ConditionOperand cond = (ConditionOperand) CondMove.getCond(s).copy();
boolean isEqualityTest = cond.isEQUAL() || cond.isNOT_EQUAL();
switch(def.getOpcode()) {
case INT_ADD_opcode:
if (isEqualityTest) {
int c1 = getIntValue(Binary.getVal2(def));
int c2 = getIntValue(CondMove.getVal2(s));
// x = a + c1; y = x cmp c2 ? trueValue : falseValue
return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), IC(c2 - c1), cond, trueValue, falseValue);
}
break;
case LONG_ADD_opcode:
if (isEqualityTest) {
long c1 = getLongValue(Binary.getVal2(def));
long c2 = getLongValue(CondMove.getVal2(s));
// x = a + c1; y = x cmp c2 ? trueValue : falseValue
return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), LC(c2 - c1), cond, trueValue, falseValue);
}
break;
case REF_ADD_opcode:
if (isEqualityTest) {
Address c1 = getAddressValue(Binary.getVal2(def));
Address c2 = getAddressValue(CondMove.getVal2(s));
// x = a + c1; y = x cmp c2 ? trueValue : falseValue
return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), AC(c2.toWord().minus(c1.toWord()).toAddress()), cond, trueValue, falseValue);
}
break;
case FLOAT_ADD_opcode:
{
float c1 = getFloatValue(Binary.getVal2(def));
float c2 = getFloatValue(CondMove.getVal2(s));
// x = a + c1; y = x cmp c2 ? trueValue : falseValue
return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), FC(c2 - c1), cond, trueValue, falseValue);
}
case DOUBLE_ADD_opcode:
{
double c1 = getDoubleValue(Binary.getVal2(def));
double c2 = getDoubleValue(CondMove.getVal2(s));
// x = a + c1; y = x cmp c2 ? trueValue : falseValue
return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), DC(c2 - c1), cond, trueValue, falseValue);
}
case INT_SUB_opcode:
if (isEqualityTest) {
int c1 = getIntValue(Binary.getVal2(def));
int c2 = getIntValue(CondMove.getVal2(s));
// x = a - c1; y = x cmp c2 ? trueValue : falseValue
return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), IC(c1 + c2), cond, trueValue, falseValue);
}
break;
case LONG_SUB_opcode:
if (isEqualityTest) {
long c1 = getLongValue(Binary.getVal2(def));
long c2 = getLongValue(CondMove.getVal2(s));
// x = a - c1; y = x cmp c2 ? trueValue : falseValue
return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), LC(c1 + c2), cond, trueValue, falseValue);
}
break;
case REF_SUB_opcode:
if (isEqualityTest) {
Address c1 = getAddressValue(Binary.getVal2(def));
Address c2 = getAddressValue(CondMove.getVal2(s));
// x = a - c1; y = x cmp c2 ? trueValue : falseValue
return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), AC(c1.toWord().plus(c2.toWord()).toAddress()), cond, trueValue, falseValue);
}
break;
case FLOAT_SUB_opcode:
{
float c1 = getFloatValue(Binary.getVal2(def));
float c2 = getFloatValue(CondMove.getVal2(s));
// x = a - c1; y = x cmp c2 ? trueValue : falseValue
return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), FC(c1 + c2), cond, trueValue, falseValue);
}
case DOUBLE_SUB_opcode:
{
double c1 = getDoubleValue(Binary.getVal2(def));
double c2 = getDoubleValue(CondMove.getVal2(s));
// x = a - c1; y = x cmp c2 ? trueValue : falseValue
return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), DC(c1 + c2), cond, trueValue, falseValue);
}
case INT_NEG_opcode:
if (isEqualityTest) {
int c2 = getIntValue(CondMove.getVal2(s));
// x = -a; y = x cmp c2 ? trueValue : falseValue
return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), IC(-c2), cond.flipOperands(), trueValue, falseValue);
}
break;
case LONG_NEG_opcode:
if (isEqualityTest) {
long c2 = getLongValue(CondMove.getVal2(s));
// x = -a; y = x cmp c2 ? trueValue : falseValue
return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), LC(-c2), cond.flipOperands(), trueValue, falseValue);
}
break;
case REF_NEG_opcode:
if (isEqualityTest) {
Address c2 = getAddressValue(CondMove.getVal2(s));
// x = -a; y = x cmp c2 ? trueValue : falseValue
return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), AC(Word.zero().minus(c2.toWord()).toAddress()), cond.flipOperands(), trueValue, falseValue);
}
break;
case FLOAT_NEG_opcode:
{
float c2 = getFloatValue(CondMove.getVal2(s));
// x = -a; y = x cmp c2 ? trueValue : falseValue
return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), FC(-c2), cond.flipOperands(), trueValue, falseValue);
}
case DOUBLE_NEG_opcode:
{
double c2 = getDoubleValue(CondMove.getVal2(s));
// x = -a; y = x cmp c2 ? trueValue : falseValue
return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), DC(-c2), cond.flipOperands(), trueValue, falseValue);
}
case BOOLEAN_CMP_INT_opcode:
{
int c1 = getIntValue(BooleanCmp.getVal2(def));
int c2 = getIntValue(CondMove.getVal2(s));
// x = a cmp c1 ? true : false; y = x cmp c2 ? trueValue : falseValue
if ((cond.isEQUAL() && c2 == 1) || (cond.isNOT_EQUAL() && c2 == 0)) {
return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), IC(c1), BooleanCmp.getCond(def).copy().asCondition(), trueValue, falseValue);
} else if ((cond.isEQUAL() && c2 == 0) || (cond.isNOT_EQUAL() && c2 == 1)) {
return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), IC(c1), BooleanCmp.getCond(def).copy().asCondition().flipCode(), trueValue, falseValue);
}
break;
}
case BOOLEAN_CMP_ADDR_opcode:
{
Address c1 = getAddressValue(BooleanCmp.getVal2(def));
int c2 = getIntValue(CondMove.getVal2(s));
// x = a cmp c1 ? true : false; y = x cmp c2 ? trueValue : falseValue
if ((cond.isEQUAL() && c2 == 1) || (cond.isNOT_EQUAL() && c2 == 0)) {
return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), AC(c1), BooleanCmp.getCond(def).copy().asCondition(), trueValue, falseValue);
} else if ((cond.isEQUAL() && c2 == 0) || (cond.isNOT_EQUAL() && c2 == 1)) {
return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), AC(c1), BooleanCmp.getCond(def).flipCode(), trueValue, falseValue);
}
break;
}
case BOOLEAN_CMP_LONG_opcode:
{
long c1 = getLongValue(BooleanCmp.getVal2(def));
int c2 = getIntValue(CondMove.getVal2(s));
// x = a cmp c1 ? true : false; y = x cmp c2 ? trueValue : falseValue
if ((cond.isEQUAL() && c2 == 1) || (cond.isNOT_EQUAL() && c2 == 0)) {
return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), LC(c1), BooleanCmp.getCond(def).copy().asCondition(), trueValue, falseValue);
} else if ((cond.isEQUAL() && c2 == 0) || (cond.isNOT_EQUAL() && c2 == 1)) {
return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), LC(c1), BooleanCmp.getCond(def).copy().asCondition().flipCode(), trueValue, falseValue);
} else {
return null;
}
}
case BOOLEAN_CMP_DOUBLE_opcode:
{
double c1 = getDoubleValue(BooleanCmp.getVal2(def));
int c2 = getIntValue(CondMove.getVal2(s));
// x = a cmp c1 ? true : false; y = x cmp c2 ? trueValue : falseValue
if ((cond.isEQUAL() && c2 == 1) || (cond.isNOT_EQUAL() && c2 == 0)) {
return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), DC(c1), BooleanCmp.getCond(def).copy().asCondition(), trueValue, falseValue);
} else if ((cond.isEQUAL() && c2 == 0) || (cond.isNOT_EQUAL() && c2 == 1)) {
return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), DC(c1), BooleanCmp.getCond(def).copy().asCondition().flipCode(), trueValue, falseValue);
}
break;
}
case BOOLEAN_CMP_FLOAT_opcode:
{
float c1 = getFloatValue(BooleanCmp.getVal2(def));
int c2 = getIntValue(CondMove.getVal2(s));
// x = a cmp c1 ? true : false; y = x cmp c2 ? trueValue : falseValue
if ((cond.isEQUAL() && c2 == 1) || (cond.isNOT_EQUAL() && c2 == 0)) {
return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), FC(c1), BooleanCmp.getCond(def).copy().asCondition(), trueValue, falseValue);
} else if ((cond.isEQUAL() && c2 == 0) || (cond.isNOT_EQUAL() && c2 == 1)) {
return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), FC(c1), BooleanCmp.getCond(def).copy().asCondition().flipCode(), trueValue, falseValue);
}
break;
}
case LONG_CMP_opcode:
{
long c1 = getLongValue(Binary.getVal2(def));
int c2 = getIntValue(CondMove.getVal2(s));
// x = a lcmp c1; y = y = x cmp c2 ? trueValue : falseValue
if (cond.isEQUAL() && c2 == 0) {
return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.EQUAL(), trueValue, falseValue);
} else if (cond.isNOT_EQUAL() && c2 == 0) {
return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.NOT_EQUAL(), trueValue, falseValue);
} else if ((cond.isEQUAL() && c2 == 1) || (cond.isGREATER() && c2 == 0)) {
return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.GREATER(), trueValue, falseValue);
} else if (cond.isGREATER_EQUAL() && c2 == 0) {
return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.GREATER_EQUAL(), trueValue, falseValue);
} else if ((cond.isEQUAL() && c2 == -1) || (cond.isLESS() && c2 == 0)) {
return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.LESS(), trueValue, falseValue);
} else if (cond.isLESS_EQUAL() && c2 == 0) {
return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.LESS_EQUAL(), trueValue, falseValue);
}
break;
}
default:
}
}
return null;
}
case INT_NEG_opcode:
{
if (FOLD_INTS && FOLD_NEGS) {
if (def.operator() == INT_NEG) {
// x = -z; y = -x;
return Move.create(INT_MOVE, y.copyRO(), Unary.getVal(def).copy());
} else if (def.operator() == INT_MUL) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a * c1; y = -x;
return Binary.create(INT_MUL, y.copyRO(), a.copyRO(), IC(-c1));
} else if (def.operator() == INT_DIV) {
int c1 = getIntValue(GuardedBinary.getVal2(def));
Operand guard = GuardedBinary.getGuard(def);
// x = a / c1; y = -x;
return GuardedBinary.create(INT_DIV, y.copyRO(), a.copyRO(), IC(-c1), guard.copy());
} else if (FOLD_CONSTANTS_TO_LHS && (def.operator() == INT_ADD)) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a + c1; y = -x;
return Binary.create(INT_SUB, y.copyRO(), IC(-c1), a.copyRO());
} else if (FOLD_CONSTANTS_TO_LHS && (def.operator() == INT_SUB)) {
int c1 = getIntValue(Binary.getVal2(def));
// x = a - c1; y = -x;
return Binary.create(INT_SUB, y.copyRO(), IC(c1), a.copyRO());
}
}
return null;
}
case REF_NEG_opcode:
{
if (FOLD_REFS && FOLD_NEGS) {
if (def.operator() == REF_NEG) {
// x = -z; y = -x;
return Move.create(REF_MOVE, y.copyRO(), Unary.getVal(def).copy());
} else if (FOLD_CONSTANTS_TO_LHS && (def.operator() == REF_ADD)) {
Address c1 = getAddressValue(Binary.getVal2(def));
// x = a + c1; y = -x;
return Binary.create(REF_SUB, y.copyRO(), AC(Word.zero().minus(c1.toWord()).toAddress()), a.copyRO());
} else if (FOLD_CONSTANTS_TO_LHS && (def.operator() == REF_SUB)) {
Address c1 = getAddressValue(Binary.getVal2(def));
// x = a - c1; y = -x;
return Binary.create(REF_SUB, y.copyRO(), AC(c1), a.copyRO());
}
}
return null;
}
case LONG_NEG_opcode:
{
if (FOLD_LONGS && FOLD_NEGS) {
if (def.operator() == LONG_NEG) {
// x = -z; y = -x;
return Move.create(LONG_MOVE, y.copyRO(), Unary.getVal(def).copy());
} else if (def.operator() == LONG_MUL) {
long c1 = getLongValue(Binary.getVal2(def));
// x = a * c1; y = -x;
return Binary.create(LONG_MUL, y.copyRO(), a.copyRO(), LC(-c1));
} else if (def.operator() == LONG_DIV) {
long c1 = getLongValue(GuardedBinary.getVal2(def));
Operand guard = GuardedBinary.getGuard(def);
// x = a / c1; y = -x;
return GuardedBinary.create(LONG_DIV, y.copyRO(), a.copyRO(), LC(-c1), guard.copy());
} else if (FOLD_CONSTANTS_TO_LHS && (def.operator() == LONG_ADD)) {
long c1 = getLongValue(Binary.getVal2(def));
// x = a + c1; y = -x;
return Binary.create(LONG_SUB, y.copyRO(), LC(-c1), a.copyRO());
} else if (FOLD_CONSTANTS_TO_LHS && (def.operator() == LONG_SUB)) {
long c1 = getLongValue(Binary.getVal2(def));
// x = a - c1; y = -x;
return Binary.create(LONG_SUB, y.copyRO(), LC(c1), a.copyRO());
}
}
return null;
}
case FLOAT_NEG_opcode:
{
if (FOLD_FLOATS && FOLD_NEGS) {
if (def.operator() == FLOAT_NEG) {
// x = -z; y = -x;
return Move.create(FLOAT_MOVE, y.copyRO(), Unary.getVal(def).copy());
} else if (def.operator() == FLOAT_MUL) {
float c1 = getFloatValue(Binary.getVal2(def));
// x = a * c1; y = -x;
return Binary.create(FLOAT_MUL, y.copyRO(), a.copyRO(), FC(-c1));
} else if (def.operator() == FLOAT_DIV) {
float c1 = getFloatValue(Binary.getVal2(def));
// x = a / c1; y = -x;
return Binary.create(FLOAT_DIV, y.copyRO(), a.copyRO(), FC(-c1));
} else if (FOLD_CONSTANTS_TO_LHS && (def.operator() == FLOAT_ADD)) {
float c1 = getFloatValue(Binary.getVal2(def));
// x = a + c1; y = -x;
return Binary.create(FLOAT_SUB, y.copyRO(), FC(-c1), a.copyRO());
} else if (FOLD_CONSTANTS_TO_LHS && (def.operator() == FLOAT_SUB)) {
float c1 = getFloatValue(Binary.getVal2(def));
// x = a - c1; y = -x;
return Binary.create(FLOAT_SUB, y.copyRO(), FC(c1), a.copyRO());
}
}
return null;
}
case DOUBLE_NEG_opcode:
{
if (FOLD_DOUBLES && FOLD_NEGS) {
if (def.operator() == DOUBLE_NEG) {
// x = -z; y = -x;
return Move.create(DOUBLE_MOVE, y.copyRO(), Unary.getVal(def).copy());
} else if (def.operator() == DOUBLE_MUL) {
double c1 = getDoubleValue(Binary.getVal2(def));
// x = a * c1; y = -x;
return Binary.create(DOUBLE_MUL, y.copyRO(), a.copyRO(), DC(-c1));
} else if (def.operator() == DOUBLE_DIV) {
double c1 = getDoubleValue(Binary.getVal2(def));
// x = a / c1; y = -x;
return Binary.create(DOUBLE_DIV, y.copyRO(), a.copyRO(), DC(-c1));
} else if (FOLD_CONSTANTS_TO_LHS && (def.operator() == DOUBLE_ADD)) {
double c1 = getDoubleValue(Binary.getVal2(def));
// x = a + c1; y = -x;
return Binary.create(DOUBLE_SUB, y.copyRO(), DC(-c1), a.copyRO());
} else if (FOLD_CONSTANTS_TO_LHS && (def.operator() == DOUBLE_SUB)) {
double c1 = getDoubleValue(Binary.getVal2(def));
// x = a - c1; y = -x;
return Binary.create(DOUBLE_SUB, y.copyRO(), DC(c1), a.copyRO());
}
}
return null;
}
case BOOLEAN_NOT_opcode:
{
if (FOLD_INTS && FOLD_NOTS) {
if (def.operator() == BOOLEAN_NOT) {
// x = 1 ^ a; y = 1 ^ x;
return Move.create(INT_MOVE, y.copyRO(), Unary.getVal(def).copy());
} else if (BooleanCmp.conforms(def)) {
// x = a cmp b; y = !x
return BooleanCmp.create(def.operator(), y.copyRO(), BooleanCmp.getVal1(def).copy(), BooleanCmp.getVal2(def).copy(), ((ConditionOperand) BooleanCmp.getCond(def).copy()).flipCode(), ((BranchProfileOperand) BooleanCmp.getBranchProfile(def).copy()));
}
}
return null;
}
case INT_NOT_opcode:
{
if (FOLD_INTS && FOLD_NOTS) {
if (def.operator() == INT_NOT) {
// x = -1 ^ a; y = -1 ^ x;
return Move.create(INT_MOVE, y.copyRO(), a.copy());
}
}
return null;
}
case REF_NOT_opcode:
{
if (FOLD_REFS && FOLD_NOTS) {
if (def.operator() == REF_NOT) {
// x = -1 ^ a; y = -1 ^ x;
return Move.create(REF_MOVE, y.copyRO(), a.copy());
}
}
return null;
}
case LONG_NOT_opcode:
{
if (FOLD_LONGS && FOLD_NOTS) {
if (def.operator() == LONG_NOT) {
// x = -1 ^ a; y = -1 ^ x;
return Move.create(LONG_MOVE, y.copyRO(), a.copy());
}
}
return null;
}
case INT_2BYTE_opcode:
{
if (FOLD_INTS && FOLD_2CONVERSION) {
if ((def.operator() == INT_2BYTE) || (def.operator() == INT_2SHORT)) {
// x = (short)a; y = (byte)x;
return Unary.create(INT_2BYTE, y.copyRO(), a.copy());
} else if (def.operator() == INT_2USHORT) {
// x = (char)a; y = (byte)x;
return Binary.create(INT_AND, y.copyRO(), a.copy(), IC(0xFF));
}
}
return null;
}
case INT_2SHORT_opcode:
{
if (FOLD_INTS && FOLD_2CONVERSION) {
if (def.operator() == INT_2BYTE) {
// x = (byte)a; y = (short)x;
return Unary.create(INT_2BYTE, y.copyRO(), a.copy());
} else if (def.operator() == INT_2SHORT) {
// x = (short)a; y = (short)x;
return Unary.create(INT_2SHORT, y.copyRO(), a.copy());
} else if (def.operator() == INT_2USHORT) {
// x = (char)a; y = (short)x;
return Unary.create(INT_2USHORT, y.copyRO(), a.copy());
}
}
return null;
}
case INT_2USHORT_opcode:
{
if (FOLD_INTS && FOLD_2CONVERSION) {
if ((def.operator() == INT_2SHORT) || (def.operator() == INT_2USHORT)) {
// x = (short)a; y = (char)x;
return Unary.create(INT_2USHORT, y.copyRO(), a.copy());
}
}
return null;
}
case LONG_2INT_opcode:
{
if (FOLD_LONGS && FOLD_2CONVERSION) {
if (def.operator() == INT_2LONG) {
// x = (long)a; y = (int)x;
return Move.create(INT_MOVE, y.copyRO(), a.copy());
}
}
return null;
}
case INT_2LONG_opcode:
// unused
return null;
case DOUBLE_2FLOAT_opcode:
{
if (FOLD_DOUBLES && FOLD_2CONVERSION) {
if (def.operator() == FLOAT_2DOUBLE) {
// x = (double)a; y = (float)x;
return Move.create(FLOAT_MOVE, y.copyRO(), a.copy());
}
}
return null;
}
case FLOAT_2DOUBLE_opcode:
// unused
return null;
case INT_ZERO_CHECK_opcode:
{
if (FOLD_INTS && FOLD_CHECKS) {
if (def.operator() == INT_NEG) {
// x = -z; y = zerocheck x;
return ZeroCheck.create(INT_ZERO_CHECK, y.copyRO(), Unary.getVal(def).copy());
}
}
return null;
}
case LONG_ZERO_CHECK_opcode:
{
if (FOLD_INTS && FOLD_CHECKS) {
if (def.operator() == INT_NEG) {
// x = -z; y = zerocheck x;
return ZeroCheck.create(INT_ZERO_CHECK, y.copyRO(), Unary.getVal(def).copy());
}
}
return null;
}
case NEWARRAY_opcode:
// unused
return null;
case BOUNDS_CHECK_opcode:
{
if (FOLD_CHECKS) {
if (def.operator() == NEWARRAY) {
// x = newarray xxx[c1]; y = boundscheck x, c2;
int c1 = getIntValue(NewArray.getSize(def));
int c2 = getIntValue(BoundsCheck.getIndex(s));
if (c2 >= 0 && c2 < c1) {
return Move.create(GUARD_MOVE, y.copyRO(), BoundsCheck.getGuard(def).copy());
}
}
}
return null;
}
case NULL_CHECK_opcode:
{
if (FOLD_CHECKS) {
if (def.operator() == NEWARRAY || def.operator() == NEW) {
// x = new xxx; y = nullcheck x;
return Move.create(GUARD_MOVE, y.copyRO(), new TrueGuardOperand());
}
}
return null;
}
case INSTANCEOF_opcode:
{
if (FOLD_CHECKS) {
TypeReference newType;
if (def.operator() == NEW) {
// x = new xxx; y = instanceof x, zzz;
newType = New.getType(def).getTypeRef();
} else if (def.operator() == NEWARRAY) {
// x = newarray xxx; y = instanceof x, zzz;
newType = NewArray.getType(def).getTypeRef();
} else {
return null;
}
TypeReference instanceofType = InstanceOf.getType(s).getTypeRef();
if (newType == instanceofType) {
return Move.create(INT_MOVE, y.copyRO(), IC(1));
} else {
return Move.create(INT_MOVE, y.copyRO(), IC(RuntimeEntrypoints.isAssignableWith(instanceofType.resolve(), newType.resolve()) ? 1 : 0));
}
}
return null;
}
case ARRAYLENGTH_opcode:
{
if (FOLD_CHECKS) {
if (def.operator() == NEWARRAY) {
// x = newarray xxx[c1]; y = arraylength x;
return Move.create(INT_MOVE, y.copyRO(), NewArray.getSize(def).copy());
}
}
return null;
}
default:
OptimizingCompilerException.UNREACHABLE();
return null;
}
}
use of org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand in project JikesRVM by JikesRVM.
the class BURS_Helpers method ATTEMPT_LONG_IFCMP.
/**
* This routine expands the compound pattern IFCMP(ATTEMPT_LONG, ZERO) into an
* atomic compare/exchange followed by a branch on success/failure of the
* attempted atomic compare/exchange.
*
* @param mo the address at which to attempt the exchange
* @param oldValue the old value at the address mo
* @param newValue the new value at the address mo
* @param cond the condition to branch on
* @param target the branch target
* @param bp the branch profile information
*/
protected final void ATTEMPT_LONG_IFCMP(MemoryOperand mo, Operand oldValue, Operand newValue, ConditionOperand cond, BranchOperand target, BranchProfileOperand bp) {
if (VM.VerifyAssertions)
opt_assert(VM.BuildFor64Addr, "Expansion of ifcmp of attempt_long NYI for 32-bit addressing!");
RegisterOperand temp = regpool.makeTempLong();
EMIT(MIR_Move.create(IA32_MOV, temp, newValue.copy()));
EMIT(MIR_Move.create(IA32_MOV, new RegisterOperand(getEAX(), TypeReference.Long), oldValue.copy()));
EMIT(MIR_CompareExchange.create(IA32_LOCK_CMPXCHG, new RegisterOperand(getEAX(), TypeReference.Long), mo, temp.copyRO()));
EMIT(MIR_CondBranch.create(IA32_JCC, COND(cond), target.copy().asBranch(), (BranchProfileOperand) bp.copy()));
}
use of org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand in project JikesRVM by JikesRVM.
the class BC2IR method generateFrom.
/**
* Generate instructions for a basic block.
* May discover other basic blocks that need to be generated along the way.
*
* @param fromIndex bytecode index to start from
*/
private void generateFrom(int fromIndex) {
if (DBG_BB || DBG_SELECTED) {
db("generating code into " + currentBBLE + " with runoff " + runoff);
}
currentBBLE.setGenerated();
endOfBasicBlock = fallThrough = false;
lastInstr = null;
bcodes.reset(fromIndex);
while (true) {
// Must keep currentBBLE.high up-to-date in case we try to jump into
// the middle of the block we're currently generating. Simply updating
// high once endsBasicBlock is true doesn't enable us to catch this case.
currentBBLE.high = instrIndex = bcodes.index();
int code = bcodes.nextInstruction();
if (DBG_BCPARSE) {
db("parsing " + instrIndex + " " + code + " : 0x" + Integer.toHexString(code) + " " + JBC_name(code));
}
Instruction s = null;
lastOsrBarrier = null;
switch(code) {
case JBC_nop:
break;
case JBC_aconst_null:
push(new NullConstantOperand());
break;
case JBC_iconst_m1:
case JBC_iconst_0:
case JBC_iconst_1:
case JBC_iconst_2:
case JBC_iconst_3:
case JBC_iconst_4:
case JBC_iconst_5:
push(new IntConstantOperand(code - JBC_iconst_0));
break;
case JBC_lconst_0:
case JBC_lconst_1:
pushDual(new LongConstantOperand(code - JBC_lconst_0));
break;
case JBC_fconst_0:
push(new FloatConstantOperand(0.f));
break;
case JBC_fconst_1:
push(new FloatConstantOperand(1.f));
break;
case JBC_fconst_2:
push(new FloatConstantOperand(2.f));
break;
case JBC_dconst_0:
pushDual(new DoubleConstantOperand(0.));
break;
case JBC_dconst_1:
pushDual(new DoubleConstantOperand(1.));
break;
case JBC_bipush:
push(new IntConstantOperand(bcodes.getByteValue()));
break;
case JBC_sipush:
push(new IntConstantOperand(bcodes.getShortValue()));
break;
case JBC_ldc:
push(getConstantOperand(bcodes.getConstantIndex()));
break;
case JBC_ldc_w:
push(getConstantOperand(bcodes.getWideConstantIndex()));
break;
case JBC_ldc2_w:
pushDual(getConstantOperand(bcodes.getWideConstantIndex()));
break;
case JBC_iload:
s = do_iload(bcodes.getLocalNumber());
break;
case JBC_lload:
s = do_lload(bcodes.getLocalNumber());
break;
case JBC_fload:
s = do_fload(bcodes.getLocalNumber());
break;
case JBC_dload:
s = do_dload(bcodes.getLocalNumber());
break;
case JBC_aload:
s = do_aload(bcodes.getLocalNumber());
break;
case JBC_iload_0:
case JBC_iload_1:
case JBC_iload_2:
case JBC_iload_3:
s = do_iload(code - JBC_iload_0);
break;
case JBC_lload_0:
case JBC_lload_1:
case JBC_lload_2:
case JBC_lload_3:
s = do_lload(code - JBC_lload_0);
break;
case JBC_fload_0:
case JBC_fload_1:
case JBC_fload_2:
case JBC_fload_3:
s = do_fload(code - JBC_fload_0);
break;
case JBC_dload_0:
case JBC_dload_1:
case JBC_dload_2:
case JBC_dload_3:
s = do_dload(code - JBC_dload_0);
break;
case JBC_aload_0:
case JBC_aload_1:
case JBC_aload_2:
case JBC_aload_3:
s = do_aload(code - JBC_aload_0);
break;
case JBC_iaload:
{
Operand index = popInt();
Operand ref = pop();
clearCurrentGuard();
if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
break;
}
if (VM.VerifyAssertions) {
assertIsType(ref, TypeReference.IntArray);
}
s = _aloadHelper(INT_ALOAD, ref, index, TypeReference.Int);
}
break;
case JBC_laload:
{
Operand index = popInt();
Operand ref = pop();
clearCurrentGuard();
if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
break;
}
if (VM.VerifyAssertions) {
assertIsType(ref, TypeReference.LongArray);
}
s = _aloadHelper(LONG_ALOAD, ref, index, TypeReference.Long);
}
break;
case JBC_faload:
{
Operand index = popInt();
Operand ref = pop();
clearCurrentGuard();
if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
break;
}
if (VM.VerifyAssertions) {
assertIsType(ref, TypeReference.FloatArray);
}
s = _aloadHelper(FLOAT_ALOAD, ref, index, TypeReference.Float);
}
break;
case JBC_daload:
{
Operand index = popInt();
Operand ref = pop();
clearCurrentGuard();
if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
break;
}
if (VM.VerifyAssertions) {
assertIsType(ref, TypeReference.DoubleArray);
}
s = _aloadHelper(DOUBLE_ALOAD, ref, index, TypeReference.Double);
}
break;
case JBC_aaload:
{
Operand index = popInt();
Operand ref = pop();
clearCurrentGuard();
if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
break;
}
TypeReference type = getRefTypeOf(ref).getArrayElementType();
if (VM.VerifyAssertions)
opt_assert(type.isReferenceType());
s = _aloadHelper(REF_ALOAD, ref, index, type);
}
break;
case JBC_baload:
{
Operand index = popInt();
Operand ref = pop();
clearCurrentGuard();
if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
break;
}
TypeReference type = getArrayTypeOf(ref);
if (VM.VerifyAssertions) {
opt_assert(type == TypeReference.ByteArray || type == TypeReference.BooleanArray);
}
if (type == TypeReference.ByteArray) {
s = _aloadHelper(BYTE_ALOAD, ref, index, TypeReference.Byte);
} else {
s = _aloadHelper(UBYTE_ALOAD, ref, index, TypeReference.Boolean);
}
}
break;
case JBC_caload:
{
Operand index = popInt();
Operand ref = pop();
clearCurrentGuard();
if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
break;
}
if (VM.VerifyAssertions) {
assertIsType(ref, TypeReference.CharArray);
}
s = _aloadHelper(USHORT_ALOAD, ref, index, TypeReference.Char);
}
break;
case JBC_saload:
{
Operand index = popInt();
Operand ref = pop();
clearCurrentGuard();
if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
break;
}
if (VM.VerifyAssertions) {
assertIsType(ref, TypeReference.ShortArray);
}
s = _aloadHelper(SHORT_ALOAD, ref, index, TypeReference.Short);
}
break;
case JBC_istore:
s = do_store(bcodes.getLocalNumber(), popInt());
break;
case JBC_lstore:
s = do_store(bcodes.getLocalNumber(), popLong());
break;
case JBC_fstore:
s = do_store(bcodes.getLocalNumber(), popFloat());
break;
case JBC_dstore:
s = do_store(bcodes.getLocalNumber(), popDouble());
break;
case JBC_astore:
s = do_astore(bcodes.getLocalNumber());
break;
case JBC_istore_0:
case JBC_istore_1:
case JBC_istore_2:
case JBC_istore_3:
s = do_store(code - JBC_istore_0, popInt());
break;
case JBC_lstore_0:
case JBC_lstore_1:
case JBC_lstore_2:
case JBC_lstore_3:
s = do_store(code - JBC_lstore_0, popLong());
break;
case JBC_fstore_0:
case JBC_fstore_1:
case JBC_fstore_2:
case JBC_fstore_3:
s = do_store(code - JBC_fstore_0, popFloat());
break;
case JBC_dstore_0:
case JBC_dstore_1:
case JBC_dstore_2:
case JBC_dstore_3:
s = do_store(code - JBC_dstore_0, popDouble());
break;
case JBC_astore_0:
case JBC_astore_1:
case JBC_astore_2:
case JBC_astore_3:
s = do_astore(code - JBC_astore_0);
break;
case JBC_iastore:
{
Operand val = popInt();
Operand index = popInt();
Operand ref = pop();
clearCurrentGuard();
if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
break;
}
if (VM.VerifyAssertions) {
assertIsType(ref, TypeReference.IntArray);
}
s = AStore.create(INT_ASTORE, val, ref, index, new LocationOperand(TypeReference.Int), getCurrentGuard());
}
break;
case JBC_lastore:
{
Operand val = popLong();
Operand index = popInt();
Operand ref = pop();
clearCurrentGuard();
if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
break;
}
if (VM.VerifyAssertions) {
assertIsType(ref, TypeReference.LongArray);
}
s = AStore.create(LONG_ASTORE, val, ref, index, new LocationOperand(TypeReference.Long), getCurrentGuard());
}
break;
case JBC_fastore:
{
Operand val = popFloat();
Operand index = popInt();
Operand ref = pop();
clearCurrentGuard();
if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
break;
}
if (VM.VerifyAssertions) {
assertIsType(ref, TypeReference.FloatArray);
}
s = AStore.create(FLOAT_ASTORE, val, ref, index, new LocationOperand(TypeReference.Float), getCurrentGuard());
}
break;
case JBC_dastore:
{
Operand val = popDouble();
Operand index = popInt();
Operand ref = pop();
clearCurrentGuard();
if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
break;
}
if (VM.VerifyAssertions) {
assertIsType(ref, TypeReference.DoubleArray);
}
s = AStore.create(DOUBLE_ASTORE, val, ref, index, new LocationOperand(TypeReference.Double), getCurrentGuard());
}
break;
case JBC_aastore:
{
Operand val = pop();
Operand index = popInt();
Operand ref = pop();
clearCurrentGuard();
if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
break;
}
TypeReference type = getRefTypeOf(ref).getArrayElementType();
if (VM.VerifyAssertions)
opt_assert(type.isReferenceType());
if (do_CheckStore(ref, val, type)) {
break;
}
s = AStore.create(REF_ASTORE, val, ref, index, new LocationOperand(type), getCurrentGuard());
}
break;
case JBC_bastore:
{
Operand val = popInt();
Operand index = popInt();
Operand ref = pop();
clearCurrentGuard();
if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
break;
}
TypeReference type = getArrayTypeOf(ref);
if (VM.VerifyAssertions) {
opt_assert(type == TypeReference.ByteArray || type == TypeReference.BooleanArray);
}
if (type == TypeReference.ByteArray) {
type = TypeReference.Byte;
} else {
type = TypeReference.Boolean;
}
s = AStore.create(BYTE_ASTORE, val, ref, index, new LocationOperand(type), getCurrentGuard());
}
break;
case JBC_castore:
{
Operand val = popInt();
Operand index = popInt();
Operand ref = pop();
clearCurrentGuard();
if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
break;
}
if (VM.VerifyAssertions) {
assertIsType(ref, TypeReference.CharArray);
}
s = AStore.create(SHORT_ASTORE, val, ref, index, new LocationOperand(TypeReference.Char), getCurrentGuard());
}
break;
case JBC_sastore:
{
Operand val = popInt();
Operand index = popInt();
Operand ref = pop();
clearCurrentGuard();
if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
break;
}
if (VM.VerifyAssertions) {
assertIsType(ref, TypeReference.ShortArray);
}
s = AStore.create(SHORT_ASTORE, val, ref, index, new LocationOperand(TypeReference.Short), getCurrentGuard());
}
break;
case JBC_pop:
stack.pop();
break;
case JBC_pop2:
stack.pop2();
break;
case JBC_dup:
{
Operand op1 = stack.pop();
stack.push(op1);
s = pushCopy(op1);
}
break;
case JBC_dup_x1:
{
Operand op1 = stack.pop();
Operand op2 = stack.pop();
stack.push(op1);
stack.push(op2);
s = pushCopy(op1);
}
break;
case JBC_dup_x2:
{
Operand op1 = stack.pop();
Operand op2 = stack.pop();
Operand op3 = stack.pop();
stack.push(op1);
stack.push(op3);
stack.push(op2);
s = pushCopy(op1);
}
break;
case JBC_dup2:
{
Operand op1 = stack.pop();
Operand op2 = stack.pop();
stack.push(op2);
stack.push(op1);
s = pushCopy(op2);
if (s != null) {
appendInstruction(s);
s = null;
}
s = pushCopy(op1);
}
break;
case JBC_dup2_x1:
{
Operand op1 = stack.pop();
Operand op2 = stack.pop();
Operand op3 = stack.pop();
stack.push(op2);
stack.push(op1);
stack.push(op3);
s = pushCopy(op2);
if (s != null) {
appendInstruction(s);
s = null;
}
s = pushCopy(op1);
}
break;
case JBC_dup2_x2:
{
Operand op1 = stack.pop();
Operand op2 = stack.pop();
Operand op3 = stack.pop();
Operand op4 = stack.pop();
stack.push(op2);
stack.push(op1);
stack.push(op4);
stack.push(op3);
s = pushCopy(op2);
if (s != null) {
appendInstruction(s);
s = null;
}
s = pushCopy(op1);
}
break;
case JBC_swap:
{
stack.swap();
}
break;
case JBC_iadd:
{
Operand op2 = popInt();
Operand op1 = popInt();
s = _binaryHelper(INT_ADD, op1, op2, TypeReference.Int);
}
break;
case JBC_ladd:
{
Operand op2 = popLong();
Operand op1 = popLong();
s = _binaryDualHelper(LONG_ADD, op1, op2, TypeReference.Long);
}
break;
case JBC_fadd:
{
Operand op2 = popFloat();
Operand op1 = popFloat();
s = _binaryHelper(FLOAT_ADD, op1, op2, TypeReference.Float);
}
break;
case JBC_dadd:
{
Operand op2 = popDouble();
Operand op1 = popDouble();
s = _binaryDualHelper(DOUBLE_ADD, op1, op2, TypeReference.Double);
}
break;
case JBC_isub:
{
Operand op2 = popInt();
Operand op1 = popInt();
s = _binaryHelper(INT_SUB, op1, op2, TypeReference.Int);
}
break;
case JBC_lsub:
{
Operand op2 = popLong();
Operand op1 = popLong();
s = _binaryDualHelper(LONG_SUB, op1, op2, TypeReference.Long);
}
break;
case JBC_fsub:
{
Operand op2 = popFloat();
Operand op1 = popFloat();
s = _binaryHelper(FLOAT_SUB, op1, op2, TypeReference.Float);
}
break;
case JBC_dsub:
{
Operand op2 = popDouble();
Operand op1 = popDouble();
s = _binaryDualHelper(DOUBLE_SUB, op1, op2, TypeReference.Double);
}
break;
case JBC_imul:
{
Operand op2 = popInt();
Operand op1 = popInt();
s = _binaryHelper(INT_MUL, op1, op2, TypeReference.Int);
}
break;
case JBC_lmul:
{
Operand op2 = popLong();
Operand op1 = popLong();
s = _binaryDualHelper(LONG_MUL, op1, op2, TypeReference.Long);
}
break;
case JBC_fmul:
{
Operand op2 = popFloat();
Operand op1 = popFloat();
s = _binaryHelper(FLOAT_MUL, op1, op2, TypeReference.Float);
}
break;
case JBC_dmul:
{
Operand op2 = popDouble();
Operand op1 = popDouble();
s = _binaryDualHelper(DOUBLE_MUL, op1, op2, TypeReference.Double);
}
break;
case JBC_idiv:
{
clearCurrentGuard();
Operand op2 = popInt();
Operand op1 = popInt();
if (do_IntZeroCheck(op2)) {
break;
}
s = _guardedBinaryHelper(INT_DIV, op1, op2, getCurrentGuard(), TypeReference.Int);
}
break;
case JBC_ldiv:
{
clearCurrentGuard();
Operand op2 = popLong();
Operand op1 = popLong();
if (do_LongZeroCheck(op2)) {
break;
}
s = _guardedBinaryDualHelper(LONG_DIV, op1, op2, getCurrentGuard(), TypeReference.Long);
}
break;
case JBC_fdiv:
{
Operand op2 = popFloat();
Operand op1 = popFloat();
s = _binaryHelper(FLOAT_DIV, op1, op2, TypeReference.Float);
}
break;
case JBC_ddiv:
{
Operand op2 = popDouble();
Operand op1 = popDouble();
s = _binaryDualHelper(DOUBLE_DIV, op1, op2, TypeReference.Double);
}
break;
case JBC_irem:
{
clearCurrentGuard();
Operand op2 = popInt();
Operand op1 = popInt();
if (do_IntZeroCheck(op2)) {
break;
}
s = _guardedBinaryHelper(INT_REM, op1, op2, getCurrentGuard(), TypeReference.Int);
}
break;
case JBC_lrem:
{
clearCurrentGuard();
Operand op2 = popLong();
Operand op1 = popLong();
if (do_LongZeroCheck(op2)) {
break;
}
s = _guardedBinaryDualHelper(LONG_REM, op1, op2, getCurrentGuard(), TypeReference.Long);
}
break;
case JBC_frem:
{
Operand op2 = popFloat();
Operand op1 = popFloat();
s = _binaryHelper(FLOAT_REM, op1, op2, TypeReference.Float);
}
break;
case JBC_drem:
{
Operand op2 = popDouble();
Operand op1 = popDouble();
s = _binaryDualHelper(DOUBLE_REM, op1, op2, TypeReference.Double);
}
break;
case JBC_ineg:
s = _unaryHelper(INT_NEG, popInt(), TypeReference.Int);
break;
case JBC_lneg:
s = _unaryDualHelper(LONG_NEG, popLong(), TypeReference.Long);
break;
case JBC_fneg:
s = _unaryHelper(FLOAT_NEG, popFloat(), TypeReference.Float);
break;
case JBC_dneg:
s = _unaryDualHelper(DOUBLE_NEG, popDouble(), TypeReference.Double);
break;
case JBC_ishl:
{
Operand op2 = popShiftInt(false);
Operand op1 = popInt();
s = _binaryHelper(INT_SHL, op1, op2, TypeReference.Int);
}
break;
case JBC_lshl:
{
Operand op2 = popShiftInt(true);
Operand op1 = popLong();
s = _binaryDualHelper(LONG_SHL, op1, op2, TypeReference.Long);
}
break;
case JBC_ishr:
{
Operand op2 = popShiftInt(false);
Operand op1 = popInt();
s = _binaryHelper(INT_SHR, op1, op2, TypeReference.Int);
}
break;
case JBC_lshr:
{
Operand op2 = popShiftInt(true);
Operand op1 = popLong();
s = _binaryDualHelper(LONG_SHR, op1, op2, TypeReference.Long);
}
break;
case JBC_iushr:
{
Operand op2 = popShiftInt(false);
Operand op1 = popInt();
s = _binaryHelper(INT_USHR, op1, op2, TypeReference.Int);
}
break;
case JBC_lushr:
{
Operand op2 = popShiftInt(true);
Operand op1 = popLong();
s = _binaryDualHelper(LONG_USHR, op1, op2, TypeReference.Long);
}
break;
case JBC_iand:
{
Operand op2 = popInt();
Operand op1 = popInt();
s = _binaryHelper(INT_AND, op1, op2, TypeReference.Int);
}
break;
case JBC_land:
{
Operand op2 = popLong();
Operand op1 = popLong();
s = _binaryDualHelper(LONG_AND, op1, op2, TypeReference.Long);
}
break;
case JBC_ior:
{
Operand op2 = popInt();
Operand op1 = popInt();
s = _binaryHelper(INT_OR, op1, op2, TypeReference.Int);
}
break;
case JBC_lor:
{
Operand op2 = popLong();
Operand op1 = popLong();
s = _binaryDualHelper(LONG_OR, op1, op2, TypeReference.Long);
}
break;
case JBC_ixor:
{
Operand op2 = popInt();
Operand op1 = popInt();
s = _binaryHelper(INT_XOR, op1, op2, TypeReference.Int);
}
break;
case JBC_lxor:
{
Operand op2 = popLong();
Operand op1 = popLong();
s = _binaryDualHelper(LONG_XOR, op1, op2, TypeReference.Long);
}
break;
case JBC_iinc:
{
int index = bcodes.getLocalNumber();
s = do_iinc(index, bcodes.getIncrement());
}
break;
case JBC_i2l:
s = _unaryDualHelper(INT_2LONG, popInt(), TypeReference.Long);
break;
case JBC_i2f:
s = _unaryHelper(INT_2FLOAT, popInt(), TypeReference.Float);
break;
case JBC_i2d:
s = _unaryDualHelper(INT_2DOUBLE, popInt(), TypeReference.Double);
break;
case JBC_l2i:
s = _unaryHelper(LONG_2INT, popLong(), TypeReference.Int);
break;
case JBC_l2f:
s = _unaryHelper(LONG_2FLOAT, popLong(), TypeReference.Float);
break;
case JBC_l2d:
s = _unaryDualHelper(LONG_2DOUBLE, popLong(), TypeReference.Double);
break;
case JBC_f2i:
s = _unaryHelper(FLOAT_2INT, popFloat(), TypeReference.Int);
break;
case JBC_f2l:
s = _unaryDualHelper(FLOAT_2LONG, popFloat(), TypeReference.Long);
break;
case JBC_f2d:
s = _unaryDualHelper(FLOAT_2DOUBLE, popFloat(), TypeReference.Double);
break;
case JBC_d2i:
s = _unaryHelper(DOUBLE_2INT, popDouble(), TypeReference.Int);
break;
case JBC_d2l:
s = _unaryDualHelper(DOUBLE_2LONG, popDouble(), TypeReference.Long);
break;
case JBC_d2f:
s = _unaryHelper(DOUBLE_2FLOAT, popDouble(), TypeReference.Float);
break;
case JBC_int2byte:
s = _unaryHelper(INT_2BYTE, popInt(), TypeReference.Byte);
break;
case JBC_int2char:
s = _unaryHelper(INT_2USHORT, popInt(), TypeReference.Char);
break;
case JBC_int2short:
s = _unaryHelper(INT_2SHORT, popInt(), TypeReference.Short);
break;
case JBC_lcmp:
{
Operand op2 = popLong();
Operand op1 = popLong();
s = _binaryHelper(LONG_CMP, op1, op2, TypeReference.Int);
}
break;
case JBC_fcmpl:
{
Operand op2 = popFloat();
Operand op1 = popFloat();
s = _binaryHelper(FLOAT_CMPL, op1, op2, TypeReference.Int);
}
break;
case JBC_fcmpg:
{
Operand op2 = popFloat();
Operand op1 = popFloat();
s = _binaryHelper(FLOAT_CMPG, op1, op2, TypeReference.Int);
}
break;
case JBC_dcmpl:
{
Operand op2 = popDouble();
Operand op1 = popDouble();
s = _binaryHelper(DOUBLE_CMPL, op1, op2, TypeReference.Int);
}
break;
case JBC_dcmpg:
{
Operand op2 = popDouble();
Operand op1 = popDouble();
s = _binaryHelper(DOUBLE_CMPG, op1, op2, TypeReference.Int);
}
break;
case JBC_ifeq:
s = _intIfHelper(ConditionOperand.EQUAL());
break;
case JBC_ifne:
s = _intIfHelper(ConditionOperand.NOT_EQUAL());
break;
case JBC_iflt:
s = _intIfHelper(ConditionOperand.LESS());
break;
case JBC_ifge:
s = _intIfHelper(ConditionOperand.GREATER_EQUAL());
break;
case JBC_ifgt:
s = _intIfHelper(ConditionOperand.GREATER());
break;
case JBC_ifle:
s = _intIfHelper(ConditionOperand.LESS_EQUAL());
break;
case JBC_if_icmpeq:
s = _intIfCmpHelper(ConditionOperand.EQUAL());
break;
case JBC_if_icmpne:
s = _intIfCmpHelper(ConditionOperand.NOT_EQUAL());
break;
case JBC_if_icmplt:
s = _intIfCmpHelper(ConditionOperand.LESS());
break;
case JBC_if_icmpge:
s = _intIfCmpHelper(ConditionOperand.GREATER_EQUAL());
break;
case JBC_if_icmpgt:
s = _intIfCmpHelper(ConditionOperand.GREATER());
break;
case JBC_if_icmple:
s = _intIfCmpHelper(ConditionOperand.LESS_EQUAL());
break;
case JBC_if_acmpeq:
s = _refIfCmpHelper(ConditionOperand.EQUAL());
break;
case JBC_if_acmpne:
s = _refIfCmpHelper(ConditionOperand.NOT_EQUAL());
break;
case JBC_goto:
{
int offset = bcodes.getBranchOffset();
if (offset != 3) {
// skip generating frivolous goto's
s = _gotoHelper(offset);
}
}
break;
case JBC_jsr:
s = _jsrHelper(bcodes.getBranchOffset());
break;
case JBC_ret:
s = _retHelper(bcodes.getLocalNumber());
break;
case JBC_tableswitch:
{
bcodes.alignSwitch();
Operand op0 = popInt();
int defaultoff = bcodes.getDefaultSwitchOffset();
int low = bcodes.getLowSwitchValue();
int high = bcodes.getHighSwitchValue();
int number = high - low + 1;
if (CF_TABLESWITCH && op0 instanceof IntConstantOperand) {
int v1 = ((IntConstantOperand) op0).value;
int match = bcodes.computeTableSwitchOffset(v1, low, high);
int offset = match == 0 ? defaultoff : match;
bcodes.skipTableSwitchOffsets(number);
if (DBG_CF) {
db("changed tableswitch to goto because index (" + v1 + ") is constant");
}
s = _gotoHelper(offset);
break;
}
s = TableSwitch.create(TABLESWITCH, op0, null, null, new IntConstantOperand(low), new IntConstantOperand(high), generateTarget(defaultoff), null, number * 2);
for (int i = 0; i < number; ++i) {
TableSwitch.setTarget(s, i, generateTarget(bcodes.getTableSwitchOffset(i)));
}
bcodes.skipTableSwitchOffsets(number);
// Set branch probabilities
SwitchBranchProfile sp = gc.getSwitchProfile(instrIndex - bciAdjustment);
if (sp == null) {
// number targets + default
float approxProb = 1.0f / (number + 1);
TableSwitch.setDefaultBranchProfile(s, new BranchProfileOperand(approxProb));
for (int i = 0; i < number; ++i) {
TableSwitch.setBranchProfile(s, i, new BranchProfileOperand(approxProb));
}
} else {
TableSwitch.setDefaultBranchProfile(s, new BranchProfileOperand(sp.getDefaultProbability()));
for (int i = 0; i < number; ++i) {
TableSwitch.setBranchProfile(s, i, new BranchProfileOperand(sp.getCaseProbability(i)));
}
}
}
break;
case JBC_lookupswitch:
{
bcodes.alignSwitch();
Operand op0 = popInt();
int defaultoff = bcodes.getDefaultSwitchOffset();
int numpairs = bcodes.getSwitchLength();
if (numpairs == 0) {
s = _gotoHelper(defaultoff);
break;
}
if (CF_LOOKUPSWITCH && op0 instanceof IntConstantOperand) {
int v1 = ((IntConstantOperand) op0).value;
int match = bcodes.computeLookupSwitchOffset(v1, numpairs);
int offset = match == 0 ? defaultoff : match;
bcodes.skipLookupSwitchPairs(numpairs);
if (DBG_CF) {
db("changed lookupswitch to goto because index (" + v1 + ") is constant");
}
s = _gotoHelper(offset);
break;
}
// Construct switch
s = LookupSwitch.create(LOOKUPSWITCH, op0, null, null, generateTarget(defaultoff), null, numpairs * 3);
for (int i = 0; i < numpairs; ++i) {
LookupSwitch.setMatch(s, i, new IntConstantOperand(bcodes.getLookupSwitchValue(i)));
LookupSwitch.setTarget(s, i, generateTarget(bcodes.getLookupSwitchOffset(i)));
}
bcodes.skipLookupSwitchPairs(numpairs);
// Set branch probabilities
SwitchBranchProfile sp = gc.getSwitchProfile(instrIndex - bciAdjustment);
if (sp == null) {
// num targets + default
float approxProb = 1.0f / (numpairs + 1);
LookupSwitch.setDefaultBranchProfile(s, new BranchProfileOperand(approxProb));
for (int i = 0; i < numpairs; ++i) {
LookupSwitch.setBranchProfile(s, i, new BranchProfileOperand(approxProb));
}
} else {
LookupSwitch.setDefaultBranchProfile(s, new BranchProfileOperand(sp.getDefaultProbability()));
for (int i = 0; i < numpairs; ++i) {
LookupSwitch.setBranchProfile(s, i, new BranchProfileOperand(sp.getCaseProbability(i)));
}
}
}
break;
case JBC_ireturn:
_returnHelper(INT_MOVE, popInt());
break;
case JBC_lreturn:
_returnHelper(LONG_MOVE, popLong());
break;
case JBC_freturn:
_returnHelper(FLOAT_MOVE, popFloat());
break;
case JBC_dreturn:
_returnHelper(DOUBLE_MOVE, popDouble());
break;
case JBC_areturn:
{
Operand op0 = popRef();
if (VM.VerifyAssertions && !op0.isDefinitelyNull()) {
TypeReference retType = op0.getType();
assertIsAssignable(gc.getMethod().getReturnType(), retType);
}
_returnHelper(REF_MOVE, op0);
}
break;
case JBC_return:
_returnHelper(null, null);
break;
case JBC_getstatic:
{
// field resolution
FieldReference ref = bcodes.getFieldReference();
boolean unresolved = ref.needsDynamicLink(bcodes.getMethod());
LocationOperand fieldOp = makeStaticFieldRef(ref);
Operand offsetOp;
TypeReference fieldType = ref.getFieldContentsType();
RegisterOperand t = gc.getTemps().makeTemp(fieldType);
if (unresolved) {
RegisterOperand offsetrop = gc.getTemps().makeTempOffset();
appendInstruction(Unary.create(RESOLVE_MEMBER, offsetrop.copyRO(), fieldOp.copy()));
offsetOp = offsetrop;
rectifyStateWithErrorHandler();
} else {
RVMField field = ref.peekResolvedField();
offsetOp = new AddressConstantOperand(field.getOffset());
// use results of field analysis to refine type of result
RVMType ft = fieldType.peekType();
if (ft != null && ft.isClassType()) {
TypeReference concreteType = FieldAnalysis.getConcreteType(field);
if (concreteType != null) {
if (concreteType == fieldType) {
t.setDeclaredType();
t.setPreciseType();
} else {
fieldType = concreteType;
t.setPreciseType(concreteType);
}
}
}
// time.
if (gc.getOptions().SIMPLIFY_CHASE_FINAL_FIELDS && field.isFinal()) {
RVMClass declaringClass = field.getDeclaringClass();
boolean initializedClassAtRuntime = VM.runningVM & declaringClass.isInitialized();
boolean fieldFromRVMInternalClassInBootImage = declaringClass.isInBootImage() && declaringClass.getDescriptor().isRVMDescriptor();
// We cannot assume that non-public fields from the host JVM's class library are present in
// the class library used by Jikes RVM: only public fields are part of the API.
boolean publicFieldInBootImage = declaringClass.isInBootImage() && field.isPublic();
if (initializedClassAtRuntime || fieldFromRVMInternalClassInBootImage || publicFieldInBootImage) {
try {
ConstantOperand rhs = StaticFieldReader.getStaticFieldValue(field);
// VM.sysWriteln("Replaced getstatic of " + field + " with " + rhs);
push(rhs, fieldType);
break;
} catch (NoSuchFieldException e) {
if (VM.runningVM) {
throw new Error("Unexpected exception", e);
} else {
// Field not found during bootstrap due to chasing a field
// only valid in the bootstrap JVM.
// Although we try to avoid most cases where this could happen, we cannot
// avoid all. For example, a NoSuchFieldException can occur when we're trying
// to optimize a public field from Jikes RVM's class library that's not present
// in the host JVM's class library (example: a field from an internal
// helper class).
}
}
}
} else if (field.isRuntimeFinal()) {
if (VM.VerifyAssertions)
opt_assert(fieldType.isBooleanType());
boolean rhsBool = field.getRuntimeFinalValue();
push(new IntConstantOperand(rhsBool ? 1 : 0));
break;
}
}
s = GetStatic.create(GETSTATIC, t, offsetOp, fieldOp);
if (fieldOp.mayBeVolatile()) {
appendInstruction(s);
s = Empty.create(READ_CEILING);
}
push(t.copyD2U(), fieldType);
}
break;
case JBC_putstatic:
{
// field resolution
FieldReference ref = bcodes.getFieldReference();
boolean unresolved = ref.needsDynamicLink(bcodes.getMethod());
LocationOperand fieldOp = makeStaticFieldRef(ref);
Operand offsetOp;
if (unresolved) {
RegisterOperand offsetrop = gc.getTemps().makeTempOffset();
appendInstruction(Unary.create(RESOLVE_MEMBER, offsetrop.copyRO(), fieldOp.copy()));
offsetOp = offsetrop;
rectifyStateWithErrorHandler();
} else {
RVMField field = ref.peekResolvedField();
offsetOp = new AddressConstantOperand(field.getOffset());
}
TypeReference fieldType = ref.getFieldContentsType();
Operand r = pop(fieldType);
if (fieldOp.mayBeVolatile()) {
appendInstruction(Empty.create(WRITE_FLOOR));
}
s = PutStatic.create(PUTSTATIC, r, offsetOp, fieldOp);
if (fieldOp.mayBeVolatile()) {
appendInstruction(s);
s = Empty.create(FENCE);
}
}
break;
case JBC_getfield:
{
// field resolution
FieldReference ref = bcodes.getFieldReference();
boolean unresolved = ref.needsDynamicLink(bcodes.getMethod());
LocationOperand fieldOp = makeInstanceFieldRef(ref);
Operand offsetOp;
TypeReference fieldType = ref.getFieldContentsType();
RVMField field = null;
RegisterOperand t = gc.getTemps().makeTemp(fieldType);
if (unresolved) {
RegisterOperand offsetrop = gc.getTemps().makeTempOffset();
appendInstruction(Unary.create(RESOLVE_MEMBER, offsetrop.copyRO(), fieldOp.copy()));
offsetOp = offsetrop;
rectifyStateWithErrorHandler();
} else {
field = ref.peekResolvedField();
offsetOp = new AddressConstantOperand(field.getOffset());
// use results of field analysis to refine type.
RVMType ft = fieldType.peekType();
if (ft != null && ft.isClassType()) {
TypeReference concreteType = FieldAnalysis.getConcreteType(field);
if (concreteType != null) {
if (concreteType == fieldType) {
t.setDeclaredType();
t.setPreciseType();
} else {
fieldType = concreteType;
t.setType(concreteType);
t.setPreciseType();
}
}
}
}
Operand op1 = pop();
clearCurrentGuard();
if (do_NullCheck(op1)) {
break;
}
// NB avoid String fields
if (op1.isConstant() && field.isFinal()) {
try {
ConstantOperand rhs = StaticFieldReader.getFieldValueAsConstant(field, op1.asObjectConstant().value);
push(rhs, fieldType);
break;
} catch (NoSuchFieldException e) {
if (VM.runningVM) {
// this is unexpected
throw new Error("Unexpected exception", e);
} else {
// Field not found during bootstrap due to chasing a field
// only valid in the bootstrap JVM
}
}
}
s = GetField.create(GETFIELD, t, op1, offsetOp, fieldOp, getCurrentGuard());
if (fieldOp.mayBeVolatile()) {
appendInstruction(s);
s = Empty.create(READ_CEILING);
}
push(t.copyD2U(), fieldType);
}
break;
case JBC_putfield:
{
// field resolution
FieldReference ref = bcodes.getFieldReference();
boolean unresolved = ref.needsDynamicLink(bcodes.getMethod());
LocationOperand fieldOp = makeInstanceFieldRef(ref);
TypeReference fieldType = ref.getFieldContentsType();
Operand offsetOp;
if (unresolved) {
RegisterOperand offsetrop = gc.getTemps().makeTempOffset();
appendInstruction(Unary.create(RESOLVE_MEMBER, offsetrop.copyRO(), fieldOp.copy()));
offsetOp = offsetrop;
rectifyStateWithErrorHandler();
} else {
RVMField field = ref.peekResolvedField();
offsetOp = new AddressConstantOperand(field.getOffset());
}
Operand val = pop(fieldType);
Operand obj = popRef();
clearCurrentGuard();
if (do_NullCheck(obj)) {
break;
}
if (fieldOp.mayBeVolatile()) {
appendInstruction(Empty.create(WRITE_FLOOR));
}
s = PutField.create(PUTFIELD, val, obj, offsetOp, fieldOp, getCurrentGuard());
if (fieldOp.mayBeVolatile()) {
appendInstruction(s);
s = Empty.create(FENCE);
}
}
break;
case JBC_invokevirtual:
{
MethodReference ref = bcodes.getMethodReference();
// If it is, generate the inline code and we are done.
if (ref.isMagic()) {
boolean generated = GenerateMagic.generateMagic(this, gc, ref);
// all done.
if (generated)
break;
}
/* just create an osr barrier right before _callHelper
* changes the states of locals and stacks.
*/
if (this.osrGuardedInline) {
lastOsrBarrier = _createOsrBarrier();
}
if (ref.isMiranda()) {
// An invokevirtual that is really an invokeinterface.
s = _callHelper(ref, MethodOperand.INTERFACE(ref, null));
if (s == null)
break;
Operand receiver = Call.getParam(s, 0);
RVMClass receiverType = (RVMClass) receiver.getType().peekType();
// null check on this parameter of call
clearCurrentGuard();
if (do_NullCheck(receiver)) {
// call will always raise null pointer exception
s = null;
break;
}
Call.setGuard(s, getCurrentGuard());
// Attempt to resolve the interface call to a particular virtual method.
// This is independent of whether or not the static type of the receiver is
// known to implement the interface and it is not that case that being able
// to prove one implies the other.
RVMMethod vmeth = null;
if (receiverType != null && receiverType.isInitialized() && !receiverType.isInterface()) {
vmeth = ClassLoaderProxy.lookupMethod(receiverType, ref);
}
if (vmeth != null) {
MethodReference vmethRef = vmeth.getMemberRef().asMethodReference();
MethodOperand mop = MethodOperand.VIRTUAL(vmethRef, vmeth);
if (receiver.isConstant() || (receiver.isRegister() && receiver.asRegister().isPreciseType())) {
mop.refine(vmeth, true);
}
Call.setMethod(s, mop);
boolean unresolved = vmethRef.needsDynamicLink(bcodes.getMethod());
if (unresolved) {
RegisterOperand offsetrop = gc.getTemps().makeTempOffset();
appendInstruction(Unary.create(RESOLVE_MEMBER, offsetrop.copyRO(), Call.getMethod(s).copy()));
Call.setAddress(s, offsetrop);
rectifyStateWithErrorHandler();
} else {
Call.setAddress(s, new AddressConstantOperand(vmeth.getOffset()));
}
// Attempt to inline virtualized call.
if (maybeInlineMethod(shouldInline(s, receiver.isConstant() || (receiver.isRegister() && receiver.asRegister().isExtant()), instrIndex - bciAdjustment), s)) {
return;
}
}
} else {
// A normal invokevirtual. Create call instruction.
boolean unresolved = ref.needsDynamicLink(bcodes.getMethod());
RVMMethod target = ref.peekResolvedMethod();
MethodOperand methOp = MethodOperand.VIRTUAL(ref, target);
s = _callHelper(ref, methOp);
if (s == null)
break;
// Must be done before null_check!
if (unresolved) {
RegisterOperand offsetrop = gc.getTemps().makeTempOffset();
appendInstruction(Unary.create(RESOLVE_MEMBER, offsetrop.copyRO(), Call.getMethod(s).copy()));
Call.setAddress(s, offsetrop);
rectifyStateWithErrorHandler();
} else {
if (VM.VerifyAssertions)
opt_assert(target != null);
Call.setAddress(s, new AddressConstantOperand(target.getOffset()));
}
// null check receiver
Operand receiver = Call.getParam(s, 0);
clearCurrentGuard();
if (do_NullCheck(receiver)) {
// call will always raise null pointer exception
s = null;
break;
}
Call.setGuard(s, getCurrentGuard());
// Use compile time type of receiver to try reduce the number
// of targets.
// If we succeed, we'll update meth and s's method operand.
boolean isExtant = false;
boolean isPreciseType = false;
TypeReference tr = null;
if (receiver.isRegister()) {
RegisterOperand rop = receiver.asRegister();
isExtant = rop.isExtant();
isPreciseType = rop.isPreciseType();
tr = rop.getType();
} else {
isExtant = true;
isPreciseType = true;
tr = receiver.getType();
}
RVMType type = tr.peekType();
if (type != null && type.isResolved()) {
if (type.isClassType()) {
RVMMethod vmeth = target;
if (target == null || type != target.getDeclaringClass()) {
vmeth = ClassLoaderProxy.lookupMethod(type.asClass(), ref);
}
if (vmeth != null) {
methOp.refine(vmeth, isPreciseType || type.asClass().isFinal());
}
} else {
// Array: will always be calling the method defined in java.lang.Object
if (VM.VerifyAssertions)
opt_assert(target != null, "Huh? Target method must already be resolved if receiver is array");
methOp.refine(target, true);
}
}
// Consider inlining it.
if (maybeInlineMethod(shouldInline(s, isExtant, instrIndex - bciAdjustment), s)) {
return;
}
}
// noninlined CALL must be treated as potential throw of anything
rectifyStateWithExceptionHandlers();
}
break;
case JBC_invokespecial:
{
MethodReference ref = bcodes.getMethodReference();
RVMMethod target = ref.resolveInvokeSpecial();
/* just create an osr barrier right before _callHelper
* changes the states of locals and stacks.
*/
if (this.osrGuardedInline) {
lastOsrBarrier = _createOsrBarrier();
}
s = _callHelper(ref, MethodOperand.SPECIAL(ref, target));
if (s == null)
break;
// NOTE: different definition of unresolved due to semantics of invokespecial.
if (target == null) {
RegisterOperand offsetrop = gc.getTemps().makeTempOffset();
appendInstruction(Unary.create(RESOLVE_MEMBER, offsetrop.copyRO(), Call.getMethod(s).copy()));
Call.setAddress(s, offsetrop);
rectifyStateWithErrorHandler();
} else {
Call.setAddress(s, new AddressConstantOperand(target.getOffset()));
}
// null check receiver
Operand receiver = Call.getParam(s, 0);
clearCurrentGuard();
if (do_NullCheck(receiver)) {
// call will always raise null pointer exception
s = null;
break;
}
Call.setGuard(s, getCurrentGuard());
// Consider inlining it.
if (maybeInlineMethod(shouldInline(s, false, instrIndex - bciAdjustment), s)) {
return;
}
// noninlined CALL must be treated as potential throw of anything
rectifyStateWithExceptionHandlers();
}
break;
case JBC_invokestatic:
{
MethodReference ref = bcodes.getMethodReference();
// If it is, generate the inline code and we are done.
if (ref.isMagic()) {
boolean generated = GenerateMagic.generateMagic(this, gc, ref);
if (generated)
break;
}
// A non-magical invokestatic. Create call instruction.
boolean unresolved = ref.needsDynamicLink(bcodes.getMethod());
RVMMethod target = ref.peekResolvedMethod();
/* just create an osr barrier right before _callHelper
* changes the states of locals and stacks.
*/
if (this.osrGuardedInline) {
lastOsrBarrier = _createOsrBarrier();
}
s = _callHelper(ref, MethodOperand.STATIC(ref, target));
if (s == null)
break;
if (Call.conforms(s)) {
MethodOperand methOp = Call.getMethod(s);
if (methOp.getTarget() == target) {
// Handle possibility of dynamic linking.
if (unresolved) {
RegisterOperand offsetrop = gc.getTemps().makeTempOffset();
appendInstruction(Unary.create(RESOLVE_MEMBER, offsetrop.copyRO(), Call.getMethod(s).copy()));
Call.setAddress(s, offsetrop);
rectifyStateWithErrorHandler();
} else {
Call.setAddress(s, new AddressConstantOperand(target.getOffset()));
}
// Consider inlining it.
if (maybeInlineMethod(shouldInline(s, false, instrIndex - bciAdjustment), s)) {
return;
}
}
}
// noninlined CALL must be treated as potential throw of anything
rectifyStateWithExceptionHandlers();
}
break;
case JBC_invokeinterface:
{
MethodReference ref = bcodes.getMethodReference();
bcodes.alignInvokeInterface();
RVMMethod resolvedMethod = null;
resolvedMethod = ref.peekInterfaceMethod();
/* just create an osr barrier right before _callHelper
* changes the states of locals and stacks.
*/
if (this.osrGuardedInline) {
lastOsrBarrier = _createOsrBarrier();
}
s = _callHelper(ref, MethodOperand.INTERFACE(ref, resolvedMethod));
if (s == null)
break;
Operand receiver = Call.getParam(s, 0);
RVMClass receiverType = (RVMClass) receiver.getType().peekType();
boolean requiresImplementsTest = VM.BuildForIMTInterfaceInvocation;
// that it is not needed.
if (requiresImplementsTest && resolvedMethod == null) {
// Sigh. Can't even resolve the reference to figure out what interface
// method we are trying to call. Therefore we must make generate a call
// to an out-of-line typechecking routine to handle it at runtime.
RVMMethod target = Entrypoints.unresolvedInvokeinterfaceImplementsTestMethod;
Instruction callCheck = Call.create2(CALL, null, new AddressConstantOperand(target.getOffset()), MethodOperand.STATIC(target), new IntConstantOperand(ref.getId()), receiver.copy());
if (gc.getOptions().H2L_NO_CALLEE_EXCEPTIONS) {
callCheck.markAsNonPEI();
}
appendInstruction(callCheck);
callCheck.setBytecodeIndex(RUNTIME_SERVICES_BCI);
// the above call subsumes the test
requiresImplementsTest = false;
// Can raise incompatible class change error.
rectifyStateWithErrorHandler();
}
// null check on this parameter of call. Must be done after dynamic linking!
clearCurrentGuard();
if (do_NullCheck(receiver)) {
// call will always raise null pointer exception
s = null;
break;
}
Call.setGuard(s, getCurrentGuard());
if (requiresImplementsTest) {
// We know what interface method the program wants to invoke.
// Attempt to avoid inserting the type check by seeing if the
// known static type of the receiver implements the desired interface.
RVMType interfaceType = resolvedMethod.getDeclaringClass();
if (receiverType != null && receiverType.isResolved() && !receiverType.isInterface()) {
byte doesImplement = ClassLoaderProxy.includesType(interfaceType.getTypeRef(), receiverType.getTypeRef());
requiresImplementsTest = doesImplement != YES;
}
}
// Attempt to resolve the interface call to a particular virtual method.
// This is independent of whether or not the static type of the receiver is
// known to implement the interface and it is not that case that being able
// to prove one implies the other.
RVMMethod vmeth = null;
if (receiverType != null && receiverType.isInitialized() && !receiverType.isInterface()) {
vmeth = ClassLoaderProxy.lookupMethod(receiverType, ref);
}
if (vmeth != null) {
MethodReference vmethRef = vmeth.getMemberRef().asMethodReference();
// Note that at this point requiresImplementsTest => resolvedMethod != null
if (requiresImplementsTest) {
RegisterOperand checkedReceiver = gc.getTemps().makeTemp(receiver);
appendInstruction(TypeCheck.create(MUST_IMPLEMENT_INTERFACE, checkedReceiver, receiver.copy(), makeTypeOperand(resolvedMethod.getDeclaringClass()), getCurrentGuard()));
checkedReceiver.refine(resolvedMethod.getDeclaringClass().getTypeRef());
Call.setParam(s, 0, checkedReceiver.copyRO());
receiver = checkedReceiver;
// Can raise incompatible class change error.
rectifyStateWithErrorHandler();
}
MethodOperand mop = MethodOperand.VIRTUAL(vmethRef, vmeth);
if (receiver.isConstant() || receiver.asRegister().isPreciseType()) {
mop.refine(vmeth, true);
}
Call.setMethod(s, mop);
boolean unresolved = vmethRef.needsDynamicLink(bcodes.getMethod());
if (unresolved) {
RegisterOperand offsetrop = gc.getTemps().makeTempOffset();
appendInstruction(Unary.create(RESOLVE_MEMBER, offsetrop.copyRO(), Call.getMethod(s).copy()));
Call.setAddress(s, offsetrop);
rectifyStateWithErrorHandler();
} else {
Call.setAddress(s, new AddressConstantOperand(vmeth.getOffset()));
}
// Attempt to inline virtualized call.
if (maybeInlineMethod(shouldInline(s, receiver.isConstant() || receiver.asRegister().isExtant(), instrIndex - bciAdjustment), s)) {
return;
}
} else {
// inline code will include DTC to ensure receiver implements the interface.
if (resolvedMethod != null && maybeInlineMethod(shouldInline(s, false, instrIndex - bciAdjustment), s)) {
return;
} else {
if (requiresImplementsTest) {
RegisterOperand checkedReceiver = gc.getTemps().makeTemp(receiver);
appendInstruction(TypeCheck.create(MUST_IMPLEMENT_INTERFACE, checkedReceiver, receiver.copy(), makeTypeOperand(resolvedMethod.getDeclaringClass()), getCurrentGuard()));
checkedReceiver.refine(resolvedMethod.getDeclaringClass().getTypeRef());
Call.setParam(s, 0, checkedReceiver.copyRO());
// don't have to rectify with error handlers; rectify call below subsumes.
}
}
}
// CALL must be treated as potential throw of anything
rectifyStateWithExceptionHandlers();
}
break;
case JBC_invokedynamic:
OptimizingCompilerException.UNREACHABLE();
break;
case JBC_new:
{
TypeReference klass = bcodes.getTypeReference();
RegisterOperand t = gc.getTemps().makeTemp(klass);
t.setPreciseType();
markGuardlessNonNull(t);
Operator operator;
TypeOperand klassOp;
RVMClass klassType = (RVMClass) klass.peekType();
if (klassType != null && (klassType.isInitialized() || klassType.isInBootImage())) {
klassOp = makeTypeOperand(klassType);
operator = NEW;
t.setExtant();
} else {
operator = NEW_UNRESOLVED;
klassOp = makeTypeOperand(klass);
}
s = New.create(operator, t, klassOp);
push(t.copyD2U());
rectifyStateWithErrorHandler();
}
break;
case JBC_newarray:
{
RVMType array = bcodes.getPrimitiveArrayType();
TypeOperand arrayOp = makeTypeOperand(array);
RegisterOperand t = gc.getTemps().makeTemp(array.getTypeRef());
t.setPreciseType();
t.setExtant();
markGuardlessNonNull(t);
s = NewArray.create(NEWARRAY, t, arrayOp, popInt());
push(t.copyD2U());
rectifyStateWithExceptionHandler(TypeReference.JavaLangNegativeArraySizeException);
}
break;
case JBC_anewarray:
{
TypeReference elementTypeRef = bcodes.getTypeReference();
s = generateAnewarray(null, elementTypeRef);
}
break;
case JBC_arraylength:
{
Operand op1 = pop();
clearCurrentGuard();
if (do_NullCheck(op1)) {
break;
}
if (VM.VerifyAssertions) {
opt_assert(getArrayTypeOf(op1).isArrayType());
}
RegisterOperand t = gc.getTemps().makeTempInt();
s = GuardedUnary.create(ARRAYLENGTH, t, op1, getCurrentGuard());
push(t.copyD2U());
}
break;
case JBC_athrow:
{
Operand op0 = pop();
clearCurrentGuard();
if (do_NullCheck(op0)) {
break;
}
TypeReference type = getRefTypeOf(op0);
if (VM.VerifyAssertions)
assertIsAssignable(TypeReference.JavaLangThrowable, type);
if (!gc.getMethod().isInterruptible()) {
// prevent code motion in or out of uninterruptible code sequence
appendInstruction(Empty.create(UNINT_END));
}
endOfBasicBlock = true;
BasicBlock definiteTarget = rectifyStateWithExceptionHandler(type, true);
if (definiteTarget != null) {
appendInstruction(CacheOp.create(SET_CAUGHT_EXCEPTION, op0));
s = Goto.create(GOTO, definiteTarget.makeJumpTarget());
definiteTarget.setExceptionHandlerWithNormalIn();
} else {
s = Athrow.create(ATHROW, op0);
}
}
break;
case JBC_checkcast:
{
TypeReference typeRef = bcodes.getTypeReference();
boolean classLoading = couldCauseClassLoading(typeRef);
Operand op2 = pop();
if (typeRef.isWordLikeType()) {
op2 = op2.copy();
if (op2 instanceof RegisterOperand) {
((RegisterOperand) op2).setType(typeRef);
}
push(op2);
if (DBG_CF)
db("skipped gen of checkcast to word type " + typeRef);
break;
}
if (VM.VerifyAssertions)
opt_assert(op2.isRef());
if (CF_CHECKCAST && !classLoading) {
if (op2.isDefinitelyNull()) {
push(op2);
if (DBG_CF)
db("skipped gen of null checkcast");
break;
}
// non-null, null case above
TypeReference type = getRefTypeOf(op2);
byte typeTestResult = ClassLoaderProxy.includesType(typeRef, type);
if (typeTestResult == YES) {
push(op2);
if (DBG_CF) {
db("skipped gen of checkcast of " + op2 + " from " + typeRef + " to " + type);
}
break;
}
if (typeTestResult == NO) {
if (isNonNull(op2)) {
// Definite class cast exception
endOfBasicBlock = true;
appendInstruction(Trap.create(TRAP, gc.getTemps().makeTempValidation(), TrapCodeOperand.CheckCast()));
rectifyStateWithExceptionHandler(TypeReference.JavaLangClassCastException);
if (DBG_CF)
db("Converted checkcast into unconditional trap");
break;
} else {
// At runtime either it is null and the checkcast succeeds or it is non-null
// and a class cast exception is raised
RegisterOperand refinedOp2 = gc.getTemps().makeTemp(op2);
s = TypeCheck.create(CHECKCAST, refinedOp2, op2.copy(), makeTypeOperand(typeRef.peekType()));
refinedOp2.refine(TypeReference.NULL_TYPE);
push(refinedOp2.copyRO());
rectifyStateWithExceptionHandler(TypeReference.JavaLangClassCastException);
if (DBG_CF)
db("Narrowed type downstream of checkcast to NULL");
break;
}
}
}
RegisterOperand refinedOp2 = gc.getTemps().makeTemp(op2);
if (classLoading) {
s = TypeCheck.create(CHECKCAST_UNRESOLVED, refinedOp2, op2.copy(), makeTypeOperand(typeRef));
} else {
TypeOperand typeOp = makeTypeOperand(typeRef.peekType());
if (isNonNull(op2)) {
s = TypeCheck.create(CHECKCAST_NOTNULL, refinedOp2, op2.copy(), typeOp, copyGuardFromOperand(op2));
} else {
s = TypeCheck.create(CHECKCAST, refinedOp2, op2.copy(), typeOp);
}
}
refinedOp2.refine(typeRef);
push(refinedOp2.copyRO());
rectifyStateWithExceptionHandler(TypeReference.JavaLangClassCastException);
if (classLoading)
rectifyStateWithErrorHandler();
}
break;
case JBC_instanceof:
{
TypeReference typeRef = bcodes.getTypeReference();
boolean classLoading = couldCauseClassLoading(typeRef);
Operand op2 = pop();
if (VM.VerifyAssertions)
opt_assert(op2.isRef());
if (CF_INSTANCEOF && !classLoading) {
if (op2.isDefinitelyNull()) {
push(new IntConstantOperand(0));
if (DBG_CF)
db("skipped gen of null instanceof");
break;
}
// non-null
TypeReference type = getRefTypeOf(op2);
int answer = ClassLoaderProxy.includesType(typeRef, type);
if (answer == YES && isNonNull(op2)) {
push(new IntConstantOperand(1));
if (DBG_CF) {
db(op2 + " instanceof " + typeRef + " is always true ");
}
break;
} else if (answer == NO) {
if (DBG_CF) {
db(op2 + " instanceof " + typeRef + " is always false ");
}
push(new IntConstantOperand(0));
break;
}
}
RegisterOperand t = gc.getTemps().makeTempInt();
if (classLoading) {
s = InstanceOf.create(INSTANCEOF_UNRESOLVED, t, makeTypeOperand(typeRef), op2);
} else {
TypeOperand typeOp = makeTypeOperand(typeRef.peekType());
if (isNonNull(op2)) {
s = InstanceOf.create(INSTANCEOF_NOTNULL, t, typeOp, op2, copyGuardFromOperand(op2));
} else {
s = InstanceOf.create(INSTANCEOF, t, typeOp, op2);
}
}
push(t.copyD2U());
if (classLoading)
rectifyStateWithErrorHandler();
}
break;
case JBC_monitorenter:
{
Operand op0 = pop();
clearCurrentGuard();
if (do_NullCheck(op0)) {
break;
}
if (VM.VerifyAssertions)
opt_assert(op0.isRef());
s = MonitorOp.create(MONITORENTER, op0, getCurrentGuard());
}
break;
case JBC_monitorexit:
{
Operand op0 = pop();
clearCurrentGuard();
if (do_NullCheck(op0)) {
break;
}
s = MonitorOp.create(MONITOREXIT, op0, getCurrentGuard());
rectifyStateWithExceptionHandler(TypeReference.JavaLangIllegalMonitorStateException);
}
break;
case JBC_wide:
{
int widecode = bcodes.getWideOpcode();
int index = bcodes.getWideLocalNumber();
switch(widecode) {
case JBC_iload:
s = do_iload(index);
break;
case JBC_lload:
s = do_lload(index);
break;
case JBC_fload:
s = do_fload(index);
break;
case JBC_dload:
s = do_dload(index);
break;
case JBC_aload:
s = do_aload(index);
break;
case JBC_istore:
s = do_store(index, popInt());
break;
case JBC_lstore:
s = do_store(index, popLong());
break;
case JBC_fstore:
s = do_store(index, popFloat());
break;
case JBC_dstore:
s = do_store(index, popDouble());
break;
case JBC_astore:
s = do_astore(index);
break;
case JBC_iinc:
s = do_iinc(index, bcodes.getWideIncrement());
break;
case JBC_ret:
s = _retHelper(index);
break;
default:
OptimizingCompilerException.UNREACHABLE();
break;
}
}
break;
case JBC_multianewarray:
{
TypeReference arrayType = bcodes.getTypeReference();
int dimensions = bcodes.getArrayDimension();
if (dimensions == 1) {
s = generateAnewarray(arrayType, null);
} else {
TypeOperand typeOp = makeTypeOperand(arrayType);
RegisterOperand result = gc.getTemps().makeTemp(arrayType);
markGuardlessNonNull(result);
result.setPreciseType();
TypeReference innermostElementTypeRef = arrayType.getInnermostElementType();
RVMType innermostElementType = innermostElementTypeRef.peekType();
if (innermostElementType != null && (innermostElementType.isInitialized() || innermostElementType.isInBootImage())) {
result.setExtant();
}
s = Multianewarray.create(NEWOBJMULTIARRAY, result, typeOp, dimensions);
for (int i = 0; i < dimensions; i++) {
Multianewarray.setDimension(s, dimensions - i - 1, popInt());
}
push(result.copyD2U());
rectifyStateWithErrorHandler();
rectifyStateWithExceptionHandler(TypeReference.JavaLangNegativeArraySizeException);
}
}
break;
case JBC_ifnull:
s = _refIfNullHelper(ConditionOperand.EQUAL());
break;
case JBC_ifnonnull:
s = _refIfNullHelper(ConditionOperand.NOT_EQUAL());
break;
case JBC_goto_w:
{
int offset = bcodes.getWideBranchOffset();
if (offset != 5) {
// skip generating frivolous goto's
s = _gotoHelper(offset);
}
}
break;
case JBC_jsr_w:
s = _jsrHelper(bcodes.getWideBranchOffset());
break;
case JBC_impdep1:
{
if (VM.BuildForAdaptiveSystem) {
int pseudo_opcode = bcodes.nextPseudoInstruction();
switch(pseudo_opcode) {
case PSEUDO_LoadIntConst:
{
int value = bcodes.readIntConst();
if (VM.TraceOnStackReplacement) {
VM.sysWriteln("PSEUDO_LoadIntConst " + value);
}
push(new IntConstantOperand(value));
// used for PSEUDO_InvokeStatic to recover the type info
param1 = param2;
param2 = value;
break;
}
case PSEUDO_LoadLongConst:
{
long value = bcodes.readLongConst();
if (VM.TraceOnStackReplacement) {
VM.sysWriteln("PSEUDO_LoadLongConst " + value);
}
pushDual(new LongConstantOperand(value));
break;
}
case PSEUDO_LoadWordConst:
{
Address a = (VM.BuildFor32Addr) ? Address.fromIntSignExtend(bcodes.readIntConst()) : Address.fromLong(bcodes.readLongConst());
push(new AddressConstantOperand(a));
if (VM.TraceOnStackReplacement) {
VM.sysWrite("PSEUDO_LoadWordConst 0x");
}
VM.sysWrite(a);
VM.sysWriteln();
break;
}
case PSEUDO_LoadFloatConst:
{
int ibits = bcodes.readIntConst();
float value = Float.intBitsToFloat(ibits);
if (VM.TraceOnStackReplacement) {
VM.sysWriteln("PSEUDO_LoadFloatConst " + value);
}
push(new FloatConstantOperand(value, Offset.zero()));
break;
}
case PSEUDO_LoadDoubleConst:
{
long lbits = bcodes.readLongConst();
double value = Magic.longBitsAsDouble(lbits);
if (VM.TraceOnStackReplacement) {
VM.sysWriteln("PSEUDO_LoadDoubleConst " + lbits);
}
pushDual(new DoubleConstantOperand(value, Offset.zero()));
break;
}
case PSEUDO_LoadRetAddrConst:
{
int value = bcodes.readIntConst();
if (VM.TraceOnStackReplacement) {
VM.sysWriteln("PSEUDO_LoadRetAddrConst " + value);
}
push(new ReturnAddressOperand(value));
break;
}
case PSEUDO_InvokeStatic:
{
/* pseudo invoke static for getRefAt and cleanRefAt, both must be resolved already */
int targetidx = bcodes.readIntConst();
RVMMethod meth = InvokeStatic.targetMethod(targetidx);
if (VM.TraceOnStackReplacement) {
VM.sysWriteln("PSEUDO_Invoke " + meth);
VM.sysWriteln();
}
s = _callHelper(meth.getMemberRef().asMethodReference(), MethodOperand.STATIC(meth));
if (s == null)
break;
Call.setAddress(s, new AddressConstantOperand(meth.getOffset()));
/* try to set the type of return register */
if (targetidx == GETREFAT) {
Object realObj = ObjectHolder.getRefAt(param1, param2);
if (VM.VerifyAssertions)
opt_assert(realObj != null);
TypeReference klass = Magic.getObjectType(realObj).getTypeRef();
RegisterOperand op0 = gc.getTemps().makeTemp(klass);
Call.setResult(s, op0);
// pop the old one and push the new return type.
pop();
push(op0.copyD2U(), klass);
}
// CALL must be treated as potential throw of anything
rectifyStateWithExceptionHandlers();
break;
}
case PSEUDO_InvokeCompiledMethod:
{
int cmid = bcodes.readIntConst();
// skip it
int origBCIdx = bcodes.readIntConst();
CompiledMethod cm = CompiledMethods.getCompiledMethod(cmid);
RVMMethod meth = cm.getMethod();
if (VM.TraceOnStackReplacement) {
VM.sysWriteln("PSEUDO_InvokeCompiledMethod " + meth);
VM.sysWriteln();
}
/* the bcIndex should be adjusted to the original */
s = _callHelper(meth.getMemberRef().asMethodReference(), MethodOperand.COMPILED(meth, cm.getOsrJTOCoffset()));
if (s == null)
break;
// adjust the bcindex of s to the original bytecode's index
// it should be able to give the correct exception handling
s.adjustBytecodeIndex(bciAdjustment);
rectifyStateWithExceptionHandlers();
break;
}
case PSEUDO_ParamInitEnd:
{
break;
}
default:
if (VM.TraceOnStackReplacement) {
VM.sysWriteln("OSR Error, no such pseudo opcode : " + pseudo_opcode);
}
OptimizingCompilerException.UNREACHABLE();
break;
}
break;
} else {
OptimizingCompilerException.UNREACHABLE();
}
}
default:
OptimizingCompilerException.UNREACHABLE();
break;
}
if (s != null && !currentBBLE.isSelfRegen()) {
appendInstruction(s);
}
// check runoff
if (VM.VerifyAssertions)
opt_assert(bcodes.index() <= runoff);
if (!endOfBasicBlock && bcodes.index() == runoff) {
if (DBG_BB || DBG_SELECTED) {
db("runoff occurred! current basic block: " + currentBBLE + ", runoff = " + runoff);
}
endOfBasicBlock = fallThrough = true;
}
if (endOfBasicBlock) {
if (currentBBLE.isSelfRegen()) {
// This block ended in a goto that jumped into the middle of it.
// Through away all out edges from this block, they're out of date
// because we're going to have to regenerate this block.
currentBBLE.block.deleteOut();
if (DBG_CFG || DBG_SELECTED) {
db("Deleted all out edges of " + currentBBLE.block);
}
return;
}
if (fallThrough) {
if (VM.VerifyAssertions)
opt_assert(bcodes.index() < bcodes.length());
// Get/Create fallthrough BBLE and record it as
// currentBBLE's fallThrough.
currentBBLE.fallThrough = getOrCreateBlock(bcodes.index());
currentBBLE.block.insertOut(currentBBLE.fallThrough.block);
}
return;
}
}
}
use of org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand in project JikesRVM by JikesRVM.
the class CallingConvention method alignStackForX64SysCall.
public static void alignStackForX64SysCall(Instruction call, IR ir, int parameterBytes, Instruction requireESP, Instruction adviseESP) {
BasicBlock originalBlockForCall = call.getBasicBlock();
// Search marker instruction
Instruction currentInst = requireESP;
do {
currentInst = currentInst.prevInstructionInCodeOrder();
if (currentInst.getOpcode() == REQUIRE_ESP_opcode && MIR_UnaryNoRes.getVal(currentInst).asIntConstant().value == MARKER) {
break;
}
} while (!(currentInst.getOpcode() == LABEL_opcode));
if (VM.VerifyAssertions)
VM._assert(currentInst != null);
if (VM.VerifyAssertions)
VM._assert(currentInst.getBasicBlock() == originalBlockForCall);
if (VM.VerifyAssertions)
VM._assert(currentInst.getOpcode() == REQUIRE_ESP_opcode);
Instruction marker = currentInst;
// Leave everything before the marker in the original block and move the rest to test block
BasicBlock testBlock = originalBlockForCall.splitNodeWithLinksAt(marker, ir);
// originalBlockForCall now has only code preceding the call,
// testBlock has call code and subsequent code
marker.remove();
// make testBlock empty
BasicBlock newBlockForCall = testBlock.splitNodeWithLinksAt(testBlock.firstInstruction(), ir);
// testBlock is now empty, newBlockForCall has the call and subsequent code
// Move everything after the call to a new block
BasicBlock callBlockRest = newBlockForCall.splitNodeWithLinksAt(adviseESP, ir);
// newBlockForCall now has the call and advise_esp / require_esp, subsequent code is in callBlockRest
BasicBlock copiedBlock = newBlockForCall.copyWithoutLinks(ir);
ir.cfg.addLastInCodeOrder(copiedBlock);
copiedBlock.appendInstruction(MIR_Branch.create(IA32_JMP, callBlockRest.makeJumpTarget()));
copiedBlock.recomputeNormalOut(ir);
// Set up test block for checking stack alignment before the call
Register espReg = ir.regpool.getPhysicalRegisterSet().asIA32().getESP();
Instruction requireEspCheck = MIR_UnaryNoRes.create(REQUIRE_ESP, IC(parameterBytes));
testBlock.appendInstruction(requireEspCheck);
Instruction spTest = MIR_Test.create(IA32_TEST, new RegisterOperand(espReg, TypeReference.Word), IC(8));
testBlock.appendInstruction(spTest);
Instruction jcc = MIR_CondBranch.create(IA32_JCC, IA32ConditionOperand.NE(), copiedBlock.makeJumpTarget(), new BranchProfileOperand());
testBlock.appendInstruction(jcc);
testBlock.recomputeNormalOut(ir);
// modify ESP in the copied block to ensure correct alignment
// when the original alignment would be incorrect. That's accomplished
// by adjusting the ESP downwards (i.e. towards the top of the stack, growing the stack).
Enumeration<Instruction> copiedInsts = copiedBlock.forwardRealInstrEnumerator();
while (copiedInsts.hasMoreElements()) {
Instruction inst = copiedInsts.nextElement();
if (inst.getOpcode() == REQUIRE_ESP_opcode || inst.getOpcode() == ADVISE_ESP_opcode) {
int val = MIR_UnaryNoRes.getVal(inst).asIntConstant().value;
MIR_UnaryNoRes.setVal(inst, IC(val - WORDSIZE));
}
}
}
use of org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand in project JikesRVM by JikesRVM.
the class GenerateMagic method _cmpHelper.
private static Instruction _cmpHelper(BC2IR bc2ir, GenerationContext gc, ConditionOperand cond, Operand given_o2) {
Operand o2 = given_o2 == null ? bc2ir.pop() : given_o2;
Operand o1 = bc2ir.pop();
RegisterOperand res = gc.getTemps().makeTempInt();
Instruction s = BooleanCmp.create(BOOLEAN_CMP_ADDR, res, o1, o2, cond, new BranchProfileOperand());
Simplifier.DefUseEffect simp = Simplifier.simplify(true, gc.getTemps(), gc.getOptions(), s);
if ((simp == Simplifier.DefUseEffect.MOVE_FOLDED) || (simp == Simplifier.DefUseEffect.MOVE_REDUCED)) {
gc.getTemps().release(res);
bc2ir.push(Move.getClearVal(s));
return null;
} else {
bc2ir.push(res.copyD2U());
return s;
}
}
Aggregations