summaryrefslogtreecommitdiff
path: root/compiler/optimizing
diff options
context:
space:
mode:
author Aart Bik <ajcbik@google.com> 2017-06-01 15:45:09 -0700
committer Aart Bik <ajcbik@google.com> 2017-06-02 08:52:13 -0700
commit8523ea11a677b78e1fc05915976c04b1ff081451 (patch)
tree249523715fbba92a524fe01725a218c695c1b19e /compiler/optimizing
parent85b82e35d810a21257fec9d850d95f8abc900670 (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')
-rw-r--r--compiler/optimizing/induction_var_range.cc24
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) {