When undistribute_ops_list calls linearize_expr with an outer
RDIV_EXPR we fail to consider that RDIV_EXPR is not associative
and end up linearizing the RHS.

Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed.

        PR tree-optimization/128089
        * tree-ssa-reassoc.cc (linearize_expr_tree): Do not make
        binrhsisreassoc true unless is_associative.

        * gcc.dg/pr128089.c: New testcase.
---
 gcc/testsuite/gcc.dg/pr128089.c | 17 +++++++++++++++++
 gcc/tree-ssa-reassoc.cc         | 10 ++++++----
 2 files changed, 23 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/pr128089.c

diff --git a/gcc/testsuite/gcc.dg/pr128089.c b/gcc/testsuite/gcc.dg/pr128089.c
new file mode 100644
index 00000000000..718513836b0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr128089.c
@@ -0,0 +1,17 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fassociative-math -fno-trapping-math -fno-signed-zeros" 
} */
+
+__attribute__ ((noipa)) double
+f (double a)
+{
+  return (a / 3) / (a / 6) + a * a;
+}
+
+int
+main (void)
+{
+  double result = f (6);
+  if (result != 38)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/tree-ssa-reassoc.cc b/gcc/tree-ssa-reassoc.cc
index 8df554ebc8c..10c9c721a4e 100644
--- a/gcc/tree-ssa-reassoc.cc
+++ b/gcc/tree-ssa-reassoc.cc
@@ -6229,7 +6229,8 @@ linearize_expr_tree (vec<operand_entry *> *ops, gimple 
*stmt,
   if (TREE_CODE (binrhs) == SSA_NAME)
     {
       binrhsdef = SSA_NAME_DEF_STMT (binrhs);
-      binrhsisreassoc = (is_reassociable_op (binrhsdef, rhscode, loop)
+      binrhsisreassoc = (is_associative
+                        && is_reassociable_op (binrhsdef, rhscode, loop)
                         && !stmt_could_throw_p (cfun, binrhsdef));
     }
 
@@ -6296,9 +6297,10 @@ linearize_expr_tree (vec<operand_entry *> *ops, gimple 
*stmt,
       binrhs = gimple_assign_rhs2 (stmt);
     }
 
-  gcc_assert (TREE_CODE (binrhs) != SSA_NAME
-             || !is_reassociable_op (SSA_NAME_DEF_STMT (binrhs),
-                                     rhscode, loop));
+  gcc_checking_assert (TREE_CODE (binrhs) != SSA_NAME
+                      || !is_associative
+                      || !is_reassociable_op (SSA_NAME_DEF_STMT (binrhs),
+                                              rhscode, loop));
   linearize_expr_tree (ops, SSA_NAME_DEF_STMT (binlhs),
                       is_associative, set_visited);
 

base-commit: ab8d26c0d68f49841a8225be53a7f947fb664476
-- 
2.51.0

Reply via email to