use of org.jikesrvm.compilers.opt.ir.Operator in project JikesRVM by JikesRVM.
the class Simplifier method multiplyByConstant.
private static DefUseEffect multiplyByConstant(AbstractRegisterPool regpool, Instruction s, Operand op1, Operand op2, OptOptions opts) {
Operator addOperator, moveOperator, negateOperator, shiftLeftOperator;
ConstantOperand zero;
long val2;
int numBits;
if (op2.isIntConstant()) {
val2 = op2.asIntConstant().value;
addOperator = INT_ADD;
moveOperator = INT_MOVE;
negateOperator = INT_NEG;
shiftLeftOperator = INT_SHL;
zero = IntConstantOperand.zero;
numBits = 32;
} else {
val2 = op2.asLongConstant().value;
addOperator = LONG_ADD;
moveOperator = LONG_MOVE;
negateOperator = LONG_NEG;
shiftLeftOperator = LONG_SHL;
zero = LongConstantOperand.zero;
numBits = 64;
}
// ATTEMPT TO APPLY AXIOMS
if (val2 == 0) {
// x * 0 == 0
Move.mutate(s, moveOperator, Binary.getClearResult(s), zero.copy());
return DefUseEffect.MOVE_FOLDED;
} else if (numBits == 32 && ((int) val2 == ((int) -val2))) {
// x * MIN_INT == x << 31
Binary.mutate(s, INT_SHL, Binary.getClearResult(s), op1, IC(31));
return DefUseEffect.REDUCED;
} else if (numBits == 64 && val2 == -val2) {
// x * MIN_LONG == x << 63
Binary.mutate(s, LONG_SHL, Binary.getClearResult(s), op1, IC(63));
return DefUseEffect.REDUCED;
}
// Try to reduce x*c into shift and adds, but only if cost is cheap
if (s.hasPrev()) {
// don't attempt to reduce if this instruction isn't
// part of a well-formed sequence
// Cost of shift and add replacement
int cost = 0;
boolean negative = val2 < 0;
if (negative) {
val2 = -val2;
cost++;
}
if (VM.BuildForIA32 && numBits <= BITS_IN_ADDRESS) {
int lastShift = 0;
boolean lastShiftWasShort = false;
for (int i = 1; i < numBits; i++) {
if ((val2 & (1L << i)) != 0) {
// the original operand)
if (i < 4) {
// can use LEA of operand
cost++;
} else if ((i - lastShift) < 4 && !lastShiftWasShort) {
// can use LEA of last shift
cost++;
lastShiftWasShort = true;
} else {
// need separate shift and add
cost += 2;
lastShiftWasShort = false;
}
lastShift = i;
}
}
} else if (numBits > BITS_IN_ADDRESS) {
for (int i = 1; i < BITS_IN_ADDRESS; i++) {
if ((val2 & (1L << i)) != 0) {
// each 1 requires a shift and add
cost += 2;
}
}
for (int i = BITS_IN_ADDRESS; i < numBits; i++) {
if ((val2 & (1L << i)) != 0) {
// when the shift is > than the bits in the address we can just 0
// the bottom word, make the cost cheaper
cost++;
}
}
} else {
for (int i = 1; i < numBits; i++) {
if ((val2 & (1L << i)) != 0) {
// each 1 requires a shift and add
cost += 2;
}
}
}
int targetCost;
if (VM.BuildForIA32) {
targetCost = numBits == 64 ? 6 : 4;
} else {
targetCost = 2;
}
if (cost <= targetCost) {
// generate shift and adds
RegisterOperand val1Operand = op1.copy().asRegister();
RegisterOperand resultOperand = numBits == 32 ? regpool.makeTempInt() : regpool.makeTempLong();
Instruction move;
if ((val2 & 1) == 1) {
// result = val1 * 1
move = Move.create(moveOperator, resultOperand, val1Operand);
} else {
// result = 0
move = Move.create(moveOperator, resultOperand, zero.copy());
}
move.copyPosition(s);
s.insertBefore(move);
int lastShift = 0;
RegisterOperand lastShiftResult = null;
boolean lastShiftWasShort = false;
for (int i = 1; i < numBits; i++) {
if ((val2 & (1L << i)) != 0) {
Instruction shift;
RegisterOperand shiftResult = numBits == 32 ? regpool.makeTempInt() : regpool.makeTempLong();
if (VM.BuildForIA32 && numBits <= BITS_IN_ADDRESS && lastShiftResult != null && ((i - lastShift) <= 3) && (i > 3) && !lastShiftWasShort) {
// We can produce a short shift (1, 2 or 3) using the result of the last shift
shift = Binary.create(shiftLeftOperator, shiftResult, lastShiftResult.copyRO(), IC(i - lastShift));
lastShiftWasShort = true;
} else {
shift = Binary.create(shiftLeftOperator, shiftResult, val1Operand.copyRO(), IC(i));
lastShiftWasShort = false;
}
shift.copyPosition(s);
s.insertBefore(shift);
lastShiftResult = shiftResult;
lastShift = i;
RegisterOperand addResult = numBits == 32 ? regpool.makeTempInt() : regpool.makeTempLong();
Instruction add = Binary.create(addOperator, addResult, resultOperand.copyRO(), shiftResult.copyRO());
add.copyPosition(s);
s.insertBefore(add);
resultOperand = addResult;
}
}
if (negative) {
Unary.mutate(s, negateOperator, Binary.getClearResult(s), resultOperand.copyRO());
} else {
Move.mutate(s, moveOperator, Binary.getClearResult(s), resultOperand.copyRO());
}
return DefUseEffect.REDUCED;
}
}
return DefUseEffect.UNCHANGED;
}
use of org.jikesrvm.compilers.opt.ir.Operator in project JikesRVM by JikesRVM.
the class BC2IR method _intIfHelper.
// helper function for if?? bytecodes
private Instruction _intIfHelper(ConditionOperand cond) {
int offset = bcodes.getBranchOffset();
Operand op0 = popInt();
if (offset == 3) {
// remove frivolous IFs
return null;
}
if (CF_INTIF && op0 instanceof IntConstantOperand) {
int c = cond.evaluate(((IntConstantOperand) op0).value, 0);
if (c == ConditionOperand.TRUE) {
if (DBG_CF) {
db(cond + ": changed branch to goto because predicate (" + op0 + ") is constant true");
}
return _gotoHelper(offset);
} else if (c == ConditionOperand.FALSE) {
if (DBG_CF) {
db(cond + ": eliminated branch because predicate (" + op0 + ") is constant false");
}
return null;
}
}
fallThrough = true;
if (!(op0 instanceof RegisterOperand)) {
if (DBG_CF)
db("generated int_ifcmp of " + op0 + " with 0");
RegisterOperand guard = gc.getTemps().makeTempValidation();
return IfCmp.create(INT_IFCMP, guard, op0, new IntConstantOperand(0), cond, generateTarget(offset), gc.getConditionalBranchProfileOperand(instrIndex - bciAdjustment, offset < 0));
}
RegisterOperand val = (RegisterOperand) op0;
BranchOperand branch = null;
if (lastInstr != null) {
switch(lastInstr.getOpcode()) {
case INSTANCEOF_opcode:
case INSTANCEOF_UNRESOLVED_opcode:
{
if (DBG_TYPE)
db("last instruction was instanceof");
RegisterOperand res = InstanceOf.getResult(lastInstr);
if (DBG_TYPE)
db("result was in " + res + ", we are checking " + val);
if (val.getRegister() != res.getRegister()) {
// not our value
break;
}
Operand ref = InstanceOf.getRef(lastInstr);
// should've been constant folded anyway
if (!(ref instanceof RegisterOperand)) {
break;
}
RegisterOperand guard = null;
// Propagate types and non-nullness along the CFG edge where we
// know that refReg is an instanceof type2
RegisterOperand refReg = (RegisterOperand) ref;
TypeReference type2 = InstanceOf.getType(lastInstr).getTypeRef();
if (cond.isNOT_EQUAL()) {
// IS an instance of on the branch-taken edge
boolean generated = false;
if (refReg.getRegister().isLocal()) {
int locNum = gc.getLocalNumberFor(refReg.getRegister(), refReg.getType());
if (locNum != -1) {
Operand loc = getLocal(locNum);
if (loc instanceof RegisterOperand) {
if (DBG_TYPE) {
db(val + " is from instanceof test, propagating new type of " + refReg + " (" + type2 + ") to basic block at " + offset);
}
RegisterOperand locr = (RegisterOperand) loc;
RegisterOperand tlocr = locr.copyU2U();
guard = gc.makeNullCheckGuard(tlocr.getRegister());
setGuardForRegOp(tlocr, guard.copyD2U());
tlocr.clearDeclaredType();
tlocr.clearPreciseType();
tlocr.setType(type2);
setLocal(locNum, tlocr);
branch = generateTarget(offset);
generated = true;
setLocal(locNum, locr);
}
}
}
if (!generated) {
branch = generateTarget(offset);
}
} else if (cond.isEQUAL()) {
// IS an instance of on the fallthrough edge.
branch = generateTarget(offset);
if (refReg.getRegister().isLocal()) {
int locNum = gc.getLocalNumberFor(refReg.getRegister(), refReg.getType());
if (locNum != -1) {
Operand loc = getLocal(locNum);
if (loc instanceof RegisterOperand) {
if (DBG_TYPE) {
db(val + " is from instanceof test, propagating new type of " + refReg + " (" + type2 + ") along fallthrough edge");
}
RegisterOperand locr = (RegisterOperand) loc;
guard = gc.makeNullCheckGuard(locr.getRegister());
setGuardForRegOp(locr, guard.copyD2U());
locr.clearDeclaredType();
locr.clearPreciseType();
locr.setType(type2);
setLocal(locNum, loc);
}
}
}
}
if (guard == null) {
guard = gc.getTemps().makeTempValidation();
}
return IfCmp.create(INT_IFCMP, guard, val, new IntConstantOperand(0), cond, branch, gc.getConditionalBranchProfileOperand(instrIndex - bciAdjustment, offset < 0));
}
case INSTANCEOF_NOTNULL_opcode:
{
if (DBG_TYPE)
db("last instruction was instanceof");
RegisterOperand res = InstanceOf.getResult(lastInstr);
if (DBG_TYPE) {
db("result was in " + res + ", we are checking " + val);
}
if (val.getRegister() != res.getRegister()) {
// not our value
break;
}
Operand ref = InstanceOf.getRef(lastInstr);
// should've been constant folded anyway
if (!(ref instanceof RegisterOperand)) {
break;
}
// Propagate types along the CFG edge where we know that
// refReg is an instanceof type2
RegisterOperand refReg = (RegisterOperand) ref;
TypeReference type2 = InstanceOf.getType(lastInstr).getTypeRef();
if (cond.isNOT_EQUAL()) {
// IS an instance of on the branch-taken edge
boolean generated = false;
if (refReg.getRegister().isLocal()) {
int locNum = gc.getLocalNumberFor(refReg.getRegister(), refReg.getType());
if (locNum != -1) {
Operand loc = getLocal(locNum);
if (loc instanceof RegisterOperand) {
if (DBG_TYPE) {
db(val + " is from instanceof test, propagating new type of " + refReg + " (" + type2 + ") to basic block at " + offset);
}
RegisterOperand locr = (RegisterOperand) loc;
RegisterOperand tlocr = locr.copyU2U();
tlocr.clearDeclaredType();
tlocr.clearPreciseType();
tlocr.setType(type2);
setLocal(locNum, tlocr);
branch = generateTarget(offset);
generated = true;
setLocal(locNum, locr);
}
}
}
if (!generated) {
branch = generateTarget(offset);
}
} else if (cond.isEQUAL()) {
// IS an instance of on the fallthrough edge.
branch = generateTarget(offset);
if (refReg.getRegister().isLocal()) {
int locNum = gc.getLocalNumberFor(refReg.getRegister(), refReg.getType());
if (locNum != -1) {
Operand loc = getLocal(locNum);
if (loc instanceof RegisterOperand) {
if (DBG_TYPE) {
db(val + " is from instanceof test, propagating new type of " + refReg + " (" + type2 + ") along fallthrough edge");
}
RegisterOperand locr = (RegisterOperand) loc;
locr.setType(type2);
locr.clearDeclaredType();
setLocal(locNum, loc);
}
}
}
}
RegisterOperand guard = gc.getTemps().makeTempValidation();
return IfCmp.create(INT_IFCMP, guard, val, new IntConstantOperand(0), cond, branch, gc.getConditionalBranchProfileOperand(instrIndex - bciAdjustment, offset < 0));
}
case DOUBLE_CMPG_opcode:
case DOUBLE_CMPL_opcode:
case FLOAT_CMPG_opcode:
case FLOAT_CMPL_opcode:
case LONG_CMP_opcode:
{
RegisterOperand res = Binary.getResult(lastInstr);
if (val.getRegister() != res.getRegister()) {
// not our value
break;
}
Operator operator = null;
switch(lastInstr.getOpcode()) {
case DOUBLE_CMPG_opcode:
cond.translateCMPG();
operator = DOUBLE_IFCMP;
break;
case DOUBLE_CMPL_opcode:
cond.translateCMPL();
operator = DOUBLE_IFCMP;
break;
case FLOAT_CMPG_opcode:
cond.translateCMPG();
operator = FLOAT_IFCMP;
break;
case FLOAT_CMPL_opcode:
cond.translateCMPL();
operator = FLOAT_IFCMP;
break;
case LONG_CMP_opcode:
operator = LONG_IFCMP;
break;
default:
OptimizingCompilerException.UNREACHABLE();
break;
}
Operand val1 = Binary.getClearVal1(lastInstr);
Operand val2 = Binary.getClearVal2(lastInstr);
if (!(val1 instanceof RegisterOperand)) {
// swap operands
Operand temp = val1;
val1 = val2;
val2 = temp;
cond = cond.flipOperands();
}
lastInstr.remove();
lastInstr = null;
branch = generateTarget(offset);
RegisterOperand guard = gc.getTemps().makeTempValidation();
return IfCmp.create(operator, guard, val1, val2, cond, branch, gc.getConditionalBranchProfileOperand(instrIndex - bciAdjustment, offset < 0));
}
default:
// Fall through and Insert INT_IFCMP
break;
}
}
branch = generateTarget(offset);
RegisterOperand guard = gc.getTemps().makeTempValidation();
return IfCmp.create(INT_IFCMP, guard, val, new IntConstantOperand(0), cond, branch, gc.getConditionalBranchProfileOperand(instrIndex - bciAdjustment, offset < 0));
}
use of org.jikesrvm.compilers.opt.ir.Operator in project JikesRVM by JikesRVM.
the class BC2IR method generateAnewarray.
// pops the length off the stack
//
public Instruction generateAnewarray(TypeReference arrayTypeRef, TypeReference elementTypeRef) {
if (arrayTypeRef == null) {
if (VM.VerifyAssertions)
opt_assert(elementTypeRef != null);
arrayTypeRef = elementTypeRef.getArrayTypeForElementType();
}
if (elementTypeRef == null) {
elementTypeRef = arrayTypeRef.getArrayElementType();
}
RegisterOperand t = gc.getTemps().makeTemp(arrayTypeRef);
t.setPreciseType();
markGuardlessNonNull(t);
// We can do early resolution of the array type if the element type
// is already initialized.
RVMType arrayType = arrayTypeRef.peekType();
Operator op;
TypeOperand arrayOp;
if ((arrayType != null) && (arrayType.isInitialized() || arrayType.isInBootImage())) {
op = NEWARRAY;
arrayOp = makeTypeOperand(arrayType);
t.setExtant();
} else {
RVMType elementType = elementTypeRef.peekType();
if ((elementType != null) && (elementType.isInitialized() || elementType.isInBootImage())) {
arrayType = arrayTypeRef.resolve();
arrayType.prepareForFirstUse();
op = NEWARRAY;
arrayOp = makeTypeOperand(arrayType);
t.setExtant();
} else {
op = NEWARRAY_UNRESOLVED;
arrayOp = makeTypeOperand(arrayTypeRef);
}
}
Instruction s = NewArray.create(op, t, arrayOp, popInt());
push(t.copyD2U());
rectifyStateWithErrorHandler();
rectifyStateWithExceptionHandler(TypeReference.JavaLangNegativeArraySizeException);
return s;
}
use of org.jikesrvm.compilers.opt.ir.Operator in project JikesRVM by JikesRVM.
the class BC2IR method _loadLocalForOSR.
/**
* make a temporary register, and create a move instruction
* @param op the local variable.
* @return operand marked as use.
*/
private Operand _loadLocalForOSR(Operand op) {
/* return address is processed specially */
if (op instanceof ReturnAddressOperand) {
return op;
}
RegisterOperand t = gc.getTemps().makeTemp(op.getType());
byte tcode = op.getType().getName().parseForTypeCode();
Operator operator = null;
switch(tcode) {
case ClassTypeCode:
case ArrayTypeCode:
operator = REF_MOVE;
break;
case BooleanTypeCode:
case ByteTypeCode:
case ShortTypeCode:
case CharTypeCode:
case IntTypeCode:
operator = INT_MOVE;
break;
case LongTypeCode:
operator = LONG_MOVE;
break;
case FloatTypeCode:
operator = FLOAT_MOVE;
break;
case DoubleTypeCode:
operator = DOUBLE_MOVE;
break;
case VoidTypeCode:
return null;
}
appendInstruction(Move.create(operator, t, op.copy()));
return t.copyD2U();
}
use of org.jikesrvm.compilers.opt.ir.Operator in project JikesRVM by JikesRVM.
the class MutateSplits method perform.
/**
* The main entrypoint for this pass.
*/
@Override
public void perform(IR ir) {
for (Enumeration<Instruction> e = ir.forwardInstrEnumerator(); e.hasMoreElements(); ) {
Instruction s = e.nextElement();
if (s.operator() == SPLIT) {
RegisterOperand lhs = Unary.getResult(s);
Operator mv = IRTools.getMoveOp(lhs.getType());
Operand rhs = Unary.getVal(s);
Move.mutate(s, mv, lhs, rhs);
}
}
}
Aggregations