diff options
author | 2017-06-01 15:45:09 -0700 | |
---|---|---|
committer | 2017-06-02 08:52:13 -0700 | |
commit | 8523ea11a677b78e1fc05915976c04b1ff081451 (patch) | |
tree | 249523715fbba92a524fe01725a218c695c1b19e /compiler/optimizing/induction_var_range.cc | |
parent | 85b82e35d810a21257fec9d850d95f8abc900670 (diff) |
Fixed bug in relying on precise FP in periodic sequence.
Rationale:
FP arithmetic is not always precise, so relying on FP
period sequences to "compute back" precisely is not
valid; when all values in the period are "fetches"
however, the rotation is precise.
Bug found by fuzz testing. With regression test.
Bug: 62196559
Test: test-art-host
Change-Id: Ie8f6b965b1921ff2762b90eebb8c20503c44c6bb
Diffstat (limited to 'compiler/optimizing/induction_var_range.cc')
-rw-r--r-- | compiler/optimizing/induction_var_range.cc | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/compiler/optimizing/induction_var_range.cc b/compiler/optimizing/induction_var_range.cc index 7c833cf70c..c0ec58f824 100644 --- a/compiler/optimizing/induction_var_range.cc +++ b/compiler/optimizing/induction_var_range.cc @@ -1132,11 +1132,27 @@ bool InductionVarRange::GenerateLastValuePeriodic(HInductionVarAnalysis::Inducti /*out*/bool* needs_taken_test) const { DCHECK(info != nullptr); DCHECK_EQ(info->induction_class, HInductionVarAnalysis::kPeriodic); - // Count period. + // Count period and detect all-invariants. int64_t period = 1; - for (HInductionVarAnalysis::InductionInfo* p = info; - p->induction_class == HInductionVarAnalysis::kPeriodic; - p = p->op_b, ++period) {} + bool all_invariants = true; + HInductionVarAnalysis::InductionInfo* p = info; + for (; p->induction_class == HInductionVarAnalysis::kPeriodic; p = p->op_b, ++period) { + DCHECK_EQ(p->op_a->induction_class, HInductionVarAnalysis::kInvariant); + if (p->op_a->operation != HInductionVarAnalysis::kFetch) { + all_invariants = false; + } + } + DCHECK_EQ(p->induction_class, HInductionVarAnalysis::kInvariant); + if (p->operation != HInductionVarAnalysis::kFetch) { + all_invariants = false; + } + // Don't rely on FP arithmetic to be precise, unless the full period + // consist of pre-computed expressions only. + if (info->type == Primitive::kPrimFloat || info->type == Primitive::kPrimDouble) { + if (!all_invariants) { + return false; + } + } // Handle any periodic(x, periodic(.., y)) for known maximum index value m. int64_t m = 0; if (IsConstant(trip->op_a, kExact, &m) && m >= 1) { |