On Thu, May 11, 2017 at 11:54 AM, Richard Biener <richard.guent...@gmail.com> wrote: > On Tue, Apr 18, 2017 at 12:53 PM, Bin Cheng <bin.ch...@arm.com> wrote: >> Hi, >> Simplification of (T1)(X *+- CST) is already implemented in >> aff_combination_expand, >> this patch moves it to tree_to_aff_combination. It also supports unsigned >> types >> if range information allows the transformation, as well as special case >> (T1)(X + X). >> Is it OK? > > Can you first please simply move it? > > + /* In case X's type has wrapping overflow behavior, we can still > + convert (T1)(X - CST) into (T1)X - (T1)CST if X - CST doesn't > + overflow by range information. Also Convert (T1)(X + CST) as > + if it's (T1)(X - (-CST)). */ > + if (TYPE_UNSIGNED (itype) > + && TYPE_OVERFLOW_WRAPS (itype) > + && TREE_CODE (op0) == SSA_NAME > + && TREE_CODE (op1) == INTEGER_CST > + && (icode == PLUS_EXPR || icode == MINUS_EXPR) > + && get_range_info (op0, &minv, &maxv) == VR_RANGE) > + { > + if (icode == PLUS_EXPR) > + op1 = fold_build1 (NEGATE_EXPR, itype, op1); > > Negating -INF will produce -INF(OVF) which we don't want to have in our IL, > I suggest to use > > op1 = wide_int_to_tree (itype, wi::neg (op1)); > > instead. > > + if (wi::geu_p (minv, op1)) > + { > + op0 = fold_convert (otype, op0); > + op1 = fold_convert (otype, op1); > + expr = fold_build2 (MINUS_EXPR, otype, op0, op1); > + tree_to_aff_combination (expr, type, comb); > + return; > + } > + } > > I think this is similar to a part of what Robin Dapp (sp?) is > proposing as fix for PR69526? > > The same trick should work for (int)((unsigned)X - CST) with different > overflow checks > (you need to make sure the resulting expr does not overflow). Hi, As suggested, I separated the patch into three. Other review comments are also addressed. I read Robin's PR and patch, I think it's two different issues sharing some aspects, for example, the overflow check using range information are quite the same. In effect, this should also captures the result of Robin's patch because we don't want to fold (T1)(x +- CST) in general, but here in tree-affine.
Bootstrap and test, is it OK? Part1: 2017-04-11 Bin Cheng <bin.ch...@arm.com> (aff_combination_expand): Move (T1)(X *+- CST) simplification to ... (tree_to_aff_combination): ... here. Part2: 2017-04-11 Bin Cheng <bin.ch...@arm.com> * tree-affine.c (tree_to_aff_combination): Handle (T1)(X + X). Part3: 2017-04-11 Bin Cheng <bin.ch...@arm.com> * tree-affine.c (ssa.h): Include header file. (tree_to_aff_combination): Handle (T1)(X - CST) when inner type has wrapping overflow behavior. Thanks, bin > > Richard. > > >> Thanks, >> bin >> 2017-04-11 Bin Cheng <bin.ch...@arm.com> >> >> * tree-affine.c: Include header file. >> (aff_combination_expand): Move (T1)(X *+- CST) simplification to ... >> (tree_to_aff_combination): ... here. Support (T1)(X + X) case, and >> unsigned type case if range information allows.
From 16697043ffafdd096dce18f8c9e35c1433d809b0 Mon Sep 17 00:00:00 2001 From: Bin Cheng <binch...@e108451-lin.cambridge.arm.com> Date: Thu, 11 May 2017 14:06:32 +0100 Subject: [PATCH 2/9] move-fold-convert-20170510.txt --- gcc/tree-affine.c | 53 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/gcc/tree-affine.c b/gcc/tree-affine.c index 13c477d..cbe2bdb 100644 --- a/gcc/tree-affine.c +++ b/gcc/tree-affine.c @@ -363,6 +363,33 @@ tree_to_aff_combination (tree expr, tree type, aff_tree *comb) aff_combination_add (comb, &tmp); return; + CASE_CONVERT: + { + tree otype = TREE_TYPE (expr); + tree inner = TREE_OPERAND (expr, 0); + tree itype = TREE_TYPE (inner); + enum tree_code icode = TREE_CODE (inner); + + /* In principle this is a valid folding, but it isn't necessarily + an optimization, so do it here and not in fold_unary. */ + if ((icode == PLUS_EXPR || icode == MINUS_EXPR || icode == MULT_EXPR) + && TREE_CODE (itype) == INTEGER_TYPE + && TREE_CODE (otype) == INTEGER_TYPE + && TYPE_PRECISION (otype) > TYPE_PRECISION (itype) + && TYPE_OVERFLOW_UNDEFINED (itype) + && TREE_CODE (TREE_OPERAND (inner, 1)) == INTEGER_CST) + { + /* Convert (T1)(X *+- CST) into (T1)X *+- (T1)CST if X's type has + undefined overflow behavior. */ + tree op0 = fold_convert (otype, TREE_OPERAND (inner, 0)); + tree op1 = fold_convert (otype, TREE_OPERAND (inner, 1)); + expr = fold_build2 (icode, otype, op0, op1); + tree_to_aff_combination (expr, type, comb); + return; + } + } + break; + default: break; } @@ -639,28 +666,10 @@ aff_combination_expand (aff_tree *comb ATTRIBUTE_UNUSED, exp = XNEW (struct name_expansion); exp->in_progress = 1; *slot = exp; - /* In principle this is a generally valid folding, but - it is not unconditionally an optimization, so do it - here and not in fold_unary. */ - /* Convert (T1)(X *+- CST) into (T1)X *+- (T1)CST if T1 is wider - than the type of X and overflow for the type of X is - undefined. */ - if (e != name - && INTEGRAL_TYPE_P (type) - && INTEGRAL_TYPE_P (TREE_TYPE (name)) - && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (name)) - && TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (name)) - && (code == PLUS_EXPR || code == MINUS_EXPR || code == MULT_EXPR) - && TREE_CODE (gimple_assign_rhs2 (def)) == INTEGER_CST) - rhs = fold_build2 (code, type, - fold_convert (type, gimple_assign_rhs1 (def)), - fold_convert (type, gimple_assign_rhs2 (def))); - else - { - rhs = gimple_assign_rhs_to_tree (def); - if (e != name) - rhs = fold_convert (type, rhs); - } + rhs = gimple_assign_rhs_to_tree (def); + if (e != name) + rhs = fold_convert (type, rhs); + tree_to_aff_combination_expand (rhs, comb->type, ¤t, cache); exp->expansion = current; exp->in_progress = 0; -- 1.9.1
From 4b82e9a37ceec33d123cc52185eb04f16f5f354d Mon Sep 17 00:00:00 2001 From: Bin Cheng <binch...@e108451-lin.cambridge.arm.com> Date: Thu, 11 May 2017 14:28:20 +0100 Subject: [PATCH 3/9] fold-conversion-of-x-plus-x.20170510.txt --- gcc/tree-affine.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/gcc/tree-affine.c b/gcc/tree-affine.c index cbe2bdb..d2983ab 100644 --- a/gcc/tree-affine.c +++ b/gcc/tree-affine.c @@ -375,17 +375,24 @@ tree_to_aff_combination (tree expr, tree type, aff_tree *comb) if ((icode == PLUS_EXPR || icode == MINUS_EXPR || icode == MULT_EXPR) && TREE_CODE (itype) == INTEGER_TYPE && TREE_CODE (otype) == INTEGER_TYPE - && TYPE_PRECISION (otype) > TYPE_PRECISION (itype) - && TYPE_OVERFLOW_UNDEFINED (itype) - && TREE_CODE (TREE_OPERAND (inner, 1)) == INTEGER_CST) + && TYPE_PRECISION (otype) > TYPE_PRECISION (itype)) { - /* Convert (T1)(X *+- CST) into (T1)X *+- (T1)CST if X's type has - undefined overflow behavior. */ - tree op0 = fold_convert (otype, TREE_OPERAND (inner, 0)); - tree op1 = fold_convert (otype, TREE_OPERAND (inner, 1)); - expr = fold_build2 (icode, otype, op0, op1); - tree_to_aff_combination (expr, type, comb); - return; + tree op0 = TREE_OPERAND (inner, 0), op1 = TREE_OPERAND (inner, 1); + + /* If inner type has undefined overflow behavior, fold conversion + for below two cases: + (T1)(X *+- CST) -> (T1)X *+- (T1)CST + (T1)(X + X) -> (T1)X + (T1)X. */ + if (TYPE_OVERFLOW_UNDEFINED (itype) + && (TREE_CODE (op1) == INTEGER_CST + || (icode == PLUS_EXPR && operand_equal_p (op0, op1, 0)))) + { + op0 = fold_convert (otype, op0); + op1 = fold_convert (otype, op1); + expr = fold_build2 (icode, otype, op0, op1); + tree_to_aff_combination (expr, type, comb); + return; + } } } break; -- 1.9.1
From 4fec14255d42c6ccd40f4a4d90fa88e09c0a4f29 Mon Sep 17 00:00:00 2001 From: Bin Cheng <binch...@e108451-lin.cambridge.arm.com> Date: Thu, 11 May 2017 14:52:57 +0100 Subject: [PATCH 4/9] fold-conversion-of-unsigned-20170510.txt --- gcc/tree-affine.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/gcc/tree-affine.c b/gcc/tree-affine.c index d2983ab..f7a5f12 100644 --- a/gcc/tree-affine.c +++ b/gcc/tree-affine.c @@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see #include "rtl.h" #include "tree.h" #include "gimple.h" +#include "ssa.h" #include "tree-pretty-print.h" #include "fold-const.h" #include "tree-affine.h" @@ -393,6 +394,30 @@ tree_to_aff_combination (tree expr, tree type, aff_tree *comb) tree_to_aff_combination (expr, type, comb); return; } + wide_int minv, maxv; + /* If inner type has wrapping overflow behavior, fold conversion + for below case: + (T1)(X - CST) -> (T1)X - (T1)CST + if X - CST doesn't overflow by range information. Also handle + (T1)(X + CST) as (T1)(X - (-CST)). */ + if (TYPE_UNSIGNED (itype) + && TYPE_OVERFLOW_WRAPS (itype) + && TREE_CODE (op0) == SSA_NAME + && TREE_CODE (op1) == INTEGER_CST + && icode != MULT_EXPR + && get_range_info (op0, &minv, &maxv) == VR_RANGE) + { + if (icode == PLUS_EXPR) + op1 = wide_int_to_tree (itype, wi::neg (op1)); + if (wi::geu_p (minv, op1)) + { + op0 = fold_convert (otype, op0); + op1 = fold_convert (otype, op1); + expr = fold_build2 (MINUS_EXPR, otype, op0, op1); + tree_to_aff_combination (expr, type, comb); + return; + } + } } } break; -- 1.9.1