OSDN Git Service

ABM popcount intrinsics.
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-math-opts.c
index 11ce546..2a984a1 100644 (file)
@@ -1,18 +1,18 @@
 /* Global, SSA-based optimizations using mathematical identities.
    Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
-   
+
 This file is part of GCC.
-   
+
 GCC is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
 Free Software Foundation; either version 3, or (at your option) any
 later version.
-   
+
 GCC is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
-   
+
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
@@ -312,7 +312,7 @@ insert_reciprocals (gimple_stmt_iterator *def_gsi, struct occurrence *occ,
       recip_def = make_rename_temp (type, "reciptmp");
       new_stmt = gimple_build_assign_with_ops (RDIV_EXPR, recip_def,
                                               build_one_cst (type), def);
-  
+
       if (occ->bb_has_division)
         {
           /* Case 1: insert before an existing division.  */
@@ -418,7 +418,7 @@ execute_cse_reciprocals_1 (gimple_stmt_iterator *def_gsi, tree def)
          count++;
        }
     }
-  
+
   /* Do the expensive part only if we can hope to optimize something.  */
   threshold = targetm.min_divisions_for_recip_mul (TYPE_MODE (TREE_TYPE (def)));
   if (count >= threshold)
@@ -531,7 +531,9 @@ execute_cse_reciprocals (void)
                      || DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD))
                {
                  enum built_in_function code;
-                 bool md_code;
+                 bool md_code, fail;
+                 imm_use_iterator ui;
+                 use_operand_p use_p;
 
                  code = DECL_FUNCTION_CODE (fndecl);
                  md_code = DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD;
@@ -540,12 +542,37 @@ execute_cse_reciprocals (void)
                  if (!fndecl)
                    continue;
 
+                 /* Check that all uses of the SSA name are divisions,
+                    otherwise replacing the defining statement will do
+                    the wrong thing.  */
+                 fail = false;
+                 FOR_EACH_IMM_USE_FAST (use_p, ui, arg1)
+                   {
+                     gimple stmt2 = USE_STMT (use_p);
+                     if (is_gimple_debug (stmt2))
+                       continue;
+                     if (!is_gimple_assign (stmt2)
+                         || gimple_assign_rhs_code (stmt2) != RDIV_EXPR
+                         || gimple_assign_rhs1 (stmt2) == arg1
+                         || gimple_assign_rhs2 (stmt2) != arg1)
+                       {
+                         fail = true;
+                         break;
+                       }
+                   }
+                 if (fail)
+                   continue;
+
+                 gimple_replace_lhs (stmt1, arg1);
                  gimple_call_set_fndecl (stmt1, fndecl);
                  update_stmt (stmt1);
 
-                 gimple_assign_set_rhs_code (stmt, MULT_EXPR);
-                 fold_stmt_inplace (stmt);
-                 update_stmt (stmt);
+                 FOR_EACH_IMM_USE_STMT (stmt, ui, arg1)
+                   {
+                     gimple_assign_set_rhs_code (stmt, MULT_EXPR);
+                     fold_stmt_inplace (stmt);
+                     update_stmt (stmt);
+                   }
                }
            }
        }
@@ -710,7 +737,7 @@ execute_cse_sincos_1 (tree name)
 
        gsi = gsi_for_stmt (use_stmt);
        gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
-       gsi_remove (&gsi, true); 
+       gsi_remove (&gsi, true);
     }
 
   VEC_free(gimple, heap, stmts);
@@ -791,98 +818,6 @@ struct gimple_opt_pass pass_cse_sincos =
  }
 };
 
-/* Find all expressions in the form of sqrt(a/b) and
-   convert them to rsqrt(b/a).  */
-
-static unsigned int
-execute_convert_to_rsqrt (void)
-{
-  basic_block bb;
-
-  FOR_EACH_BB (bb)
-    {
-      gimple_stmt_iterator gsi;
-
-      for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi); gsi_next (&gsi))
-        {
-         gimple stmt = gsi_stmt (gsi);
-         tree fndecl;
-
-         if (is_gimple_call (stmt)
-             && gimple_call_lhs (stmt)
-             && (fndecl = gimple_call_fndecl (stmt))
-             && (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
-                 || DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD))
-           {
-             enum built_in_function code;
-             bool md_code;
-             tree arg1;
-             gimple stmt1;
-
-             code = DECL_FUNCTION_CODE (fndecl);
-             md_code = DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD;
-
-             fndecl = targetm.builtin_reciprocal (code, md_code, true);
-             if (!fndecl)
-               continue;
-
-             arg1 = gimple_call_arg (stmt, 0);
-
-             if (TREE_CODE (arg1) != SSA_NAME)
-               continue;
-
-             stmt1 = SSA_NAME_DEF_STMT (arg1);
-
-             if (is_gimple_assign (stmt1)
-                 && gimple_assign_rhs_code (stmt1) == RDIV_EXPR)
-               {
-                 tree arg10, arg11;
-
-                 arg10 = gimple_assign_rhs1 (stmt1);
-                 arg11 = gimple_assign_rhs2 (stmt1);
-
-                 /* Swap operands of RDIV_EXPR.  */
-                 gimple_assign_set_rhs1 (stmt1, arg11);
-                 gimple_assign_set_rhs2 (stmt1, arg10);
-                 fold_stmt_inplace (stmt1);
-                 update_stmt (stmt1);
-
-                 gimple_call_set_fndecl (stmt, fndecl);
-                 update_stmt (stmt);
-               }
-           }
-       }
-    }
-
-  return 0;
-}
-
-static bool
-gate_convert_to_rsqrt (void)
-{
-  return flag_unsafe_math_optimizations && optimize;
-}
-
-struct gimple_opt_pass pass_convert_to_rsqrt =
-{
- {
-  GIMPLE_PASS,
-  "rsqrt",                             /* name */
-  gate_convert_to_rsqrt,               /* gate */
-  execute_convert_to_rsqrt,            /* execute */
-  NULL,                                        /* sub */
-  NULL,                                        /* next */
-  0,                                   /* static_pass_number */
-  TV_NONE,                             /* tv_id */
-  PROP_ssa,                            /* properties_required */
-  0,                                   /* properties_provided */
-  0,                                   /* properties_destroyed */
-  0,                                   /* todo_flags_start */
-  TODO_dump_func | TODO_update_ssa | TODO_verify_ssa
-    | TODO_verify_stmts                 /* todo_flags_finish */
- }
-};
-
 /* A symbolic number is used to detect byte permutation and selection
    patterns.  Therefore the field N contains an artificial number
    consisting of byte size markers: