Deoptimization-based BCE for unknown loop bounds.
For loop like:
for (int i = start; i < end; i++) {
array[i] = 1;
}
We add the following to the loop pre-header:
if (start < 0) deoptimize();
if (end > array.length) deoptimize();
Then we can eliminate bounds-check of array[i] inside the loop.
We also take care of indexing with induction variable plus some offsets,
like array[i - 1]/array[i + 1] inside the loop, and adjust the condition
for deoptimization accordingly.
Change-Id: I9e24c6b5e134ff95eff5b5605ff8f95d6546616f
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index c158ddf..ca470f4 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -498,6 +498,28 @@
}
}
+void HEnvironment::CopyFromWithLoopPhiAdjustment(HEnvironment* env,
+ HBasicBlock* loop_header) {
+ DCHECK(loop_header->IsLoopHeader());
+ for (size_t i = 0; i < env->Size(); i++) {
+ HInstruction* instruction = env->GetInstructionAt(i);
+ SetRawEnvAt(i, instruction);
+ if (instruction == nullptr) {
+ continue;
+ }
+ if (instruction->IsLoopHeaderPhi() && (instruction->GetBlock() == loop_header)) {
+ // At the end of the loop pre-header, the corresponding value for instruction
+ // is the first input of the phi.
+ HInstruction* initial = instruction->AsPhi()->InputAt(0);
+ DCHECK(initial->GetBlock()->Dominates(loop_header));
+ SetRawEnvAt(i, initial);
+ initial->AddEnvUseAt(this, i);
+ } else {
+ instruction->AddEnvUseAt(this, i);
+ }
+ }
+}
+
void HEnvironment::RemoveAsUserOfInput(size_t index) const {
const HUserRecord<HEnvironment*> user_record = vregs_.Get(index);
user_record.GetInstruction()->RemoveEnvironmentUser(user_record.GetUseNode());