	* tree-ssa-reassoc.c (linearize_expr_tree, undistribute_ops_list,
	reassociate_bb, do_reassoc, execute_reassoc): Take extra EARLY_PASS
	bool argument to distinguish between the early and late reassociation
	pass.
	(acceptable_pow_call): Do not look at first_pass_instance.
	(execute_early_reassoc, execute_late_reassoc): New functions.
	(pass_early_reassoc, pass_late_reassoc): New gimple_opt_pass structs.
	(pass_reassoc): Removed.
	* tree-pass.h (pass_reassoc): Removed.
	(pass_early_reassoc, pass_late_reassoc): Declare.
	* passes.c (init_optimization_passes): Schedule pass_early_reassoc and
	pass_late_reassoc instead of pass_reassoc.

Index: tree-ssa-reassoc.c
===================================================================
--- tree-ssa-reassoc.c	(revision 189427)
+++ tree-ssa-reassoc.c	(working copy)
@@ -944,7 +944,7 @@ eliminate_using_constants (enum tree_cod
 
 
 static void linearize_expr_tree (VEC(operand_entry_t, heap) **, gimple,
-				 bool, bool);
+				 bool, bool, bool);
 
 /* Structure for tracking and counting operands.  */
 typedef struct oecount_s {
@@ -1263,11 +1263,15 @@ build_and_add_sum (tree tmpvar, tree op1
 
   The alternate addition chains built are re-processed by the main
   reassociation algorithm which allows optimizing a * x * y + b * y * x
-  to (a + b ) * x * y in one invocation of the reassociation pass.  */
+  to (a + b ) * x * y in one invocation of the reassociation pass. 
+
+  If EARLY_PASS is true, then this is called in the early reassociation
+  pass.  */
 
 static bool
 undistribute_ops_list (enum tree_code opcode,
-		       VEC (operand_entry_t, heap) **ops, struct loop *loop)
+		       VEC (operand_entry_t, heap) **ops, struct loop *loop,
+		       bool early_pass)
 {
   unsigned int length = VEC_length (operand_entry_t, *ops);
   operand_entry_t oe1;
@@ -1337,7 +1341,8 @@ undistribute_ops_list (enum tree_code op
       oedef = SSA_NAME_DEF_STMT (VEC_index (operand_entry_t, *ops, i)->op);
       oecode = gimple_assign_rhs_code (oedef);
       linearize_expr_tree (&subops[i], oedef,
-			   associative_tree_code (oecode), false);
+			   associative_tree_code (oecode),
+			   false, early_pass);
 
       FOR_EACH_VEC_ELT (operand_entry_t, subops[i], j, oe1)
 	{
@@ -2693,9 +2698,9 @@ break_up_subtract (gimple stmt, gimple_s
 }
 
 /* Determine whether STMT is a builtin call that raises an SSA name
-   to an integer power and has only one use.  If so, and this is early
-   reassociation and unsafe math optimizations are permitted, place
-   the SSA name in *BASE and the exponent in *EXPONENT, and return TRUE.
+   to an integer power and has only one use.  If so, and unsafe math
+   optimizations are permitted, place the SSA name in *BASE and the
+   exponent in *EXPONENT, and return TRUE.
    If any of these conditions does not hold, return FALSE.  */
 
 static bool
@@ -2704,8 +2709,7 @@ acceptable_pow_call (gimple stmt, tree *
   tree fndecl, arg1;
   REAL_VALUE_TYPE c, cint;
 
-  if (!first_pass_instance
-      || !flag_unsafe_math_optimizations
+  if (!flag_unsafe_math_optimizations
       || !is_gimple_call (stmt)
       || !has_single_use (gimple_call_lhs (stmt)))
     return false;
@@ -2762,11 +2766,14 @@ acceptable_pow_call (gimple stmt, tree *
 }
 
 /* Recursively linearize a binary expression that is the RHS of STMT.
-   Place the operands of the expression tree in the vector named OPS.  */
+   Place the operands of the expression tree in the vector named OPS.
+   If EARLY_PASS is true, then this is called in the early reassociation
+   pass, and we may try to expand builtins like 'pow' to some sequence
+   of simpler instructions.  */
 
 static void
 linearize_expr_tree (VEC(operand_entry_t, heap) **ops, gimple stmt,
-		     bool is_associative, bool set_visited)
+		     bool is_associative, bool set_visited, bool early_pass)
 {
   tree binlhs = gimple_assign_rhs1 (stmt);
   tree binrhs = gimple_assign_rhs2 (stmt);
@@ -2816,6 +2823,7 @@ linearize_expr_tree (VEC(operand_entry_t
 	{
 	  if (rhscode == MULT_EXPR
 	      && TREE_CODE (binrhs) == SSA_NAME
+	      && early_pass
 	      && acceptable_pow_call (binrhsdef, &base, &exponent))
 	    {
 	      add_repeat_to_ops_vec (ops, base, exponent);
@@ -2826,6 +2834,7 @@ linearize_expr_tree (VEC(operand_entry_t
 
 	  if (rhscode == MULT_EXPR
 	      && TREE_CODE (binlhs) == SSA_NAME
+	      && early_pass
 	      && acceptable_pow_call (binlhsdef, &base, &exponent))
 	    {
 	      add_repeat_to_ops_vec (ops, base, exponent);
@@ -2871,10 +2880,11 @@ linearize_expr_tree (VEC(operand_entry_t
 	      || !is_reassociable_op (SSA_NAME_DEF_STMT (binrhs),
 				      rhscode, loop));
   linearize_expr_tree (ops, SSA_NAME_DEF_STMT (binlhs),
-		       is_associative, set_visited);
+		       is_associative, set_visited, early_pass);
 
   if (rhscode == MULT_EXPR
       && TREE_CODE (binrhs) == SSA_NAME
+      && early_pass
       && acceptable_pow_call (SSA_NAME_DEF_STMT (binrhs), &base, &exponent))
     {
       add_repeat_to_ops_vec (ops, base, exponent);
@@ -3449,10 +3459,10 @@ transform_stmt_to_multiply (gimple_stmt_
 }
 
 /* Reassociate expressions in basic block BB and its post-dominator as
-   children.  */
+   children.  EARLY_PASS is true if this is an early re-associate pass.  */
 
 static void
-reassociate_bb (basic_block bb)
+reassociate_bb (basic_block bb, bool early_pass)
 {
   gimple_stmt_iterator gsi;
   basic_block son;
@@ -3526,11 +3536,12 @@ reassociate_bb (basic_block bb)
 		continue;
 
 	      gimple_set_visited (stmt, true);
-	      linearize_expr_tree (&ops, stmt, true, true);
+	      linearize_expr_tree (&ops, stmt, true, true, early_pass);
 	      VEC_qsort (operand_entry_t, ops, sort_by_operand_rank);
 	      optimize_ops_list (rhs_code, &ops);
 	      if (undistribute_ops_list (rhs_code, &ops,
-					 loop_containing_stmt (stmt)))
+					 loop_containing_stmt (stmt),
+					 early_pass))
 		{
 		  VEC_qsort (operand_entry_t, ops, sort_by_operand_rank);
 		  optimize_ops_list (rhs_code, &ops);
@@ -3539,7 +3550,7 @@ reassociate_bb (basic_block bb)
 	      if (rhs_code == BIT_IOR_EXPR || rhs_code == BIT_AND_EXPR)
 		optimize_range_tests (rhs_code, &ops);
 
-	      if (first_pass_instance
+	      if (early_pass
 		  && rhs_code == MULT_EXPR
 		  && flag_unsafe_math_optimizations)
 		powi_result = attempt_builtin_powi (stmt, &ops, &target);
@@ -3600,7 +3611,7 @@ reassociate_bb (basic_block bb)
   for (son = first_dom_son (CDI_POST_DOMINATORS, bb);
        son;
        son = next_dom_son (CDI_POST_DOMINATORS, son))
-    reassociate_bb (son);
+    reassociate_bb (son, early_pass);
 }
 
 void dump_ops_vector (FILE *file, VEC (operand_entry_t, heap) *ops);
@@ -3630,10 +3641,10 @@ debug_ops_vector (VEC (operand_entry_t, 
 }
 
 static void
-do_reassoc (void)
+do_reassoc (bool early_pass)
 {
   break_up_subtract_bb (ENTRY_BLOCK_PTR);
-  reassociate_bb (EXIT_BLOCK_PTR);
+  reassociate_bb (EXIT_BLOCK_PTR, early_pass);
 }
 
 /* Initialize the reassociation pass.  */
@@ -3708,33 +3719,66 @@ fini_reassoc (void)
   loop_optimizer_finalize ();
 }
 
-/* Gate and execute functions for Reassociation.  */
+/* Gate and execute functions for reassociation.  */
 
 static unsigned int
-execute_reassoc (void)
+execute_reassoc (bool early_pass)
 {
   init_reassoc ();
 
-  do_reassoc ();
+  do_reassoc (early_pass);
   repropagate_negates ();
 
   fini_reassoc ();
   return 0;
 }
 
+static unsigned int
+execute_early_reassoc (void)
+{
+  return execute_reassoc (/*early_pass=*/true);
+}
+
+static unsigned int
+execute_late_reassoc (void)
+{
+  return execute_reassoc (/*early_pass=*/false);
+}
+
 static bool
 gate_tree_ssa_reassoc (void)
 {
   return flag_tree_reassoc != 0;
 }
 
-struct gimple_opt_pass pass_reassoc =
+struct gimple_opt_pass pass_early_reassoc =
+{
+ {
+  GIMPLE_PASS,
+  "reassoc1",				/* name */
+  gate_tree_ssa_reassoc,		/* gate */
+  execute_early_reassoc,		/* execute */
+  NULL,					/* sub */
+  NULL,					/* next */
+  0,					/* static_pass_number */
+  TV_TREE_REASSOC,			/* tv_id */
+  PROP_cfg | PROP_ssa,			/* properties_required */
+  0,					/* properties_provided */
+  0,					/* properties_destroyed */
+  0,					/* todo_flags_start */
+  TODO_verify_ssa
+    | TODO_verify_flow
+    | TODO_ggc_collect			/* todo_flags_finish */
+ }
+};
+
+struct gimple_opt_pass pass_late_reassoc =
 {
  {
   GIMPLE_PASS,
-  "reassoc",				/* name */
+  "reassoc2",				/* name */
   gate_tree_ssa_reassoc,		/* gate */
-  execute_reassoc,			/* execute */
+  execute_late_reassoc,			/* execute */
   NULL,					/* sub */
   NULL,					/* next */
   0,					/* static_pass_number */
Index: tree-pass.h
===================================================================
--- tree-pass.h	(revision 189427)
+++ tree-pass.h	(working copy)
@@ -437,7 +437,8 @@ extern struct gimple_opt_pass pass_copy_
 extern struct gimple_opt_pass pass_vrp;
 extern struct gimple_opt_pass pass_uncprop;
 extern struct gimple_opt_pass pass_return_slot;
-extern struct gimple_opt_pass pass_reassoc;
+extern struct gimple_opt_pass pass_early_reassoc;
+extern struct gimple_opt_pass pass_late_reassoc;
 extern struct gimple_opt_pass pass_rebuild_cgraph_edges;
 extern struct gimple_opt_pass pass_remove_cgraph_callee_edges;
 extern struct gimple_opt_pass pass_build_cgraph_edges;
Index: passes.c
===================================================================
--- passes.c	(revision 189427)
+++ passes.c	(working copy)
@@ -1409,7 +1409,7 @@ init_optimization_passes (void)
 	 opportunities.  */
       NEXT_PASS (pass_phi_only_cprop);
       NEXT_PASS (pass_dse);
-      NEXT_PASS (pass_reassoc);
+      NEXT_PASS (pass_early_reassoc);
       NEXT_PASS (pass_dce);
       NEXT_PASS (pass_forwprop);
       NEXT_PASS (pass_phiopt);
@@ -1461,7 +1461,7 @@ init_optimization_passes (void)
 	}
       NEXT_PASS (pass_lower_vector_ssa);
       NEXT_PASS (pass_cse_reciprocals);
-      NEXT_PASS (pass_reassoc);
+      NEXT_PASS (pass_late_reassoc);
       NEXT_PASS (pass_vrp);
       NEXT_PASS (pass_strength_reduction);
       NEXT_PASS (pass_dominator);
