summaryrefslogtreecommitdiffstats
path: root/compiler/dex/local_value_numbering_test.cc
diff options
context:
space:
mode:
authorRazvan A Lupusoru <razvan.a.lupusoru@intel.com>2014-11-14 14:36:55 -0800
committerRazvan A Lupusoru <razvan.a.lupusoru@intel.com>2014-11-22 00:57:31 +0000
commite0951144d71a4791a5319ec507d84fce373018e0 (patch)
tree5b065aac7c7fc419f65a74b8234908e972462f02 /compiler/dex/local_value_numbering_test.cc
parentda4b7e8979e9b7de634aecee62da6ce867ccaa8d (diff)
downloadart-e0951144d71a4791a5319ec507d84fce373018e0.tar.gz
art-e0951144d71a4791a5319ec507d84fce373018e0.tar.bz2
art-e0951144d71a4791a5319ec507d84fce373018e0.zip
ART: Add div-zero check elimination to LVN/GVN
GVN has been updated to also consider div/rem zero check elimination. This means that whenever a divisor is used in two sequential divisions, the second division will surely not throw exception. The algorithm has been updated to work on global level by considering splits and merges. Obviously, if "div_zero" checked on one path but not the other, at merge point consider that division has not been eliminated. One big deficiency of this algorithm is that it does not consider literals in the divisor. Namely, in cases where the operand is a literal or a constant (literal created by another bytecode), it does not mark as divide by zero checked. However, in reality this is not an issue because none of the backends generate the divide by zero check when the constant value is known. Issue: CAR-868 Category: device enablement Domain: AOSP.ART-ME Origin: internal Upstream-Candidate: yes Change-Id: I617569055c73a45e13e2a83392b99b48f4e33362 Signed-off-by: Razvan A Lupusoru <razvan.a.lupusoru@intel.com>
Diffstat (limited to 'compiler/dex/local_value_numbering_test.cc')
-rw-r--r--compiler/dex/local_value_numbering_test.cc26
1 files changed, 26 insertions, 0 deletions
diff --git a/compiler/dex/local_value_numbering_test.cc b/compiler/dex/local_value_numbering_test.cc
index 824c323b4b..20c005b94d 100644
--- a/compiler/dex/local_value_numbering_test.cc
+++ b/compiler/dex/local_value_numbering_test.cc
@@ -84,6 +84,10 @@ class LocalValueNumberingTest : public testing::Test {
{ opcode, 0u, 0u, 1, { reg }, 0, { } }
#define DEF_UNIQUE_REF(opcode, reg) \
{ opcode, 0u, 0u, 0, { }, 1, { reg } } // CONST_CLASS, CONST_STRING, NEW_ARRAY, ...
+#define DEF_DIV_REM(opcode, result, dividend, divisor) \
+ { opcode, 0u, 0u, 2, { dividend, divisor }, 1, { result } }
+#define DEF_DIV_REM_WIDE(opcode, result, dividend, divisor) \
+ { opcode, 0u, 0u, 4, { dividend, dividend + 1, divisor, divisor + 1 }, 2, { result, result + 1 } }
void DoPrepareIFields(const IFieldDef* defs, size_t count) {
cu_.mir_graph->ifield_lowering_infos_.clear();
@@ -735,4 +739,26 @@ TEST_F(LocalValueNumberingTest, ClInitOnSget) {
EXPECT_NE(value_names_[0], value_names_[3]);
}
+TEST_F(LocalValueNumberingTest, DivZeroCheck) {
+ static const MIRDef mirs[] = {
+ DEF_DIV_REM(Instruction::DIV_INT, 1u, 10u, 20u),
+ DEF_DIV_REM(Instruction::DIV_INT, 2u, 20u, 20u),
+ DEF_DIV_REM(Instruction::DIV_INT_2ADDR, 3u, 10u, 1u),
+ DEF_DIV_REM(Instruction::REM_INT, 4u, 30u, 20u),
+ DEF_DIV_REM_WIDE(Instruction::REM_LONG, 5u, 12u, 14u),
+ DEF_DIV_REM_WIDE(Instruction::DIV_LONG_2ADDR, 7u, 16u, 14u),
+ };
+
+ static const bool expected_ignore_div_zero_check[] = {
+ false, true, false, true, false, true,
+ };
+
+ PrepareMIRs(mirs);
+ PerformLVN();
+ for (size_t i = 0u; i != mir_count_; ++i) {
+ int expected = expected_ignore_div_zero_check[i] ? MIR_IGNORE_DIV_ZERO_CHECK : 0u;
+ EXPECT_EQ(expected, mirs_[i].optimization_flags) << i;
+ }
+}
+
} // namespace art