* overlap with either operand and send that case to a runtime handler.
*/
RegLocation rl_result;
- if (BadOverlap(rl_src1, rl_dest) || (BadOverlap(rl_src2, rl_dest))) {
+ if (PartiallyIntersects(rl_src1, rl_dest) || (PartiallyIntersects(rl_src2, rl_dest))) {
FlushAllRegs();
CallRuntimeHelperRegLocationRegLocation(kQuickLmul, rl_src1, rl_src2, false);
rl_result = GetReturnWide(kCoreReg);
StoreValueWide(rl_dest, rl_src);
return;
}
- if (BadOverlap(rl_src, rl_dest)) {
+ if (PartiallyIntersects(rl_src, rl_dest)) {
GenShiftOpLong(opcode, rl_dest, rl_src, rl_shift);
return;
}
std::swap(rl_src1, rl_src2);
}
}
- if (BadOverlap(rl_src1, rl_dest)) {
+ if (PartiallyIntersects(rl_src1, rl_dest)) {
GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2);
return;
}
return bit_posn;
}
-bool Mir2Lir::BadOverlap(RegLocation rl_src, RegLocation rl_dest) {
+bool Mir2Lir::PartiallyIntersects(RegLocation rl_src, RegLocation rl_dest) {
DCHECK(rl_src.wide);
DCHECK(rl_dest.wide);
return (abs(mir_graph_->SRegToVReg(rl_src.s_reg_low) - mir_graph_->SRegToVReg(rl_dest.s_reg_low)) == 1);
}
+bool Mir2Lir::Intersects(RegLocation rl_src, RegLocation rl_dest) {
+ DCHECK(rl_src.wide);
+ DCHECK(rl_dest.wide);
+ return (abs(mir_graph_->SRegToVReg(rl_src.s_reg_low) - mir_graph_->SRegToVReg(rl_dest.s_reg_low)) <= 1);
+}
+
LIR *Mir2Lir::OpCmpMemImmBranch(ConditionCode cond, RegStorage temp_reg, RegStorage base_reg,
int offset, int check_value, LIR* target, LIR** compare) {
// Handle this for architectures that can't compare to memory.
* is not usual for dx to generate, but it is legal (for now). In a future rev of
* dex, we'll want to make this case illegal.
*/
- bool BadOverlap(RegLocation rl_op1, RegLocation rl_op2);
+ bool PartiallyIntersects(RegLocation rl_op1, RegLocation rl_op2);
+
+ /*
+ * @brief Do these SRs intersect?
+ * @param rl_op1 One RegLocation
+ * @param rl_op2 The other RegLocation
+ * @return 'true' if the VR pairs intersect
+ *
+ * Check to see if a result pair has misaligned overlap or
+ * full overlap with an operand pair.
+ */
+ bool Intersects(RegLocation rl_op1, RegLocation rl_op2);
/*
* @brief Force a location (in a register) into a temporary register
return true;
} else if (IsPowerOfTwo(val)) {
int shift_amount = LowestSetBit(val);
- if (!BadOverlap(rl_src1, rl_dest)) {
+ if (!PartiallyIntersects(rl_src1, rl_dest)) {
rl_src1 = LoadValueWide(rl_src1, kCoreReg);
RegLocation rl_result = GenShiftImmOpLong(Instruction::SHL_LONG, rl_dest, rl_src1,
shift_amount);
x86op = GetOpcode(op, rl_dest, rl_src, true);
NewLIR2(x86op, rl_dest.reg.GetHighReg(), rl_src.reg.GetHighReg());
- FreeTemp(rl_src.reg); // ???
}
return;
}
GenLongRegOrMemOp(rl_result, rl_src, op);
StoreFinalValueWide(rl_dest, rl_result);
return;
+ } else if (!cu_->target64 && Intersects(rl_src, rl_dest)) {
+ // Handle the case when src and dest are intersect.
+ rl_src = LoadValueWide(rl_src, kCoreReg);
+ RegLocation rl_result = EvalLocWide(rl_dest, kCoreReg, true);
+ rl_src = UpdateLocWideTyped(rl_src, kCoreReg);
+ GenLongRegOrMemOp(rl_result, rl_src, op);
+ StoreFinalValueWide(rl_dest, rl_result);
+ return;
}
// It wasn't in registers, so it better be in memory.
AnnotateDalvikRegAccess(lir, (displacement + HIWORD_OFFSET) >> 2,
false /* is_load */, true /* is64bit */);
}
- FreeTemp(rl_src.reg);
}
void X86Mir2Lir::GenLongArith(RegLocation rl_dest, RegLocation rl_src1,
GenArithOpLong(Instruction::ADD_LONG, rl_dest, rl_src, rl_src);
return;
}
- if (BadOverlap(rl_src, rl_dest)) {
+ if (PartiallyIntersects(rl_src, rl_dest)) {
GenShiftOpLong(opcode, rl_dest, rl_src, rl_shift);
return;
}