aboutsummaryrefslogtreecommitdiff
path: root/gcc/hwint.h
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2021-01-20 11:28:30 +0100
committerRichard Biener <rguenther@suse.de>2021-01-20 16:32:11 +0100
commit261cdd23195bc921737fd7a44e34a93aaaaccc44 (patch)
tree7f37b944a8f399454214be858ba4b5dad56c7252 /gcc/hwint.h
parent49e8c14ef6f1f968602a04c8499a672182590e87 (diff)
downloadgcc-261cdd23195bc921737fd7a44e34a93aaaaccc44.zip
gcc-261cdd23195bc921737fd7a44e34a93aaaaccc44.tar.gz
gcc-261cdd23195bc921737fd7a44e34a93aaaaccc44.tar.bz2
Handle overflow in dependence analysis lambda ops gracefully
The following tries to handle overflow in the integer computations done by lambda ops of dependence analysis by failing instead of silently continuing with overflowed values. It also avoids treating large unsigned CHREC_RIGHT as negative unless the chrec is of pointer type and avoids the most negative integer value to avoid excessive overflow checking (with this the fix for PR98758 can be partly simplified as seen). I've added add_hwi and mul_hwi functions computing HOST_WIDE_INT signed sum and product with indicating overflow, they hopefully get matched to the appropriate internal functions. I don't have any testcases triggering overflow in any of the guarded computations. 2021-01-20 Richard Biener <rguenther@suse.de> * hwint.h (add_hwi): New function. (mul_hwi): Likewise. * tree-data-ref.c (initialize_matrix_A): Properly translate tree constants and avoid HOST_WIDE_INT_MIN. (lambda_matrix_row_add): Avoid undefined integer overflow and return true on such overflow. (lambda_matrix_right_hermite): Handle overflow from lambda_matrix_row_add gracefully. Simplify previous fix. (analyze_subscript_affine_affine): Likewise.
Diffstat (limited to 'gcc/hwint.h')
-rw-r--r--gcc/hwint.h42
1 files changed, 42 insertions, 0 deletions
diff --git a/gcc/hwint.h b/gcc/hwint.h
index 127b013..0e895f8 100644
--- a/gcc/hwint.h
+++ b/gcc/hwint.h
@@ -333,4 +333,46 @@ absu_hwi (HOST_WIDE_INT x)
return x >= 0 ? (unsigned HOST_WIDE_INT)x : -(unsigned HOST_WIDE_INT)x;
}
+/* Compute the sum of signed A and B and indicate in *OVERFLOW whether
+ that operation overflowed. */
+
+inline HOST_WIDE_INT
+add_hwi (HOST_WIDE_INT a, HOST_WIDE_INT b, bool *overflow)
+{
+#if GCC_VERSION < 11000
+ unsigned HOST_WIDE_INT result = a + (unsigned HOST_WIDE_INT)b;
+ if ((((result ^ a) & (result ^ b))
+ >> (HOST_BITS_PER_WIDE_INT - 1)) & 1)
+ *overflow = true;
+ else
+ *overflow = false;
+ return result;
+#else
+ HOST_WIDE_INT result;
+ *overflow = __builtin_add_overflow (a, b, &result);
+ return result;
+#endif
+}
+
+/* Compute the product of signed A and B and indicate in *OVERFLOW whether
+ that operation overflowed. */
+
+inline HOST_WIDE_INT
+mul_hwi (HOST_WIDE_INT a, HOST_WIDE_INT b, bool *overflow)
+{
+#if GCC_VERSION < 11000
+ unsigned HOST_WIDE_INT result = a * (unsigned HOST_WIDE_INT)b;
+ if ((a == -1 && b == HOST_WIDE_INT_MIN)
+ || (a != 0 && (HOST_WIDE_INT)result / a != b))
+ *overflow = true;
+ else
+ *overflow = false;
+ return result;
+#else
+ HOST_WIDE_INT result;
+ *overflow = __builtin_mul_overflow (a, b, &result);
+ return result;
+#endif
+}
+
#endif /* ! GCC_HWINT_H */