diff options
author | Vladimir Marko <vmarko@google.com> | 2015-02-18 17:52:39 +0000 |
---|---|---|
committer | Vladimir Marko <vmarko@google.com> | 2015-02-18 17:52:39 +0000 |
commit | 22c7f5bc70d0c8f3e5915b7fb98c9f9930cfdff0 (patch) | |
tree | 9a2890b5abbbd296bb04d56c8866212bb6b58775 | |
parent | ca47c2ece95c9ea511864c51c5c3923e087d4499 (diff) | |
download | art-22c7f5bc70d0c8f3e5915b7fb98c9f9930cfdff0.tar.gz art-22c7f5bc70d0c8f3e5915b7fb98c9f9930cfdff0.tar.bz2 art-22c7f5bc70d0c8f3e5915b7fb98c9f9930cfdff0.zip |
Distinguish FP and integral constants in LVN.
Change-Id: I31a58ff19fb95a2f56420359e50332c1dce6cbc7
-rw-r--r-- | compiler/dex/local_value_numbering.cc | 79 | ||||
-rw-r--r-- | compiler/dex/local_value_numbering.h | 2 | ||||
-rw-r--r-- | compiler/dex/local_value_numbering_test.cc | 78 |
3 files changed, 117 insertions, 42 deletions
diff --git a/compiler/dex/local_value_numbering.cc b/compiler/dex/local_value_numbering.cc index d677680777..99b6683b26 100644 --- a/compiler/dex/local_value_numbering.cc +++ b/compiler/dex/local_value_numbering.cc @@ -1214,6 +1214,31 @@ uint16_t LocalValueNumbering::HandlePhi(MIR* mir) { return value_name; } +uint16_t LocalValueNumbering::HandleConst(MIR* mir, uint32_t value) { + RegLocation raw_dest = gvn_->GetMirGraph()->GetRawDest(mir); + uint16_t res; + if (value == 0u && raw_dest.ref) { + res = GlobalValueNumbering::kNullValue; + } else { + Instruction::Code op = raw_dest.fp ? Instruction::CONST_HIGH16 : Instruction::CONST; + res = gvn_->LookupValue(op, Low16Bits(value), High16Bits(value), 0); + } + SetOperandValue(mir->ssa_rep->defs[0], res); + return res; +} + +uint16_t LocalValueNumbering::HandleConstWide(MIR* mir, uint64_t value) { + RegLocation raw_dest = gvn_->GetMirGraph()->GetRawDest(mir); + Instruction::Code op = raw_dest.fp ? Instruction::CONST_HIGH16 : Instruction::CONST; + uint32_t low_word = Low32Bits(value); + uint32_t high_word = High32Bits(value); + uint16_t low_res = gvn_->LookupValue(op, Low16Bits(low_word), High16Bits(low_word), 1); + uint16_t high_res = gvn_->LookupValue(op, Low16Bits(high_word), High16Bits(high_word), 2); + uint16_t res = gvn_->LookupValue(op, low_res, high_res, 3); + SetOperandValueWide(mir->ssa_rep->defs[0], res); + return res; +} + uint16_t LocalValueNumbering::HandleAGet(MIR* mir, uint16_t opcode) { uint16_t array = GetOperandValue(mir->ssa_rep->uses[0]); HandleNullCheck(mir, array); @@ -1652,58 +1677,28 @@ uint16_t LocalValueNumbering::GetValueNumber(MIR* mir) { break; case Instruction::CONST_HIGH16: - if (mir->dalvikInsn.vB != 0) { - res = gvn_->LookupValue(Instruction::CONST, 0, mir->dalvikInsn.vB, 0); - SetOperandValue(mir->ssa_rep->defs[0], res); - break; - } - FALLTHROUGH_INTENDED; + res = HandleConst(mir, mir->dalvikInsn.vB << 16); + break; case Instruction::CONST: case Instruction::CONST_4: case Instruction::CONST_16: - if (mir->dalvikInsn.vB == 0 && gvn_->GetMirGraph()->GetRawDest(mir).ref) { - res = GlobalValueNumbering::kNullValue; - } else { - res = gvn_->LookupValue(Instruction::CONST, Low16Bits(mir->dalvikInsn.vB), - High16Bits(mir->dalvikInsn.vB), 0); - } - SetOperandValue(mir->ssa_rep->defs[0], res); + res = HandleConst(mir, mir->dalvikInsn.vB); break; case Instruction::CONST_WIDE_16: - case Instruction::CONST_WIDE_32: { - uint16_t low_res = gvn_->LookupValue(Instruction::CONST, Low16Bits(mir->dalvikInsn.vB), - High16Bits(mir->dalvikInsn.vB), 1); - uint16_t high_res; - if (mir->dalvikInsn.vB & 0x80000000) { - high_res = gvn_->LookupValue(Instruction::CONST, 0xffff, 0xffff, 2); - } else { - high_res = gvn_->LookupValue(Instruction::CONST, 0, 0, 2); - } - res = gvn_->LookupValue(Instruction::CONST, low_res, high_res, 3); - SetOperandValueWide(mir->ssa_rep->defs[0], res); - } + case Instruction::CONST_WIDE_32: + res = HandleConstWide( + mir, + mir->dalvikInsn.vB + + ((mir->dalvikInsn.vB & 0x80000000) != 0 ? UINT64_C(0xffffffff00000000) : 0u)); break; - case Instruction::CONST_WIDE: { - uint32_t low_word = Low32Bits(mir->dalvikInsn.vB_wide); - uint32_t high_word = High32Bits(mir->dalvikInsn.vB_wide); - uint16_t low_res = gvn_->LookupValue(Instruction::CONST, Low16Bits(low_word), - High16Bits(low_word), 1); - uint16_t high_res = gvn_->LookupValue(Instruction::CONST, Low16Bits(high_word), - High16Bits(high_word), 2); - res = gvn_->LookupValue(Instruction::CONST, low_res, high_res, 3); - SetOperandValueWide(mir->ssa_rep->defs[0], res); - } + case Instruction::CONST_WIDE: + res = HandleConstWide(mir, mir->dalvikInsn.vB_wide); break; - case Instruction::CONST_WIDE_HIGH16: { - uint16_t low_res = gvn_->LookupValue(Instruction::CONST, 0, 0, 1); - uint16_t high_res = gvn_->LookupValue(Instruction::CONST, 0, - Low16Bits(mir->dalvikInsn.vB), 2); - res = gvn_->LookupValue(Instruction::CONST, low_res, high_res, 3); - SetOperandValueWide(mir->ssa_rep->defs[0], res); - } + case Instruction::CONST_WIDE_HIGH16: + res = HandleConstWide(mir, static_cast<uint64_t>(mir->dalvikInsn.vB) << 48); break; case Instruction::ARRAY_LENGTH: { diff --git a/compiler/dex/local_value_numbering.h b/compiler/dex/local_value_numbering.h index f51b886112..bfacf8ea53 100644 --- a/compiler/dex/local_value_numbering.h +++ b/compiler/dex/local_value_numbering.h @@ -308,6 +308,8 @@ class LocalValueNumbering : public DeletableArenaObject<kArenaAllocMisc> { void HandleEscapingRef(uint16_t base); void HandleInvokeArgs(const MIR* mir, const LocalValueNumbering* mir_lvn); uint16_t HandlePhi(MIR* mir); + uint16_t HandleConst(MIR* mir, uint32_t value); + uint16_t HandleConstWide(MIR* mir, uint64_t value); uint16_t HandleAGet(MIR* mir, uint16_t opcode); void HandleAPut(MIR* mir, uint16_t opcode); uint16_t HandleIGet(MIR* mir, uint16_t opcode); diff --git a/compiler/dex/local_value_numbering_test.cc b/compiler/dex/local_value_numbering_test.cc index 4490f0657b..d1c3a6b4ba 100644 --- a/compiler/dex/local_value_numbering_test.cc +++ b/compiler/dex/local_value_numbering_test.cc @@ -780,6 +780,7 @@ TEST_F(LocalValueNumberingTest, DivZeroCheck) { TEST_F(LocalValueNumberingTest, ConstWide) { static const MIRDef mirs[] = { + // Core reg constants. DEF_CONST(Instruction::CONST_WIDE_16, 0u, 0), DEF_CONST(Instruction::CONST_WIDE_16, 1u, 1), DEF_CONST(Instruction::CONST_WIDE_16, 2u, -1), @@ -801,9 +802,86 @@ TEST_F(LocalValueNumberingTest, ConstWide) { DEF_CONST(Instruction::CONST_WIDE, 18u, (INT64_C(1) << 48) - 1), DEF_CONST(Instruction::CONST_WIDE, 19u, (INT64_C(-1) << 48) + 1), DEF_CONST(Instruction::CONST_WIDE, 20u, (INT64_C(-1) << 48) - 1), + // FP reg constants. + DEF_CONST(Instruction::CONST_WIDE_16, 21u, 0), + DEF_CONST(Instruction::CONST_WIDE_16, 22u, 1), + DEF_CONST(Instruction::CONST_WIDE_16, 23u, -1), + DEF_CONST(Instruction::CONST_WIDE_32, 24u, 1 << 16), + DEF_CONST(Instruction::CONST_WIDE_32, 25u, -1 << 16), + DEF_CONST(Instruction::CONST_WIDE_32, 26u, (1 << 16) + 1), + DEF_CONST(Instruction::CONST_WIDE_32, 27u, (1 << 16) - 1), + DEF_CONST(Instruction::CONST_WIDE_32, 28u, -(1 << 16) + 1), + DEF_CONST(Instruction::CONST_WIDE_32, 29u, -(1 << 16) - 1), + DEF_CONST(Instruction::CONST_WIDE, 30u, INT64_C(1) << 32), + DEF_CONST(Instruction::CONST_WIDE, 31u, INT64_C(-1) << 32), + DEF_CONST(Instruction::CONST_WIDE, 32u, (INT64_C(1) << 32) + 1), + DEF_CONST(Instruction::CONST_WIDE, 33u, (INT64_C(1) << 32) - 1), + DEF_CONST(Instruction::CONST_WIDE, 34u, (INT64_C(-1) << 32) + 1), + DEF_CONST(Instruction::CONST_WIDE, 35u, (INT64_C(-1) << 32) - 1), + DEF_CONST(Instruction::CONST_WIDE_HIGH16, 36u, 1), // Effectively 1 << 48. + DEF_CONST(Instruction::CONST_WIDE_HIGH16, 37u, 0xffff), // Effectively -1 << 48. + DEF_CONST(Instruction::CONST_WIDE, 38u, (INT64_C(1) << 48) + 1), + DEF_CONST(Instruction::CONST_WIDE, 39u, (INT64_C(1) << 48) - 1), + DEF_CONST(Instruction::CONST_WIDE, 40u, (INT64_C(-1) << 48) + 1), + DEF_CONST(Instruction::CONST_WIDE, 41u, (INT64_C(-1) << 48) - 1), }; PrepareMIRs(mirs); + for (size_t i = arraysize(mirs) / 2u; i != arraysize(mirs); ++i) { + cu_.mir_graph->reg_location_[mirs_[i].ssa_rep->defs[0]].fp = true; + } + PerformLVN(); + for (size_t i = 0u; i != mir_count_; ++i) { + for (size_t j = i + 1u; j != mir_count_; ++j) { + EXPECT_NE(value_names_[i], value_names_[j]) << i << " " << j; + } + } +} + +TEST_F(LocalValueNumberingTest, Const) { + static const MIRDef mirs[] = { + // Core reg constants. + DEF_CONST(Instruction::CONST_4, 0u, 0), + DEF_CONST(Instruction::CONST_4, 1u, 1), + DEF_CONST(Instruction::CONST_4, 2u, -1), + DEF_CONST(Instruction::CONST_16, 3u, 1 << 4), + DEF_CONST(Instruction::CONST_16, 4u, -1 << 4), + DEF_CONST(Instruction::CONST_16, 5u, (1 << 4) + 1), + DEF_CONST(Instruction::CONST_16, 6u, (1 << 4) - 1), + DEF_CONST(Instruction::CONST_16, 7u, -(1 << 4) + 1), + DEF_CONST(Instruction::CONST_16, 8u, -(1 << 4) - 1), + DEF_CONST(Instruction::CONST_HIGH16, 9u, 1), // Effectively 1 << 16. + DEF_CONST(Instruction::CONST_HIGH16, 10u, 0xffff), // Effectively -1 << 16. + DEF_CONST(Instruction::CONST, 11u, (1 << 16) + 1), + DEF_CONST(Instruction::CONST, 12u, (1 << 16) - 1), + DEF_CONST(Instruction::CONST, 13u, (-1 << 16) + 1), + DEF_CONST(Instruction::CONST, 14u, (-1 << 16) - 1), + // FP reg constants. + DEF_CONST(Instruction::CONST_4, 15u, 0), + DEF_CONST(Instruction::CONST_4, 16u, 1), + DEF_CONST(Instruction::CONST_4, 17u, -1), + DEF_CONST(Instruction::CONST_16, 18u, 1 << 4), + DEF_CONST(Instruction::CONST_16, 19u, -1 << 4), + DEF_CONST(Instruction::CONST_16, 20u, (1 << 4) + 1), + DEF_CONST(Instruction::CONST_16, 21u, (1 << 4) - 1), + DEF_CONST(Instruction::CONST_16, 22u, -(1 << 4) + 1), + DEF_CONST(Instruction::CONST_16, 23u, -(1 << 4) - 1), + DEF_CONST(Instruction::CONST_HIGH16, 24u, 1), // Effectively 1 << 16. + DEF_CONST(Instruction::CONST_HIGH16, 25u, 0xffff), // Effectively -1 << 16. + DEF_CONST(Instruction::CONST, 26u, (1 << 16) + 1), + DEF_CONST(Instruction::CONST, 27u, (1 << 16) - 1), + DEF_CONST(Instruction::CONST, 28u, (-1 << 16) + 1), + DEF_CONST(Instruction::CONST, 29u, (-1 << 16) - 1), + // null reference constant. + DEF_CONST(Instruction::CONST_4, 30u, 0), + }; + + PrepareMIRs(mirs); + static_assert((arraysize(mirs) & 1) != 0, "missing null or unmatched fp/core"); + cu_.mir_graph->reg_location_[arraysize(mirs) - 1].ref = true; + for (size_t i = arraysize(mirs) / 2u; i != arraysize(mirs) - 1; ++i) { + cu_.mir_graph->reg_location_[mirs_[i].ssa_rep->defs[0]].fp = true; + } PerformLVN(); for (size_t i = 0u; i != mir_count_; ++i) { for (size_t j = i + 1u; j != mir_count_; ++j) { |