summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/c/ChangeLog5
-rw-r--r--gcc/c/c-typeck.c8
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/semantics.c13
-rw-r--r--gcc/fold-const.c50
-rw-r--r--gcc/match.pd52
7 files changed, 90 insertions, 52 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2ec877a9256..63319ad6ed5 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2015-10-22 Richard Biener <rguenther@suse.de>
+
+ * fold-const.c (fold_addr_of_array_ref_difference): Properly
+ convert operands before folding a MINUS_EXPR.
+ (fold_binary_loc): Move simplification of MINUS_EXPR on
+ converted POINTER_PLUS_EXPRs ...
+ * match.pd: ... here.
+
2015-10-22 Richard Sandiford <richard.sandiford@arm.com>
* builtins.c (fold_builtin_tan): Delete.
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index b5179a3a714..aed7a627932 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,8 @@
+2015-10-22 Richard Biener <rguenther@suse.de>
+
+ * c-typeck.c (c_finish_omp_clauses): Properly convert operands
+ before folding a MINUS_EXPR.
+
2015-10-21 Marek Polacek <polacek@redhat.com>
PR c/68024
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 6b32781c03b..61c5313c25b 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -12547,7 +12547,9 @@ c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd)
s = pointer_int_sum (OMP_CLAUSE_LOCATION (c), PLUS_EXPR,
OMP_CLAUSE_DECL (c), s);
s = fold_build2_loc (OMP_CLAUSE_LOCATION (c), MINUS_EXPR,
- sizetype, s, OMP_CLAUSE_DECL (c));
+ sizetype, fold_convert (sizetype, s),
+ fold_convert
+ (sizetype, OMP_CLAUSE_DECL (c)));
if (s == error_mark_node)
s = size_one_node;
OMP_CLAUSE_LINEAR_STEP (c) = s;
@@ -12671,7 +12673,9 @@ c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd)
neg ? MINUS_EXPR : PLUS_EXPR,
decl, offset);
t2 = fold_build2_loc (OMP_CLAUSE_LOCATION (c), MINUS_EXPR,
- sizetype, t2, decl);
+ sizetype,
+ fold_convert (sizetype, t2),
+ fold_convert (sizetype, decl));
if (t2 == error_mark_node)
{
remove = true;
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 0ed4e29615d..8dbff11574c 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2015-10-22 Richard Biener <rguenther@suse.de>
+
+ * semantics.c (cp_finish_omp_clause_depend_sink): Properly convert
+ before folding a MINUS_EXPR.
+ (finish_omp_clauses): Likewise.
+
2015-10-21 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/66781
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index c0a8b322767..11315d90668 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -5632,8 +5632,9 @@ cp_finish_omp_clause_depend_sink (tree sink_clause)
neg ? MINUS_EXPR : PLUS_EXPR,
decl, offset);
t2 = fold_build2_loc (OMP_CLAUSE_LOCATION (sink_clause),
- MINUS_EXPR, sizetype, t2,
- decl);
+ MINUS_EXPR, sizetype,
+ fold_convert (sizetype, t2),
+ fold_convert (sizetype, decl));
if (t2 == error_mark_node)
return true;
TREE_PURPOSE (t) = t2;
@@ -5783,7 +5784,9 @@ finish_omp_clauses (tree clauses, bool allow_fields, bool declare_simd)
t = pointer_int_sum (OMP_CLAUSE_LOCATION (c), PLUS_EXPR,
d, t);
t = fold_build2_loc (OMP_CLAUSE_LOCATION (c),
- MINUS_EXPR, sizetype, t, d);
+ MINUS_EXPR, sizetype,
+ fold_convert (sizetype, t),
+ fold_convert (sizetype, d));
if (t == error_mark_node)
{
remove = true;
@@ -5804,7 +5807,9 @@ finish_omp_clauses (tree clauses, bool allow_fields, bool declare_simd)
t = pointer_int_sum (OMP_CLAUSE_LOCATION (c), PLUS_EXPR,
d, t);
t = fold_build2_loc (OMP_CLAUSE_LOCATION (c),
- MINUS_EXPR, sizetype, t, d);
+ MINUS_EXPR, sizetype,
+ fold_convert (sizetype, t),
+ fold_convert (sizetype, d));
if (t == error_mark_node)
{
remove = true;
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 602ea240cb4..c4be017c50c 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -8841,9 +8841,11 @@ fold_addr_of_array_ref_difference (location_t loc, tree type,
= fold_addr_of_array_ref_difference (loc, type, base0, base1)))
|| (INDIRECT_REF_P (base0)
&& INDIRECT_REF_P (base1)
- && (base_offset = fold_binary_loc (loc, MINUS_EXPR, type,
- TREE_OPERAND (base0, 0),
- TREE_OPERAND (base1, 0))))
+ && (base_offset
+ = fold_binary_loc (loc, MINUS_EXPR, type,
+ fold_convert (type, TREE_OPERAND (base0, 0)),
+ fold_convert (type,
+ TREE_OPERAND (base1, 0)))))
|| operand_equal_p (base0, base1, OEP_ADDRESS_OF))
{
tree op0 = fold_convert_loc (loc, type, TREE_OPERAND (aref0, 1));
@@ -9637,48 +9639,6 @@ fold_binary_loc (location_t loc,
return NULL_TREE;
case MINUS_EXPR:
- /* Pointer simplifications for subtraction, simple reassociations. */
- if (POINTER_TYPE_P (TREE_TYPE (arg1)) && POINTER_TYPE_P (TREE_TYPE (arg0)))
- {
- /* (PTR0 p+ A) - (PTR1 p+ B) -> (PTR0 - PTR1) + (A - B) */
- if (TREE_CODE (arg0) == POINTER_PLUS_EXPR
- && TREE_CODE (arg1) == POINTER_PLUS_EXPR)
- {
- tree arg00 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
- tree arg01 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 1));
- tree arg10 = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 0));
- tree arg11 = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 1));
- return fold_build2_loc (loc, PLUS_EXPR, type,
- fold_build2_loc (loc, MINUS_EXPR, type,
- arg00, arg10),
- fold_build2_loc (loc, MINUS_EXPR, type,
- arg01, arg11));
- }
- /* (PTR0 p+ A) - PTR1 -> (PTR0 - PTR1) + A, assuming PTR0 - PTR1 simplifies. */
- else if (TREE_CODE (arg0) == POINTER_PLUS_EXPR)
- {
- tree arg00 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
- tree arg01 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 1));
- tree tmp = fold_binary_loc (loc, MINUS_EXPR, type, arg00,
- fold_convert_loc (loc, type, arg1));
- if (tmp)
- return fold_build2_loc (loc, PLUS_EXPR, type, tmp, arg01);
- }
- /* PTR0 - (PTR1 p+ A) -> (PTR0 - PTR1) - A, assuming PTR0 - PTR1
- simplifies. */
- else if (TREE_CODE (arg1) == POINTER_PLUS_EXPR)
- {
- tree arg10 = fold_convert_loc (loc, type,
- TREE_OPERAND (arg1, 0));
- tree arg11 = fold_convert_loc (loc, type,
- TREE_OPERAND (arg1, 1));
- tree tmp = fold_binary_loc (loc, MINUS_EXPR, type,
- fold_convert_loc (loc, type, arg0),
- arg10);
- if (tmp)
- return fold_build2_loc (loc, MINUS_EXPR, type, tmp, arg11);
- }
- }
/* (-A) - B -> (-B) - A where B is easily negated and we can swap. */
if (TREE_CODE (arg0) == NEGATE_EXPR
&& negate_expr_p (arg1)
diff --git a/gcc/match.pd b/gcc/match.pd
index 1ba43c44c16..b399786bac2 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -1056,7 +1056,57 @@ along with GCC; see the file COPYING3. If not see
|| (POINTER_TYPE_P (TREE_TYPE (@0))
&& TREE_CODE (@1) == INTEGER_CST
&& tree_int_cst_sign_bit (@1) == 0))
- (convert @1))))))
+ (convert @1))))
+
+ /* (T)P - (T)(P + A) -> -(T) A */
+ (for add (plus pointer_plus)
+ (simplify
+ (minus (convert @0)
+ (convert (add @0 @1)))
+ (if (element_precision (type) <= element_precision (TREE_TYPE (@1))
+ /* For integer types, if A has a smaller type
+ than T the result depends on the possible
+ overflow in P + A.
+ E.g. T=size_t, A=(unsigned)429497295, P>0.
+ However, if an overflow in P + A would cause
+ undefined behavior, we can assume that there
+ is no overflow. */
+ || (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))
+ /* For pointer types, if the conversion of A to the
+ final type requires a sign- or zero-extension,
+ then we have to punt - it is not defined which
+ one is correct. */
+ || (POINTER_TYPE_P (TREE_TYPE (@0))
+ && TREE_CODE (@1) == INTEGER_CST
+ && tree_int_cst_sign_bit (@1) == 0))
+ (negate (convert @1)))))
+
+ /* (T)(P + A) - (T)(P + B) -> (T)A - (T)B */
+ (for add (plus pointer_plus)
+ (simplify
+ (minus (convert (add @0 @1))
+ (convert (add @0 @2)))
+ (if (element_precision (type) <= element_precision (TREE_TYPE (@1))
+ /* For integer types, if A has a smaller type
+ than T the result depends on the possible
+ overflow in P + A.
+ E.g. T=size_t, A=(unsigned)429497295, P>0.
+ However, if an overflow in P + A would cause
+ undefined behavior, we can assume that there
+ is no overflow. */
+ || (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))
+ /* For pointer types, if the conversion of A to the
+ final type requires a sign- or zero-extension,
+ then we have to punt - it is not defined which
+ one is correct. */
+ || (POINTER_TYPE_P (TREE_TYPE (@0))
+ && TREE_CODE (@1) == INTEGER_CST
+ && tree_int_cst_sign_bit (@1) == 0
+ && TREE_CODE (@2) == INTEGER_CST
+ && tree_int_cst_sign_bit (@2) == 0))
+ (minus (convert @1) (convert @2)))))))
/* Simplifications of MIN_EXPR and MAX_EXPR. */