diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 26 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 8 | ||||
-rw-r--r-- | gcc/fortran/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/fortran/f95-lang.c | 13 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/vect/vect-1.f90 | 10 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/vect/vect-2.f90 | 13 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/vect/vect-3.f90 | 12 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/vect/vect-4.f90 | 13 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/vect/vect-5.f90 | 40 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/vect/vect.exp | 99 | ||||
-rw-r--r-- | gcc/tree-ssanames.c | 30 | ||||
-rw-r--r-- | gcc/tree-vect-analyze.c | 26 | ||||
-rw-r--r-- | gcc/tree-vect-transform.c | 152 | ||||
-rw-r--r-- | gcc/tree-vectorizer.c | 3 | ||||
-rw-r--r-- | gcc/tree-vectorizer.h | 4 | ||||
-rw-r--r-- | gcc/tree.h | 1 |
17 files changed, 409 insertions, 56 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9922f7e..0d5849a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,29 @@ +2005-03-29 Keith Besaw <kbesaw@us.ibm.com> + + * tree-ssanames.c (duplicate_ssa_name_ptr_info): New function. + (duplicate_ssa_name): Call duplicate_ssa_name_ptr_info. + * tree-vect-analyze.c (vect_object_analysis): additional parm + pass back a "struct ptr_info_def *" with the points-to info. + (vect_analyze_data_refs): set the STMT_VINFO_PTR_INFO for the + statement using info returned from vect_object_analysis. + * tree-vect-transform.c (update_vuses_to_preheader): New function. + (vect_create_data_ref_ptr): Remove updates to vars_to_rename + for virtual uses and defs when creating a replacement vector + reference. Call duplicate_ssa_name_ptr_info to define points-to + info for vector pointer replacement using STMT_VINFO_PTR_INFO. + (vectorizable_store): copy_virtual_operands and update + definition statements. + (vectorizable_load): copy_virtual_operands. Remove call to + mark_call_clobbered_vars_to_rename for call to "const" builtin. + * tree-vectorizer.c (vectorize_loops): Remove calls to + rewrite_into_ssa and bitmap_clear (vars_to_rename). + (new_stmt_vec_info): initialize STMT_VINFO_PTR_INFO for stmt. + * tree-vectorizer.h (_stmt_vec_info): add field ptr_info and + define macro STMT_VINFO_PTR_INFO for use in accessing. + * tree.h add export of duplicate_ssa_name_ptr_info. + * rs6000.c (altivec_init_builtins): Declare builtin function + __builtin_altivec_mask_for_load to be "const". + 2005-03-29 Jakub Jelinek <jakub@redhat.com> PR middle-end/20622 diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 3fc857a..3ac7c83 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -7665,9 +7665,11 @@ altivec_init_builtins (void) targetm.vectorize.builtin_mask_for_load. */ decl = lang_hooks.builtin_function ("__builtin_altivec_mask_for_load", - v16qi_ftype_long_pcvoid, - ALTIVEC_BUILTIN_MASK_FOR_LOAD, - BUILT_IN_MD, NULL, NULL_TREE); + v16qi_ftype_long_pcvoid, + ALTIVEC_BUILTIN_MASK_FOR_LOAD, + BUILT_IN_MD, NULL, + tree_cons (get_identifier ("const"), + NULL_TREE, NULL_TREE)); /* Record the decl. Will be used by rs6000_builtin_mask_for_load. */ altivec_builtin_mask_for_load = decl; } diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 9967174..ccbd3cb 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,8 @@ +2005-03-29 Keith Besaw <kbesaw@us.ibm.com> + + * f95-lang.c (builtin_function): Process the attrs parameter + and apply the "const" attribute to the builtin if found. + 2005-03-27 Steven G. Kargl <kargls@comcast.net> * intrinsic.texi: Document AIMAG, AINT, ALL diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c index e0c22da..2fb06a9 100644 --- a/gcc/fortran/f95-lang.c +++ b/gcc/fortran/f95-lang.c @@ -680,7 +680,7 @@ builtin_function (const char *name, int function_code, enum built_in_class class, const char *library_name, - tree attrs ATTRIBUTE_UNUSED) + tree attrs) { tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type); DECL_EXTERNAL (decl) = 1; @@ -691,6 +691,17 @@ builtin_function (const char *name, pushdecl (decl); DECL_BUILT_IN_CLASS (decl) = class; DECL_FUNCTION_CODE (decl) = function_code; + + /* Possibly apply some default attributes to this built-in function. */ + if (attrs) + { + /* FORNOW the only supported attribute is "const". If others need + to be supported then see the more general solution in procedure + builtin_function in c-decl.c */ + if (lookup_attribute ( "const", attrs )) + TREE_READONLY (decl) = 1; + } + return decl; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2cc2451..dba8cc6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2005-03-29 Dorit Naishlos <dorit@il.ibm.com> + + * gfortran.dg/vect: New directory. + * gfortran.dg/vect/vect.exp: New. + * gfortran.dg/vect/vect-1.f90: New test. + * gfortran.dg/vect/vect-2.f90: New test. + * gfortran.dg/vect/vect-3.f90: New test. + * gfortran.dg/vect/vect-4.f90: New test. + * gfortran.dg/vect/vect-5.f90: New test. + 2005-03-29 Jakub Jelinek <jakub@redhat.com> PR middle-end/20622 diff --git a/gcc/testsuite/gfortran.dg/vect/vect-1.f90 b/gcc/testsuite/gfortran.dg/vect/vect-1.f90 new file mode 100644 index 0000000..90b37e4 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/vect/vect-1.f90 @@ -0,0 +1,10 @@ +! { dg-do compile } +! { dg-require-effective-target vect_float } + +DIMENSION A(1000000), B(1000000), C(1000000) +READ*, X, Y +A = LOG(X); B = LOG(Y); C = A + B +PRINT*, C(500000) +END + +! { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" } } diff --git a/gcc/testsuite/gfortran.dg/vect/vect-2.f90 b/gcc/testsuite/gfortran.dg/vect/vect-2.f90 new file mode 100644 index 0000000..f9cc35e --- /dev/null +++ b/gcc/testsuite/gfortran.dg/vect/vect-2.f90 @@ -0,0 +1,13 @@ +! { dg-do compile } +! { dg-require-effective-target vect_float } + +SUBROUTINE FOO(A, B, C) +DIMENSION A(1000000), B(1000000), C(1000000) +READ*, X, Y +A = LOG(X); B = LOG(Y); C = A + B +PRINT*, C(500000) +END + +! { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { xfail vect_no_align } } } +! { dg-final { scan-tree-dump-times "Alignment of access forced using peeling" 3 "vect" { xfail vect_no_align } } } +! { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 2 "vect" { xfail vect_no_align } } } diff --git a/gcc/testsuite/gfortran.dg/vect/vect-3.f90 b/gcc/testsuite/gfortran.dg/vect/vect-3.f90 new file mode 100644 index 0000000..26b9c79 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/vect/vect-3.f90 @@ -0,0 +1,12 @@ +! { dg-do compile } +! { dg-require-effective-target vect_float } + +SUBROUTINE SAXPY(X, Y, A, N) +DIMENSION X(N), Y(N) +Y = Y + A * X +END + +! fail to vectorize due to failure to compute number of iterations (PR tree-optimization/18527) +! { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } +! { dg-final { scan-tree-dump-times "Alignment of access forced using peeling" 1 "vect" { xfail *-*-* } } } +! { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 2 "vect" { xfail *-*-* } } } diff --git a/gcc/testsuite/gfortran.dg/vect/vect-4.f90 b/gcc/testsuite/gfortran.dg/vect/vect-4.f90 new file mode 100644 index 0000000..7659438 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/vect/vect-4.f90 @@ -0,0 +1,13 @@ +! { dg-do compile } +! { dg-require-effective-target vect_float } + +SUBROUTINE SAXPY(X, Y, A) +DIMENSION X(64), Y(64) +Y = Y + A * X +END + +! fail to vectorize until the patch that ignores dependence-distance 0 is +! brought from autovect. +! { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } +! { dg-final { scan-tree-dump-times "Alignment of access forced using peeling" 1 "vect" { xfail *-*-* } } } +! { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 2 "vect" { xfail *-*-* } } } diff --git a/gcc/testsuite/gfortran.dg/vect/vect-5.f90 b/gcc/testsuite/gfortran.dg/vect/vect-5.f90 new file mode 100644 index 0000000..44d8b62 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/vect/vect-5.f90 @@ -0,0 +1,40 @@ +! { dg-require-effective-target vect_int } + + Subroutine foo (N, M) + Integer N + Integer M + integer A(8,16) + integer B(8) + + B = (/ 2, 3, 5, 7, 11, 13, 17, 23 /) + + ! Unknown loop bound. J depends on I. + + do I = 1, N + do J = I, M + A(J,2) = B(J) + end do + end do + + do I = 1, N + do J = I, M + if (A(J,2) /= B(J)) then + call abort () + endif + end do + end do + + Return + end + + + program main + + Call foo (16, 8) + + stop + end + +! { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" { xfail vect_no_align } } } +! { dg-final { scan-tree-dump-times "Alignment of access forced using peeling" 1 "vect" { xfail vect_no_align } } } +! { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 2 "vect" { xfail vect_no_align } } } diff --git a/gcc/testsuite/gfortran.dg/vect/vect.exp b/gcc/testsuite/gfortran.dg/vect/vect.exp new file mode 100644 index 0000000..2b84fe4 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/vect/vect.exp @@ -0,0 +1,99 @@ +# Copyright (C) 1997, 2004 Free Software Foundation, Inc. + +# This program 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 of the License, or +# (at your option) any later version. +# +# This program 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 this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# GCC testsuite that uses the `dg.exp' driver. + +# Load support procs. +load_lib gfortran-dg.exp +load_lib target-supports.exp + +# Set up flags used for tests that don't specify options. +set DEFAULT_VECTCFLAGS "" + +# These flags are used for all targets. +lappend DEFAULT_VECTCFLAGS "-O2" "-ftree-vectorize" \ + "-ftree-vectorizer-verbose=3" "-fdump-tree-vect-stats" + +# If the target system supports vector instructions, the default action +# for a test is 'run', otherwise it's 'compile'. Save current default. +# Executing vector instructions on a system without hardware vector support +# is also disabled by a call to check_vect, but disabling execution here is +# more efficient. +global dg-do-what-default +set save-dg-do-what-default ${dg-do-what-default} + +# Skip these tests for targets that do not support generating vector +# code. Set additional target-dependent vector flags, which can be +# overridden by using dg-options in individual tests. +if [istarget "powerpc*-*-*"] { + # If there are powerpc targets to skip, do it here. + + lappend DEFAULT_VECTCFLAGS "-maltivec" + if [check_vmx_hw_available] { + set dg-do-what-default run + } else { + if [is-effective-target ilp32] { + # Specify a cpu that supports VMX for compile-only tests. + lappend DEFAULT_VECTCFLAGS "-mcpu=7400" + } + set dg-do-what-default compile + } +} elseif { [istarget "i?86-*-*"] || [istarget "x86_64-*-*"] } { + lappend DEFAULT_VECTCFLAGS "-msse2" + set dg-do-what-default run +} elseif [istarget "mipsisa64*-*-*"] { + lappend DEFAULT_VECTCFLAGS "-mpaired-single" + set dg-do-what-default run +} elseif [istarget "sparc*-*-*"] { + lappend DEFAULT_VECTCFLAGS "-mcpu=ultrasparc" "-mvis" + set dg-do-what-default run +} elseif [istarget "alpha*-*-*"] { + lappend DEFAULT_VECTCFLAGS "-mmax" + if [check_alpha_max_hw_available] { + set dg-do-what-default run + } else { + set dg-do-what-default compile + } +} elseif [istarget "ia64-*-*"] { + set dg-do-what-default run +} else { + return +} + +# Return 1 if the effective target is LP64 or if the effective target +# does not support a vector alignment mechanism. + +proc check_effective_target_lp64_or_vect_no_align { } { + if { [is-effective-target lp64] + || [is-effective-target vect_no_align] } { + set answer 1 + } else { + set answer 0 + } + return $answer +} + +# Initialize `dg'. +dg-init + +# Main loop. +gfortran-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[fF\]{,90,95} ]] $DEFAULT_VECTCFLAGS + +# Clean up. +set dg-do-what-default ${save-dg-do-what-default} + +# All done. +dg-finish diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c index 38aab0b..a89d608 100644 --- a/gcc/tree-ssanames.c +++ b/gcc/tree-ssanames.c @@ -279,22 +279,38 @@ duplicate_ssa_name (tree name, tree stmt) { tree new_name = make_ssa_name (SSA_NAME_VAR (name), stmt); struct ptr_info_def *old_ptr_info = SSA_NAME_PTR_INFO (name); + + if (old_ptr_info) + duplicate_ssa_name_ptr_info (new_name, old_ptr_info); + + return new_name; +} + + +/* Creates a duplicate of the ptr_info_def at PTR_INFO for use by + the ssa name NAME. */ + +void +duplicate_ssa_name_ptr_info (tree name, struct ptr_info_def *ptr_info) +{ struct ptr_info_def *new_ptr_info; - if (!old_ptr_info) - return new_name; + gcc_assert (POINTER_TYPE_P (TREE_TYPE (name))); + gcc_assert (!SSA_NAME_PTR_INFO (name)); + + if (!ptr_info) + return; new_ptr_info = ggc_alloc (sizeof (struct ptr_info_def)); - *new_ptr_info = *old_ptr_info; + *new_ptr_info = *ptr_info; - if (old_ptr_info->pt_vars) + if (ptr_info->pt_vars) { new_ptr_info->pt_vars = BITMAP_GGC_ALLOC (); - bitmap_copy (new_ptr_info->pt_vars, old_ptr_info->pt_vars); + bitmap_copy (new_ptr_info->pt_vars, ptr_info->pt_vars); } - SSA_NAME_PTR_INFO (new_name) = new_ptr_info; - return new_name; + SSA_NAME_PTR_INFO (name) = new_ptr_info; } diff --git a/gcc/tree-vect-analyze.c b/gcc/tree-vect-analyze.c index f3144e1..97ad231 100644 --- a/gcc/tree-vect-analyze.c +++ b/gcc/tree-vect-analyze.c @@ -71,7 +71,8 @@ static bool vect_base_addr_differ_p (struct data_reference *, struct data_reference *drb, bool *); static tree vect_object_analysis (tree, tree, bool, tree, struct data_reference **, tree *, tree *, - tree *, bool *, tree *, subvar_t *); + tree *, bool *, tree *, struct ptr_info_def **, + subvar_t *); static tree vect_address_analysis (tree, tree, bool, tree, struct data_reference *, tree *, tree *, tree *, bool *); @@ -1476,6 +1477,7 @@ vect_address_analysis (tree expr, tree stmt, bool is_read, tree vectype, tree oprnd0, oprnd1, base_address, offset_expr, base_addr0, base_addr1; tree address_offset = ssize_int (0), address_misalign = ssize_int (0); tree dummy; + struct ptr_info_def *dummy1; subvar_t dummy2; switch (TREE_CODE (expr)) @@ -1529,7 +1531,7 @@ vect_address_analysis (tree expr, tree stmt, bool is_read, tree vectype, base_address = vect_object_analysis (TREE_OPERAND (expr, 0), stmt, is_read, vectype, &dr, offset, misalign, step, base_aligned, - &dummy, &dummy2); + &dummy, &dummy1, &dummy2); return base_address; case SSA_NAME: @@ -1608,6 +1610,7 @@ vect_address_analysis (tree expr, tree stmt, bool is_read, tree vectype, STEP - evolution of the DR_REF in the loop BASE_ALIGNED - indicates if BASE is aligned MEMTAG - memory tag for aliasing purposes + PTR_INFO - NULL or points-to aliasing info from a pointer SSA_NAME SUBVAR - Sub-variables of the variable If something unexpected is encountered (an unsupported form of data-ref), @@ -1618,7 +1621,7 @@ vect_object_analysis (tree memref, tree stmt, bool is_read, tree vectype, struct data_reference **dr, tree *offset, tree *misalign, tree *step, bool *base_aligned, tree *memtag, - subvar_t *subvars) + struct ptr_info_def **ptr_info, subvar_t *subvars) { tree base = NULL_TREE, base_address = NULL_TREE; tree object_offset = ssize_int (0), object_misalign = ssize_int (0); @@ -1635,6 +1638,8 @@ vect_object_analysis (tree memref, tree stmt, bool is_read, struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); struct data_reference *ptr_dr = NULL; tree access_fn, evolution_part, address_to_analyze; + + *ptr_info = NULL; /* Part 1: */ /* Case 1. handled_component_p refs. */ @@ -1722,9 +1727,13 @@ vect_object_analysis (tree memref, tree stmt, bool is_read, /* Part 1: Case 3. INDIRECT_REFs. */ else if (TREE_CODE (memref) == INDIRECT_REF) - { + { + tree ptr_ref = TREE_OPERAND (memref, 0); + if (TREE_CODE (ptr_ref) == SSA_NAME) + *ptr_info = SSA_NAME_PTR_INFO (ptr_ref); + /* 3.1 get the access function. */ - access_fn = analyze_scalar_evolution (loop, TREE_OPERAND (memref, 0)); + access_fn = analyze_scalar_evolution (loop, ptr_ref); if (!access_fn) { if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS, @@ -1849,7 +1858,7 @@ vect_object_analysis (tree memref, tree stmt, bool is_read, Call get_inner_reference for refs handled in this function. Call vect_addr_analysis(addr) to analyze pointer type expressions. Set ref_stmt.base, ref_stmt.initial_offset, ref_stmt.alignment, - ref_stmt.memtag and ref_stmt.step accordingly. + ref_stmt.memtag, ref_stmt.ptr_info and ref_stmt.step accordingly. 2- vect_analyze_dependences(): apply dependence testing using ref_stmt.DR 3- vect_analyze_drs_alignment(): check that ref_stmt.alignment is ok. 4- vect_analyze_drs_access(): check that ref_stmt.step is ok. @@ -1887,6 +1896,7 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo) tree memref = NULL; tree scalar_type, vectype; tree base, offset, misalign, step, tag; + struct ptr_info_def *ptr_info; bool base_aligned; subvar_t subvars = NULL; @@ -1952,7 +1962,8 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo) dr = NULL; base = vect_object_analysis (memref, stmt, is_read, vectype, &dr, &offset, &misalign, &step, - &base_aligned, &tag, &subvars); + &base_aligned, &tag, &ptr_info, + &subvars); if (!base) { if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS, @@ -1969,6 +1980,7 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo) STMT_VINFO_VECT_MISALIGNMENT (stmt_info) = misalign; STMT_VINFO_VECT_BASE_ALIGNED_P (stmt_info) = base_aligned; STMT_VINFO_MEMTAG (stmt_info) = tag; + STMT_VINFO_PTR_INFO (stmt_info) = ptr_info; STMT_VINFO_SUBVARS (stmt_info) = subvars; STMT_VINFO_VECTYPE (stmt_info) = vectype; VARRAY_PUSH_GENERIC_PTR (*datarefs, dr); diff --git a/gcc/tree-vect-transform.c b/gcc/tree-vect-transform.c index 5dd9efe..4940f2d 100644 --- a/gcc/tree-vect-transform.c +++ b/gcc/tree-vect-transform.c @@ -57,6 +57,7 @@ static tree vect_get_vec_def_for_operand (tree, tree); static tree vect_init_vector (tree, tree); static void vect_finish_stmt_generation (tree stmt, tree vec_stmt, block_stmt_iterator *bsi); +static void update_vuses_to_preheader (tree, struct loop*); /* Utility function dealing with loop peeling (not peeling itself). */ static void vect_generate_tmps_on_preheader @@ -304,11 +305,6 @@ vect_create_data_ref_ptr (tree stmt, block_stmt_iterator *bsi, tree offset, tree vect_ptr_type; tree vect_ptr; tree tag; - 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); - int nvuses, nv_may_defs, nv_must_defs; - int i; tree new_temp; tree vec_stmt; tree new_stmt_list = NULL_TREE; @@ -348,38 +344,14 @@ vect_create_data_ref_ptr (tree stmt, block_stmt_iterator *bsi, tree offset, add_referenced_tmp_var (vect_ptr); - /** (2) Handle aliasing information of the new vector-pointer: **/ + /** (2) Add aliasing information to the new vector-pointer: + (The points-to info (SSA_NAME_PTR_INFO) may be defined later.) **/ tag = STMT_VINFO_MEMTAG (stmt_info); gcc_assert (tag); get_var_ann (vect_ptr)->type_mem_tag = tag; get_var_ann (vect_ptr)->subvars = STMT_VINFO_SUBVARS (stmt_info); - /* Mark for renaming all aliased variables - (i.e, the may-aliases of the type-mem-tag). */ - nvuses = NUM_VUSES (vuses); - nv_may_defs = NUM_V_MAY_DEFS (v_may_defs); - nv_must_defs = NUM_V_MUST_DEFS (v_must_defs); - - for (i = 0; i < nvuses; i++) - { - tree use = VUSE_OP (vuses, i); - if (TREE_CODE (use) == SSA_NAME) - bitmap_set_bit (vars_to_rename, var_ann (SSA_NAME_VAR (use))->uid); - } - for (i = 0; i < nv_may_defs; i++) - { - tree def = V_MAY_DEF_RESULT (v_may_defs, i); - if (TREE_CODE (def) == SSA_NAME) - bitmap_set_bit (vars_to_rename, var_ann (SSA_NAME_VAR (def))->uid); - } - for (i = 0; i < nv_must_defs; i++) - { - tree def = V_MUST_DEF_RESULT (v_must_defs, i); - if (TREE_CODE (def) == SSA_NAME) - bitmap_set_bit (vars_to_rename, var_ann (SSA_NAME_VAR (def))->uid); - } - /** (3) Calculate the initial address the vector-pointer, and set the vector-pointer to point to it before the loop: **/ @@ -405,7 +377,13 @@ vect_create_data_ref_ptr (tree stmt, block_stmt_iterator *bsi, tree offset, /** (4) Handle the updating of the vector-pointer inside the loop: **/ if (only_init) /* No update in loop is required. */ - return vect_ptr_init; + { + /* Copy the points-to information if it exists. */ + if (STMT_VINFO_PTR_INFO (stmt_info)) + duplicate_ssa_name_ptr_info (vect_ptr_init, + STMT_VINFO_PTR_INFO (stmt_info)); + return vect_ptr_init; + } idx = vect_create_index_for_vector_ref (loop_vinfo); @@ -436,6 +414,9 @@ vect_create_data_ref_ptr (tree stmt, block_stmt_iterator *bsi, tree offset, bsi_insert_before (bsi, vec_stmt, BSI_SAME_STMT); data_ref_ptr = TREE_OPERAND (vec_stmt, 0); + /* Copy the points-to information if it exists. */ + if (STMT_VINFO_PTR_INFO (stmt_info)) + duplicate_ssa_name_ptr_info (data_ref_ptr, STMT_VINFO_PTR_INFO (stmt_info)); return data_ref_ptr; } @@ -865,6 +846,8 @@ vectorizable_store (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt) enum machine_mode vec_mode; tree dummy; enum dr_alignment_support alignment_support_cheme; + v_may_def_optype v_may_defs; + int nv_may_defs, i; /* Is vectorizable store? */ @@ -922,6 +905,20 @@ vectorizable_store (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt) *vec_stmt = build2 (MODIFY_EXPR, vectype, data_ref, vec_oprnd1); vect_finish_stmt_generation (stmt, *vec_stmt, bsi); + /* Copy the V_MAY_DEFS representing the aliasing of the original array + element's definition to the vector's definition then update the + defining statement. The original is being deleted so the same + SSA_NAMEs can be used. */ + copy_virtual_operands (*vec_stmt, stmt); + v_may_defs = STMT_V_MAY_DEF_OPS (*vec_stmt); + nv_may_defs = NUM_V_MAY_DEFS (v_may_defs); + + for (i = 0; i < nv_may_defs; i++) + { + tree ssa_name = V_MAY_DEF_RESULT (v_may_defs, i); + SSA_NAME_DEF_STMT (ssa_name) = *vec_stmt; + } + return true; } @@ -1023,6 +1020,7 @@ vectorizable_load (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt) new_temp = make_ssa_name (vec_dest, new_stmt); TREE_OPERAND (new_stmt, 0) = new_temp; vect_finish_stmt_generation (stmt, new_stmt, bsi); + copy_virtual_operands (new_stmt, stmt); } else if (alignment_support_cheme == dr_unaligned_software_pipeline) { @@ -1060,6 +1058,8 @@ vectorizable_load (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt) new_bb = bsi_insert_on_edge_immediate (pe, new_stmt); gcc_assert (!new_bb); msq_init = TREE_OPERAND (new_stmt, 0); + copy_virtual_operands (new_stmt, stmt); + update_vuses_to_preheader (new_stmt, loop); /* <2> Create lsq = *(floor(p2')) in the loop */ @@ -1074,6 +1074,7 @@ vectorizable_load (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt) TREE_OPERAND (new_stmt, 0) = new_temp; vect_finish_stmt_generation (stmt, new_stmt, bsi); lsq = TREE_OPERAND (new_stmt, 0); + copy_virtual_operands (new_stmt, stmt); /* <3> */ @@ -1092,9 +1093,12 @@ vectorizable_load (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt) gcc_assert (!new_bb); magic = TREE_OPERAND (new_stmt, 0); - /* Since we have just created a CALL_EXPR, we may need to - rename call-clobbered variables. */ - mark_call_clobbered_vars_to_rename (); + /* The result of the CALL_EXPR to this builtin is determined from + the value of the parameter and no global variables are touched + which makes the builtin a "const" function. Requiring the + builtin to have the "const" attribute makes it unnecessary + to call mark_call_clobbered_vars_to_rename. */ + gcc_assert (TREE_READONLY (builtin_decl)); } else { @@ -1268,6 +1272,84 @@ vect_generate_tmps_on_preheader (loop_vec_info loop_vinfo, } +/* Function update_vuses_to_preheader. + + Input: + STMT - a statement with potential VUSEs. + LOOP - the loop whose preheader will contain STMT. + + It's possible to vectorize a loop even though an SSA_NAME from a VUSE + appears to be defined in a V_MAY_DEF in another statement in a loop. + One such case is when the VUSE is at the dereference of a __restricted__ + pointer in a load and the V_MAY_DEF is at the dereference of a different + __restricted__ pointer in a store. Vectorization may result in + copy_virtual_uses being called to copy the problematic VUSE to a new + statement that is being inserted in the loop preheader. This procedure + is called to change the SSA_NAME in the new statement's VUSE from the + SSA_NAME updated in the loop to the related SSA_NAME available on the + path entering the loop. + + When this function is called, we have the following situation: + + # vuse <name1> + S1: vload + do { + # name1 = phi < name0 , name2> + + # vuse <name1> + S2: vload + + # name2 = vdef <name1> + S3: vstore + + }while... + + Stmt S1 was created in the loop preheader block as part of misaligned-load + handling. This function fixes the name of the vuse of S1 from 'name1' to + 'name0'. */ + +static void +update_vuses_to_preheader (tree stmt, struct loop *loop) +{ + basic_block header_bb = loop->header; + edge preheader_e = loop_preheader_edge (loop); + vuse_optype vuses = STMT_VUSE_OPS (stmt); + int nvuses = NUM_VUSES (vuses); + int i; + + for (i = 0; i < nvuses; i++) + { + tree ssa_name = VUSE_OP (vuses, i); + tree def_stmt = SSA_NAME_DEF_STMT (ssa_name); + tree name_var = SSA_NAME_VAR (ssa_name); + basic_block bb = bb_for_stmt (def_stmt); + + /* For a use before any definitions, def_stmt is a NOP_EXPR. */ + if (!IS_EMPTY_STMT (def_stmt) + && flow_bb_inside_loop_p (loop, bb)) + { + /* If the block containing the statement defining the SSA_NAME + is in the loop then it's necessary to find the definition + outside the loop using the PHI nodes of the header. */ + tree phi; + bool updated = false; + + for (phi = phi_nodes (header_bb); phi; phi = TREE_CHAIN (phi)) + { + if (SSA_NAME_VAR (PHI_RESULT (phi)) == name_var) + { + SET_VUSE_OP (vuses, i, + PHI_ARG_DEF (phi, preheader_e->dest_idx)); + updated = true; + break; + } + } + gcc_assert (updated); + } + } +} + + /* Function vect_update_ivs_after_vectorizer. "Advance" the induction variables of LOOP to the value they should take diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c index 5859880..9df3a68 100644 --- a/gcc/tree-vectorizer.c +++ b/gcc/tree-vectorizer.c @@ -1167,6 +1167,7 @@ new_stmt_vec_info (tree stmt, loop_vec_info loop_vinfo) STMT_VINFO_VEC_STMT (res) = NULL; STMT_VINFO_DATA_REF (res) = NULL; STMT_VINFO_MEMTAG (res) = NULL; + STMT_VINFO_PTR_INFO (res) = NULL; STMT_VINFO_SUBVARS (res) = NULL; STMT_VINFO_VECT_DR_BASE_ADDRESS (res) = NULL; STMT_VINFO_VECT_INIT_OFFSET (res) = NULL_TREE; @@ -1618,7 +1619,5 @@ vectorize_loops (struct loops *loops) loop->aux = NULL; } - rewrite_into_ssa (false); rewrite_into_loop_closed_ssa (NULL); /* FORNOW */ - bitmap_clear (vars_to_rename); } diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index e32eed2..dee7a4e 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -178,6 +178,7 @@ typedef struct _stmt_vec_info { /* Aliasing information. */ tree memtag; + struct ptr_info_def *ptr_info; subvar_t subvars; /** The following fields are used to store the information about @@ -220,7 +221,8 @@ typedef struct _stmt_vec_info { #define STMT_VINFO_VEC_STMT(S) (S)->vectorized_stmt #define STMT_VINFO_DATA_REF(S) (S)->data_ref_info #define STMT_VINFO_MEMTAG(S) (S)->memtag -#define STMT_VINFO_SUBVARS(S) (S)->subvars +#define STMT_VINFO_PTR_INFO(S) (S)->ptr_info +#define STMT_VINFO_SUBVARS(S) (S)->subvars #define STMT_VINFO_VECT_DR_BASE_ADDRESS(S)(S)->base_address #define STMT_VINFO_VECT_INIT_OFFSET(S) (S)->initial_offset #define STMT_VINFO_VECT_STEP(S) (S)->step @@ -2801,6 +2801,7 @@ extern void init_ssanames (void); extern void fini_ssanames (void); extern tree make_ssa_name (tree, tree); extern tree duplicate_ssa_name (tree, tree); +extern void duplicate_ssa_name_ptr_info (tree, struct ptr_info_def *); extern void release_ssa_name (tree); extern void release_defs (tree); extern void replace_ssa_name_symbol (tree, tree); |