diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr71269.c b/gcc/testsuite/gcc.dg/tree-ssa/pr71269.c
index e69de29..b0c89ea 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr71269.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr71269.c
@@ -0,0 +1,9 @@
+/* PR middle-end/71269 */
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+int a, b, c;
+void fn1()
+{
+  fn2 (sizeof 0 + c + a + b + b);
+}
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index c9ed679..b9a29a6 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -3767,8 +3767,10 @@ swap_ops_for_binary_stmt (vec<operand_entry *> ops,
       operand_entry temp = *oe3;
       oe3->op = oe1->op;
       oe3->rank = oe1->rank;
+      oe3->stmt_to_insert = oe1->stmt_to_insert;
       oe1->op = temp.op;
       oe1->rank= temp.rank;
+      oe1->stmt_to_insert = temp.stmt_to_insert;
     }
   else if ((oe1->rank == oe3->rank
 	    && oe2->rank != oe3->rank)
@@ -3779,8 +3781,10 @@ swap_ops_for_binary_stmt (vec<operand_entry *> ops,
       operand_entry temp = *oe2;
       oe2->op = oe1->op;
       oe2->rank = oe1->rank;
+      oe2->stmt_to_insert = oe1->stmt_to_insert;
       oe1->op = temp.op;
       oe1->rank = temp.rank;
+      oe1->stmt_to_insert = temp.stmt_to_insert;
     }
 }
 
