Quick compiler: debugging assists
A few minor assists to ease A/B debugging in the Quick
compiler:
1. To save time, the assemblers for some targets only
update the object code offsets on instructions involved with
pc-relative fixups. We add code to fix up all offsets when
doing a verbose codegen listing.
2. Temp registers are normally allocated in a round-robin
fashion. When disabling liveness tracking, we now reset the
round-robin pool to 0 on each instruction boundary. This makes
it easier to spot real codegen differences.
3. Self-register copies were previously emitted, but
marked as nops. Minor change to avoid generating them in the
first place and reduce clutter.
Change-Id: I7954bba3b9f16ee690d663be510eac7034c93723
diff --git a/compiler/dex/quick/arm/codegen_arm.h b/compiler/dex/quick/arm/codegen_arm.h
index a89b307..646859c 100644
--- a/compiler/dex/quick/arm/codegen_arm.h
+++ b/compiler/dex/quick/arm/codegen_arm.h
@@ -160,7 +160,7 @@
LIR* OpMem(OpKind op, RegStorage r_base, int disp);
LIR* OpPcRelLoad(RegStorage reg, LIR* target);
LIR* OpReg(OpKind op, RegStorage r_dest_src);
- LIR* OpRegCopy(RegStorage r_dest, RegStorage r_src);
+ void OpRegCopy(RegStorage r_dest, RegStorage r_src);
LIR* OpRegCopyNoInsert(RegStorage r_dest, RegStorage r_src);
LIR* OpRegImm(OpKind op, RegStorage r_dest_src1, int value);
LIR* OpRegMem(OpKind op, RegStorage r_dest, RegStorage r_base, int offset);
diff --git a/compiler/dex/quick/arm/int_arm.cc b/compiler/dex/quick/arm/int_arm.cc
index f47e693..a2d6373 100644
--- a/compiler/dex/quick/arm/int_arm.cc
+++ b/compiler/dex/quick/arm/int_arm.cc
@@ -361,37 +361,40 @@
return res;
}
-LIR* ArmMir2Lir::OpRegCopy(RegStorage r_dest, RegStorage r_src) {
- LIR* res = OpRegCopyNoInsert(r_dest, r_src);
- AppendLIR(res);
- return res;
+void ArmMir2Lir::OpRegCopy(RegStorage r_dest, RegStorage r_src) {
+ if (r_dest != r_src) {
+ LIR* res = OpRegCopyNoInsert(r_dest, r_src);
+ AppendLIR(res);
+ }
}
void ArmMir2Lir::OpRegCopyWide(RegStorage r_dest, RegStorage r_src) {
- bool dest_fp = ARM_FPREG(r_dest.GetLowReg());
- bool src_fp = ARM_FPREG(r_src.GetLowReg());
- if (dest_fp) {
- if (src_fp) {
- // FIXME: handle 64-bit solo's here.
- OpRegCopy(RegStorage::Solo64(S2d(r_dest.GetLowReg(), r_dest.GetHighReg())),
- RegStorage::Solo64(S2d(r_src.GetLowReg(), r_src.GetHighReg())));
- } else {
- NewLIR3(kThumb2Fmdrr, S2d(r_dest.GetLowReg(), r_dest.GetHighReg()),
- r_src.GetLowReg(), r_src.GetHighReg());
- }
- } else {
- if (src_fp) {
- NewLIR3(kThumb2Fmrrd, r_dest.GetLowReg(), r_dest.GetHighReg(), S2d(r_src.GetLowReg(),
- r_src.GetHighReg()));
- } else {
- // Handle overlap
- if (r_src.GetHighReg() == r_dest.GetLowReg()) {
- DCHECK_NE(r_src.GetLowReg(), r_dest.GetHighReg());
- OpRegCopy(r_dest.GetHigh(), r_src.GetHigh());
- OpRegCopy(r_dest.GetLow(), r_src.GetLow());
+ if (r_dest != r_src) {
+ bool dest_fp = ARM_FPREG(r_dest.GetLowReg());
+ bool src_fp = ARM_FPREG(r_src.GetLowReg());
+ if (dest_fp) {
+ if (src_fp) {
+ // FIXME: handle 64-bit solo's here.
+ OpRegCopy(RegStorage::Solo64(S2d(r_dest.GetLowReg(), r_dest.GetHighReg())),
+ RegStorage::Solo64(S2d(r_src.GetLowReg(), r_src.GetHighReg())));
} else {
- OpRegCopy(r_dest.GetLow(), r_src.GetLow());
- OpRegCopy(r_dest.GetHigh(), r_src.GetHigh());
+ NewLIR3(kThumb2Fmdrr, S2d(r_dest.GetLowReg(), r_dest.GetHighReg()),
+ r_src.GetLowReg(), r_src.GetHighReg());
+ }
+ } else {
+ if (src_fp) {
+ NewLIR3(kThumb2Fmrrd, r_dest.GetLowReg(), r_dest.GetHighReg(), S2d(r_src.GetLowReg(),
+ r_src.GetHighReg()));
+ } else {
+ // Handle overlap
+ if (r_src.GetHighReg() == r_dest.GetLowReg()) {
+ DCHECK_NE(r_src.GetLowReg(), r_dest.GetHighReg());
+ OpRegCopy(r_dest.GetHigh(), r_src.GetHigh());
+ OpRegCopy(r_dest.GetLow(), r_src.GetLow());
+ } else {
+ OpRegCopy(r_dest.GetLow(), r_src.GetLow());
+ OpRegCopy(r_dest.GetHigh(), r_src.GetHigh());
+ }
}
}
}
diff --git a/compiler/dex/quick/codegen_util.cc b/compiler/dex/quick/codegen_util.cc
index 677ee15..501e4e20 100644
--- a/compiler/dex/quick/codegen_util.cc
+++ b/compiler/dex/quick/codegen_util.cc
@@ -274,6 +274,19 @@
}
}
+void Mir2Lir::UpdateLIROffsets() {
+ // Only used for code listings.
+ size_t offset = 0;
+ for (LIR* lir = first_lir_insn_; lir != nullptr; lir = lir->next) {
+ lir->offset = offset;
+ if (!lir->flags.is_nop && !IsPseudoLirOp(lir->opcode)) {
+ offset += GetInsnSize(lir);
+ } else if (lir->opcode == kPseudoPseudoAlign4) {
+ offset += (offset & 0x2);
+ }
+ }
+}
+
/* Dump instructions and constant pool contents */
void Mir2Lir::CodegenDump() {
LOG(INFO) << "Dumping LIR insns for "
@@ -293,6 +306,7 @@
LOG(INFO) << "expansion factor: "
<< static_cast<float>(total_size_) / static_cast<float>(insns_size * 2);
DumpPromotionMap();
+ UpdateLIROffsets();
for (lir_insn = first_lir_insn_; lir_insn != NULL; lir_insn = lir_insn->next) {
DumpLIRInsn(lir_insn, 0);
}
diff --git a/compiler/dex/quick/mips/codegen_mips.h b/compiler/dex/quick/mips/codegen_mips.h
index da65f34..81d6782 100644
--- a/compiler/dex/quick/mips/codegen_mips.h
+++ b/compiler/dex/quick/mips/codegen_mips.h
@@ -159,7 +159,7 @@
LIR* OpMem(OpKind op, RegStorage r_base, int disp);
LIR* OpPcRelLoad(RegStorage reg, LIR* target);
LIR* OpReg(OpKind op, RegStorage r_dest_src);
- LIR* OpRegCopy(RegStorage r_dest, RegStorage r_src);
+ void OpRegCopy(RegStorage r_dest, RegStorage r_src);
LIR* OpRegCopyNoInsert(RegStorage r_dest, RegStorage r_src);
LIR* OpRegImm(OpKind op, RegStorage r_dest_src1, int value);
LIR* OpRegMem(OpKind op, RegStorage r_dest, RegStorage r_base, int offset);
diff --git a/compiler/dex/quick/mips/int_mips.cc b/compiler/dex/quick/mips/int_mips.cc
index 88d5d2b..7c0becd 100644
--- a/compiler/dex/quick/mips/int_mips.cc
+++ b/compiler/dex/quick/mips/int_mips.cc
@@ -177,37 +177,40 @@
return res;
}
-LIR* MipsMir2Lir::OpRegCopy(RegStorage r_dest, RegStorage r_src) {
- LIR *res = OpRegCopyNoInsert(r_dest, r_src);
- AppendLIR(res);
- return res;
+void MipsMir2Lir::OpRegCopy(RegStorage r_dest, RegStorage r_src) {
+ if (r_dest != r_src) {
+ LIR *res = OpRegCopyNoInsert(r_dest, r_src);
+ AppendLIR(res);
+ }
}
void MipsMir2Lir::OpRegCopyWide(RegStorage r_dest, RegStorage r_src) {
- bool dest_fp = MIPS_FPREG(r_dest.GetLowReg());
- bool src_fp = MIPS_FPREG(r_src.GetLowReg());
- if (dest_fp) {
- if (src_fp) {
- // FIXME: handle this here - reserve OpRegCopy for 32-bit copies.
- OpRegCopy(RegStorage::Solo64(S2d(r_dest.GetLowReg(), r_dest.GetHighReg())),
- RegStorage::Solo64(S2d(r_src.GetLowReg(), r_src.GetHighReg())));
+ if (r_dest != r_src) {
+ bool dest_fp = MIPS_FPREG(r_dest.GetLowReg());
+ bool src_fp = MIPS_FPREG(r_src.GetLowReg());
+ if (dest_fp) {
+ if (src_fp) {
+ // FIXME: handle this here - reserve OpRegCopy for 32-bit copies.
+ OpRegCopy(RegStorage::Solo64(S2d(r_dest.GetLowReg(), r_dest.GetHighReg())),
+ RegStorage::Solo64(S2d(r_src.GetLowReg(), r_src.GetHighReg())));
+ } else {
+ /* note the operands are swapped for the mtc1 instr */
+ NewLIR2(kMipsMtc1, r_src.GetLowReg(), r_dest.GetLowReg());
+ NewLIR2(kMipsMtc1, r_src.GetHighReg(), r_dest.GetHighReg());
+ }
} else {
- /* note the operands are swapped for the mtc1 instr */
- NewLIR2(kMipsMtc1, r_src.GetLowReg(), r_dest.GetLowReg());
- NewLIR2(kMipsMtc1, r_src.GetHighReg(), r_dest.GetHighReg());
- }
- } else {
- if (src_fp) {
- NewLIR2(kMipsMfc1, r_dest.GetLowReg(), r_src.GetLowReg());
- NewLIR2(kMipsMfc1, r_dest.GetHighReg(), r_src.GetHighReg());
- } else {
- // Handle overlap
- if (r_src.GetHighReg() == r_dest.GetLowReg()) {
- OpRegCopy(r_dest.GetHigh(), r_src.GetHigh());
- OpRegCopy(r_dest.GetLow(), r_src.GetLow());
+ if (src_fp) {
+ NewLIR2(kMipsMfc1, r_dest.GetLowReg(), r_src.GetLowReg());
+ NewLIR2(kMipsMfc1, r_dest.GetHighReg(), r_src.GetHighReg());
} else {
- OpRegCopy(r_dest.GetLow(), r_src.GetLow());
- OpRegCopy(r_dest.GetHigh(), r_src.GetHigh());
+ // Handle overlap
+ if (r_src.GetHighReg() == r_dest.GetLowReg()) {
+ OpRegCopy(r_dest.GetHigh(), r_src.GetHigh());
+ OpRegCopy(r_dest.GetLow(), r_src.GetLow());
+ } else {
+ OpRegCopy(r_dest.GetLow(), r_src.GetLow());
+ OpRegCopy(r_dest.GetHigh(), r_src.GetHigh());
+ }
}
}
}
diff --git a/compiler/dex/quick/mir_to_lir.cc b/compiler/dex/quick/mir_to_lir.cc
index 6d38488..b8ab609 100644
--- a/compiler/dex/quick/mir_to_lir.cc
+++ b/compiler/dex/quick/mir_to_lir.cc
@@ -990,6 +990,9 @@
ResetRegPool();
if (cu_->disable_opt & (1 << kTrackLiveTemps)) {
ClobberAllRegs();
+ // Reset temp allocation to minimize differences when A/B testing.
+ reg_pool_->next_core_reg = 0;
+ reg_pool_->next_fp_reg = 0;
}
if (cu_->disable_opt & (1 << kSuppressLoads)) {
diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h
index 8d593ae..2b6d78b 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -811,6 +811,8 @@
bool MethodBlockCodeGen(BasicBlock* bb);
bool SpecialMIR2LIR(const InlineMethod& special);
void MethodMIR2LIR();
+ // Update LIR for verbose listings.
+ void UpdateLIROffsets();
/*
* @brief Load the address of the dex method into the register.
@@ -1050,7 +1052,7 @@
virtual LIR* OpMem(OpKind op, RegStorage r_base, int disp) = 0;
virtual LIR* OpPcRelLoad(RegStorage reg, LIR* target) = 0;
virtual LIR* OpReg(OpKind op, RegStorage r_dest_src) = 0;
- virtual LIR* OpRegCopy(RegStorage r_dest, RegStorage r_src) = 0;
+ virtual void OpRegCopy(RegStorage r_dest, RegStorage r_src) = 0;
virtual LIR* OpRegCopyNoInsert(RegStorage r_dest, RegStorage r_src) = 0;
virtual LIR* OpRegImm(OpKind op, RegStorage r_dest_src1, int value) = 0;
virtual LIR* OpRegMem(OpKind op, RegStorage r_dest, RegStorage r_base, int offset) = 0;
diff --git a/compiler/dex/quick/x86/codegen_x86.h b/compiler/dex/quick/x86/codegen_x86.h
index fb61627..760290c 100644
--- a/compiler/dex/quick/x86/codegen_x86.h
+++ b/compiler/dex/quick/x86/codegen_x86.h
@@ -232,7 +232,7 @@
LIR* OpMem(OpKind op, RegStorage r_base, int disp);
LIR* OpPcRelLoad(RegStorage reg, LIR* target);
LIR* OpReg(OpKind op, RegStorage r_dest_src);
- LIR* OpRegCopy(RegStorage r_dest, RegStorage r_src);
+ void OpRegCopy(RegStorage r_dest, RegStorage r_src);
LIR* OpRegCopyNoInsert(RegStorage r_dest, RegStorage r_src);
LIR* OpRegImm(OpKind op, RegStorage r_dest_src1, int value);
LIR* OpRegMem(OpKind op, RegStorage r_dest, RegStorage r_base, int offset);
diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc
index 5ba9709..3bff497 100644
--- a/compiler/dex/quick/x86/int_x86.cc
+++ b/compiler/dex/quick/x86/int_x86.cc
@@ -116,52 +116,55 @@
return res;
}
-LIR* X86Mir2Lir::OpRegCopy(RegStorage r_dest, RegStorage r_src) {
- LIR *res = OpRegCopyNoInsert(r_dest, r_src);
- AppendLIR(res);
- return res;
+void X86Mir2Lir::OpRegCopy(RegStorage r_dest, RegStorage r_src) {
+ if (r_dest != r_src) {
+ LIR *res = OpRegCopyNoInsert(r_dest, r_src);
+ AppendLIR(res);
+ }
}
void X86Mir2Lir::OpRegCopyWide(RegStorage r_dest, RegStorage r_src) {
- // FIXME: handle k64BitSolo when we start using them.
- DCHECK(r_dest.IsPair());
- DCHECK(r_src.IsPair());
- bool dest_fp = X86_FPREG(r_dest.GetLowReg());
- bool src_fp = X86_FPREG(r_src.GetLowReg());
- if (dest_fp) {
- if (src_fp) {
- // TODO: we ought to handle this case here - reserve OpRegCopy for 32-bit copies.
- OpRegCopy(RegStorage::Solo64(S2d(r_dest.GetLowReg(), r_dest.GetHighReg())),
- RegStorage::Solo64(S2d(r_src.GetLowReg(), r_src.GetHighReg())));
- } else {
- // TODO: Prevent this from happening in the code. The result is often
- // unused or could have been loaded more easily from memory.
- NewLIR2(kX86MovdxrRR, r_dest.GetLowReg(), r_src.GetLowReg());
- RegStorage r_tmp = AllocTempDouble();
- NewLIR2(kX86MovdxrRR, r_tmp.GetLowReg(), r_src.GetHighReg());
- NewLIR2(kX86PunpckldqRR, r_dest.GetLowReg(), r_tmp.GetLowReg());
- FreeTemp(r_tmp);
- }
- } else {
- if (src_fp) {
- NewLIR2(kX86MovdrxRR, r_dest.GetLowReg(), r_src.GetLowReg());
- NewLIR2(kX86PsrlqRI, r_src.GetLowReg(), 32);
- NewLIR2(kX86MovdrxRR, r_dest.GetHighReg(), r_src.GetLowReg());
- } else {
- // Handle overlap
- if (r_src.GetHighReg() == r_dest.GetLowReg() && r_src.GetLowReg() == r_dest.GetHighReg()) {
- // Deal with cycles.
- RegStorage temp_reg = AllocTemp();
- OpRegCopy(temp_reg, r_dest.GetHigh());
- OpRegCopy(r_dest.GetHigh(), r_dest.GetLow());
- OpRegCopy(r_dest.GetLow(), temp_reg);
- FreeTemp(temp_reg);
- } else if (r_src.GetHighReg() == r_dest.GetLowReg()) {
- OpRegCopy(r_dest.GetHigh(), r_src.GetHigh());
- OpRegCopy(r_dest.GetLow(), r_src.GetLow());
+ if (r_dest != r_src) {
+ // FIXME: handle k64BitSolo when we start using them.
+ DCHECK(r_dest.IsPair());
+ DCHECK(r_src.IsPair());
+ bool dest_fp = X86_FPREG(r_dest.GetLowReg());
+ bool src_fp = X86_FPREG(r_src.GetLowReg());
+ if (dest_fp) {
+ if (src_fp) {
+ // TODO: we ought to handle this case here - reserve OpRegCopy for 32-bit copies.
+ OpRegCopy(RegStorage::Solo64(S2d(r_dest.GetLowReg(), r_dest.GetHighReg())),
+ RegStorage::Solo64(S2d(r_src.GetLowReg(), r_src.GetHighReg())));
} else {
- OpRegCopy(r_dest.GetLow(), r_src.GetLow());
- OpRegCopy(r_dest.GetHigh(), r_src.GetHigh());
+ // TODO: Prevent this from happening in the code. The result is often
+ // unused or could have been loaded more easily from memory.
+ NewLIR2(kX86MovdxrRR, r_dest.GetLowReg(), r_src.GetLowReg());
+ RegStorage r_tmp = AllocTempDouble();
+ NewLIR2(kX86MovdxrRR, r_tmp.GetLowReg(), r_src.GetHighReg());
+ NewLIR2(kX86PunpckldqRR, r_dest.GetLowReg(), r_tmp.GetLowReg());
+ FreeTemp(r_tmp);
+ }
+ } else {
+ if (src_fp) {
+ NewLIR2(kX86MovdrxRR, r_dest.GetLowReg(), r_src.GetLowReg());
+ NewLIR2(kX86PsrlqRI, r_src.GetLowReg(), 32);
+ NewLIR2(kX86MovdrxRR, r_dest.GetHighReg(), r_src.GetLowReg());
+ } else {
+ // Handle overlap
+ if (r_src.GetHighReg() == r_dest.GetLowReg() && r_src.GetLowReg() == r_dest.GetHighReg()) {
+ // Deal with cycles.
+ RegStorage temp_reg = AllocTemp();
+ OpRegCopy(temp_reg, r_dest.GetHigh());
+ OpRegCopy(r_dest.GetHigh(), r_dest.GetLow());
+ OpRegCopy(r_dest.GetLow(), temp_reg);
+ FreeTemp(temp_reg);
+ } else if (r_src.GetHighReg() == r_dest.GetLowReg()) {
+ OpRegCopy(r_dest.GetHigh(), r_src.GetHigh());
+ OpRegCopy(r_dest.GetLow(), r_src.GetLow());
+ } else {
+ OpRegCopy(r_dest.GetLow(), r_src.GetLow());
+ OpRegCopy(r_dest.GetHigh(), r_src.GetHigh());
+ }
}
}
}
diff --git a/compiler/dex/quick/x86/utility_x86.cc b/compiler/dex/quick/x86/utility_x86.cc
index 00bebd2..4d45055 100644
--- a/compiler/dex/quick/x86/utility_x86.cc
+++ b/compiler/dex/quick/x86/utility_x86.cc
@@ -426,7 +426,8 @@
RegStorage t_reg = AllocTemp();
OpRegCopy(t_reg, r_src1);
OpRegReg(op, t_reg, r_src2);
- LIR* res = OpRegCopy(r_dest, t_reg);
+ LIR* res = OpRegCopyNoInsert(r_dest, t_reg);
+ AppendLIR(res);
FreeTemp(t_reg);
return res;
}