use of org.jikesrvm.compilers.opt.ir.operand.ConditionOperand in project JikesRVM by JikesRVM.
the class BURS_Helpers method SSE2_FCMP_FCMOV.
protected final void SSE2_FCMP_FCMOV(Instruction s, RegisterOperand result, Operand lhsCmp, Operand rhsCmp, ConditionOperand cond, Operand trueValue, Operand falseValue) {
final boolean singleResult = result.isFloat();
final boolean singleCmp = lhsCmp.isFloat();
// TODO: support for the MAXSS/MAXSD instructions taking care of NaN cases
// find cmpOperator flipping code or operands as necessary
Operator cmpOperator = SSE2_CMP_OP(cond, singleCmp);
boolean needFlipOperands = false;
boolean needFlipCode = false;
if (cmpOperator == null) {
needFlipOperands = !needFlipOperands;
cmpOperator = SSE2_CMP_OP(cond.flipOperands(), singleCmp);
if (cmpOperator == null) {
needFlipCode = !needFlipCode;
cmpOperator = SSE2_CMP_OP(cond.flipCode(), singleCmp);
if (cmpOperator == null) {
needFlipOperands = !needFlipOperands;
cmpOperator = SSE2_CMP_OP(cond.flipOperands(), singleCmp);
if (VM.VerifyAssertions)
opt_assert(cmpOperator != null);
}
}
}
if (needFlipOperands) {
Operand temp = lhsCmp;
lhsCmp = rhsCmp;
rhsCmp = temp;
}
if (needFlipCode) {
Operand temp = falseValue;
falseValue = trueValue;
trueValue = temp;
}
// place true value in a temporary register to be used for generation of result
RegisterOperand temp = regpool.makeTemp(result);
EMIT(CPOS(s, MIR_Move.create(singleResult ? IA32_MOVSS : IA32_MOVSD, temp, trueValue)));
// do compare ensuring size is >= size of result
if (!singleResult && singleCmp) {
RegisterOperand temp2 = regpool.makeTemp(result);
EMIT(CPOS(s, MIR_Unary.create(IA32_CVTSS2SD, temp2, rhsCmp)));
EMIT(CPOS(s, MIR_Unary.create(IA32_CVTSS2SD, result.copyRO(), lhsCmp)));
rhsCmp = temp2;
cmpOperator = SSE2_CMP_OP(cond, false);
} else {
if (!result.similar(lhsCmp)) {
EMIT(CPOS(s, MIR_Move.create(singleResult ? IA32_MOVSS : IA32_MOVSD, result.copyRO(), lhsCmp)));
}
}
EMIT(MIR_BinaryAcc.mutate(s, cmpOperator, result, rhsCmp));
// result contains all 1s or 0s, use masks and OR to perform conditional move
EMIT(CPOS(s, MIR_BinaryAcc.create(singleResult ? IA32_ANDPS : IA32_ANDPD, temp.copyRO(), result.copyRO())));
EMIT(CPOS(s, MIR_BinaryAcc.create(singleResult ? IA32_ANDNPS : IA32_ANDNPD, result.copyRO(), falseValue)));
EMIT(CPOS(s, MIR_BinaryAcc.create(singleResult ? IA32_ORPS : IA32_ORPD, result.copyRO(), temp.copyRO())));
}
use of org.jikesrvm.compilers.opt.ir.operand.ConditionOperand in project JikesRVM by JikesRVM.
the class BURS_Helpers method LCMP_CMOV.
/**
* Generate a long compare and cmov
*
* @param s the instruction to copy position info from
* @param result the result of the conditional move
* @param val1 the first value
* @param val2 the second value
* @param cond the condition operand
* @param trueValue the value to move to result if cond is true
* @param falseValue the value to move to result if cond is not true
*/
protected final void LCMP_CMOV(Instruction s, RegisterOperand result, Operand val1, Operand val2, ConditionOperand cond, Operand trueValue, Operand falseValue) {
// ==/!= : do subtract then OR 2 32-bit quantities test for zero/non-zero
if (cond.isGREATER() || cond.isLESS_EQUAL()) {
Operand swap_temp;
cond.flipOperands();
swap_temp = val1;
val1 = val2;
val2 = swap_temp;
}
if (VM.VerifyAssertions) {
opt_assert(cond.isEQUAL() || cond.isNOT_EQUAL() || cond.isLESS() || cond.isGREATER_EQUAL());
}
RegisterOperand one = regpool.makeTempInt();
RegisterOperand lone = regpool.makeTempInt();
Operand two, ltwo;
if (val1 instanceof RegisterOperand) {
Register val1_reg = val1.asRegister().getRegister();
EMIT(CPOS(s, MIR_Move.create(IA32_MOV, one, new RegisterOperand(val1_reg, TypeReference.Int))));
EMIT(CPOS(s, MIR_Move.create(IA32_MOV, lone, new RegisterOperand(regpool.getSecondReg(val1_reg), TypeReference.Int))));
} else {
LongConstantOperand tmp = (LongConstantOperand) val1;
EMIT(CPOS(s, MIR_Move.create(IA32_MOV, one, IC(tmp.upper32()))));
EMIT(CPOS(s, MIR_Move.create(IA32_MOV, lone, IC(tmp.lower32()))));
}
if (val2 instanceof RegisterOperand) {
two = val2;
((RegisterOperand) two).setType(TypeReference.Int);
ltwo = new RegisterOperand(burs.ir.regpool.getSecondReg(val2.asRegister().getRegister()), TypeReference.Int);
} else {
LongConstantOperand tmp = (LongConstantOperand) val2;
two = IC(tmp.upper32());
ltwo = IC(tmp.lower32());
}
if (cond.isEQUAL() || cond.isNOT_EQUAL()) {
EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_SUB, lone.copyRO(), ltwo)));
EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_SBB, one.copyRO(), two)));
EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_OR, one.copyRO(), lone.copyRO())));
} else {
EMIT(CPOS(s, MIR_Compare.create(IA32_CMP, lone.copyRO(), ltwo)));
EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_SBB, one.copyRO(), two)));
}
CMOV_MOV(s, result, cond, trueValue, falseValue);
}
use of org.jikesrvm.compilers.opt.ir.operand.ConditionOperand in project JikesRVM by JikesRVM.
the class BURS_Helpers method consumeCOND.
/**
* Acquire remembered condition code in parent
*
* @return condition code
*/
protected final ConditionOperand consumeCOND() {
ConditionOperand ans = cc;
if (VM.VerifyAssertions) {
opt_assert(cc != null);
}
cc = null;
return ans;
}
use of org.jikesrvm.compilers.opt.ir.operand.ConditionOperand in project JikesRVM by JikesRVM.
the class DynamicTypeCheckExpansion method instanceOfNotNull.
/**
* Expand an instanceof instruction into the LIR sequence that implements
* the dynamic type check. Ref is known to never contain a null ptr at
* runtime.
*
* @param s an INSTANCEOF_NOTNULL instruction to expand
* @param ir the enclosing IR
* @return the last Instruction in the generated LIR sequence.
*/
static Instruction instanceOfNotNull(Instruction s, IR ir) {
RegisterOperand result = InstanceOf.getClearResult(s);
TypeReference LHStype = InstanceOf.getType(s).getTypeRef();
Operand ref = InstanceOf.getClearRef(s);
Operand guard = InstanceOf.getClearGuard(s);
Instruction next = s.nextInstructionInCodeOrder();
if (next.operator() == INT_IFCMP && IfCmp.getVal1(next) instanceof RegisterOperand && result.similar(IfCmp.getVal1(next))) {
// The result of instanceof is being consumed by a conditional branch.
// Optimize this case by generating a branching type
// check instead of producing a value.
Operand val2 = IfCmp.getVal2(next);
if (VM.VerifyAssertions) {
VM._assert(val2.isIntConstant());
}
int ival2 = ((IntConstantOperand) val2).value;
ConditionOperand cond = IfCmp.getCond(next);
boolean branchCondition = (((ival2 == 0) && (cond.isNOT_EQUAL() || cond.isLESS_EQUAL())) || ((ival2 == 1) && (cond.isEQUAL() || cond.isGREATER_EQUAL())));
BasicBlock branchBB = next.getBranchTarget();
RegisterOperand oldGuard = IfCmp.getGuardResult(next);
next.remove();
BasicBlock fallThroughBB = fallThroughBB(s, ir);
Operand RHStib = getTIB(s, ir, ref, guard);
if (branchCondition) {
return generateBranchingTypeCheck(s, ir, ref.copy(), LHStype, RHStib, branchBB, fallThroughBB, oldGuard.copyRO(), IfCmp.getClearBranchProfile(next).flip());
} else {
return generateBranchingTypeCheck(s, ir, ref.copy(), LHStype, RHStib, fallThroughBB, branchBB, oldGuard.copyRO(), IfCmp.getClearBranchProfile(next));
}
} else {
// Not a branching pattern
Operand RHStib = getTIB(s, ir, ref, guard);
return generateValueProducingTypeCheck(s, ir, ref.copy(), LHStype, RHStib, result);
}
}
use of org.jikesrvm.compilers.opt.ir.operand.ConditionOperand in project JikesRVM by JikesRVM.
the class AnnotatedLSTNode method processExit.
/**
* Process the loop exit basic block.
* @throws NonRegularLoopException if the loop was not regular
*/
private void processExit() throws NonRegularLoopException {
// If the exit isn't the header block, check it doesn't have in edges from outside the loop
if (header != exit) {
checkInEdgesAreInLoop(exit);
}
// Check the exit block leaves the loop
Enumeration<BasicBlock> exitBlock_outEdges = exit.getOut();
boolean exits = false;
// check_exit_block_exits:
while (exitBlock_outEdges.hasMoreElements()) {
BasicBlock curExitBlockOutEdgeBB = exitBlock_outEdges.nextElement();
if (isInLoop(curExitBlockOutEdgeBB)) {
// An in loop out edge from the exit block
} else {
// An out of loop edge from the exit block
exits = true;
successor = curExitBlockOutEdgeBB;
if (successor == header) {
throw new NonRegularLoopException("Unimplemented condition - see LoopUnrolling.java : 240");
}
}
}
// end of check_exit_block_exits
if (!exits) {
throw new NonRegularLoopException("Exit block (containing back edge to header) doesn't have an out of loop out edge.");
} else {
// Get the if instruction used to loop in the exit block
ifCmpInstr = exit.firstBranchInstruction();
if (ifCmpInstr == null) {
throw new NonRegularLoopException("Exit block branch doesn't have a (1st) branching instruction.");
} else if (ifCmpInstr.getOpcode() != INT_IFCMP_opcode) {
throw new NonRegularLoopException("branch is int_ifcmp but " + ifCmpInstr.operator() + "\n");
} else {
// Get the terminal and iterator operations
carriedLoopIterator = follow(IfCmp.getVal1(ifCmpInstr));
terminalIteratorValue = follow(IfCmp.getVal2(ifCmpInstr));
condition = (ConditionOperand) IfCmp.getCond(ifCmpInstr).copy();
// Check we have them the right way around and that they do the job we expect
{
boolean iteratorInvariant = isLoopInvariant(carriedLoopIterator, loop, header);
boolean terminalValueInvariant = isLoopInvariant(terminalIteratorValue, loop, header);
// Is the iterator loop invariant?
if (iteratorInvariant) {
// Yes - Is the terminal value loop invariant?
if (terminalValueInvariant) {
// Yes - both parameters to the condition are invariant
throw new NonRegularLoopException("Exit block condition values are both invariant (single or infinite loop):\n" + "Loop = " + loop.toString() + "\nIterator = " + carriedLoopIterator + "\nTerminal = " + terminalIteratorValue);
} else {
// No - swap values over
Operand temp = terminalIteratorValue;
terminalIteratorValue = carriedLoopIterator;
carriedLoopIterator = temp;
}
} else {
// No - Is the terminal value loop invariant?
if (terminalValueInvariant) {
// Yes - this is the condition we hoped for
} else {
// No - both loop values are variant and loop is too complex to analyse
throw new NonRegularLoopException("Exit block condition values are both variant.");
}
}
}
// Check target of "if" is the header
if (Label.getBlock(IfCmp.getTarget(ifCmpInstr).target).block != header) {
// TODO: swap ifxxx around so that branch is to header and fall-through is exit
throw new NonRegularLoopException("Target of exit block branch isn't the loop header.");
}
// Calculate stride value
Enumeration<RegisterOperand> iteratorDefs = DefUse.defs(((RegisterOperand) carriedLoopIterator).getRegister());
// Loop over definitions of the iterator operand ignoring moves
while (iteratorDefs.hasMoreElements()) {
Operand curDef = follow(iteratorDefs.nextElement());
// Is this definition within the loop?
if (isInLoop(curDef.instruction.getBasicBlock())) {
// Yes - have we already got an iterator instruction
if ((iteratorInstr == null) || (iteratorInstr == curDef.instruction)) {
// No - record
iteratorInstr = curDef.instruction;
} else {
// Yes - loop too complex again
throw new NonRegularLoopException("Multiple definitions of the iterator.");
}
}
}
// Did we find an instruction?
if (iteratorInstr == null) {
// No => error
throw new NonRegularLoopException("No iterator definition found.");
} else if ((iteratorInstr.getOpcode() != INT_ADD_opcode) && (iteratorInstr.getOpcode() != INT_SUB_opcode)) {
// TODO: support more iterator instructions
throw new NonRegularLoopException("Unrecognized iterator operator " + iteratorInstr.operator());
} else {
// only carry on further analysis if we think we can understand the loop
// Does this iterator instruction use the same register as it defines
Operand iteratorUse = follow(Binary.getVal1(iteratorInstr));
// The iterator should be using a phi node of the initial and generated value
if (!carriedLoopIterator.similar(iteratorUse)) {
// SSA ok so far, read PHI node
Instruction phiInstr = iteratorUse.instruction;
if (!Phi.conforms(phiInstr)) {
// We didn't find a PHI instruction
throw new NonRegularLoopException("Iterator (" + iteratorUse + ") not using a phi instruction but " + phiInstr);
}
// We have the SSA we hoped for - tidy up
strideValue = follow(Binary.getVal2(iteratorInstr));
initialIteratorValue = follow(Phi.getValue(phiInstr, 0));
phiLoopIterator = iteratorUse;
if (initialIteratorValue instanceof BasicBlockOperand) {
throw new Error("BasicBlock mess up!");
}
if (initialIteratorValue == iteratorUse) {
initialIteratorValue = follow(Phi.getValue(phiInstr, 1));
}
if (initialIteratorValue instanceof BasicBlockOperand) {
throw new Error("BasicBlock mess up!2");
}
} else {
// Not in SSA form as iterator modifies an operand
throw new NonRegularLoopException("Iterator modifies (uses and defines) operand " + iteratorUse + " and is therefore not in SSA form.");
}
// Check the initialIteratorValue was defined outside of (before) the loop header or is constant
if (!isLoopInvariant(initialIteratorValue, loop, header)) {
throw new NonRegularLoopException("Initial iterator not constant or defined outside the loop - " + initialIteratorValue);
} else if (!(strideValue instanceof ConstantOperand)) {
// Check the stride value constant
throw new NonRegularLoopException("Stride not constant - " + strideValue);
}
}
}
}
}
Aggregations