diff options
author | Alex Light <allight@google.com> | 2021-03-30 17:17:50 -0700 |
---|---|---|
committer | Alex Light <allight@google.com> | 2021-03-31 20:57:58 +0000 |
commit | e4f7fef5b3df18e7aab15307f39ae77998e4913d (patch) | |
tree | 710717b876792242b08e88b1a4c8ac53b99f35a4 /compiler | |
parent | b2a1416f6d7031d8f255398407a3e8a2bb6d6447 (diff) |
Handle predicated-gets with default values
Due to an oversight the default-value of a PredicatedGet did not
support being a Default value. This fixes that oversight.
Test: ./art/tools/compile-jar.py --profile-line 'HSLe/k/a/g/i;->i(Le/k/a/g/d;Ljava/io/OutputStream;)V' --arch arm64 ~/no.nrk.mobil.radio_10922_base_split.apk --compiler-filter=speed-profile --dump-stats -j1 --force-allow-oj-inlines
Test: LoadStoreEliminationTest.PredicatedLoadDefaultValue
Bug: 183898383
Change-Id: I11bccddb0b5a5c2e958690864ff2d4449a9f2fad
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/optimizing/load_store_elimination.cc | 6 | ||||
-rw-r--r-- | compiler/optimizing/load_store_elimination_test.cc | 83 |
2 files changed, 88 insertions, 1 deletions
diff --git a/compiler/optimizing/load_store_elimination.cc b/compiler/optimizing/load_store_elimination.cc index b1ec62a12d..1ea2ece004 100644 --- a/compiler/optimizing/load_store_elimination.cc +++ b/compiler/optimizing/load_store_elimination.cc @@ -3613,9 +3613,13 @@ HInstruction* LSEVisitor::GetPartialValueAt(HNewInstance* orig_new_inst, HInstru HInstruction* res = Replacement(pred).GetInstruction(); LSE_VLOG << pred << " materialized to " << res->DumpWithArgs(); return res; + } else if (pred.IsDefault()) { + HInstruction* res = GetDefaultValue(read->GetType()); + LSE_VLOG << pred << " materialized to " << res->DumpWithArgs(); + return res; } LOG(FATAL) << "Unable to find unescaped value at " << read->DumpWithArgs() - << "! This should be impossible!"; + << "! This should be impossible! Value is " << pred; UNREACHABLE(); } diff --git a/compiler/optimizing/load_store_elimination_test.cc b/compiler/optimizing/load_store_elimination_test.cc index 9ba364e97b..eb5079fb38 100644 --- a/compiler/optimizing/load_store_elimination_test.cc +++ b/compiler/optimizing/load_store_elimination_test.cc @@ -6242,6 +6242,89 @@ TEST_F(LoadStoreEliminationTest, PredicatedLoad3) { // // ENTRY // obj = new Obj(); +// if (parameter_value) { +// // LEFT +// obj.field = 3; +// escape(obj); +// } else { +// // RIGHT - Leave it as default value +// } +// EXIT +// predicated-ELIMINATE +// return obj.field +TEST_F(LoadStoreEliminationTest, PredicatedLoadDefaultValue) { + VariableSizedHandleScope vshs(Thread::Current()); + CreateGraph(/*handles=*/&vshs); + AdjacencyListGraph blks(SetupFromAdjacencyList("entry", + "exit", + {{"entry", "left"}, + {"entry", "right"}, + {"left", "breturn"}, + {"right", "breturn"}, + {"breturn", "exit"}})); +#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name) + GET_BLOCK(entry); + GET_BLOCK(exit); + GET_BLOCK(breturn); + GET_BLOCK(left); + GET_BLOCK(right); +#undef GET_BLOCK + EnsurePredecessorOrder(breturn, {left, right}); + HInstruction* bool_value = MakeParam(DataType::Type::kBool); + HInstruction* null_const = graph_->GetNullConstant(); + HInstruction* c0 = graph_->GetIntConstant(0); + HInstruction* c3 = graph_->GetIntConstant(3); + + HInstruction* cls = MakeClassLoad(); + HInstruction* new_inst = MakeNewInstance(cls); + HInstruction* if_inst = new (GetAllocator()) HIf(bool_value); + entry->AddInstruction(cls); + entry->AddInstruction(new_inst); + entry->AddInstruction(if_inst); + ManuallyBuildEnvFor(cls, {}); + new_inst->CopyEnvironmentFrom(cls->GetEnvironment()); + + HInstruction* write_left = MakeIFieldSet(new_inst, c3, MemberOffset(32)); + HInstruction* call_left = MakeInvoke(DataType::Type::kVoid, { new_inst }); + HInstruction* goto_left = new (GetAllocator()) HGoto(); + left->AddInstruction(write_left); + left->AddInstruction(call_left); + left->AddInstruction(goto_left); + call_left->CopyEnvironmentFrom(cls->GetEnvironment()); + + HInstruction* goto_right = new (GetAllocator()) HGoto(); + right->AddInstruction(goto_right); + + HInstruction* read_bottom = MakeIFieldGet(new_inst, DataType::Type::kInt32, MemberOffset(32)); + HInstruction* return_exit = new (GetAllocator()) HReturn(read_bottom); + breturn->AddInstruction(read_bottom); + breturn->AddInstruction(return_exit); + + SetupExit(exit); + + // PerformLSE expects this to be empty. + graph_->ClearDominanceInformation(); + LOG(INFO) << "Pre LSE " << blks; + PerformLSEWithPartial(); + LOG(INFO) << "Post LSE " << blks; + + EXPECT_INS_REMOVED(read_bottom); + EXPECT_INS_RETAINED(write_left); + EXPECT_INS_RETAINED(call_left); + HPredicatedInstanceFieldGet* pred_get = + FindSingleInstruction<HPredicatedInstanceFieldGet>(graph_, breturn); + HPhi* merge_alloc = FindSingleInstruction<HPhi>(graph_, breturn); + ASSERT_NE(merge_alloc, nullptr); + EXPECT_TRUE(merge_alloc->InputAt(0)->IsNewInstance()) << *merge_alloc; + EXPECT_EQ(merge_alloc->InputAt(0)->InputAt(0), cls) << *merge_alloc << " cls? " << *cls; + EXPECT_EQ(merge_alloc->InputAt(1), null_const); + ASSERT_NE(pred_get, nullptr); + EXPECT_INS_EQ(pred_get->GetTarget(), merge_alloc); + EXPECT_INS_EQ(pred_get->GetDefaultValue(), c0) << " pred-get is: " << *pred_get; +} + +// // ENTRY +// obj = new Obj(); // // ALL should be kept // switch (parameter_value) { // case 1: |