Fix branch bug (showed up in codegen for debug)
There are a few "safe" optimizations in the compiler - removing
register copies where source and target are the same, deleting
branches to the next instruction, etc. One of the redundant
branch optimizations, however, was incorrect and resulted in
a good branch being deleted. This one showed up in the debug
build, and resulted in a failure to do a suspend check (because
the branch to the suspend check was deleted).
I had hoped that this but might also be the case of some
other unexpected failures, but unfortunately I was only able
to trigger it when doing a "codegen for debug" build.
The source of the bug was a confusion around 16 v/ 32-bit
unconditional branch encodings. For a 32-bit unconditional
branch, going to the next instruction means an displacement
of zero. However, for 16-bit branches, the next instruction
is represented by a displacement of -1.
To help track down this sort of thing in the future, this CL
also adds a new optimization disable flag: kSafeOptimizations.
This will allow us to really turn off all optimizations for A/B
testing.
Also in this CL we are re-enabling the ability to promote argument
registers and improving somewhat the code sequence for suspend
check when debug is enabled.
Change-Id: Ib6b202746eac751cab3b4609805a389c18cb67b2
diff --git a/src/compiler/codegen/arm/Assemble.cc b/src/compiler/codegen/arm/Assemble.cc
index a1f7bd7..2c13107 100644
--- a/src/compiler/codegen/arm/Assemble.cc
+++ b/src/compiler/codegen/arm/Assemble.cc
@@ -1142,7 +1142,8 @@
intptr_t target = targetLIR->offset;
int delta = target - pc;
lir->operands[0] = delta >> 1;
- if (lir->operands[0] == 0) { // Useless branch?
+ if (!(cUnit->disableOpt & (1 << kSafeOptimizations)) &&
+ lir->operands[0] == 0) { // Useless branch
lir->flags.isNop = true;
res = kRetryAll;
}
@@ -1157,12 +1158,13 @@
lir->operands[0] = 0;
oatSetupResourceMasks(lir);
res = kRetryAll;
- }
- lir->operands[0] = delta >> 1;
- if ((lir->operands[0] == 0) ||
- (lir->operands[0] == -1)) { // Useless branch?
- lir->flags.isNop = true;
- res = kRetryAll;
+ } else {
+ lir->operands[0] = delta >> 1;
+ if (!(cUnit->disableOpt & (1 << kSafeOptimizations)) &&
+ lir->operands[0] == -1) { // Useless branch
+ lir->flags.isNop = true;
+ res = kRetryAll;
+ }
}
} else if (lir->opcode == kThumbBlx1) {
DCHECK(NEXT_LIR(lir)->opcode == kThumbBlx2);