Index: Makefile.in =================================================================== RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v retrieving revision 1.903.2.158.2.3 diff -Idpatel.pbxuser -c -3 -p -r1.903.2.158.2.3 Makefile.in *** Makefile.in 3 Jan 2004 20:25:24 -0000 1.903.2.158.2.3 --- Makefile.in 6 Jan 2004 02:11:27 -0000 *************** OBJS-common = \ *** 879,885 **** tree-ssa-pre.o tree-ssa-live.o tree-must-alias.o tree-ssa-operands.o \ tree-ssa-dom.o domwalk.o tree-tailcall.o gimple-low.o tree-iterator.o \ tree-phinodes.o tree-ssanames.o tree-sra.o tree-vectorizer.o \ ! tree-ssa-loop.o tree-ssa-loop-im.o \ alias.o bb-reorder.o bitmap.o builtins.o caller-save.o calls.o \ cfg.o cfganal.o cfgbuild.o cfgcleanup.o cfglayout.o cfgloop.o \ cfgloopanal.o cfgloopmanip.o loop-init.o loop-unswitch.o loop-unroll.o \ --- 879,885 ---- tree-ssa-pre.o tree-ssa-live.o tree-must-alias.o tree-ssa-operands.o \ tree-ssa-dom.o domwalk.o tree-tailcall.o gimple-low.o tree-iterator.o \ tree-phinodes.o tree-ssanames.o tree-sra.o tree-vectorizer.o \ ! tree-ssa-loop.o tree-ssa-loop-im.o tree-lv.o \ alias.o bb-reorder.o bitmap.o builtins.o caller-save.o calls.o \ cfg.o cfganal.o cfgbuild.o cfgcleanup.o cfglayout.o cfgloop.o \ cfgloopanal.o cfgloopmanip.o loop-init.o loop-unswitch.o loop-unroll.o \ *************** tree-vectorizer.o: tree-vectorizer.c $(C *** 1639,1644 **** --- 1639,1646 ---- errors.h $(GGC_H) $(OPTABS_H) $(TREE_H) $(RTL_H) $(BASIC_BLOCK_H) diagnostic.h \ $(TREE_FLOW_H) $(TREE_DUMP_H) $(TIMEVAR_H) cfgloop.h tree-chrec.h \ tree-vectorizer.h tree-data-ref.h tree-scalar-evolution.h tree-fold-const.h + tree-lv.o: tree-lv.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GGC_H) \ + $(TREE_H) $(BASIC_BLOCK_H) $(RTL_H) cfgloop.h $(TREE_FLOW_H) c-call-graph.o : c-call-graph.c $(CONFIG_H) $(SYSTEM_H) $(C_TREE_H) \ $(C_COMMON_H) diagnostic.h hard-reg-set.h $(BASIC_BLOCK_H) $(TREE_FLOW_H) \ $(TM_H) coretypes.h Index: tree-cfg.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v retrieving revision 1.1.4.244.2.1 diff -Idpatel.pbxuser -c -3 -p -r1.1.4.244.2.1 tree-cfg.c *** tree-cfg.c 3 Jan 2004 20:25:27 -0000 1.1.4.244.2.1 --- tree-cfg.c 6 Jan 2004 02:11:27 -0000 *************** static GTY(()) tree factored_computed_go *** 80,86 **** static GTY(()) tree factored_computed_goto; /* Basic blocks and flowgraphs. */ - static basic_block create_bb (tree, basic_block); static void create_block_annotation (basic_block); static void free_blocks_annotations (void); static void clear_blocks_annotations (void); --- 80,85 ---- *************** make_blocks (tree stmt_list) *** 347,353 **** /* Create and return a new basic block after bb AFTER. Use STMT_LIST for the body if non-null, otherwise create a new statement list. */ ! static basic_block create_bb (tree stmt_list, basic_block after) { basic_block bb; --- 346,352 ---- /* Create and return a new basic block after bb AFTER. Use STMT_LIST for the body if non-null, otherwise create a new statement list. */ ! basic_block create_bb (tree stmt_list, basic_block after) { basic_block bb; Index: tree-flow.h =================================================================== RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v retrieving revision 1.1.4.177.2.2 diff -Idpatel.pbxuser -c -3 -p -r1.1.4.177.2.2 tree-flow.h *** tree-flow.h 3 Jan 2004 20:25:27 -0000 1.1.4.177.2.2 --- tree-flow.h 6 Jan 2004 02:11:27 -0000 *************** extern void compute_dominance_frontiers *** 432,437 **** --- 432,438 ---- extern bool verify_stmt (tree); extern void verify_stmts (void); extern basic_block tree_duplicate_bb (basic_block, edge); + extern basic_block create_bb (tree, basic_block); /* In tree-pretty-print.c. */ extern void dump_generic_bb (FILE *, basic_block, int, int); Index: tree-lv.c =================================================================== RCS file: tree-lv.c diff -N tree-lv.c *** /dev/null 1 Jan 1970 00:00:00 -0000 --- tree-lv.c 6 Jan 2004 02:11:27 -0000 *************** *** 0 **** --- 1,445 ---- + /* Loop Versioning transformation. */ + /* Copyright (C) 2003, 2004 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 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. */ + + /* Loop Versioning transformation. + + This transformation given a condition and a loop, creates + -if (condition) { loop_copy1 } else { loop_copy2 }, + where loop_copy1 is the loop transformed in one way, and loop_copy2 + is the loop transformed in another way (or unchanged). 'condition' + may be a run time test for things that were not resolved by static + analysis (overlapping ranges (anti-aliasing), alignment, etc.). */ + + #include "config.h" + #include "system.h" + #include "coretypes.h" + #include "ggc.h" + #include "tm.h" + #include "tree.h" + #include "rtl.h" + #include "basic-block.h" + #include "cfgloop.h" + #include "tree-simple.h" + #include "tree-flow.h" + #include "tree-flow-inline.h" + #include "bitmap.h" + + /* CHECKME: Steal arguments field to store new cloned label. */ + #define NEW_LABEL_COPY(DECL) ((DECL)->decl.arguments) + + /* Main entry point. */ + void tree_ssa_loop_version (tree, tree, struct loop *); + + static tree lv_copy_gimple (tree); + static tree lv_copy_gimple_expr (tree); + static tree lv_copy_gimple_exceptional (tree); + static void lv_prepare_loop (struct loop *, basic_block *, tree *); + static void lv_duplicate_blocks (struct loop *, basic_block *); + static void lv_adjust_loop_entry_edge (struct loop *, basic_block *blocks, + tree cond_expr, tree entry_label); + static void lv_adjust_edges (int); + + /* Copy gimple expr for loop versioning. Handle labels + appropriately. */ + static tree + lv_copy_gimple_expr (tree t) + { + tree copy = NULL_TREE; + int i = 0; + switch (TREE_CODE (t)) + { + case GOTO_EXPR: + case LABEL_EXPR: + /* First operand is label. Use new label copy. */ + copy = copy_node (t); + if (NEW_LABEL_COPY (TREE_OPERAND (t, 0))) + TREE_OPERAND (copy, 0) = NEW_LABEL_COPY (TREE_OPERAND (t, 0)); + else + TREE_OPERAND (copy, 0) = TREE_OPERAND (t, 0); + break; + + case CASE_LABEL_EXPR: + /* Third operand is label. Use new label copy. */ + copy = copy_node (t); + TREE_OPERAND (copy, 0) = lv_copy_gimple (TREE_OPERAND (t, 0)); + TREE_OPERAND (copy, 1) = lv_copy_gimple (TREE_OPERAND (t, 1)); + if (NEW_LABEL_COPY (TREE_OPERAND (t,2))) + TREE_OPERAND (copy, 0) = NEW_LABEL_COPY (TREE_OPERAND (t, 2)); + else + TREE_OPERAND (copy, 2) = lv_copy_gimple (TREE_OPERAND (t, 2)); + break; + + case SWITCH_EXPR: + /* Third operand is TREE_VEC. */ + copy = copy_node (t); + TREE_OPERAND (copy, 0) = lv_copy_gimple (TREE_OPERAND (t, 0)); + TREE_OPERAND (copy, 1) = lv_copy_gimple (TREE_OPERAND (t, 1)); + if (TREE_OPERAND (t, 2)) + { + int i; + tree op = TREE_OPERAND (t, 2); + tree tv = make_tree_vec (TREE_VEC_LENGTH (op)); + for (i = 0; i < TREE_VEC_LENGTH (op); i++) + TREE_VEC_ELT (tv, i) = lv_copy_gimple (TREE_VEC_ELT (op, i)); + + TREE_OPERAND (copy, 2) = tv; + } + break; + + case CALL_EXPR: + /* Second operand is list. */ + copy = copy_node (t); + TREE_OPERAND (copy, 0) = lv_copy_gimple (TREE_OPERAND (t, 0)); + TREE_OPERAND (copy, 1) = copy_list (TREE_OPERAND (t, 1)); + break; + + case EH_FILTER_EXPR: + /* First operand is list. */ + copy = copy_node (t); + TREE_OPERAND (copy, 0) = copy_list (TREE_OPERAND (t, 0)); + TREE_OPERAND (copy, 1) = lv_copy_gimple (TREE_OPERAND (t, 1)); + break; + + case CONSTRUCTOR: + /* First and only operand is list. */ + copy = copy_node (t); + TREE_OPERAND (copy, 0) = copy_list (TREE_OPERAND (t, 0)); + break; + + default: + /* Copy node and all arguments using copy_node. */ + copy = copy_node (t); + if (TREE_CODE_LENGTH (TREE_CODE (t)) > 0 ) + for (i = 0; i < TREE_CODE_LENGTH (TREE_CODE (t)); i++) + TREE_OPERAND (copy, i) = lv_copy_gimple (TREE_OPERAND (t, i)); + break; + } + return copy; + } + + /* Copy exceptional gimple tree node. Take care of SSA_NAMES and + PHI_NODEs. */ + + static tree + lv_copy_gimple_exceptional (tree t) + { + tree copy = NULL_TREE; + int i; + switch (TREE_CODE (t)) + { + case SSA_NAME: + copy = copy_node (t); + SSA_NAME_VAR (copy) = lv_copy_gimple (SSA_NAME_VAR (t)); + /* FIXME: + Handle SSA_NAME_DEF_STMT */ + break; + case PHI_NODE: + /* When we rewrite all new vars in ssa form, these nodes + will be recreated. */ + break; + default: + /* Copy node and all arguments using copy_node. */ + copy = copy_node (t); + if (TREE_CODE_LENGTH (TREE_CODE (t)) > 0 ) + for (i = 0; i < TREE_CODE_LENGTH (TREE_CODE (t)); i++) + TREE_OPERAND (copy, i) = lv_copy_gimple (TREE_OPERAND (t, i)); + break; + } + return copy; + } + + /* Copy gimple node such that it is a suitable for loop versioning + transformation. */ + + static tree + lv_copy_gimple (tree t) + { + tree copy = NULL_TREE; + int i; + + if (!t) + return NULL_TREE; + + switch (TREE_CODE_CLASS (TREE_CODE (t))) + { + case 'x': + copy = lv_copy_gimple_exceptional (t); + break; + + case 'b': + copy = copy_node (t); + BLOCK_SUBBLOCKS (copy) = copy_list (BLOCK_SUBBLOCKS (t)); + BLOCK_VARS (copy) = copy_list (BLOCK_VARS (t)); + + /* CHECKME : Is this correct ? */ + BLOCK_SUPERCONTEXT (copy) = lv_copy_gimple (BLOCK_SUPERCONTEXT (t)); + BLOCK_CHAIN (copy) = copy_list (BLOCK_CHAIN (t)); + break; + + case 't': + case 'c': + /* CHECKME: OK to share constants? */ + copy = t; + break; + + case 'd': + if (TREE_CODE (t) == LABEL_DECL) + abort (); + else if (TREE_CODE (t) == VAR_DECL) + { + /* PUSH in var to rename map */ + } + copy = t; + break; + + case 'r': + /* Copy reference node and all its arguments using copy_node. */ + copy = copy_node (t); + if (TREE_CODE_LENGTH (TREE_CODE (t)) > 0 ) + for (i = 0; i < TREE_CODE_LENGTH (TREE_CODE (t)); i++) + TREE_OPERAND (copy, i) = lv_copy_gimple (TREE_OPERAND (t, i)); + break; + + case '1': + /* unary ops */ + copy = copy_node (t); + TREE_OPERAND (copy, 0) = lv_copy_gimple (TREE_OPERAND (t, 0)); + break; + + case '2': + case '<': + /* binary exprs and conditional exprs */ + copy = copy_node (t); + TREE_OPERAND (copy, 0) = lv_copy_gimple (TREE_OPERAND (t, 0)); + TREE_OPERAND (copy, 1) = lv_copy_gimple (TREE_OPERAND (t, 1)); + break; + + case 's': + case 'e': + copy = lv_copy_gimple_expr (t); + break; + + default: + /* I do not know what is this. */ + abort (); + break; + } + return copy; + } + + /* Prepare loop for loop versioning transformation. + Create cloned lablels for second version. */ + static void + lv_prepare_loop (struct loop *loop, + basic_block *blocks, + tree *entry_label) + { + size_t i; + *entry_label = NULL_TREE; + + /* Walk statements and create new labels. */ + for (i = 0; i < loop->num_nodes; i++) + { + block_stmt_iterator bsi; + + for (bsi = bsi_start (blocks[i]); !bsi_end_p (bsi); bsi_next (&bsi)) + { + tree stmt = bsi_stmt (bsi); + if (TREE_CODE (stmt) == LABEL_DECL && !NEW_LABEL_COPY (stmt)) + { + tree new_ld = copy_node (stmt); + LABEL_DECL_UID (new_ld) = -1; + NEW_LABEL_COPY (stmt) = new_ld; + + /* First label in first block is entry label. */ + if (i == 0 && !(*entry_label)) + *entry_label = stmt; + } + /* Here we can add checks to reject loops. */ + } + } + return; + } + + /* Duplicate basic blocks using lv_copy_gimple. Use 'aux' field + to maintain relation between original bb and new bb. */ + + static void + lv_duplicate_blocks (struct loop * loop, basic_block *blocks) + { + size_t i; + + /* Duplicate blocks. Relate new and old blocks using 'aux' field. */ + for (i = 0; i < loop->num_nodes; i++) + { + basic_block new_bb; + block_stmt_iterator bsi; + tree new_list = alloc_stmt_list (); + tree_stmt_iterator new_list_tsi = tsi_start (new_list); + + for (bsi = bsi_start (blocks[i]); !bsi_end_p (bsi); bsi_next (&bsi)) + { + tree stmt = bsi_stmt (bsi); + tree copy = lv_copy_gimple (stmt); + tsi_link_after (&new_list_tsi, copy, TSI_CONTINUE_LINKING); + } + + /* FIXME: Insert after the exit block */ + new_bb = create_bb (new_list, BASIC_BLOCK (n_basic_blocks - 1)); + new_bb->aux = blocks[i]; + blocks[i]->aux = new_bb; + + /* Set bb for statment list. */ + new_list_tsi = tsi_start (new_list); + while (!tsi_end_p (new_list_tsi)) + { + tree stmt = tsi_stmt (new_list_tsi); + set_bb_for_stmt (stmt, new_bb); + tsi_next (&new_list_tsi); + } + + /* FIXME What about computed gotos ? */ + } + } + + static void + lv_adjust_loop_entry_edge (struct loop *loop, + basic_block *blocks, + tree cond_expr, + tree entry_label) + { + + edge e; + for (e = blocks[0]->pred; e; e = e->pred_next) + { + if (flow_loop_outside_edge_p (loop, e)) + { + + /* This is a incoming edge. + + --- edge e ---- > [loop entry label] + + Split it and insert new conditional expression and adjust edges. + + --- edge e ---> [cond expr] ---> [loop entry label] + | + +---------> [2nd loop entry label] + */ + block_stmt_iterator bsi; + basic_block second_head = NULL; + basic_block new_head = NULL; + tree goto1 = NULL_TREE; + tree goto2 = NULL_TREE; + tree new_cond_expr = NULL_TREE; + + + new_head = tree_split_edge (e); + + /* Build new conditional expr */ + goto1 = build1 (GOTO_EXPR, void_type_node, entry_label); + goto2 = build1 (GOTO_EXPR, void_type_node, + NEW_LABEL_COPY (entry_label)); + + new_cond_expr = build (COND_EXPR, void_type_node, + cond_expr, goto1, goto2); + + + /* Replace goto with new cond. in loop_entry_block. */ + bsi = bsi_start (new_head); + bsi_insert_after (&bsi, new_cond_expr, BSI_NEW_STMT); + + second_head = (basic_block) blocks[0]->aux; + if (!second_head) + abort (); + + /* Remove old edge from loop entry edge and adjust edges for + new loop entry block. */ + remove_edge (e); + make_edge (new_head, blocks[0], EDGE_TRUE_VALUE); + set_immediate_dominator (CDI_DOMINATORS, blocks[0], new_head); + make_edge (new_head, second_head, EDGE_FALSE_VALUE); + set_immediate_dominator (CDI_DOMINATORS, second_head, new_head); + + break; + } + } + } + + /* Adjust edges for newly created basic blocks. */ + static void + lv_adjust_edges (int first_bb_no) + { + int i; + /* Traverse basic block array placing edges. */ + for (i = first_bb_no; i < n_basic_blocks; i++) + { + edge e; + basic_block bb = BASIC_BLOCK (i); + basic_block original_bb = (basic_block) bb->aux; + + /* create and copy annotation */ + bb->tree_annotations = ggc_alloc_cleared (sizeof (struct bb_ann_d)); + + for (e = original_bb->succ; e; e = e->succ_next) + { + if (e->dest->aux) + make_edge (bb, (basic_block) e->dest->aux, e->flags); + else + make_edge (bb, (basic_block) e->dest, e->flags); + } + } + } + + /* Main entry point. */ + void + tree_ssa_loop_version (tree fndecl, + tree cond_expr, + struct loop * loop) + { + size_t i; + basic_block *blocks; + + int initial_bb_count; + tree entry_label = NULL_TREE; + tree new_cond_expr = NULL_TREE; + + blocks = get_loop_body (loop); + + /* Prepare loop for versioning by creating new labels appropriately. */ + lv_prepare_loop (loop, blocks, &entry_label); + + /* Record initial bb count. */ + initial_bb_count = n_basic_blocks; + + /* Duplicate loop body. */ + lv_duplicate_blocks (loop, blocks); + + /* Split loop entry edge and insert new block with cond expr. */ + lv_adjust_loop_entry_edge (loop, blocks, cond_expr, entry_label); + + /* Adjust new basic blocks edges. */ + lv_adjust_edges (initial_bb_count); + + /* CHECKME: Is this OK ? */ + free_dominance_info (CDI_DOMINATORS); + calculate_dominance_info (CDI_DOMINATORS); + + return; + } Index: tree-lv.h =================================================================== RCS file: tree-lv.h diff -N tree-lv.h *** /dev/null 1 Jan 1970 00:00:00 -0000 --- tree-lv.h 6 Jan 2004 02:11:27 -0000 *************** *** 0 **** --- 1,28 ---- + /* Loop Versioning transformation. */ + /* Copyright (C) 2003, 2004 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 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. */ + + /* Loop Versioning transformation. */ + + #ifndef GCC_TREE_LV_H + #define GCC_TREE_LV_H + + void tree_ssa_loop_version (tree, tree, struct loop *); + + #endif /* GCC_TREE_LV_H */ Index: tree-vectorizer.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/Attic/tree-vectorizer.c,v retrieving revision 1.1.2.7 diff -Idpatel.pbxuser -c -3 -p -r1.1.2.7 tree-vectorizer.c *** tree-vectorizer.c 5 Jan 2004 14:14:28 -0000 1.1.2.7 --- tree-vectorizer.c 6 Jan 2004 02:11:27 -0000 *************** *** 1,4 **** ! /* Scalar evolution detector. Copyright (C) 2003, 2004 Free Software Foundation, Inc. Contributed by Dorit Naishlos --- 1,4 ---- ! /* Tree vectorization pass. Copyright (C) 2003, 2004 Free Software Foundation, Inc. Contributed by Dorit Naishlos