use of org.jikesrvm.compilers.opt.ir.Operator 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.Operator in project JikesRVM by JikesRVM.
the class AnnotatedLSTNode method generateLoopInvariantOperand.
/**
* Loop invariants may not be accessible before a loop, so generate
* the instructions so they are
*
* @param block to generate instructions into
* @param op the operand we hope to use before the loop
* @return a (possibly new) operand
*/
public Operand generateLoopInvariantOperand(BasicBlock block, Operand op) {
Instruction instr = definingInstruction(op);
if (op.isConstant() || !CFGTransformations.inLoop(instr.getBasicBlock(), loop)) {
// the operand is already invariant
return op;
} else {
RegisterOperand result;
Instruction opInstr = definingInstruction(op);
// create result of correct type
if (ResultCarrier.conforms(opInstr)) {
result = ResultCarrier.getResult(opInstr).copyRO();
result.setRegister(ir.regpool.getReg(result));
} else {
if (VM.VerifyAssertions)
VM._assert(GuardResultCarrier.conforms(opInstr));
result = GuardResultCarrier.getGuardResult(opInstr).copyRO();
result.setRegister(ir.regpool.getReg(result));
}
Instruction resultInstruction;
Operator operator = instr.operator();
switch(operator.format) {
case InstructionFormat.Binary_format:
resultInstruction = Binary.create(operator, result, generateLoopInvariantOperand(block, Binary.getVal1(instr)), generateLoopInvariantOperand(block, Binary.getVal2(instr)));
break;
case InstructionFormat.BoundsCheck_format:
resultInstruction = BoundsCheck.create(operator, result, generateLoopInvariantOperand(block, BoundsCheck.getRef(instr)), generateLoopInvariantOperand(block, BoundsCheck.getIndex(instr)), generateLoopInvariantOperand(block, BoundsCheck.getGuard(instr)));
break;
case InstructionFormat.GuardedBinary_format:
resultInstruction = GuardedBinary.create(operator, result, generateLoopInvariantOperand(block, GuardedBinary.getVal1(instr)), generateLoopInvariantOperand(block, GuardedBinary.getVal2(instr)), generateLoopInvariantOperand(block, GuardedBinary.getGuard(instr)));
break;
case InstructionFormat.GuardedUnary_format:
resultInstruction = GuardedUnary.create(operator, result, generateLoopInvariantOperand(block, GuardedUnary.getVal(instr)), generateLoopInvariantOperand(block, GuardedUnary.getGuard(instr)));
break;
case InstructionFormat.Move_format:
resultInstruction = Move.create(operator, result, generateLoopInvariantOperand(block, Move.getVal(instr)));
break;
case InstructionFormat.NullCheck_format:
resultInstruction = NullCheck.create(operator, result, generateLoopInvariantOperand(block, NullCheck.getRef(instr)));
break;
case InstructionFormat.Unary_format:
resultInstruction = Unary.create(operator, result, generateLoopInvariantOperand(block, Unary.getVal(instr)));
break;
default:
// Unknown instruction format so leave
throw new Error("TODO: generate loop invariant for operator " + operator);
}
resultInstruction.copyPosition(instr);
block.appendInstruction(resultInstruction);
DefUse.updateDUForNewInstruction(resultInstruction);
return result.copyRO();
}
}
use of org.jikesrvm.compilers.opt.ir.Operator in project JikesRVM by JikesRVM.
the class BranchOptimizations method doCondMove.
/**
* Perform the transformation to replace conditional branch with a
* sequence using conditional moves.
*
* @param ir governing IR
* @param diamond the IR diamond structure to replace
* @param cb conditional branch instruction at the head of the diamond
*/
private void doCondMove(IR ir, Diamond diamond, Instruction cb) {
BasicBlock taken = diamond.getTaken();
BasicBlock notTaken = diamond.getNotTaken();
// for each non-branch instruction s in the diamond,
// copy s to a new instruction s'
// and store a mapping from s to s'
HashMap<Instruction, Instruction> takenInstructions = new HashMap<Instruction, Instruction>();
Instruction[] takenInstructionList = copyAndMapInstructions(taken, takenInstructions);
HashMap<Instruction, Instruction> notTakenInstructions = new HashMap<Instruction, Instruction>();
Instruction[] notTakenInstructionList = copyAndMapInstructions(notTaken, notTakenInstructions);
// Extract the values and condition from the conditional branch.
Operand val1 = IfCmp.getVal1(cb);
Operand val2 = IfCmp.getVal2(cb);
ConditionOperand cond = IfCmp.getCond(cb);
// Copy val1 and val2 to temporaries, just in case they're defined in
// the diamond. If they're not defined in the diamond, copy prop
// should clean these moves up.
RegisterOperand tempVal1 = ir.regpool.makeTemp(val1);
Operator op = IRTools.getMoveOp(tempVal1.getType());
cb.insertBefore(Move.create(op, tempVal1.copyRO(), val1.copy()));
RegisterOperand tempVal2 = ir.regpool.makeTemp(val2);
op = IRTools.getMoveOp(tempVal2.getType());
cb.insertBefore(Move.create(op, tempVal2.copyRO(), val2.copy()));
// For each instruction in each temporary set, rewrite it to def a new
// temporary, and insert it before the branch.
rewriteWithTemporaries(takenInstructionList, ir);
rewriteWithTemporaries(notTakenInstructionList, ir);
insertBefore(takenInstructionList, cb);
insertBefore(notTakenInstructionList, cb);
// For each register defined in the TAKEN branch, save a mapping to
// the corresponding conditional move.
HashMap<Register, Instruction> takenMap = new HashMap<Register, Instruction>();
// First handle the taken branch.
if (taken != null) {
for (Enumeration<Instruction> e = taken.forwardRealInstrEnumerator(); e.hasMoreElements(); ) {
Instruction s = e.nextElement();
if (s.isBranch())
continue;
Operand def = s.getDefs().nextElement();
// that will now be dead
if (def.asRegister().getRegister().spansBasicBlock()) {
Instruction tempS = takenInstructions.get(s);
RegisterOperand temp = (RegisterOperand) tempS.getDefs().nextElement();
op = IRTools.getCondMoveOp(def.asRegister().getType());
Instruction cmov = CondMove.create(op, def.copy().asRegister(), tempVal1.copy(), tempVal2.copy(), cond.copy().asCondition(), temp.copy(), def.copy());
takenMap.put(def.asRegister().getRegister(), cmov);
cb.insertBefore(cmov);
}
s.remove();
}
}
// For each register defined in the NOT-TAKEN branch, save a mapping to
// the corresponding conditional move.
HashMap<Register, Instruction> notTakenMap = new HashMap<Register, Instruction>();
// Next handle the not taken branch.
if (notTaken != null) {
for (Enumeration<Instruction> e = notTaken.forwardRealInstrEnumerator(); e.hasMoreElements(); ) {
Instruction s = e.nextElement();
if (s.isBranch())
continue;
Operand def = s.getDefs().nextElement();
// that will now be dead
if (def.asRegister().getRegister().spansBasicBlock()) {
Instruction tempS = notTakenInstructions.get(s);
RegisterOperand temp = (RegisterOperand) tempS.getDefs().nextElement();
Instruction prevCmov = takenMap.get(def.asRegister().getRegister());
if (prevCmov != null) {
// if this register was also defined in the taken branch, change
// the previous cmov with a different 'False' Value
CondMove.setFalseValue(prevCmov, temp.copy());
notTakenMap.put(def.asRegister().getRegister(), prevCmov);
} else {
// create a new cmov instruction
op = IRTools.getCondMoveOp(def.asRegister().getType());
Instruction cmov = CondMove.create(op, def.asRegister(), tempVal1.copy(), tempVal2.copy(), cond.copy().asCondition(), def.copy(), temp.copy());
cb.insertBefore(cmov);
notTakenMap.put(def.asRegister().getRegister(), cmov);
}
}
s.remove();
}
}
// Mutate the conditional branch into a GOTO.
BranchOperand target = diamond.getBottom().makeJumpTarget();
Goto.mutate(cb, GOTO, target);
// Delete a potential GOTO after cb.
Instruction next = cb.nextInstructionInCodeOrder();
if (next.operator() != BBEND) {
next.remove();
}
// Recompute the CFG.
// fix the CFG
diamond.getTop().recomputeNormalOut(ir);
}
Aggregations