summaryrefslogtreecommitdiff
path: root/compiler/optimizing/induction_var_range.cc
diff options
context:
space:
mode:
author Aart Bik <ajcbik@google.com> 2017-03-07 21:22:58 +0000
committer Gerrit Code Review <noreply-gerritcodereview@google.com> 2017-03-07 21:23:00 +0000
commite6a60bff7a78efe7c2c4365984f1f7f036c12158 (patch)
tree04a83a2361a9103f2968c8f608980563cadcc343 /compiler/optimizing/induction_var_range.cc
parent7ba6ed786aa21257cfeefb917157d7d4768b9501 (diff)
parentb603a5cdff7c1fb300b83175bfb3cd990fdd6265 (diff)
Merge "Bug fix in overflow detection on pow. With regression test."
Diffstat (limited to 'compiler/optimizing/induction_var_range.cc')
-rw-r--r--compiler/optimizing/induction_var_range.cc24
1 files changed, 15 insertions, 9 deletions
diff --git a/compiler/optimizing/induction_var_range.cc b/compiler/optimizing/induction_var_range.cc
index 1cd65c1c66..3dfe17647c 100644
--- a/compiler/optimizing/induction_var_range.cc
+++ b/compiler/optimizing/induction_var_range.cc
@@ -57,21 +57,27 @@ static bool IsIntAndGet(HInstruction* instruction, int64_t* value) {
return false;
}
-/** Returns b^e for b,e >= 1. Sets overflow if arithmetic wrap-around occurred. */
+/** Computes a * b for a,b > 0 (at least until first overflow happens). */
+static int64_t SafeMul(int64_t a, int64_t b, /*out*/ bool* overflow) {
+ if (a > 0 && b > 0 && a > (std::numeric_limits<int64_t>::max() / b)) {
+ *overflow = true;
+ }
+ return a * b;
+}
+
+/** Returns b^e for b,e > 0. Sets overflow if arithmetic wrap-around occurred. */
static int64_t IntPow(int64_t b, int64_t e, /*out*/ bool* overflow) {
- DCHECK_GE(b, 1);
- DCHECK_GE(e, 1);
+ DCHECK_LT(0, b);
+ DCHECK_LT(0, e);
int64_t pow = 1;
while (e) {
if (e & 1) {
- int64_t oldpow = pow;
- pow *= b;
- if (pow < oldpow) {
- *overflow = true;
- }
+ pow = SafeMul(pow, b, overflow);
}
e >>= 1;
- b *= b;
+ if (e) {
+ b = SafeMul(b, b, overflow);
+ }
}
return pow;
}