This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[autovect]: Pointer alignment analysis


This is the lno pointer alignment analysis,  ported to the propagation
engine.
It bootstrapped and regtested okay on powerpc darwin (there are two vect
failure, vect-8, and vect-30, that i get with and without the patch).

Commmitted to autovect branch.
2004-11-17  Daniel Berlin  <dberlin@dberlin.org>

	* Makefile.in (OBJS-common): Add tree-ssa-align.o
	(tree-ssa-align.o): Add.
	* tree-flow.h (struct alignment_d): New.
	(dump_align_info): Add proto.
	(debug_align_info): Add proto.
	* tree-optimize.c (init_tree_optimization_passes): Add
	pass_align_info. 
	* tree-pass.h (PROP_align): New.
	(pass_align_analysis): New.
	* tree-ssa-align.c: New file.
	* tree-vectorizer.c (vect_get_ptr_offset): Copy code from
	lno-branch, written by Ira Rosen (irar@il.ibm.com).
	
Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.1419
diff -u -p -r1.1419 Makefile.in
--- Makefile.in	8 Nov 2004 21:49:07 -0000	1.1419
+++ Makefile.in	17 Nov 2004 18:20:48 -0000
@@ -889,7 +889,7 @@ OBJS-common = \
  tree-chrec.o tree-scalar-evolution.o tree-data-ref.o			   \
  tree-cfg.o tree-dfa.o tree-eh.o tree-ssa.o tree-optimize.o tree-gimple.o  \
  gimplify.o tree-pretty-print.o tree-into-ssa.o          \
- tree-outof-ssa.o tree-ssa-ccp.o tree-vn.o             \
+ tree-outof-ssa.o tree-ssa-ccp.o tree-ssa-align.o tree-vn.o             \
  tree-ssa-dce.o  tree-ssa-copy.o tree-nrv.o tree-ssa-copyrename.o  \
  tree-ssa-pre.o tree-ssa-live.o tree-ssa-operands.o tree-ssa-alias.o       \
  tree-ssa-phiopt.o tree-ssa-forwprop.o tree-nested.o tree-ssa-dse.o	   \
@@ -1951,6 +1951,11 @@ tree-ssa-ccp.o : tree-ssa-ccp.c $(TREE_F
    diagnostic.h errors.h function.h $(TIMEVAR_H) $(TM_H) coretypes.h \
    $(TREE_DUMP_H) $(BASIC_BLOCK_H) tree-pass.h langhooks.h \
    tree-ssa-propagate.h
+tree-ssa-align.o : tree-ssa-align.c $(TREE_FLOW_H) $(CONFIG_H) \
+   $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) output.h \
+   diagnostic.h errors.h function.h $(TIMEVAR_H) $(TM_H) coretypes.h \
+   $(TREE_DUMP_H) $(BASIC_BLOCK_H) tree-pass.h langhooks.h \
+   tree-ssa-propagate.h
 tree-sra.o : tree-sra.c $(CONFIG_H) system.h errors.h $(TREE_H) $(RTL_H) \
     $(TM_P_H) $(TREE_FLOW_H) diagnostic.h tree-inline.h \
     $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) $(TREE_GIMPLE_H) \
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-flow.h,v
retrieving revision 2.61
diff -u -p -r2.61 tree-flow.h
--- tree-flow.h	9 Nov 2004 14:59:49 -0000	2.61
+++ tree-flow.h	17 Nov 2004 18:20:48 -0000
@@ -74,6 +74,14 @@ struct ptr_info_def GTY(())
      pointer will be represented by this memory tag, instead of the type
      tag computed by TBAA.  */
   tree name_mem_tag;
+
+  /*  The alignment of a pointer p is n if "(p - offset) mod n == 0". */
+  struct alignment_d
+  {
+    unsigned int n;
+    unsigned int offset;
+  } alignment;
+
 };
 
 
