diff options
| author | 2021-04-22 15:15:13 -0700 | |
|---|---|---|
| committer | 2021-04-30 03:32:43 +0000 | |
| commit | ba320165975387e780be2bd16fac4a522411b59c (patch) | |
| tree | 914a3c6b730e662131ad082ba3a9e1f51955efa8 | |
| parent | 7a76e234402df797c2cd97d0defbb507ed9a7329 (diff) | |
Improve simplifier slightly
It's possible thanks to the dead-code-elimination and other passes to
end up with a PredicatedInstanceFieldGet that either has a null or a
'never-null' target value. We can simplify this down to either the
default value or a normal ifield-get respectively.
Test: ./test.py --host
Change-Id: I92d9ff159a7b30294d29dbf4349d201dc654f0e1
| -rw-r--r-- | compiler/optimizing/instruction_simplifier.cc | 61 | ||||
| -rw-r--r-- | test/530-checker-instance-of-simplifier/jasmin/Main.j | 5 |
2 files changed, 36 insertions, 30 deletions
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc index 23a432ef9d..a6104effd7 100644 --- a/compiler/optimizing/instruction_simplifier.cc +++ b/compiler/optimizing/instruction_simplifier.cc @@ -949,36 +949,12 @@ void InstructionSimplifierVisitor::VisitPredicatedInstanceFieldGet( HPredicatedInstanceFieldGet* pred_get) { HInstruction* target = pred_get->GetTarget(); HInstruction* default_val = pred_get->GetDefaultValue(); - // TODO Technically we could end up with a case where the target isn't a phi - // (allowing us to eliminate the instruction and replace with either a - // InstanceFieldGet or the default) but due to the ordering of compilation - // passes this can't happen in ART. - if (!target->IsPhi() || !default_val->IsPhi() || default_val->GetBlock() != target->GetBlock()) { - // Already reduced the target or the phi selection will differ between the - // target and default. + if (target->IsNullConstant()) { + pred_get->ReplaceWith(default_val); + pred_get->GetBlock()->RemoveInstruction(pred_get); + RecordSimplification(); return; - } - DCHECK_EQ(default_val->InputCount(), target->InputCount()); - // In the same block both phis only one non-null we can remove the phi from default_val. - HInstruction* single_value = nullptr; - auto inputs = target->GetInputs(); - for (auto [input, idx] : ZipCount(MakeIterationRange(inputs))) { - if (input->CanBeNull()) { - if (single_value == nullptr) { - single_value = default_val->InputAt(idx); - } else if (single_value != default_val->InputAt(idx) && - !single_value->Equals(default_val->InputAt(idx))) { - // Multiple values are associated with potential nulls, can't combine. - return; - } - } - } - if (single_value == nullptr) { - // None of the inputs can be null so we can just remove the predicatedness - // of this instruction. - DCHECK(std::none_of(inputs.cbegin(), inputs.cend(), [](const HInstruction* input) { - return input->CanBeNull(); - })); + } else if (!target->CanBeNull()) { HInstruction* replace_with = new (GetGraph()->GetAllocator()) HInstanceFieldGet(pred_get->GetTarget(), pred_get->GetFieldInfo().GetField(), @@ -996,7 +972,32 @@ void InstructionSimplifierVisitor::VisitPredicatedInstanceFieldGet( pred_get->ReplaceWith(replace_with); pred_get->GetBlock()->RemoveInstruction(pred_get); RecordSimplification(); - } else if (single_value->StrictlyDominates(pred_get)) { + return; + } + if (!target->IsPhi() || !default_val->IsPhi() || default_val->GetBlock() != target->GetBlock()) { + // The iget has already been reduced. We know the target or the phi + // selection will differ between the target and default. + return; + } + DCHECK_EQ(default_val->InputCount(), target->InputCount()); + // In the same block both phis only one non-null we can remove the phi from default_val. + HInstruction* single_value = nullptr; + auto inputs = target->GetInputs(); + for (auto [input, idx] : ZipCount(MakeIterationRange(inputs))) { + if (input->CanBeNull()) { + if (single_value == nullptr) { + single_value = default_val->InputAt(idx); + } else if (single_value != default_val->InputAt(idx) && + !single_value->Equals(default_val->InputAt(idx))) { + // Multiple values are associated with potential nulls, can't combine. + return; + } + } + } + DCHECK(single_value != nullptr) << "All target values are non-null but the phi as a whole still" + << " can be null? This should not be possible." << std::endl + << pred_get->DumpWithArgs(); + if (single_value->StrictlyDominates(pred_get)) { // Combine all the maybe null values into one. pred_get->ReplaceInput(single_value, 0); RecordSimplification(); diff --git a/test/530-checker-instance-of-simplifier/jasmin/Main.j b/test/530-checker-instance-of-simplifier/jasmin/Main.j index 07152eda06..83cb4fa5c6 100644 --- a/test/530-checker-instance-of-simplifier/jasmin/Main.j +++ b/test/530-checker-instance-of-simplifier/jasmin/Main.j @@ -28,6 +28,11 @@ ; ;; CHECK-START: int Main.$noinline$test(boolean) instruction_simplifier (after) ;; CHECK-NOT: InstanceOf +; +;; CHECK-START: int Main.$noinline$test(boolean) instruction_simplifier$before_codegen (after) +;; CHECK-NOT: InstanceFieldSet +;; CHECK-NOT: InstanceFieldGet +;; CHECK-NOT: PredicatedInstanceFieldGet ; public static int $noinline$test(boolean escape) { ; Foo f = new Foo(); |