Distinguish FP and integral constants in LVN.
Change-Id: I31a58ff19fb95a2f56420359e50332c1dce6cbc7
diff --git a/compiler/dex/local_value_numbering.cc b/compiler/dex/local_value_numbering.cc
index d677680..99b6683 100644
--- a/compiler/dex/local_value_numbering.cc
+++ b/compiler/dex/local_value_numbering.cc
@@ -1214,6 +1214,31 @@
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 @@
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 f51b886..bfacf8e 100644
--- a/compiler/dex/local_value_numbering.h
+++ b/compiler/dex/local_value_numbering.h
@@ -308,6 +308,8 @@
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 4490f06..d1c3a6b 100644
--- a/compiler/dex/local_value_numbering_test.cc
+++ b/compiler/dex/local_value_numbering_test.cc
@@ -780,6 +780,7 @@
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 @@
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) {