@@ -739,6 +747,10 @@ extern bool expr_invariant_in_loop_p (st
 
 tree force_gimple_operand (tree, tree *, bool, tree);
 
+/* In tree-ssa-align.c  */
+extern void dump_align_info (FILE *);
+extern void debug_align_info (void);
+
 #include "tree-flow-inline.h"
 
 #endif /* _TREE_FLOW_H  */
Index: tree-optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-optimize.c,v
retrieving revision 2.61
diff -u -p -r2.61 tree-optimize.c
--- tree-optimize.c	2 Nov 2004 00:23:04 -0000	2.61
+++ tree-optimize.c	17 Nov 2004 18:20:48 -0000
@@ -396,6 +396,7 @@ init_tree_optimization_passes (void)
   NEXT_PASS (pass_linear_transform);
   NEXT_PASS (pass_iv_canon);
   NEXT_PASS (pass_if_conversion);
+  NEXT_PASS (pass_align_analysis);
   NEXT_PASS (pass_vectorize);
   NEXT_PASS (pass_complete_unroll);
   NEXT_PASS (pass_iv_optimize);
Index: tree-pass.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-pass.h,v
retrieving revision 2.20
diff -u -p -r2.20 tree-pass.h
--- tree-pass.h	27 Oct 2004 17:45:20 -0000	2.20
+++ tree-pass.h	17 Nov 2004 18:20:48 -0000
@@ -95,6 +95,7 @@ struct dump_file_info
 #define PROP_no_crit_edges      (1 << 7)
 #define PROP_rtl		(1 << 8)
 #define PROP_alias		(1 << 9)
+#define PROP_align              (1 << 10)
 
 #define PROP_trees \
   (PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh)
@@ -130,6 +131,7 @@ extern struct tree_opt_pass pass_unswitc
 extern struct tree_opt_pass pass_iv_canon;
 extern struct tree_opt_pass pass_record_bounds;
 extern struct tree_opt_pass pass_if_conversion;
+extern struct tree_opt_pass pass_align_analysis;
 extern struct tree_opt_pass pass_vectorize;
 extern struct tree_opt_pass pass_complete_unroll;
 extern struct tree_opt_pass pass_iv_optimize;
Index: tree-ssa-align.c
===================================================================
RCS file: tree-ssa-align.c
diff -N tree-ssa-align.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tree-ssa-align.c	17 Nov 2004 18:20:48 -0000
@@ -0,0 +1,708 @@
+/* Alignment analysis for trees.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   Contributed by Daniel Berlin <dberlin@dberlin.org>
+
+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 "tree.h"
+#include "rtl.h"
+#include "tm_p.h"
+#include "hard-reg-set.h"
+#include "basic-block.h"
+#include "timevar.h"
+#include "expr.h"
+#include "ggc.h"
+#include "langhooks.h"
+#include "flags.h"
+#include "function.h"
+#include "diagnostic.h"
+#include "tree-dump.h"
+#include "tree-gimple.h"
+#include "tree-flow.h"
+#include "tree-inline.h"
+#include "tree-pass.h"
+#include "convert.h"
+#include "params.h"
+#include "tree-ssa-propagate.h"
+ 
+/* Compute alignment/misalignment info for SSA pointers, using
+   results of masks, guaranteed alignment properties, or whatever
+   other information we can find around that tells us something about
+   alignment.  */
+
+/* Possible lattice values.  */
+typedef enum
+{
+  UNINITIALIZED = 0,
+  KNOWN,
+  UNDEFINED
+} latticevalue;
+
+
+/* Main structure for CCP.  Contains the lattice value and, if it's a
+    constant, the constant value.  */
+typedef struct
+{
+  latticevalue lattice_val;
+  struct
+  {
+    unsigned int n;
+    unsigned int offset;
+  } alignment;
+} value;
+
+/* This is used to track the current value of each variable.  */
+static value *value_vector;
+
+static void initialize (void);
+static void finalize (void);
+static enum ssa_prop_result visit_phi_node (tree);
+static value cp_lattice_meet (value, value);
+static enum ssa_prop_result visit_stmt (tree, edge *, tree *);
+static enum ssa_prop_result visit_assignment (tree, tree *);
+static void def_to_known_bpu_0 (tree);
+static bool set_lattice_value (tree, value);
+static value evaluate_stmt (tree);
+static void dump_lattice_value (FILE *, const char *, value);
+static value *get_value (tree);
+static value get_default_value (tree);
+static bool need_imm_uses_for (tree var);
+ 
+/* Main entry point for SSA alignment analysis */
+
+static void
+compute_ptr_alignment (void)
+{
+  unsigned int i = 0;
+  initialize ();
+  ssa_propagate (visit_stmt, visit_phi_node);
+
+
+  /* Set the alignments */
+  for (i = 0; i < num_ssa_names; i++)
+    {
+      tree ssa_var = ssa_name (i);
+      if (ssa_var && POINTER_TYPE_P (TREE_TYPE (ssa_var)))
+	{
+	  struct ptr_info_def *pi = get_ptr_info (ssa_var);
+	  value *val = get_value (ssa_var);
+	  if (val->lattice_val == KNOWN)
+	    {
+	      pi->alignment.n = val->alignment.n;
+	      pi->alignment.offset = val->alignment.offset;
+	    }
+	}
+    }
+/* Free allocated memory.  */
+  finalize ();
+   
+  /* Debugging dumps.  */
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    {
+      dump_referenced_vars (dump_file);
+      dump_align_info (dump_file);
+      fprintf (dump_file, "\n\n");
+    }
+}
+
+
+/* Loop through the PHI_NODE's parameters for BLOCK and compare their
+   lattice values to determine PHI_NODE's lattice value.  The value of a
+   PHI node is determined calling cp_lattice_meet() with all the arguments
+   of the PHI node */
+
+static enum ssa_prop_result
+visit_phi_node (tree phi)
+{
+  value phi_val, *curr_val;
+  int i;
+
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    {
+      fprintf (dump_file, "\nVisiting PHI node: ");
+      print_generic_expr (dump_file, phi, dump_flags);
+    }
+
+  curr_val = get_value (PHI_RESULT (phi));
+  phi_val = *curr_val;
+  if (phi_val.lattice_val == UNINITIALIZED)
+    phi_val.lattice_val = UNDEFINED;
+
+  for (i = 0; i < PHI_NUM_ARGS (phi); i++)
+    {
+      /* Compute the meet operator over all the PHI arguments.  */
+      edge e = PHI_ARG_EDGE (phi, i);      
+      tree rdef = PHI_ARG_DEF (phi, i);
+      value rdef_val;      
+      if (dump_file && (dump_flags & TDF_DETAILS))
+	{
+	  fprintf (dump_file,
+		   "\n    Argument #%d (%d -> %d)\n",
+		   i, e->src->index, e->dest->index);
+	}      
+      if (TREE_CODE (rdef) == INTEGER_CST)
+	{
+	  rdef_val.lattice_val = KNOWN;
+	  rdef_val.alignment.n = TREE_INT_CST_LOW (rdef) * BITS_PER_UNIT;
+	  if (rdef_val.alignment.n == 0)
+	    rdef_val.alignment.n = 1;
+	  rdef_val.alignment.offset = 0;
+	}
+      else  if (TREE_CODE (rdef) == SSA_NAME)
+	{
+	  rdef_val = *(get_value (rdef));
+	}
+      else
+	{
+	  rdef_val.lattice_val = KNOWN;
+	  rdef_val.alignment.n = BITS_PER_UNIT;
+	  rdef_val.alignment.offset = 0;
+	}
+      phi_val = cp_lattice_meet (phi_val, rdef_val);
+      
+      if (dump_file && (dump_flags & TDF_DETAILS))
+	{
+	  fprintf (dump_file, "\t");
+	  print_generic_expr (dump_file, rdef, dump_flags);
+	  dump_lattice_value (dump_file, "\tValue: ", rdef_val);
+	  fprintf (dump_file, "\n");
+	}
+    }
+  
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    {
+      dump_lattice_value (dump_file, "\n    PHI node value: ", phi_val);
+      fprintf (dump_file, "\n\n");
+    }
+  
+  if (set_lattice_value (PHI_RESULT (phi), phi_val))
+    {
+      if (phi_val.lattice_val == UNDEFINED)
+	return SSA_PROP_VARYING;
+      else 
+	return SSA_PROP_INTERESTING;
+    }
+  else
+    return SSA_PROP_NOT_INTERESTING;
+
+}
+
+/* Find the greatest common denominator of A and B.  */
+
+static int
+gcd (int a, int b)
+{ 
+  
+  int x, y, z;
+  
+  x = a;
+  y = b;
+  
+  while (x>0)
+    {
+      z = y % x;
+      y = x;
+      x = z;
+    }
+  
+  return (y);
+}
+
+/* Find the largest power of two alignment such that off1 % newalign
+   == off2 % newalign.  */
+
+static unsigned int 
+find_largest_common_alignment (unsigned int off1, unsigned int off2)
+{
+  unsigned int mask;
+  mask = ((unsigned HOST_WIDE_INT)1 << ceil_log2 (MIN (off1, off2))) - 1;
+  while ((off1 & mask) != (off2 & mask))
+    mask >>= 1;
+  return mask + 1;
+}
+/* Compute the meet operator between VAL1 and VAL2:
+
+   any M UNDEFINED = any
+   n1, off1 M n2, off2 = n1, off1 if n1 == n2 && off1 == off2
+   n1, off1 M n2, off2 = largest_common_alignment (off1 % gcd (n1, n2), off2 % gcd (n1 ,n2))
+*/		
+		
+static value
+cp_lattice_meet (value val1, value val2)
+{
+  value result;
+
+  /* any M UNDEFINED = any.  */
+  if (val1.lattice_val == UNDEFINED)
+    return val2;
+  else if (val2.lattice_val == UNDEFINED)
+    return val1;
+
+  if (val1.alignment.n == val2.alignment.n 
+      && val1.alignment.offset == val2.alignment.offset)
+    {
+      result.lattice_val = KNOWN;
+      result.alignment.n = val2.alignment.n;
+      result.alignment.offset = val2.alignment.offset;
+    }
+  else
+    {
+      unsigned int newalign;
+      unsigned int newoff1;
+      unsigned int newoff2;
+      newalign = gcd (val1.alignment.n, val2.alignment.n);
+      newoff1 = val1.alignment.offset % newalign;
+      newoff2 = val2.alignment.offset % newalign;
+      if (newoff1 != newoff2)
+	{
+	  newalign = find_largest_common_alignment (newoff1, newoff2);
+	  newoff1 = newoff1 % newalign;
+	  newoff2 = newoff2 % newalign;
+	}
+      result.lattice_val = KNOWN;
+      result.alignment.n = newalign;
+      result.alignment.offset = newoff1;
+    }
+
+  return result;
+}
+
+
+/* Evaluate statement STMT.  If the statement produces an alignment value and
+   its evaluation changes the lattice value of its output, do the following:
+
+   - If the statement is an assignment, add all the SSA edges starting at
+   this definition.  */
+
+static enum ssa_prop_result
+visit_stmt (tree stmt, edge *taken_edge_p ATTRIBUTE_UNUSED, tree *output_p)
+{
+  stmt_ann_t ann;
+  tree def;
+  ssa_op_iter iter;
+
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    {
+      fprintf (dump_file, "\nVisiting statement: ");
+      print_generic_stmt (dump_file, stmt, TDF_SLIM);
+      fprintf (dump_file, "\n");
+    }
+
+  ann = stmt_ann (stmt);
+
+  /* Now examine the statement.  If the statement is an assignment that
+     produces a single output value, evaluate its RHS to see if the lattice
+     value of its output has changed.  */
+  if (TREE_CODE (stmt) == MODIFY_EXPR
+      && TREE_CODE (TREE_OPERAND (stmt, 0)) == SSA_NAME)
+    return visit_assignment (stmt, output_p);
+  
+  /* Definitions made by statements other than assignments to SSA_NAMEs
+     represent unknown modifications to their outputs.  Mark them KNOWN.  */
+  FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_DEF)
+    def_to_known_bpu_0 (def);
+  
+  return SSA_PROP_VARYING;
+}
+
+
+/* Visit the assignment statement STMT.  Set the value of its LHS to the
+   value computed by the RHS.  */
+
+static enum ssa_prop_result
+visit_assignment (tree stmt, tree *output_p)
+{
+  value val;
+  tree lhs, rhs;
+
+  lhs = TREE_OPERAND (stmt, 0);
+  rhs = TREE_OPERAND (stmt, 1);
+  STRIP_NOPS (rhs);
+  
+  if (TREE_CODE (rhs) == SSA_NAME)
+    {
+      /* For a simple copy operation, we copy the lattice values.  */
+      value *nval = get_value (rhs);
+      val = *nval;
+    }
+  else
+    {
+      /* Evaluate the statement.  */
+      val = evaluate_stmt (stmt);
+    }
+
+  /* Set the lattice value of the statement's output.  */
+  if (set_lattice_value (lhs, val))
+    {
+      *output_p = lhs;
+      if (val.lattice_val == UNDEFINED)
+	return SSA_PROP_VARYING;
+      else
+	return SSA_PROP_INTERESTING;
+    }
+  else
+    return SSA_PROP_NOT_INTERESTING;
+      
+}
+
+
+/* Evaluate statement STMT.  */
+
+static value
+evaluate_stmt (tree stmt)
+{
+  value val;
+  tree rhs;
+  rhs = get_rhs (stmt);
+  
+  if (TREE_CODE (rhs) == INTEGER_CST)
+    {
+      val.lattice_val = KNOWN;
+      val.alignment.n = TREE_INT_CST_LOW (rhs) * BITS_PER_UNIT;
+      if (val.alignment.n == 0)
+        val.alignment.n = 1;
+      val.alignment.offset = 0;
+    }
+  else if (TREE_CODE (rhs) == PLUS_EXPR || TREE_CODE (rhs) == MINUS_EXPR)
+    {
+      tree op1 = TREE_OPERAND (rhs, 0);
+      tree op2 = TREE_OPERAND (rhs, 1);
+      value *op1val = NULL;
+      int newoffset = 0;
+      if (TREE_CODE (op1) == SSA_NAME)
+	op1val = get_value (op1);
+      if (TREE_CODE (op2) == INTEGER_CST)
+	newoffset = TREE_INT_CST_LOW (op2);
+      if (op1val == NULL 
+	  || newoffset == 0 
+	  || (op1val && op1val->lattice_val == UNDEFINED))
+	{
+	   val.lattice_val = KNOWN;
+	   val.alignment.n = BITS_PER_UNIT;
+	   val.alignment.offset = 0;
+	}
+      else
+	{
+	  val = *op1val;
+	  val.alignment.offset += (BITS_PER_UNIT * newoffset) % val.alignment.n;
+	}
+    } 
+  else
+    {
+      val.lattice_val = KNOWN;
+      val.alignment.n = BITS_PER_UNIT;
+      val.alignment.offset = 0;
+    }
+  return val;
+}
+
+
+/* Debugging dumps.  */
+
+static void
+dump_lattice_value (FILE *outf, const char *prefix, value val)
+{
+  switch (val.lattice_val)
+    {
+    case UNDEFINED:
+      fprintf (outf, "%sUNDEFINED", prefix);
+      break;
+    case KNOWN:
+      fprintf (outf, "%sKNOWN (%d, %d)", prefix, 
+	       val.alignment.n, val.alignment.offset);
+      break;
+    default:
+      abort ();
+    }
+}
+
+/* Function indicating whether we ought to include information for 'var'
+   when calculating immediate uses.  */
+
+static bool
+need_imm_uses_for (tree var ATTRIBUTE_UNUSED)
+{
+  return true;
+}
+
+/* Initialize local data structures and worklists for CCP.  */
+
+static void
+initialize (void)
+{
+  basic_block bb;
+
+  value_vector = (value *) xmalloc (num_ssa_names * sizeof (value));
+  memset (value_vector, 0, num_ssa_names * sizeof (value));
+
+  /* Compute immediate uses for variables we care about.  */
+  compute_immediate_uses (TDFA_USE_OPS, need_imm_uses_for);
+
+  FOR_EACH_BB (bb)
+    {
+      tree phi;
+      block_stmt_iterator bsi;
+      for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+	DONT_SIMULATE_AGAIN (phi) = false;
+      for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
+	{
+	  tree stmt = bsi_stmt (bsi);
+	  DONT_SIMULATE_AGAIN (stmt) = false;
+	}
+    }
+      
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    dump_immediate_uses (dump_file);
+}
+
+
+/* Free allocated storage.  */
+
+static void
+finalize (void)
+{
+
+  free (value_vector);
+  free_df ();
+}
+
+/* Set the lattice value for the variable VAR to KNOWN, {BITS PER
+   UNIT, 0}.  */
+
+static void
+def_to_known_bpu_0(tree var)
+{
+  value val;
+  val.lattice_val = KNOWN;
+  val.alignment.n = BITS_PER_UNIT;
+  val.alignment.offset = 0;
+  set_lattice_value (var, val);
+}
+
+/* Set the lattice value for variable VAR to VAL.  */
+
+static bool
+set_lattice_value (tree var, value val)
+{
+  value *old = get_value (var);
+
+#ifdef ENABLE_CHECKING
+  if (val.lattice_val == UNDEFINED)
+    {
+      /* (KNOWN->UNDEFINED) is never a valid state transition, unless
+	 the default value f the var was known.  */
+      if (old->lattice_val == KNOWN 
+	  && get_default_value (var).lattice_val  != KNOWN)
+	abort ();
+    }
+#endif  
+
+  if (old->lattice_val != val.lattice_val)
+    {
+      if (dump_file && (dump_flags & TDF_DETAILS))
+	{
+	  dump_lattice_value (dump_file,
+			      "Lattice value changed to ", val);
+	  fprintf (dump_file, ".  Adding definition to SSA edges.\n");
+	}
+      *old = val;
+      return true;
+    }
+  return false;
+}
+
+/* Return a default value for variable VAR using the following rules:
+
+   1- Global and static variables are considered KNOWN,
+   {BITS_PER_UNIT, 0}, or the minimum alignment required by their
+   underlying type, for pointers.
+
+   2- Function arguments are considered KNOWN, {BITS_PER_UNIT, 0}, or
+   the minimum alignment required by their underlying type, for pointers.
+
+   3- Any other value is considered UNDEFINED.  This is useful when
+      considering PHI nodes.  PHI arguments that are undefined do not
+      change the alignment of the phi.  */
+
+static value
+get_default_value (tree var)
+{
+  value val;
+  tree sym;
+
+  if (TREE_CODE (var) == SSA_NAME)
+    sym = SSA_NAME_VAR (var);
+  else
+    {
+#ifdef ENABLE_CHECKING
+      if (!DECL_P (var))
+	abort ();
+#endif
+      sym = var;
+    }
+
+  val.lattice_val = UNDEFINED;
+  val.alignment.n = 0;
+  val.alignment.offset = 0;
+  if (TREE_CODE (sym) == PARM_DECL 
+      || (decl_function_context (sym) != current_function_decl
+	  || TREE_STATIC (sym)))
+    {
+      val.lattice_val = KNOWN;
+      /* Pointer types are assumed to have the minimum alignment
+	 required by their underlying type.  */
+      if (POINTER_TYPE_P (TREE_TYPE (sym)))
+	val.alignment.n = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (sym)));
+      else
+	val.alignment.n = BITS_PER_UNIT;
+      val.alignment.offset = 0;
+    }
+  else
+    {
+      enum tree_code code;
+      tree stmt = SSA_NAME_DEF_STMT (var);
+
+      if (stmt && !IS_EMPTY_STMT (stmt))
+        {
+	  code = TREE_CODE (stmt);
+	  if (code != MODIFY_EXPR && code != PHI_NODE)
+	    {
+	      val.lattice_val = KNOWN;
+	      val.alignment.n = BITS_PER_UNIT;
+	      val.alignment.offset = 0;
+	    }
+	}
+    }
+  return val;
+}
+
+
+
+struct tree_opt_pass pass_align_analysis = 
+{
+  "align",				/* name */
+  NULL,					/* gate */
+  compute_ptr_alignment,			/* execute */
+  NULL,					/* sub */
+  NULL,					/* next */
+  0,					/* static_pass_number */
+  0,			/* tv_id */
+  PROP_cfg | PROP_ssa,	                /* properties_required */
+  PROP_align,			/* properties_provided */
+  0,					/* properties_destroyed */
+  0,					/* todo_flags_start */
+  0,                                    /* todo_flags_finish */
+  0					/* letter */
+};
+/* Get the lattice + alignment  info associated with var */
+
+static value *
+get_value (tree var)
+{
+  value *val;
+  if (TREE_CODE (var) != SSA_NAME)
+    abort ();
+  val = &value_vector [SSA_NAME_VERSION (var)];
+  if (val->lattice_val == UNINITIALIZED)
+    *val = get_default_value (var);
+  return val;
+}
+
+/* Dump alignment information for SSA_NAME PTR into FILE.  */
+
+static void
+dump_align_info_for (FILE *file, tree ptr)
+{
+  struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
+
+  fprintf (file, "Pointer ");
+  print_generic_expr (file, ptr, dump_flags);
+
+  if (pi == NULL)
+    return;
+
+  fprintf (file, " alignment n, offset = (%d, %d)\n",
+	   pi->alignment.n, pi->alignment.offset);
+  
+}
+
+/* Dump alignment information into FILE.  NOTE: This function is slow, as
+   it needs to traverse the whole CFG looking for pointer SSA_NAMEs.  */
+
+void
+dump_align_info (FILE *file)
+{
+  basic_block bb;
+  block_stmt_iterator si;
+  size_t i;
+  const char *fname =
+    lang_hooks.decl_printable_name (current_function_decl, 2);
+
+  fprintf (file, "\nAlignment info for pointers in %s\n\n", fname);
+
+  /* First dump points-to information for the default definitions of
+     pointer variables.  This is necessary because default definitions are
+     not part of the code.  */
+  for (i = 0; i < num_referenced_vars; i++)
+    {
+      tree var = referenced_var (i);
+      if (POINTER_TYPE_P (TREE_TYPE (var)))
+	{
+	  var_ann_t ann = var_ann (var);
+	  if (ann->default_def)
+	    dump_align_info_for (file, ann->default_def);
+	}
+    }
+
+  /* Dump points-to information for every pointer defined in the program.  */
+  FOR_EACH_BB (bb)
+    {
+      tree phi;
+
+      for (phi = phi_nodes (bb); phi; phi = TREE_CHAIN (phi))
+	{
+	  tree ptr = PHI_RESULT (phi);
+	  if (POINTER_TYPE_P (TREE_TYPE (ptr)))
+	    dump_align_info_for (file, ptr);
+	}
+
+	for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
+	  {
+	    stmt_ann_t ann = stmt_ann (bsi_stmt (si));
+	    def_optype defs = DEF_OPS (ann);
+	    if (defs)
+	      for (i = 0; i < NUM_DEFS (defs); i++)
+		if (POINTER_TYPE_P (TREE_TYPE (DEF_OP (defs, i))))
+		  dump_align_info_for (file, DEF_OP (defs, i));
+	  }
+    }
+
+  fprintf (file, "\n");
+}
+
+/* Dump out alignment info for pointers to stderr */
+void 
+debug_align_info (void)
+{
+  dump_align_info (stderr);
+}
+
Index: tree-vectorizer.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-vectorizer.c,v
retrieving revision 2.25.2.1
diff -u -p -r2.25.2.1 tree-vectorizer.c
--- tree-vectorizer.c	12 Nov 2004 23:50:15 -0000	2.25.2.1
+++ tree-vectorizer.c	17 Nov 2004 18:20:48 -0000
@@ -1268,12 +1268,44 @@ vect_debug_details (struct loop *loop)
    Compute the OFFSET modulo vector-type alignment of pointer REF in bits.  */
 
 static tree 
