Hi,
This patch is to fix PR80153. As analyzed in the PR, root cause is tree_affine
lacks
ability differentiating (unsigned)(ptr + offset) and (unsigned)ptr +
(unsigned)offset,
even worse, it always returns the former expression in aff_combination_tree,
which
is wrong if the original expression has the latter form. The patch resolves
the issue
by always returning the latter form expression, i.e, always trying to generate
folded
expression. Also as analyzed in comment, I think this change won't result in
substantial
code gen difference.
I also need to adjust get_computation_aff for test case
gcc.dg/tree-ssa/reassoc-19.c.
Well, I think the changed behavior is correct, but for case the original
pointer candidate
is chosen, it should be unnecessary to compute in uutype. Also this adjustment
only
generates (unsigned)(pointer + offset) which is generated by tree-affine.c.
Bootstrap and test on x86_64 and AArch64. Is it OK?
2017-03-27 Bin Cheng <bin.ch...@arm.com>
PR tree-optimization/80153
* tree-affine.c (add_elt_to_tree): Convert to type as required
by function's parameter.
* tree-ssa-loop-ivopts.c (alloc_iv): Pass in consistent types.
(get_computation_aff): Use utype directly for original candidate.
gcc/testsuite/ChangeLog
2017-03-27 Bin Cheng <bin.ch...@arm.com>
PR tree-optimization/80153
* gcc.c-torture/execute/pr80153.c: New.
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr80153.c
b/gcc/testsuite/gcc.c-torture/execute/pr80153.c
new file mode 100644
index 0000000..3eed578
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr80153.c
@@ -0,0 +1,48 @@
+/* PR tree-optimization/80153 */
+
+void check (int, int, int) __attribute__((noinline));
+void check (int c, int c2, int val)
+{
+ if (!val) {
+ __builtin_abort();
+ }
+}
+
+static const char *buf;
+static int l, i;
+
+void _fputs(const char *str) __attribute__((noinline));
+void _fputs(const char *str)
+{
+ buf = str;
+ i = 0;
+ l = __builtin_strlen(buf);
+}
+
+char _fgetc() __attribute__((noinline));
+char _fgetc()
+{
+ char val = buf[i];
+ i++;
+ if (i > l)
+ return -1;
+ else
+ return val;
+}
+
+static const char *string = "oops!\n";
+
+int main(void)
+{
+ int i;
+ int c;
+
+ _fputs(string);
+
+ for (i = 0; i < __builtin_strlen(string); i++) {
+ c = _fgetc();
+ check(c, string[i], c == string[i]);
+ }
+
+ return 0;
+}
diff --git a/gcc/tree-affine.c b/gcc/tree-affine.c
index e620eea..b10b1aa 100644
--- a/gcc/tree-affine.c
+++ b/gcc/tree-affine.c
@@ -391,6 +391,8 @@ add_elt_to_tree (tree expr, tree type, tree elt, const
widest_int &scale_in,
elt = fold_build1 (NEGATE_EXPR, TREE_TYPE (elt), elt);
scale = 1;
}
+ else
+ elt = fold_convert (type, elt);
if (scale == 1)
{
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index 8dc65881..fa993ab 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -1171,7 +1171,7 @@ alloc_iv (struct ivopts_data *data, tree base, tree step,
|| contain_complex_addr_expr (expr))
{
aff_tree comb;
- tree_to_aff_combination (expr, TREE_TYPE (base), &comb);
+ tree_to_aff_combination (expr, TREE_TYPE (expr), &comb);
base = fold_convert (TREE_TYPE (base), aff_combination_to_tree (&comb));
}
@@ -3787,6 +3787,12 @@ get_computation_aff (struct loop *loop,
overflows, as all the arithmetics will in the end be performed in UUTYPE
anyway. */
common_type = determine_common_wider_type (&ubase, &cbase);
+ /* We don't need to compute in UUTYPE if this is the original candidate,
+ and candidate/use have the same (pointer) type. */
+ if (ctype == utype && common_type == utype
+ && POINTER_TYPE_P (utype) && TYPE_UNSIGNED (utype)
+ && cand->pos == IP_ORIGINAL && cand->incremented_at == use->stmt)
+ uutype = utype;
/* use = ubase - ratio * cbase + ratio * var. */
tree_to_aff_combination (ubase, common_type, aff);