@@ -3790,6 +3794,42 @@ swap_ops_for_binary_stmt (vec<operand_entry *> ops,
 static inline gimple *
 find_insert_point (gimple *stmt, tree rhs1, tree rhs2)
 {
+  /* If rhs1 is defined by stmt_to_insert, insert after its argument
+     definion stmt.  */
+  if (TREE_CODE (rhs1) == SSA_NAME
+      && !gimple_nop_p (SSA_NAME_DEF_STMT (rhs1))
+      && !gimple_bb (SSA_NAME_DEF_STMT (rhs1)))
+    {
+      gimple *stmt1 = SSA_NAME_DEF_STMT (rhs1);
+      gcc_assert (is_gimple_assign (stmt1));
+      tree rhs11 = gimple_assign_rhs1 (stmt1);
+      tree rhs12 = gimple_assign_rhs2 (stmt1);
+      if (TREE_CODE (rhs11) == SSA_NAME
+	  && reassoc_stmt_dominates_stmt_p (stmt, SSA_NAME_DEF_STMT (rhs11)))
+	stmt = SSA_NAME_DEF_STMT (rhs11);
+      if (TREE_CODE (rhs12) == SSA_NAME
+	  && reassoc_stmt_dominates_stmt_p (stmt, SSA_NAME_DEF_STMT (rhs12)))
+	stmt = SSA_NAME_DEF_STMT (rhs12);
+    }
+
+  /* If rhs2 is defined by stmt_to_insert, insert after its argument
+     definion stmt.  */
+  if (TREE_CODE (rhs2) == SSA_NAME
+      && !gimple_nop_p (SSA_NAME_DEF_STMT (rhs2))
+      && !gimple_bb (SSA_NAME_DEF_STMT (rhs2)))
+    {
+      gimple *stmt1 = SSA_NAME_DEF_STMT (rhs2);
+      gcc_assert (is_gimple_assign (stmt1));
+      tree rhs11 = gimple_assign_rhs1 (stmt1);
+      tree rhs12 = gimple_assign_rhs2 (stmt1);
+      if (TREE_CODE (rhs11) == SSA_NAME
+	  && reassoc_stmt_dominates_stmt_p (stmt, SSA_NAME_DEF_STMT (rhs11)))
+	stmt = SSA_NAME_DEF_STMT (rhs11);
+      if (TREE_CODE (rhs12) == SSA_NAME
+	  && reassoc_stmt_dominates_stmt_p (stmt, SSA_NAME_DEF_STMT (rhs12)))
+	stmt = SSA_NAME_DEF_STMT (rhs12);
+    }
+
   if (TREE_CODE (rhs1) == SSA_NAME
       && reassoc_stmt_dominates_stmt_p (stmt, SSA_NAME_DEF_STMT (rhs1)))
     stmt = SSA_NAME_DEF_STMT (rhs1);
@@ -3845,10 +3885,6 @@ rewrite_expr_tree (gimple *stmt, unsigned int opindex,
 		= find_insert_point (stmt, oe1->op, oe2->op);
 	      /* If the stmt that defines operand has to be inserted, insert it
 		 before the use.  */
-	      if (oe1->stmt_to_insert)
-		insert_stmt_before_use (stmt, oe1->stmt_to_insert);
-	      if (oe2->stmt_to_insert)
-		insert_stmt_before_use (stmt, oe2->stmt_to_insert);
 	      lhs = make_ssa_name (TREE_TYPE (lhs));
 	      stmt
 		= gimple_build_assign (lhs, gimple_assign_rhs_code (stmt),
@@ -3866,15 +3902,17 @@ rewrite_expr_tree (gimple *stmt, unsigned int opindex,
 				   == stmt);
 	      /* If the stmt that defines operand has to be inserted, insert it
 		 before the use.  */
-	      if (oe1->stmt_to_insert)
-		insert_stmt_before_use (stmt, oe1->stmt_to_insert);
-	      if (oe2->stmt_to_insert)
-		insert_stmt_before_use (stmt, oe2->stmt_to_insert);
 	      gimple_assign_set_rhs1 (stmt, oe1->op);
 	      gimple_assign_set_rhs2 (stmt, oe2->op);
 	      update_stmt (stmt);
 	    }
 
+	  /* If the stmt that defines operand has to be inserted, insert it
+	     before the use after the stmt is inserted.  */
+	  if (oe1->stmt_to_insert)
+	    insert_stmt_before_use (stmt, oe1->stmt_to_insert);
+	  if (oe2->stmt_to_insert)
+	    insert_stmt_before_use (stmt, oe2->stmt_to_insert);
 	  if (rhs1 != oe1->op && rhs1 != oe2->op)
 	    remove_visited_stmt_chain (rhs1);
 
@@ -3893,11 +3931,6 @@ rewrite_expr_tree (gimple *stmt, unsigned int opindex,
   /* Rewrite the next operator.  */
   oe = ops[opindex];
 
-  /* If the stmt that defines operand has to be inserted, insert it
-     before the use.  */
-  if (oe->stmt_to_insert)
-    insert_stmt_before_use (stmt, oe->stmt_to_insert);
-
   /* Recurse on the LHS of the binary operator, which is guaranteed to
      be the non-leaf side.  */
   tree new_rhs1
@@ -3944,6 +3977,10 @@ rewrite_expr_tree (gimple *stmt, unsigned int opindex,
 	  update_stmt (stmt);
 	}
 
+      /* If the stmt that defines operand has to be inserted, insert it
+	 before the use after the use_stmt is inserted.  */
+      if (oe->stmt_to_insert)
+	insert_stmt_before_use (stmt, oe->stmt_to_insert);
       if (dump_file && (dump_flags & TDF_DETAILS))
 	{
 	  fprintf (dump_file, " into ");
@@ -4115,24 +4152,41 @@ rewrite_expr_tree_parallel (gassign *stmt, int width,
 	{
 	  /* If the stmt that defines operand has to be inserted, insert it
 	     before the use.  */
-	  if (stmt1)
-	    insert_stmt_before_use (stmts[i], stmt1);
-	  if (stmt2)
-	    insert_stmt_before_use (stmts[i], stmt2);
 	  gimple_assign_set_rhs1 (stmts[i], op1);
 	  gimple_assign_set_rhs2 (stmts[i], op2);
 	  update_stmt (stmts[i]);
 	}
       else
 	{
+	  /* PR71252: stmt_to_insert has to be inserted after use stmt created
+	     by build_and_add_sum. However if the other operand doesnt have define-stmt
+	     or is defined by GIMPLE_NOP, we have to insert it first.  */
+	  if (stmt1
+	      && (TREE_CODE (op2) != SSA_NAME
+		  || !gimple_bb (SSA_NAME_DEF_STMT (op2))
+		  || gimple_nop_p (SSA_NAME_DEF_STMT (op2))))
+	    {
+	      insert_stmt_before_use (stmts[i], stmt1);
+	      stmt1 = NULL;
+	    }
+	  if (stmt2
+	      && (TREE_CODE (op1) != SSA_NAME
+		  || !gimple_bb (SSA_NAME_DEF_STMT (op1))
+		  || gimple_nop_p (SSA_NAME_DEF_STMT (op1))))
+	    {
+	      insert_stmt_before_use (stmts[i], stmt2);
+	      stmt2 = NULL;
+	    }
 	  stmts[i] = build_and_add_sum (TREE_TYPE (last_rhs1), op1, op2, opcode);
-	  /* If the stmt that defines operand has to be inserted, insert it
-	     before new build_and_add stmt after it is created.  */
-	  if (stmt1)
-	    insert_stmt_before_use (stmts[i], stmt1);
-	  if (stmt2)
-	    insert_stmt_before_use (stmts[i], stmt2);
 	}
+
+      /* If the stmt that defines operand has to be inserted, insert it
+	 before new use stmt after it is created.  */
+      if (stmt1)
+	insert_stmt_before_use (stmts[i], stmt1);
+      if (stmt2)
+	insert_stmt_before_use (stmts[i], stmt2);
+      stmt1 = stmt2 = NULL;
       if (dump_file && (dump_flags & TDF_DETAILS))
 	{
 	  fprintf (dump_file, " into ");
@@ -5312,15 +5366,15 @@ reassociate_bb (basic_block bb)
 		{
 		  tree last_op = ops.last ()->op;
 
-		  /* If the stmt that defines operand has to be inserted, insert it
-		     before the use.  */
-		  if (ops.last ()->stmt_to_insert)
-		    insert_stmt_before_use (stmt, ops.last ()->stmt_to_insert);
 		  if (powi_result)
 		    transform_stmt_to_multiply (&gsi, stmt, last_op,
 						powi_result);
 		  else
 		    transform_stmt_to_copy (&gsi, stmt, last_op);
+		  /* If the stmt that defines operand has to be inserted, insert it
+		     before the use.  */
+		  if (ops.last ()->stmt_to_insert)
+		    insert_stmt_before_use (stmt, ops.last ()->stmt_to_insert);
 		}
 	      else
 		{