-vect_get_ptr_offset (tree ref ATTRIBUTE_UNUSED, 
-		     tree vectype ATTRIBUTE_UNUSED, 
-		     tree *offset ATTRIBUTE_UNUSED)
+vect_get_ptr_offset (tree ref, tree vectype, tree *offset)
 {
-  /* TODO: Use alignment information.  */
-  return NULL_TREE; 
+  unsigned int ptr_n, ptr_offset;
+
+  if (!POINTER_TYPE_P (TREE_TYPE (ref)))
+    return NULL_TREE;
+
+  if (vect_debug_details (NULL))
+    {
+      fprintf (dump_file, "alignment of pointer ");
+      print_generic_expr (dump_file, ref, TDF_SLIM);
+      fprintf (dump_file, " offset %d n %d\n ",
+	       get_ptr_info (ref)->alignment.offset,
+	       get_ptr_info (ref)->alignment.n);
+    }
+  /* The pointer is aligned to N with offset OFFSET.  */
+  ptr_offset = get_ptr_info (ref)->alignment.offset;
+  ptr_n = get_ptr_info (ref)->alignment.n;  
+		  
+  if (ptr_n/TYPE_ALIGN (vectype) >= 1 && ptr_n % TYPE_ALIGN (vectype) == 0)
+    {
+      /* Compute the offset for vectype.  */
+      ptr_offset = ptr_offset % TYPE_ALIGN (vectype);
+      /* In bits.  */
+      ptr_offset = ptr_offset * BITS_PER_UNIT;
+      *offset = fold_convert (unsigned_type_node,
+			      build_int_cst (NULL_TREE, ptr_offset));
+      return ref;
+    }
+  else 
+    {
+      if (vect_debug_details (NULL))
+	{
+	  fprintf (dump_file, "misaligned pointer access: ");
+	  print_generic_expr (dump_file, ref, TDF_SLIM);
+	}
+      return NULL_TREE;	      
+    }
 }
 
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]