aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-loop-memset.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-ssa-loop-memset.c')
-rw-r--r--gcc/tree-ssa-loop-memset.c733
1 files changed, 733 insertions, 0 deletions
diff --git a/gcc/tree-ssa-loop-memset.c b/gcc/tree-ssa-loop-memset.c
new file mode 100644
index 00000000000..b3dbd154e20
--- /dev/null
+++ b/gcc/tree-ssa-loop-memset.c
@@ -0,0 +1,733 @@
+/* APPLE LOCAL begin loops-to-memset (ENTIRE FILE!) */
+/* Loops to memset.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+ Contributed by Andrew Pinski <apinski@apple.com>.
+
+ 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 2, 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 COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "ggc.h"
+#include "tree.h"
+#include "rtl.h"
+#include "tm_p.h"
+#include "hard-reg-set.h"
+#include "basic-block.h"
+#include "output.h"
+#include "diagnostic.h"
+#include "tree-flow.h"
+#include "tree-dump.h"
+#include "timevar.h"
+#include "cfgloop.h"
+#include "domwalk.h"
+#include "params.h"
+#include "tree-pass.h"
+#include "flags.h"
+#include "tree-data-ref.h"
+#include "tree-scalar-evolution.h"
+#include "tree-chrec.h"
+#include "tree-vectorizer.h"
+
+static bool memset_debug_stats (struct loop *loop);
+static bool memset_debug_details (struct loop *loop);
+
+/* Function memset_analyze_data_refs.
+
+ Find all the data references in the loop.
+
+ Handle INDIRECT_REFs and one dimensional ARRAY_REFs
+ which base is really an array (not a pointer).
+
+ This is different from vect_analyze_data_refs in tree-vectorizer.c as
+ we handle unaligned data stores and we only handle data stores. */
+
+static bool
+memset_analyze_data_refs (loop_vec_info loop_vinfo)
+{
+ struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
+ basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
+ int nbbs = loop->num_nodes;
+ block_stmt_iterator si;
+ int j;
+ struct data_reference *dr;
+
+ if (memset_debug_details (NULL))
+ fprintf (dump_file, "\n<<memset_analyze_data_refs>>\n");
+
+ for (j = 0; j < nbbs; j++)
+ {
+ basic_block bb = bbs[j];
+ for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
+ {
+ tree stmt = bsi_stmt (si);
+ stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ v_may_def_optype v_may_defs = STMT_V_MAY_DEF_OPS (stmt);
+ v_must_def_optype v_must_defs = STMT_V_MUST_DEF_OPS (stmt);
+ vuse_optype vuses = STMT_VUSE_OPS (stmt);
+ varray_type *datarefs = NULL;
+ int nvuses, nv_may_defs, nv_must_defs;
+ tree memref = NULL;
+ tree array_base;
+ tree symbl;
+
+ /* Assumption: there exists a data-ref in stmt, if and only if
+ it has vuses/vdefs. */
+
+ if (!vuses && !v_may_defs && !v_must_defs)
+ continue;
+
+ nvuses = NUM_VUSES (vuses);
+ nv_may_defs = NUM_V_MAY_DEFS (v_may_defs);
+ nv_must_defs = NUM_V_MUST_DEFS (v_must_defs);
+
+ if (nvuses && (nv_may_defs || nv_must_defs))
+ {
+ if (memset_debug_details (NULL))
+ {
+ fprintf (dump_file, "unexpected vdefs and vuses in stmt: ");
+ print_generic_expr (dump_file, stmt, TDF_SLIM);
+ }
+ return false;
+ }
+
+ if (TREE_CODE (stmt) != MODIFY_EXPR)
+ {
+ if (memset_debug_details (NULL))
+ {
+ fprintf (dump_file, "unexpected vops in stmt: ");
+ print_generic_expr (dump_file, stmt, TDF_SLIM);
+ }
+ return false;
+ }
+
+ if (vuses)
+ {
+ if (memset_debug_details (NULL))
+ {
+ fprintf (dump_file, "Memory access in the loop: ");
+ print_generic_expr (dump_file, stmt, TDF_SLIM);
+ }
+ return false;
+ }
+ else /* vdefs */
+ {
+ memref = TREE_OPERAND (stmt, 0);
+ datarefs = &(LOOP_VINFO_DATAREF_WRITES (loop_vinfo));
+ }
+
+ if (TREE_CODE (memref) == INDIRECT_REF)
+ {
+ /* MERGE FIXME */
+ abort ();
+ /* dr = vect_analyze_pointer_ref_access (memref, stmt, false); */
+ if (! dr)
+ return false;
+ symbl = DR_BASE_NAME (dr);
+ }
+ else if (TREE_CODE (memref) == ARRAY_REF)
+ {
+ tree base;
+ array_base = TREE_OPERAND (memref, 0);
+
+ if (TREE_CODE (array_base) == ARRAY_REF)
+ {
+ if (memset_debug_stats (loop) || memset_debug_details (loop))
+ {
+ fprintf (dump_file,
+ "not vectorized: multi-dimensional array.");
+ print_generic_expr (dump_file, stmt, TDF_SLIM);
+ }
+ return false;
+ }
+
+ dr = analyze_array (stmt, memref, false);
+
+ /* Find the relevant symbol for aliasing purposes. */
+ base = DR_BASE_NAME (dr);
+ switch (TREE_CODE (base))
+ {
+ case VAR_DECL:
+ symbl = base;
+ break;
+ default:
+ if (memset_debug_stats (loop)
+ || memset_debug_details (loop))
+ {
+ fprintf (dump_file,
+ "not transformed: unhandled struct/class field access ");
+ print_generic_expr (dump_file, stmt, TDF_SLIM);
+ }
+ return false;
+ } /* switch */
+ }
+ else
+ {
+ if (memset_debug_stats (loop) || memset_debug_details (loop))
+ {
+ fprintf (dump_file, "not transformed: unhandled data ref: ");
+ print_generic_expr (dump_file, stmt, TDF_SLIM);
+ }
+ return false;
+ }
+
+ /* Find and record the memtag assigned to this data-ref. */
+ if (TREE_CODE (symbl) == VAR_DECL
+ || (TREE_CODE (symbl) == COMPONENT_REF
+ && TREE_CODE (TREE_OPERAND (symbl, 0)) == VAR_DECL))
+ STMT_VINFO_MEMTAG (stmt_info) = symbl;
+ else if (TREE_CODE (symbl) == SSA_NAME)
+ {
+ tree tag;
+ symbl = SSA_NAME_VAR (symbl);
+ tag = get_var_ann (symbl)->type_mem_tag;
+ if (!tag)
+ {
+ tree ptr = TREE_OPERAND (memref, 0);
+ if (TREE_CODE (ptr) == SSA_NAME)
+ tag = get_var_ann (SSA_NAME_VAR (ptr))->type_mem_tag;
+ }
+ if (!tag)
+ {
+ if (memset_debug_stats (loop) || memset_debug_details (loop))
+ fprintf (dump_file, "not vectorized: no memtag for ref.");
+ return false;
+ }
+ STMT_VINFO_MEMTAG (stmt_info) = tag;
+ }
+ else
+ {
+ if (memset_debug_stats (loop) || memset_debug_details (loop))
+ {
+ fprintf (dump_file, "not vectorized: unsupported data-ref: ");
+ print_generic_expr (dump_file, memref, TDF_SLIM);
+ }
+ return false;
+ }
+
+ VARRAY_PUSH_GENERIC_PTR (*datarefs, dr);
+ STMT_VINFO_DATA_REF (stmt_info) = dr;
+ }
+ }
+
+ return true;
+}
+
+/* Function memset_analyze_loop_with_symbolic_num_of_iters.
+
+ In case the number of iterations that LOOP iterates in unknown at compile
+ time, an epilog loop will be generated, and the loop induction variables
+ (IVs) will be "advanced" to the value they are supposed to take just before
+ the epilog loop. Here we check that the access function of the loop IVs
+ and the expression that represents the loop bound are simple enough.
+ These restrictions will be relxed in the future. */
+
+static bool
+memset_analyze_loop_with_symbolic_num_of_iters (tree niters,
+ struct loop *loop)
+{
+ basic_block bb = loop->header;
+ tree phi;
+
+ if (memset_debug_details (NULL))
+ fprintf (dump_file,
+ "\n<<memset_analyze_loop_with_symbolic_num_of_iters>>\n");
+
+ if (chrec_contains_undetermined (niters))
+ {
+ if (memset_debug_details (NULL))
+ fprintf (dump_file, "Infinite number of iterations.");
+ return false;
+ }
+
+ if (!niters)
+ {
+ if (memset_debug_details (NULL))
+ fprintf (dump_file, "niters is NULL pointer.");
+ return false;
+ }
+
+ if (memset_debug_details (NULL))
+ {
+ fprintf (dump_file, "Symbolic number of iterations is ");
+ print_generic_expr (dump_file, niters, TDF_DETAILS);
+ }
+
+ /* Analyze phi functions of the loop header. */
+
+ for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+ {
+ tree access_fn = NULL;
+ tree evolution_part;
+
+ if (memset_debug_details (NULL))
+ {
+ fprintf (dump_file, "Analyze phi: ");
+ print_generic_expr (dump_file, phi, TDF_SLIM);
+ }
+
+ /* Skip virtual phi's. The data dependences that are associated with
+ virtual defs/uses (i.e., memory accesses) are analyzed elsewhere. */
+
+ if (!is_gimple_reg (SSA_NAME_VAR (PHI_RESULT (phi))))
+ {
+ if (memset_debug_details (NULL))
+ fprintf (dump_file, "virtual phi. skip.");
+ continue;
+ }
+
+ /* Analyze the evolution function. */
+
+ access_fn = instantiate_parameters
+ (loop, analyze_scalar_evolution (loop, PHI_RESULT (phi)));
+
+ if (!access_fn)
+ {
+ if (memset_debug_details (NULL))
+ fprintf (dump_file, "No Access function.");
+ return false;
+ }
+
+ if (memset_debug_details (NULL))
+ {
+ fprintf (dump_file, "Access function of PHI: ");
+ print_generic_expr (dump_file, access_fn, TDF_SLIM);
+ }
+
+ evolution_part = evolution_part_in_loop_num (access_fn, loop->num);
+
+ if (evolution_part == NULL_TREE)
+ return false;
+
+ /* FORNOW: We do not transform initial conditions of IVs
+ which evolution functions are a polynomial of degree >= 2. */
+
+ if (tree_is_chrec (evolution_part))
+ return false;
+ }
+
+ return true;
+}
+
+
+/* Function debug_loop_details.
+
+ For memset debug dumps. */
+
+static bool
+memset_debug_details (struct loop *loop)
+{
+ basic_block bb;
+ block_stmt_iterator si;
+ tree node = NULL_TREE;
+
+ if (!dump_file || !(dump_flags & TDF_DETAILS))
+ return false;
+
+ if (!loop)
+ {
+ fprintf (dump_file, "\n");
+ return true;
+ }
+
+ if (!loop->header)
+ return false;
+
+ bb = loop->header;
+
+ for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
+ {
+ node = bsi_stmt (si);
+ if (node && EXPR_P (node) && EXPR_LOCUS (node))
+ break;
+ }
+
+ if (node && EXPR_P (node) && EXPR_LOCUS (node)
+ && EXPR_FILENAME (node) && EXPR_LINENO (node))
+ {
+ fprintf (dump_file, "\nloop at %s:%d: ",
+ EXPR_FILENAME (node), EXPR_LINENO (node));
+ return true;
+ }
+
+ return false;
+}
+
+/* Function debug_loop_stats.
+
+ For vectorization statistics dumps. */
+
+static bool
+memset_debug_stats (struct loop *loop)
+{
+ basic_block bb;
+ block_stmt_iterator si;
+ tree node = NULL_TREE;
+
+ if (!dump_file || !(dump_flags & TDF_STATS))
+ return false;
+
+ if (!loop)
+ {
+ fprintf (dump_file, "\n");
+ return true;
+ }
+
+ if (!loop->header)
+ return false;
+
+ bb = loop->header;
+
+ for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
+ {
+ node = bsi_stmt (si);
+ if (node && EXPR_P (node) && EXPR_LOCUS (node))
+ break;
+ }
+
+ if (node && EXPR_P (node) && EXPR_LOCUS (node)
+ && EXPR_FILENAME (node) && EXPR_LINENO (node))
+ {
+ fprintf (dump_file, "\nloop at %s:%d: ",
+ EXPR_FILENAME (node), EXPR_LINENO (node));
+ return true;
+ }
+
+ return false;
+}
+
+/* Function memset_analyze_loop_form.
+
+ Verify the following restrictions:
+ - it's an inner-most loop
+ - number of BBs = 2 (which are the loop header and the latch)
+ - the loop has a pre-header
+ - the loop has a single entry and exit
+ - the loop exit condition is simple enough, and the number of iterations
+ can be analyzed (a countable loop).
+
+ This differs from vect_analyze_loop_form by we handle non constant
+ interations. */
+
+static loop_vec_info
+memset_analyze_loop_form (struct loop *loop)
+{
+ loop_vec_info loop_vinfo;
+ tree loop_cond;
+ tree number_of_iterations = NULL_TREE;
+
+ if (memset_debug_details (loop))
+ fprintf (dump_file, "\n<<memset_analyze_loop_form>>\n");
+
+ if (loop->level > 1 /* FORNOW: inner-most loop */
+ || loop->num_exits > 1 || loop->num_entries > 1 || loop->num_nodes != 2
+ || !loop->pre_header || !loop->header || !loop->latch)
+ {
+ if (memset_debug_stats (loop) || memset_debug_details (loop))
+ {
+ fprintf (dump_file, "not vectorized: bad loop form.\n");
+ if (loop->level > 1)
+ fprintf (dump_file, "nested loop.\n");
+ else if (loop->num_exits > 1 || loop->num_entries > 1)
+ fprintf (dump_file, "multiple entries or exits.\n");
+ else if (loop->num_nodes != 2 || !loop->header || !loop->latch)
+ fprintf (dump_file, "too many BBs in loop.\n");
+ else if (!loop->pre_header)
+ fprintf (dump_file, "no pre-header BB for loop.\n");
+ }
+
+ return NULL;
+ }
+
+ /* We assume that the loop exit condition is at the end of the loop. i.e,
+ that the loop is represented as a do-while (with a proper if-guard
+ before the loop if needed), where the loop header contains all the
+ executable statements, and the latch is empty. */
+ if (!empty_block_p (loop->latch))
+ {
+ if (memset_debug_stats (loop) || memset_debug_details (loop))
+ fprintf (dump_file, "not vectorized: unexpectd loop form.");
+ return NULL;
+ }
+
+ if (empty_block_p (loop->header))
+ {
+ if (memset_debug_stats (loop) || memset_debug_details (loop))
+ fprintf (dump_file, "not transformed: empty loop.");
+ return NULL;
+ }
+
+ loop_cond = vect_get_loop_niters (loop, &number_of_iterations);
+ if (!loop_cond)
+ {
+ if (memset_debug_stats (loop) || memset_debug_details (loop))
+ fprintf (dump_file, "not vectorized: complicated exit condition.\n");
+ return NULL;
+ }
+
+ if (!number_of_iterations)
+ {
+ if (memset_debug_stats (loop) || memset_debug_details (loop))
+ fprintf (dump_file,
+ "not vectorized: number of iterations cannot be computed.");
+ return NULL;
+ }
+
+ loop_vinfo = new_loop_vec_info (loop);
+ LOOP_VINFO_NITERS (loop_vinfo) = number_of_iterations;
+
+ if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo))
+ {
+ if (memset_debug_details (NULL))
+ fprintf (dump_file, "loop bound unknown.");
+
+ /* Unknown loop bound. */
+ if (!memset_analyze_loop_with_symbolic_num_of_iters (number_of_iterations,
+ loop))
+ {
+ if (memset_debug_stats (loop) || memset_debug_details (loop))
+ fprintf (dump_file, "not transformed: can't determine loop bound.\n");
+ return NULL;
+ }
+ else
+ {
+ /* We need only one loop entry for unknown loop bound support. */
+ if (loop->num_entries != 1 || !loop->pre_header)
+ {
+ if (memset_debug_stats (loop) || memset_debug_details (loop))
+ fprintf (dump_file,
+ "not transformed: more than one loop entry.");
+ return NULL;
+ }
+ }
+ }
+ else if (LOOP_VINFO_INT_NITERS (loop_vinfo) == 0)
+ {
+ if (memset_debug_stats (loop) || memset_debug_details (loop))
+ fprintf (dump_file, "not transformed: number of iterations = 0.\n");
+ return NULL;
+ }
+
+ LOOP_VINFO_EXIT_COND (loop_vinfo) = loop_cond;
+
+ return loop_vinfo;
+}
+
+/* Mark all the variables in V_MAY_DEF or V_MUST_DEF operands for STMT for
+ renaming. This becomes necessary when we modify all of a non-scalar. */
+
+static void
+mark_all_v_defs (tree stmt)
+{
+ tree sym;
+ ssa_op_iter iter;
+
+ get_stmt_operands (stmt);
+
+ FOR_EACH_SSA_TREE_OPERAND (sym, stmt, iter, SSA_OP_VIRTUAL_DEFS)
+ {
+ if (TREE_CODE (sym) == SSA_NAME)
+ sym = SSA_NAME_VAR (sym);
+ bitmap_set_bit (vars_to_rename, var_ann (sym)->uid);
+ }
+}
+
+
+/* This is the main entry point for the transformation. */
+void
+tree_ssa_memset (struct loops *loops)
+{
+ unsigned i;
+
+ for (i = 1; i < loops->num; i++)
+ {
+ struct loop *loop = loops->parray[i];
+ loop_vec_info vectorizer_info;
+ varray_type writes;
+ struct data_reference *drw;
+ tree access_chrec;
+ tree noi;
+
+ if (!loop)
+ continue;
+
+ flow_loop_scan (loop, LOOP_ALL);
+ vectorizer_info = memset_analyze_loop_form (loop);
+ if (!vectorizer_info)
+ continue;
+
+ if (!memset_analyze_data_refs (vectorizer_info))
+ {
+ if (memset_debug_details (loop))
+ fprintf (dump_file, "bad data references.");
+ destroy_loop_vec_info (vectorizer_info);
+ continue;
+ }
+
+ writes = LOOP_VINFO_DATAREF_WRITES (vectorizer_info);
+
+ /* TODO: handle more than data write. */
+ if (VARRAY_ACTIVE_SIZE (writes) != 1)
+ {
+ if (memset_debug_details (loop))
+ fprintf (dump_file, "no or more than one store.");
+ destroy_loop_vec_info (vectorizer_info);
+ continue;
+ }
+
+ drw = VARRAY_GENERIC_PTR (writes, 0);
+
+ /* TODO: handle multi-dimension arrays. */
+ if (DR_NUM_DIMENSIONS (drw) != 1)
+ {
+ if (memset_debug_details (loop))
+ fprintf (dump_file, "cannot handle multiple dimension array.");
+ destroy_loop_vec_info (vectorizer_info);
+ continue;
+ }
+
+ if (TREE_CODE (TREE_OPERAND (DR_STMT (drw), 1)) != INTEGER_CST)
+ {
+ if (memset_debug_details (loop))
+ fprintf (dump_file, "non constant store value.");
+ destroy_loop_vec_info (vectorizer_info);
+ continue;
+ }
+
+ /* TODO: handle other than zero values in types
+ where the unit size is greater than one. */
+ if (!integer_zerop (TREE_OPERAND (DR_STMT (drw), 1))
+ && !integer_onep (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (drw)))))
+ {
+ if (memset_debug_details (loop))
+ fprintf (dump_file, "cannot handle other zero value for types of other than char (for now).");
+ destroy_loop_vec_info (vectorizer_info);
+ continue;
+ }
+
+ access_chrec = DR_ACCESS_FN (drw, 0);
+
+ noi = LOOP_VINFO_NITERS (vectorizer_info);
+
+ /* Build the memset call. */
+ {
+ tree array = DR_BASE_NAME (drw);
+ tree value = TREE_OPERAND (DR_STMT (drw), 1);
+ tree function = implicit_built_in_decls[BUILT_IN_MEMSET];
+ tree args = NULL_TREE;
+ block_stmt_iterator bsi = bsi_last (loop->pre_header);
+ tree array_1 = make_rename_temp (ptr_type_node, NULL);
+ tree temp, stmt, var;
+ tree ni_name;
+
+ stmt = DR_STMT (drw);
+
+ /* Remove the array access stmt. */
+ {
+ block_stmt_iterator access_bsi;
+ /* Mark the MAY_DEF as needed to be renamed. */
+ mark_all_v_defs (stmt);
+ access_bsi = bsi_for_stmt (stmt);
+ bsi_remove (&access_bsi);
+ }
+
+ if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE)
+ {
+ tree type = TREE_TYPE (TREE_TYPE (array));
+ tree base = array;
+
+ while (TREE_CODE (base) == REALPART_EXPR
+ || TREE_CODE (base) == IMAGPART_EXPR
+ || handled_component_p (base))
+ base = TREE_OPERAND (base, 0);
+
+ if (DECL_P (base))
+ TREE_ADDRESSABLE (base) = 1;
+
+ array = build4 (ARRAY_REF, type, array, size_zero_node,
+ NULL_TREE, NULL_TREE);
+ array = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (array)),
+ array);
+ }
+
+ {
+ tree start = CHREC_LEFT (access_chrec);
+ tree size_mult;
+ tree array_var;
+ start = fold_convert (TREE_TYPE (array), start);
+ size_mult = fold_convert (TREE_TYPE (array),
+ TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (array))));
+ array = fold (build2 (PLUS_EXPR,
+ TREE_TYPE (array),
+ array,
+ fold (build2 (MULT_EXPR,
+ TREE_TYPE (array),
+ start,
+ size_mult))));
+ array_var = create_tmp_var (TREE_TYPE (array), "tmp");
+ add_referenced_tmp_var (array_var);
+ array = force_gimple_operand (array, &stmt, false, array_var);
+
+ if (stmt)
+ bsi_insert_after (&bsi, stmt, BSI_CONTINUE_LINKING);
+ }
+
+ var = create_tmp_var (size_type_node, "tmp");
+ add_referenced_tmp_var (var);
+
+ noi = fold (build2 (MULT_EXPR, TREE_TYPE (noi), noi,
+ fold_convert (TREE_TYPE (noi),
+ TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (array))))));
+
+ stmt = NULL_TREE;
+ ni_name = force_gimple_operand (noi, &stmt, false, var);
+
+ if (stmt)
+ bsi_insert_after (&bsi, stmt, BSI_CONTINUE_LINKING);
+
+ temp = build2 (MODIFY_EXPR, void_type_node, array_1,
+ array);
+
+ bsi_insert_after (&bsi, temp, BSI_CONTINUE_LINKING);
+
+ args = tree_cons (NULL, ni_name, args);
+ args = tree_cons (NULL, fold_convert (integer_type_node, value), args);
+ args = tree_cons (NULL, array_1, args);
+
+ temp = build_function_call_expr (function, args);
+
+ bsi_insert_after (&bsi, temp, BSI_CONTINUE_LINKING);
+ }
+
+ destroy_loop_vec_info (vectorizer_info);
+
+ }
+
+ rewrite_into_ssa (false);
+ if (!bitmap_empty_p (vars_to_rename))
+ {
+ /* The rewrite of ssa names may cause violation of loop closed ssa
+ form invariants. TODO -- avoid these rewrites completely.
+ Information in virtual phi nodes is sufficient for it. */
+ rewrite_into_loop_closed_ssa ();
+ }
+ bitmap_clear (vars_to_rename);
+}
+
+/* APPLE LOCAL end loops-to-memset (ENTIRE FILE!) */