Revert "Revert "Better support for x86 XMM registers""
This reverts commit 8ff67e3338952c70ccf3b609559bf8cc0f379cfd.
Fix applied to loc.fp usage.
Change-Id: I1eb3005392544fcf30c595923ed25bcee2dc4859
diff --git a/compiler/dex/quick/x86/target_x86.cc b/compiler/dex/quick/x86/target_x86.cc
index b281063..5c993c5 100644
--- a/compiler/dex/quick/x86/target_x86.cc
+++ b/compiler/dex/quick/x86/target_x86.cc
@@ -416,7 +416,7 @@
if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) {
low_reg = AllocTempDouble();
- high_reg = low_reg + 1;
+ high_reg = low_reg; // only one allocated!
res = (low_reg & 0xff) | ((high_reg & 0xff) << 8);
return res;
}
@@ -546,4 +546,254 @@
return X86Mir2Lir::EncodingMap[opcode].fmt;
}
+/*
+ * Return an updated location record with current in-register status.
+ * If the value lives in live temps, reflect that fact. No code
+ * is generated. If the live value is part of an older pair,
+ * clobber both low and high.
+ */
+// TODO: Reunify with common code after 'pair mess' has been fixed
+RegLocation X86Mir2Lir::UpdateLocWide(RegLocation loc) {
+ DCHECK(loc.wide);
+ DCHECK(CheckCorePoolSanity());
+ if (loc.location != kLocPhysReg) {
+ DCHECK((loc.location == kLocDalvikFrame) ||
+ (loc.location == kLocCompilerTemp));
+ // Are the dalvik regs already live in physical registers?
+ RegisterInfo* info_lo = AllocLive(loc.s_reg_low, kAnyReg);
+
+ // Handle FP registers specially on x86.
+ if (info_lo && IsFpReg(info_lo->reg)) {
+ bool match = true;
+
+ // We can't match a FP register with a pair of Core registers.
+ match = match && (info_lo->pair == 0);
+
+ if (match) {
+ // We can reuse;update the register usage info.
+ loc.low_reg = info_lo->reg;
+ loc.high_reg = info_lo->reg; // Play nice with existing code.
+ loc.location = kLocPhysReg;
+ loc.vec_len = kVectorLength8;
+ DCHECK(IsFpReg(loc.low_reg));
+ return loc;
+ }
+ // We can't easily reuse; clobber and free any overlaps.
+ if (info_lo) {
+ Clobber(info_lo->reg);
+ FreeTemp(info_lo->reg);
+ if (info_lo->pair)
+ Clobber(info_lo->partner);
+ }
+ } else {
+ RegisterInfo* info_hi = AllocLive(GetSRegHi(loc.s_reg_low), kAnyReg);
+ bool match = true;
+ match = match && (info_lo != NULL);
+ match = match && (info_hi != NULL);
+ // Are they both core or both FP?
+ match = match && (IsFpReg(info_lo->reg) == IsFpReg(info_hi->reg));
+ // If a pair of floating point singles, are they properly aligned?
+ if (match && IsFpReg(info_lo->reg)) {
+ match &= ((info_lo->reg & 0x1) == 0);
+ match &= ((info_hi->reg - info_lo->reg) == 1);
+ }
+ // If previously used as a pair, it is the same pair?
+ if (match && (info_lo->pair || info_hi->pair)) {
+ match = (info_lo->pair == info_hi->pair);
+ match &= ((info_lo->reg == info_hi->partner) &&
+ (info_hi->reg == info_lo->partner));
+ }
+ if (match) {
+ // Can reuse - update the register usage info
+ loc.low_reg = info_lo->reg;
+ loc.high_reg = info_hi->reg;
+ loc.location = kLocPhysReg;
+ MarkPair(loc.low_reg, loc.high_reg);
+ DCHECK(!IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0));
+ return loc;
+ }
+ // Can't easily reuse - clobber and free any overlaps
+ if (info_lo) {
+ Clobber(info_lo->reg);
+ FreeTemp(info_lo->reg);
+ if (info_lo->pair)
+ Clobber(info_lo->partner);
+ }
+ if (info_hi) {
+ Clobber(info_hi->reg);
+ FreeTemp(info_hi->reg);
+ if (info_hi->pair)
+ Clobber(info_hi->partner);
+ }
+ }
+ }
+ return loc;
+}
+
+// TODO: Reunify with common code after 'pair mess' has been fixed
+RegLocation X86Mir2Lir::EvalLocWide(RegLocation loc, int reg_class, bool update) {
+ DCHECK(loc.wide);
+ int32_t new_regs;
+ int32_t low_reg;
+ int32_t high_reg;
+
+ loc = UpdateLocWide(loc);
+
+ /* If it is already in a register, we can assume proper form. Is it the right reg class? */
+ if (loc.location == kLocPhysReg) {
+ DCHECK_EQ(IsFpReg(loc.low_reg), loc.IsVectorScalar());
+ if (!RegClassMatches(reg_class, loc.low_reg)) {
+ /* It is the wrong register class. Reallocate and copy. */
+ if (!IsFpReg(loc.low_reg)) {
+ // We want this in a FP reg, and it is in core registers.
+ DCHECK(reg_class != kCoreReg);
+ // Allocate this into any FP reg, and mark it with the right size.
+ low_reg = AllocTypedTemp(true, reg_class);
+ OpVectorRegCopyWide(low_reg, loc.low_reg, loc.high_reg);
+ CopyRegInfo(low_reg, loc.low_reg);
+ Clobber(loc.low_reg);
+ Clobber(loc.high_reg);
+ loc.low_reg = low_reg;
+ loc.high_reg = low_reg; // Play nice with existing code.
+ loc.vec_len = kVectorLength8;
+ } else {
+ // The value is in a FP register, and we want it in a pair of core registers.
+ DCHECK_EQ(reg_class, kCoreReg);
+ DCHECK_EQ(loc.low_reg, loc.high_reg);
+ new_regs = AllocTypedTempPair(false, kCoreReg); // Force to core registers.
+ low_reg = new_regs & 0xff;
+ high_reg = (new_regs >> 8) & 0xff;
+ DCHECK_NE(low_reg, high_reg);
+ OpRegCopyWide(low_reg, high_reg, loc.low_reg, loc.high_reg);
+ CopyRegInfo(low_reg, loc.low_reg);
+ CopyRegInfo(high_reg, loc.high_reg);
+ Clobber(loc.low_reg);
+ Clobber(loc.high_reg);
+ loc.low_reg = low_reg;
+ loc.high_reg = high_reg;
+ MarkPair(loc.low_reg, loc.high_reg);
+ DCHECK(!IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0));
+ }
+ }
+ return loc;
+ }
+
+ DCHECK_NE(loc.s_reg_low, INVALID_SREG);
+ if (IsFpReg(loc.low_reg) && reg_class != kCoreReg) {
+ // Need a wide vector register.
+ low_reg = AllocTypedTemp(true, reg_class);
+ loc.low_reg = low_reg;
+ loc.high_reg = low_reg; // Play nice with existing code.
+ loc.vec_len = kVectorLength8;
+ if (update) {
+ loc.location = kLocPhysReg;
+ MarkLive(loc.low_reg, loc.s_reg_low);
+ }
+ DCHECK(IsFpReg(loc.low_reg));
+ } else {
+ DCHECK_NE(GetSRegHi(loc.s_reg_low), INVALID_SREG);
+
+ new_regs = AllocTypedTempPair(loc.fp, reg_class);
+ loc.low_reg = new_regs & 0xff;
+ loc.high_reg = (new_regs >> 8) & 0xff;
+
+ MarkPair(loc.low_reg, loc.high_reg);
+ if (update) {
+ loc.location = kLocPhysReg;
+ MarkLive(loc.low_reg, loc.s_reg_low);
+ MarkLive(loc.high_reg, GetSRegHi(loc.s_reg_low));
+ }
+ DCHECK(!IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0));
+ }
+ return loc;
+}
+
+// TODO: Reunify with common code after 'pair mess' has been fixed
+RegLocation X86Mir2Lir::EvalLoc(RegLocation loc, int reg_class, bool update) {
+ int new_reg;
+
+ if (loc.wide)
+ return EvalLocWide(loc, reg_class, update);
+
+ loc = UpdateLoc(loc);
+
+ if (loc.location == kLocPhysReg) {
+ if (!RegClassMatches(reg_class, loc.low_reg)) {
+ /* Wrong register class. Realloc, copy and transfer ownership. */
+ new_reg = AllocTypedTemp(loc.fp, reg_class);
+ OpRegCopy(new_reg, loc.low_reg);
+ CopyRegInfo(new_reg, loc.low_reg);
+ Clobber(loc.low_reg);
+ loc.low_reg = new_reg;
+ if (IsFpReg(loc.low_reg) && reg_class != kCoreReg)
+ loc.vec_len = kVectorLength4;
+ }
+ return loc;
+ }
+
+ DCHECK_NE(loc.s_reg_low, INVALID_SREG);
+
+ new_reg = AllocTypedTemp(loc.fp, reg_class);
+ loc.low_reg = new_reg;
+ if (IsFpReg(loc.low_reg) && reg_class != kCoreReg)
+ loc.vec_len = kVectorLength4;
+
+ if (update) {
+ loc.location = kLocPhysReg;
+ MarkLive(loc.low_reg, loc.s_reg_low);
+ }
+ return loc;
+}
+
+int X86Mir2Lir::AllocTempDouble() {
+ // We really don't need a pair of registers.
+ return AllocTempFloat();
+}
+
+// TODO: Reunify with common code after 'pair mess' has been fixed
+void X86Mir2Lir::ResetDefLocWide(RegLocation rl) {
+ DCHECK(rl.wide);
+ RegisterInfo* p_low = IsTemp(rl.low_reg);
+ if (IsFpReg(rl.low_reg)) {
+ // We are using only the low register.
+ if (p_low && !(cu_->disable_opt & (1 << kSuppressLoads))) {
+ NullifyRange(p_low->def_start, p_low->def_end, p_low->s_reg, rl.s_reg_low);
+ }
+ ResetDef(rl.low_reg);
+ } else {
+ RegisterInfo* p_high = IsTemp(rl.high_reg);
+ if (p_low && !(cu_->disable_opt & (1 << kSuppressLoads))) {
+ DCHECK(p_low->pair);
+ NullifyRange(p_low->def_start, p_low->def_end, p_low->s_reg, rl.s_reg_low);
+ }
+ if (p_high && !(cu_->disable_opt & (1 << kSuppressLoads))) {
+ DCHECK(p_high->pair);
+ }
+ ResetDef(rl.low_reg);
+ ResetDef(rl.high_reg);
+ }
+}
+
+void X86Mir2Lir::GenConstWide(RegLocation rl_dest, int64_t value) {
+ // Can we do this directly to memory?
+ rl_dest = UpdateLocWide(rl_dest);
+ if ((rl_dest.location == kLocDalvikFrame) ||
+ (rl_dest.location == kLocCompilerTemp)) {
+ int32_t val_lo = Low32Bits(value);
+ int32_t val_hi = High32Bits(value);
+ int rBase = TargetReg(kSp);
+ int displacement = SRegOffset(rl_dest.s_reg_low);
+
+ LIR * store = NewLIR3(kX86Mov32MI, rBase, displacement + LOWORD_OFFSET, val_lo);
+ AnnotateDalvikRegAccess(store, (displacement + LOWORD_OFFSET) >> 2,
+ false /* is_load */, true /* is64bit */);
+ store = NewLIR3(kX86Mov32MI, rBase, displacement + HIWORD_OFFSET, val_hi);
+ AnnotateDalvikRegAccess(store, (displacement + HIWORD_OFFSET) >> 2,
+ false /* is_load */, true /* is64bit */);
+ return;
+ }
+
+ // Just use the standard code to do the generation.
+ Mir2Lir::GenConstWide(rl_dest, value);
+}
} // namespace art