* tree-ssa-loop-ivopts.c: Include tree-affine.h.
authorrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 14 Dec 2006 02:05:20 +0000 (02:05 +0000)
committerrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 14 Dec 2006 02:05:20 +0000 (02:05 +0000)
(divide): Removed.
(constant_multiple_of): Fix order of operators for division.
(aff_combination_const, aff_combination_elt, aff_combination_scale,
aff_combination_add_elt, aff_combination_add, aff_combination_convert,
tree_to_aff_combination, add_elt_to_tree, unshare_aff_combination,
aff_combination_to_tree): Moved to tree-affine.c and made to work with
double_int coefficients.
(get_computation_aff, get_computation_at): Work with double_int
coefficients.
(get_computation_cost_at): Do not use divide.
(rewrite_use_nonlinear_expr, rewrite_use_address, rewrite_use_compare):
Assert that expressing the computation did not fail.
* tree-ssa-address.c: Include tree-affine.h.
(add_to_parts, most_expensive_mult_to_index, addr_to_parts,
create_mem_ref): Work with double_int coefficients.
* tree-affine.c: New file.
* tree-affine.h: New file.
* tree-flow.h (struct affine_tree_combination): Removed.
* Makefile.in (tree-affine.o): Add.
(tree-ssa-address.o, tree-ssa-loop-ivopts.o): Add tree-affine.h
dependency.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@119854 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/Makefile.in
gcc/tree-affine.c [new file with mode: 0644]
gcc/tree-affine.h [new file with mode: 0644]
gcc/tree-flow.h
gcc/tree-ssa-address.c
gcc/tree-ssa-loop-ivopts.c

index daf8eb7..d7b85b7 100644 (file)
@@ -1,3 +1,28 @@
+2006-12-13  Zdenek Dvorak <dvorakz@suse.cz>
+
+       * tree-ssa-loop-ivopts.c: Include tree-affine.h.
+       (divide): Removed.
+       (constant_multiple_of): Fix order of operators for division.
+       (aff_combination_const, aff_combination_elt, aff_combination_scale,
+       aff_combination_add_elt, aff_combination_add, aff_combination_convert,
+       tree_to_aff_combination, add_elt_to_tree, unshare_aff_combination,
+       aff_combination_to_tree): Moved to tree-affine.c and made to work with
+       double_int coefficients.
+       (get_computation_aff, get_computation_at): Work with double_int
+       coefficients.
+       (get_computation_cost_at): Do not use divide.
+       (rewrite_use_nonlinear_expr, rewrite_use_address, rewrite_use_compare):
+       Assert that expressing the computation did not fail.
+       * tree-ssa-address.c: Include tree-affine.h.
+       (add_to_parts, most_expensive_mult_to_index, addr_to_parts,
+       create_mem_ref): Work with double_int coefficients.
+       * tree-affine.c: New file.
+       * tree-affine.h: New file.
+       * tree-flow.h (struct affine_tree_combination): Removed.
+       * Makefile.in (tree-affine.o): Add.
+       (tree-ssa-address.o, tree-ssa-loop-ivopts.o): Add tree-affine.h
+       dependency.
+
 2006-12-13  Peter Bergner  <bergner@vnet.ibm.com>
 
        PR middle-end/30191
index b291609..7ff6a40 100644 (file)
@@ -988,7 +988,7 @@ OBJS-common = \
  tree-vectorizer.o tree-vect-analyze.o tree-vect-transform.o              \
  tree-vect-patterns.o tree-ssa-loop-prefetch.o tree-ssa-coalesce.o        \
  tree-ssa-loop-ivcanon.o tree-ssa-propagate.o tree-ssa-address.o          \
- tree-ssa-math-opts.o                                                     \
+ tree-ssa-math-opts.o tree-affine.o                                       \
  tree-ssa-loop-ivopts.o tree-if-conv.o tree-ssa-loop-unswitch.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            \
@@ -1992,7 +1992,7 @@ tree-ssa-address.o : tree-ssa-address.c $(TREE_FLOW_H) $(CONFIG_H) \
    $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) \
    output.h $(DIAGNOSTIC_H) $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
    tree-pass.h $(FLAGS_H) $(TREE_INLINE_H) $(RECOG_H) insn-config.h $(EXPR_H) \
-   gt-tree-ssa-address.h $(GGC_H)
+   gt-tree-ssa-address.h $(GGC_H) tree-affine.h
 tree-ssa-loop-niter.o : tree-ssa-loop-niter.c $(TREE_FLOW_H) $(CONFIG_H) \
    $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) $(PARAMS_H) \
    $(TREE_INLINE_H) output.h $(DIAGNOSTIC_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
@@ -2018,7 +2018,10 @@ tree-ssa-loop-ivopts.o : tree-ssa-loop-ivopts.c $(TREE_FLOW_H) $(CONFIG_H) \
    output.h $(DIAGNOSTIC_H) $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
    tree-pass.h $(GGC_H) $(RECOG_H) insn-config.h $(HASHTAB_H) $(SCEV_H) \
    $(CFGLOOP_H) $(PARAMS_H) langhooks.h $(BASIC_BLOCK_H) hard-reg-set.h \
-   tree-chrec.h $(VARRAY_H)
+   tree-chrec.h $(VARRAY_H) tree-affine.h
+tree-affine.o : tree-affine.c tree-affine.h $(CONFIG_H) \
+   $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) \
+   output.h $(DIAGNOSTIC_H) $(TM_H) coretypes.h $(TREE_DUMP_H)
 tree-ssa-loop-manip.o : tree-ssa-loop-manip.c $(TREE_FLOW_H) $(CONFIG_H) \
    $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) \
    output.h $(DIAGNOSTIC_H) $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
diff --git a/gcc/tree-affine.c b/gcc/tree-affine.c
new file mode 100644 (file)
index 0000000..762e82e
--- /dev/null
@@ -0,0 +1,414 @@
+/* Operations with affine combinations of trees.
+   Copyright (C) 2005 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, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, 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 "output.h"
+#include "diagnostic.h"
+#include "tree-dump.h"
+#include "tree-affine.h"
+
+/* Extends CST as appropriate for the affine combinations COMB.  */
+
+double_int
+double_int_ext_for_comb (double_int cst, aff_tree *comb)
+{
+  return double_int_sext (cst, TYPE_PRECISION (comb->type));
+}
+
+/* Initializes affine combination COMB so that its value is zero in TYPE.  */
+
+static void
+aff_combination_zero (aff_tree *comb, tree type)
+{
+  comb->type = type;
+  comb->offset = double_int_zero;
+  comb->n = 0;
+  comb->rest = NULL_TREE;
+}
+
+/* Sets COMB to CST.  */
+
+void
+aff_combination_const (aff_tree *comb, tree type, double_int cst)
+{
+  aff_combination_zero (comb, type);
+  comb->offset = double_int_ext_for_comb (cst, comb);
+}
+
+/* Sets COMB to single element ELT.  */
+
+void
+aff_combination_elt (aff_tree *comb, tree type, tree elt)
+{
+  aff_combination_zero (comb, type);
+
+  comb->n = 1;
+  comb->elts[0].val = elt;
+  comb->elts[0].coef = double_int_one;
+}
+
+/* Scales COMB by SCALE.  */
+
+void
+aff_combination_scale (aff_tree *comb, double_int scale)
+{
+  unsigned i, j;
+
+  scale = double_int_ext_for_comb (scale, comb);
+  if (double_int_one_p (scale))
+    return;
+
+  if (double_int_zero_p (scale))
+    {
+      aff_combination_zero (comb, comb->type);
+      return;
+    }
+
+  comb->offset
+    = double_int_ext_for_comb (double_int_mul (scale, comb->offset), comb);
+  for (i = 0, j = 0; i < comb->n; i++)
+    {
+      double_int new_coef;
+
+      new_coef
+       = double_int_ext_for_comb (double_int_mul (scale, comb->elts[i].coef),
+                                  comb);
+      /* A coefficient may become zero due to overflow.  Remove the zero
+        elements.  */
+      if (double_int_zero_p (new_coef))
+       continue;
+      comb->elts[j].coef = new_coef;
+      comb->elts[j].val = comb->elts[i].val;
+      j++;
+    }
+  comb->n = j;
+
+  if (comb->rest)
+    {
+      if (comb->n < MAX_AFF_ELTS)
+       {
+         comb->elts[comb->n].coef = scale;
+         comb->elts[comb->n].val = comb->rest;
+         comb->rest = NULL_TREE;
+         comb->n++;
+       }
+      else
+       comb->rest = fold_build2 (MULT_EXPR, comb->type, comb->rest, 
+                                 double_int_to_tree (comb->type, scale));
+    }
+}
+
+/* Adds ELT * SCALE to COMB.  */
+
+void
+aff_combination_add_elt (aff_tree *comb, tree elt, double_int scale)
+{
+  unsigned i;
+
+  scale = double_int_ext_for_comb (scale, comb);
+  if (double_int_zero_p (scale))
+    return;
+
+  for (i = 0; i < comb->n; i++)
+    if (operand_equal_p (comb->elts[i].val, elt, 0))
+      {
+       double_int new_coef;
+
+       new_coef = double_int_add (comb->elts[i].coef, scale);
+       new_coef = double_int_ext_for_comb (new_coef, comb);
+       if (!double_int_zero_p (new_coef))
+         {
+           comb->elts[i].coef = new_coef;
+           return;
+         }
+
+       comb->n--;
+       comb->elts[i] = comb->elts[comb->n];
+
+       if (comb->rest)
+         {
+           gcc_assert (comb->n == MAX_AFF_ELTS - 1);
+           comb->elts[comb->n].coef = double_int_one;
+           comb->elts[comb->n].val = comb->rest;
+           comb->rest = NULL_TREE;
+           comb->n++;
+         }
+       return;
+      }
+  if (comb->n < MAX_AFF_ELTS)
+    {
+      comb->elts[comb->n].coef = scale;
+      comb->elts[comb->n].val = elt;
+      comb->n++;
+      return;
+    }
+
+  if (double_int_one_p (scale))
+    elt = fold_convert (comb->type, elt);
+  else
+    elt = fold_build2 (MULT_EXPR, comb->type,
+                      fold_convert (comb->type, elt),
+                      double_int_to_tree (comb->type, scale)); 
+
+  if (comb->rest)
+    comb->rest = fold_build2 (PLUS_EXPR, comb->type, comb->rest, elt);
+  else
+    comb->rest = elt;
+}
+
+/* Adds COMB2 to COMB1.  */
+
+void
+aff_combination_add (aff_tree *comb1, aff_tree *comb2)
+{
+  unsigned i;
+
+  comb1->offset
+    = double_int_ext_for_comb (double_int_add (comb1->offset, comb2->offset),
+                              comb1);
+  for (i = 0; i < comb2->n; i++)
+    aff_combination_add_elt (comb1, comb2->elts[i].val, comb2->elts[i].coef);
+  if (comb2->rest)
+    aff_combination_add_elt (comb1, comb2->rest, double_int_one);
+}
+
+/* Converts affine combination COMB to TYPE.  */
+
+void
+aff_combination_convert (aff_tree *comb, tree type)
+{
+  unsigned i, j;
+  tree comb_type = comb->type;
+
+  gcc_assert (TYPE_PRECISION (type) <= TYPE_PRECISION (comb_type));
+  comb->type = type;
+  if (comb->rest)
+    comb->rest = fold_convert (type, comb->rest);
+
+  if (TYPE_PRECISION (type) == TYPE_PRECISION (comb_type))
+    return;
+
+  comb->offset = double_int_ext_for_comb (comb->offset, comb);
+  for (i = j = 0; i < comb->n; i++)
+    {
+      double_int new_coef = double_int_ext_for_comb (comb->elts[i].coef, comb);
+      if (double_int_zero_p (new_coef))
+       continue;
+      comb->elts[j].coef = new_coef;
+      comb->elts[j].val = fold_convert (type, comb->elts[i].val);
+      j++;
+    }
+
+  comb->n = j;
+  if (comb->n < MAX_AFF_ELTS && comb->rest)
+    {
+      comb->elts[comb->n].coef = double_int_one;
+      comb->elts[comb->n].val = comb->rest;
+      comb->rest = NULL_TREE;
+      comb->n++;
+    }
+}
+
+/* Splits EXPR into an affine combination of parts.  */
+
+void
+tree_to_aff_combination (tree expr, tree type, aff_tree *comb)
+{
+  aff_tree tmp;
+  enum tree_code code;
+  tree cst, core, toffset;
+  HOST_WIDE_INT bitpos, bitsize;
+  enum machine_mode mode;
+  int unsignedp, volatilep;
+
+  STRIP_NOPS (expr);
+
+  code = TREE_CODE (expr);
+  switch (code)
+    {
+    case INTEGER_CST:
+      aff_combination_const (comb, type, tree_to_double_int (expr));
+      return;
+
+    case PLUS_EXPR:
+    case MINUS_EXPR:
+      tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
+      tree_to_aff_combination (TREE_OPERAND (expr, 1), type, &tmp);
+      if (code == MINUS_EXPR)
+       aff_combination_scale (&tmp, double_int_minus_one);
+      aff_combination_add (comb, &tmp);
+      return;
+
+    case MULT_EXPR:
+      cst = TREE_OPERAND (expr, 1);
+      if (TREE_CODE (cst) != INTEGER_CST)
+       break;
+      tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
+      aff_combination_scale (comb, tree_to_double_int (cst));
+      return;
+
+    case NEGATE_EXPR:
+      tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
+      aff_combination_scale (comb, double_int_minus_one);
+      return;
+
+    case ADDR_EXPR:
+      core = get_inner_reference (TREE_OPERAND (expr, 0), &bitsize, &bitpos,
+                                 &toffset, &mode, &unsignedp, &volatilep,
+                                 false);
+      if (bitpos % BITS_PER_UNIT != 0)
+       break;
+      aff_combination_const (comb, type,
+                            uhwi_to_double_int (bitpos / BITS_PER_UNIT));
+      core = build_fold_addr_expr (core);
+      if (TREE_CODE (core) == ADDR_EXPR)
+       aff_combination_add_elt (comb, core, double_int_one);
+      else
+       {
+         tree_to_aff_combination (core, type, &tmp);
+         aff_combination_add (comb, &tmp);
+       }
+      if (toffset)
+       {
+         tree_to_aff_combination (toffset, type, &tmp);
+         aff_combination_add (comb, &tmp);
+       }
+      return;
+
+    default:
+      break;
+    }
+
+  aff_combination_elt (comb, type, expr);
+}
+
+/* Creates EXPR + ELT * SCALE in TYPE.  EXPR is taken from affine
+   combination COMB.  */
+
+static tree
+add_elt_to_tree (tree expr, tree type, tree elt, double_int scale,
+                aff_tree *comb)
+{
+  enum tree_code code;
+
+  scale = double_int_ext_for_comb (scale, comb);
+  elt = fold_convert (type, elt);
+
+  if (double_int_one_p (scale))
+    {
+      if (!expr)
+       return elt;
+
+      return fold_build2 (PLUS_EXPR, type, expr, elt);
+    }
+
+  if (double_int_minus_one_p (scale))
+    {
+      if (!expr)
+       return fold_build1 (NEGATE_EXPR, type, elt);
+
+      return fold_build2 (MINUS_EXPR, type, expr, elt);
+    }
+
+  if (!expr)
+    return fold_build2 (MULT_EXPR, type, elt,
+                       double_int_to_tree (type, scale));
+
+  if (double_int_negative_p (scale))
+    {
+      code = MINUS_EXPR;
+      scale = double_int_neg (scale);
+    }
+  else
+    code = PLUS_EXPR;
+
+  elt = fold_build2 (MULT_EXPR, type, elt,
+                    double_int_to_tree (type, scale));
+  return fold_build2 (code, type, expr, elt);
+}
+
+/* Makes tree from the affine combination COMB.  */
+
+tree
+aff_combination_to_tree (aff_tree *comb)
+{
+  tree type = comb->type;
+  tree expr = comb->rest;
+  unsigned i;
+  double_int off, sgn;
+
+  gcc_assert (comb->n == MAX_AFF_ELTS || comb->rest == NULL_TREE);
+
+  for (i = 0; i < comb->n; i++)
+    expr = add_elt_to_tree (expr, type, comb->elts[i].val, comb->elts[i].coef,
+                           comb);
+
+  /* Ensure that we get x - 1, not x + (-1) or x + 0xff..f if x is
+     unsigned.  */
+  if (double_int_negative_p (comb->offset))
+    {
+      off = double_int_neg (comb->offset);
+      sgn = double_int_minus_one;
+    }
+  else
+    {
+      off = comb->offset;
+      sgn = double_int_one;
+    }
+  return add_elt_to_tree (expr, type, double_int_to_tree (type, off), sgn,
+                         comb);
+}
+
+/* Copies the tree elements of COMB to ensure that they are not shared.  */
+
+void
+unshare_aff_combination (aff_tree *comb)
+{
+  unsigned i;
+
+  for (i = 0; i < comb->n; i++)
+    comb->elts[i].val = unshare_expr (comb->elts[i].val);
+  if (comb->rest)
+    comb->rest = unshare_expr (comb->rest);
+}
+
+/* Remove M-th element from COMB.  */
+
+void
+aff_combination_remove_elt (aff_tree *comb, unsigned m)
+{
+  comb->n--;
+  if (m <= comb->n)
+    comb->elts[m] = comb->elts[comb->n];
+  if (comb->rest)
+    {
+      comb->elts[comb->n].coef = double_int_one;
+      comb->elts[comb->n].val = comb->rest;
+      comb->rest = NULL_TREE;
+      comb->n++;
+    }
+}
diff --git a/gcc/tree-affine.h b/gcc/tree-affine.h
new file mode 100644 (file)
index 0000000..010f4a7
--- /dev/null
@@ -0,0 +1,71 @@
+/* Operations with affine combinations of trees.
+   Copyright (C) 2005 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, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
+
+/* Affine combination of trees.  We keep track of at most MAX_AFF_ELTS elements
+   to make things simpler; this is sufficient in most cases.  */
+
+#define MAX_AFF_ELTS 8
+
+/* Element of an affine combination.  */
+
+struct aff_comb_elt
+{
+  /* The value of the element.  */
+  tree val;
+  
+  /* Its coefficient in the combination.  */
+  double_int coef;
+};
+
+typedef struct affine_tree_combination
+{
+  /* Type of the result of the combination.  */
+  tree type;
+
+  /* Constant offset.  */
+  double_int offset;
+
+  /* Number of elements of the combination.  */
+  unsigned n;
+
+  /* Elements and their coefficients.  Type of elements may be different from
+     TYPE, but their sizes must be the same (STRIP_NOPS is applied to the
+     elements).
+     
+     The coefficients are always sign extened from the precision of TYPE
+     (regardless of signedness of TYPE).  */
+  struct aff_comb_elt elts[MAX_AFF_ELTS];
+
+  /* Remainder of the expression.  Usually NULL, used only if there are more
+     than MAX_AFF_ELTS elements.  Type of REST must be TYPE.  */
+  tree rest;
+} aff_tree;
+
+double_int double_int_ext_for_comb (double_int, aff_tree *);
+void aff_combination_const (aff_tree *, tree, double_int);
+void aff_combination_elt (aff_tree *, tree, tree);
+void aff_combination_scale (aff_tree *, double_int);
+void aff_combination_add (aff_tree *, aff_tree *);
+void aff_combination_add_elt (aff_tree *, tree, double_int);
+void aff_combination_remove_elt (aff_tree *, unsigned);
+void aff_combination_convert (aff_tree *, tree);
+void tree_to_aff_combination (tree, tree, aff_tree *);
+tree aff_combination_to_tree (aff_tree *);
+void unshare_aff_combination (aff_tree *);
index e0ef809..f4337d2 100644 (file)
@@ -1002,33 +1002,6 @@ extern void remove_unused_locals (void);
 
 /* In tree-ssa-address.c  */
 
-/* Affine combination of trees.  We keep track of at most MAX_AFF_ELTS elements
-   to make things simpler; this is sufficient in most cases.  */
-
-#define MAX_AFF_ELTS 8
-
-struct affine_tree_combination
-{
-  /* Type of the result of the combination.  */
-  tree type;
-
-  /* Mask modulo that the operations are performed.  */
-  unsigned HOST_WIDE_INT mask;
-
-  /* Constant offset.  */
-  unsigned HOST_WIDE_INT offset;
-
-  /* Number of elements of the combination.  */
-  unsigned n;
-
-  /* Elements and their coefficients.  */
-  tree elts[MAX_AFF_ELTS];
-  unsigned HOST_WIDE_INT coefs[MAX_AFF_ELTS];
-
-  /* Remainder of the expression.  */
-  tree rest;
-};
-
 /* Description of a memory address.  */
 
 struct mem_address
@@ -1036,6 +1009,7 @@ struct mem_address
   tree symbol, base, index, step, offset;
 };
 
+struct affine_tree_combination;
 tree create_mem_ref (block_stmt_iterator *, tree, 
                     struct affine_tree_combination *);
 rtx addr_for_mem_ref (struct mem_address *, bool);
index c339449..eb39370 100644 (file)
@@ -42,6 +42,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "recog.h"
 #include "expr.h"
 #include "ggc.h"
+#include "tree-affine.h"
 
 /* TODO -- handling of symbols (according to Richard Hendersons
    comments, http://gcc.gnu.org/ml/gcc-patches/2005-04/msg00949.html):
@@ -346,25 +347,20 @@ fixed_address_object_p (tree obj)
    construct.  */
 
 static void
-add_to_parts (struct mem_address *parts, tree type, tree elt,
-             unsigned HOST_WIDE_INT coef)
+add_to_parts (struct mem_address *parts, tree type, tree elt)
 {
+  tree elt_core = elt;
+  STRIP_NOPS (elt_core);
+
   /* Check if this is a symbol.  */
   if (!parts->symbol
-      && coef == 1
-      && TREE_CODE (elt) == ADDR_EXPR
-      && fixed_address_object_p (TREE_OPERAND (elt, 0)))
+      && TREE_CODE (elt_core) == ADDR_EXPR
+      && fixed_address_object_p (TREE_OPERAND (elt_core, 0)))
     {
-      parts->symbol = TREE_OPERAND (elt, 0);
+      parts->symbol = TREE_OPERAND (elt_core, 0);
       return;
     }
 
-  if (coef != 1)
-    elt = fold_build2 (MULT_EXPR, type, fold_convert (type, elt),
-                      build_int_cst_type (type, coef));
-  else
-    elt = fold_convert (type, elt);
-
   if (!parts->base)
     {
       parts->base = elt;
@@ -388,52 +384,69 @@ add_to_parts (struct mem_address *parts, tree type, tree elt,
 
 static void
 most_expensive_mult_to_index (struct mem_address *parts, tree type,
-                             struct affine_tree_combination *addr)
+                             aff_tree *addr)
 {
-  unsigned HOST_WIDE_INT best_mult = 0;
+  HOST_WIDE_INT coef;
+  double_int best_mult, amult, amult_neg;
   unsigned best_mult_cost = 0, acost;
   tree mult_elt = NULL_TREE, elt;
   unsigned i, j;
+  enum tree_code op_code;
 
+  best_mult = double_int_zero;
   for (i = 0; i < addr->n; i++)
     {
+      if (!double_int_fits_in_shwi_p (addr->elts[i].coef))
+       continue;
+
       /* FIXME: Should use the correct memory mode rather than Pmode.  */
-      if (addr->coefs[i] == 1
-         || !multiplier_allowed_in_address_p (addr->coefs[i], Pmode))
+
+      coef = double_int_to_shwi (addr->elts[i].coef);
+      if (coef == 1
+         || !multiplier_allowed_in_address_p (coef, Pmode))
        continue;
-      
-      acost = multiply_by_cost (addr->coefs[i], Pmode);
+
+      acost = multiply_by_cost (coef, Pmode);
 
       if (acost > best_mult_cost)
        {
          best_mult_cost = acost;
-         best_mult = addr->coefs[i];
+         best_mult = addr->elts[i].coef;
        }
     }
 
-  if (!best_mult)
+  if (!best_mult_cost)
     return;
 
+  /* Collect elements multiplied by best_mult.  */
   for (i = j = 0; i < addr->n; i++)
     {
-      if (addr->coefs[i] != best_mult)
+      amult = addr->elts[i].coef;
+      amult_neg = double_int_ext_for_comb (double_int_neg (amult), addr);
+      if (double_int_equal_p (amult, best_mult))
+       op_code = PLUS_EXPR;
+      else if (double_int_equal_p (amult_neg, best_mult))
+       op_code = MINUS_EXPR;
+      else
        {
-         addr->coefs[j] = addr->coefs[i];
          addr->elts[j] = addr->elts[i];
          j++;
          continue;
        }
-
-      elt = fold_convert (type, addr->elts[i]);
-      if (!mult_elt)
+  
+      elt = fold_convert (type, addr->elts[i].val);
+      if (mult_elt)
+       mult_elt = fold_build2 (op_code, type, mult_elt, elt);
+      else if (op_code == PLUS_EXPR)
        mult_elt = elt;
       else
-       mult_elt = fold_build2 (PLUS_EXPR, type, mult_elt, elt);
+       mult_elt = fold_build1 (NEGATE_EXPR, type, elt);
     }
   addr->n = j;
-
+  
   parts->index = mult_elt;
-  parts->step = build_int_cst_type (type, best_mult);
+  parts->step = double_int_to_tree (type, best_mult);
 }
 
 /* Splits address ADDR into PARTS.
@@ -442,13 +455,13 @@ most_expensive_mult_to_index (struct mem_address *parts, tree type,
    to PARTS.  Some architectures do not support anything but single
    register in address, possibly with a small integer offset; while
    create_mem_ref will simplify the address to an acceptable shape
-   later, it would be a small bit more efficient to know that asking
-   for complicated addressing modes is useless.  */
+   later, it would be more efficient to know that asking for complicated
+   addressing modes is useless.  */
 
 static void
-addr_to_parts (struct affine_tree_combination *addr, tree type,
-              struct mem_address *parts)
+addr_to_parts (aff_tree *addr, tree type, struct mem_address *parts)
 {
+  tree part;
   unsigned i;
 
   parts->symbol = NULL_TREE;
@@ -456,8 +469,8 @@ addr_to_parts (struct affine_tree_combination *addr, tree type,
   parts->index = NULL_TREE;
   parts->step = NULL_TREE;
 
-  if (addr->offset)
-    parts->offset = build_int_cst_type (type, addr->offset);
+  if (!double_int_zero_p (addr->offset))
+    parts->offset = double_int_to_tree (type, addr->offset);
   else
     parts->offset = NULL_TREE;
 
@@ -467,9 +480,15 @@ addr_to_parts (struct affine_tree_combination *addr, tree type,
 
   /* Then try to process the remaining elements.  */
   for (i = 0; i < addr->n; i++)
-    add_to_parts (parts, type, addr->elts[i], addr->coefs[i]);
+    {
+      part = fold_convert (type, addr->elts[i].val);
+      if (!double_int_one_p (addr->elts[i].coef))
+       part = fold_build2 (MULT_EXPR, type, part,
+                           double_int_to_tree (type, addr->elts[i].coef));
+      add_to_parts (parts, type, part);
+    }
   if (addr->rest)
-    add_to_parts (parts, type, addr->rest, 1);
+    add_to_parts (parts, type, addr->rest);
 }
 
 /* Force the PARTS to register.  */
@@ -490,8 +509,7 @@ gimplify_mem_ref_parts (block_stmt_iterator *bsi, struct mem_address *parts)
    of created memory reference.  */
 
 tree
-create_mem_ref (block_stmt_iterator *bsi, tree type,
-               struct affine_tree_combination *addr)
+create_mem_ref (block_stmt_iterator *bsi, tree type, aff_tree *addr)
 {
   tree mem_ref, tmp;
   tree addr_type = build_pointer_type (type);
index 4543740..1efaf99 100644 (file)
@@ -89,6 +89,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "cfgloop.h"
 #include "params.h"
 #include "langhooks.h"
+#include "tree-affine.h"
 
 /* The infinite cost.  */
 #define INFTY 10000000
@@ -524,57 +525,6 @@ name_info (struct ivopts_data *data, tree name)
   return ver_info (data, SSA_NAME_VERSION (name));
 }
 
-/* Checks whether there exists number X such that X * B = A, counting modulo
-   2^BITS.  */
-
-static bool
-divide (unsigned bits, unsigned HOST_WIDE_INT a, unsigned HOST_WIDE_INT b,
-       HOST_WIDE_INT *x)
-{
-  unsigned HOST_WIDE_INT mask = ~(~(unsigned HOST_WIDE_INT) 0 << (bits - 1) << 1);
-  unsigned HOST_WIDE_INT inv, ex, val;
-  unsigned i;
-
-  a &= mask;
-  b &= mask;
-
-  /* First divide the whole equation by 2 as long as possible.  */
-  while (!(a & 1) && !(b & 1))
-    {
-      a >>= 1;
-      b >>= 1;
-      bits--;
-      mask >>= 1;
-    }
-
-  if (!(b & 1))
-    {
-      /* If b is still even, a is odd and there is no such x.  */
-      return false;
-    }
-
-  /* Find the inverse of b.  We compute it as
-     b^(2^(bits - 1) - 1) (mod 2^bits).  */
-  inv = 1;
-  ex = b;
-  for (i = 0; i < bits - 1; i++)
-    {
-      inv = (inv * ex) & mask;
-      ex = (ex * ex) & mask;
-    }
-
-  val = (a * inv) & mask;
-
-  gcc_assert (((val * b) & mask) == a);
-
-  if ((val >> (bits - 1)) & 1)
-    val |= ~mask;
-
-  *x = val;
-
-  return true;
-}
-
 /* Returns true if STMT is after the place where the IP_NORMAL ivs will be
    emitted in LOOP.  */
 
@@ -2613,8 +2563,8 @@ constant_multiple_of (tree top, tree bot, double_int *mul)
       if (TREE_CODE (bot) != INTEGER_CST)
        return false;
 
-      p0 = double_int_sext (tree_to_double_int (bot), precision);
-      p1 = double_int_sext (tree_to_double_int (top), precision);
+      p0 = double_int_sext (tree_to_double_int (top), precision);
+      p1 = double_int_sext (tree_to_double_int (bot), precision);
       if (double_int_zero_p (p1))
        return false;
       *mul = double_int_sext (double_int_sdivmod (p0, p1, FLOOR_DIV_EXPR, &res),
@@ -2626,354 +2576,6 @@ constant_multiple_of (tree top, tree bot, double_int *mul)
     }
 }
 
-/* Sets COMB to CST.  */
-
-static void
-aff_combination_const (struct affine_tree_combination *comb, tree type,
-                      unsigned HOST_WIDE_INT cst)
-{
-  unsigned prec = TYPE_PRECISION (type);
-
-  comb->type = type;
-  comb->mask = (((unsigned HOST_WIDE_INT) 2 << (prec - 1)) - 1);
-
-  comb->n = 0;
-  comb->rest = NULL_TREE;
-  comb->offset = cst & comb->mask;
-}
-
-/* Sets COMB to single element ELT.  */
-
-static void
-aff_combination_elt (struct affine_tree_combination *comb, tree type, tree elt)
-{
-  unsigned prec = TYPE_PRECISION (type);
-
-  comb->type = type;
-  comb->mask = (((unsigned HOST_WIDE_INT) 2 << (prec - 1)) - 1);
-
-  comb->n = 1;
-  comb->elts[0] = elt;
-  comb->coefs[0] = 1;
-  comb->rest = NULL_TREE;
-  comb->offset = 0;
-}
-
-/* Scales COMB by SCALE.  */
-
-static void
-aff_combination_scale (struct affine_tree_combination *comb,
-                      unsigned HOST_WIDE_INT scale)
-{
-  unsigned i, j;
-
-  if (scale == 1)
-    return;
-
-  if (scale == 0)
-    {
-      aff_combination_const (comb, comb->type, 0);
-      return;
-    }
-
-  comb->offset = (scale * comb->offset) & comb->mask;
-  for (i = 0, j = 0; i < comb->n; i++)
-    {
-      comb->coefs[j] = (scale * comb->coefs[i]) & comb->mask;
-      comb->elts[j] = comb->elts[i];
-      if (comb->coefs[j] != 0)
-       j++;
-    }
-  comb->n = j;
-
-  if (comb->rest)
-    {
-      if (comb->n < MAX_AFF_ELTS)
-       {
-         comb->coefs[comb->n] = scale;
-         comb->elts[comb->n] = comb->rest;
-         comb->rest = NULL_TREE;
-         comb->n++;
-       }
-      else
-       comb->rest = fold_build2 (MULT_EXPR, comb->type, comb->rest,
-                                 build_int_cst_type (comb->type, scale));
-    }
-}
-
-/* Adds ELT * SCALE to COMB.  */
-
-static void
-aff_combination_add_elt (struct affine_tree_combination *comb, tree elt,
-                        unsigned HOST_WIDE_INT scale)
-{
-  unsigned i;
-
-  if (scale == 0)
-    return;
-
-  for (i = 0; i < comb->n; i++)
-    if (operand_equal_p (comb->elts[i], elt, 0))
-      {
-       comb->coefs[i] = (comb->coefs[i] + scale) & comb->mask;
-       if (comb->coefs[i])
-         return;
-
-       comb->n--;
-       comb->coefs[i] = comb->coefs[comb->n];
-       comb->elts[i] = comb->elts[comb->n];
-
-       if (comb->rest)
-         {
-           gcc_assert (comb->n == MAX_AFF_ELTS - 1);
-           comb->coefs[comb->n] = 1;
-           comb->elts[comb->n] = comb->rest;
-           comb->rest = NULL_TREE;
-           comb->n++;
-         }
-       return;
-      }
-  if (comb->n < MAX_AFF_ELTS)
-    {
-      comb->coefs[comb->n] = scale;
-      comb->elts[comb->n] = elt;
-      comb->n++;
-      return;
-    }
-
-  if (scale == 1)
-    elt = fold_convert (comb->type, elt);
-  else
-    elt = fold_build2 (MULT_EXPR, comb->type,
-                      fold_convert (comb->type, elt),
-                      build_int_cst_type (comb->type, scale)); 
-
-  if (comb->rest)
-    comb->rest = fold_build2 (PLUS_EXPR, comb->type, comb->rest, elt);
-  else
-    comb->rest = elt;
-}
-
-/* Adds COMB2 to COMB1.  */
-
-static void
-aff_combination_add (struct affine_tree_combination *comb1,
-                    struct affine_tree_combination *comb2)
-{
-  unsigned i;
-
-  comb1->offset = (comb1->offset + comb2->offset) & comb1->mask;
-  for (i = 0; i < comb2->n; i++)
-    aff_combination_add_elt (comb1, comb2->elts[i], comb2->coefs[i]);
-  if (comb2->rest)
-    aff_combination_add_elt (comb1, comb2->rest, 1);
-}
-
-/* Convert COMB to TYPE.  */
-
-static void
-aff_combination_convert (tree type, struct affine_tree_combination *comb)
-{
-  unsigned prec = TYPE_PRECISION (type);
-  unsigned i;
-
-  /* If the precision of both types is the same, it suffices to change the type
-     of the whole combination -- the elements are allowed to have another type
-     equivalent wrto STRIP_NOPS.  */
-  if (prec == TYPE_PRECISION (comb->type))
-    {
-      comb->type = type;
-      return;
-    }
-
-  comb->mask = (((unsigned HOST_WIDE_INT) 2 << (prec - 1)) - 1);
-  comb->offset = comb->offset & comb->mask;
-
-  /* The type of the elements can be different from comb->type only as
-     much as what STRIP_NOPS would remove.  We can just directly cast
-     to TYPE.  */
-  for (i = 0; i < comb->n; i++)
-    comb->elts[i] = fold_convert (type, comb->elts[i]);
-  if (comb->rest)
-    comb->rest = fold_convert (type, comb->rest);
-
-  comb->type = type;
-}
-
-/* Splits EXPR into an affine combination of parts.  */
-
-static void
-tree_to_aff_combination (tree expr, tree type,
-                        struct affine_tree_combination *comb)
-{
-  struct affine_tree_combination tmp;
-  enum tree_code code;
-  tree cst, core, toffset;
-  HOST_WIDE_INT bitpos, bitsize;
-  enum machine_mode mode;
-  int unsignedp, volatilep;
-
-  STRIP_NOPS (expr);
-
-  code = TREE_CODE (expr);
-  switch (code)
-    {
-    case INTEGER_CST:
-      aff_combination_const (comb, type, int_cst_value (expr));
-      return;
-
-    case PLUS_EXPR:
-    case MINUS_EXPR:
-      tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
-      tree_to_aff_combination (TREE_OPERAND (expr, 1), type, &tmp);
-      if (code == MINUS_EXPR)
-       aff_combination_scale (&tmp, -1);
-      aff_combination_add (comb, &tmp);
-      return;
-
-    case MULT_EXPR:
-      cst = TREE_OPERAND (expr, 1);
-      if (TREE_CODE (cst) != INTEGER_CST)
-       break;
-      tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
-      aff_combination_scale (comb, int_cst_value (cst));
-      return;
-
-    case NEGATE_EXPR:
-      tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
-      aff_combination_scale (comb, -1);
-      return;
-
-    case ADDR_EXPR:
-      core = get_inner_reference (TREE_OPERAND (expr, 0), &bitsize, &bitpos,
-                                 &toffset, &mode, &unsignedp, &volatilep,
-                                 false);
-      if (bitpos % BITS_PER_UNIT != 0)
-       break;
-      aff_combination_const (comb, type, bitpos / BITS_PER_UNIT);
-      core = build_fold_addr_expr (core);
-      if (TREE_CODE (core) == ADDR_EXPR)
-       aff_combination_add_elt (comb, core, 1);
-      else
-       {
-         tree_to_aff_combination (core, type, &tmp);
-         aff_combination_add (comb, &tmp);
-       }
-      if (toffset)
-       {
-         tree_to_aff_combination (toffset, type, &tmp);
-         aff_combination_add (comb, &tmp);
-       }
-      return;
-
-    default:
-      break;
-    }
-
-  aff_combination_elt (comb, type, expr);
-}
-
-/* Creates EXPR + ELT * SCALE in TYPE.  MASK is the mask for width of TYPE.  */
-
-static tree
-add_elt_to_tree (tree expr, tree type, tree elt, unsigned HOST_WIDE_INT scale,
-                unsigned HOST_WIDE_INT mask)
-{
-  enum tree_code code;
-
-  scale &= mask;
-  elt = fold_convert (type, elt);
-
-  if (scale == 1)
-    {
-      if (!expr)
-       return elt;
-
-      return fold_build2 (PLUS_EXPR, type, expr, elt);
-    }
-
-  if (scale == mask)
-    {
-      if (!expr)
-       return fold_build1 (NEGATE_EXPR, type, elt);
-
-      return fold_build2 (MINUS_EXPR, type, expr, elt);
-    }
-
-  if (!expr)
-    return fold_build2 (MULT_EXPR, type, elt,
-                       build_int_cst_type (type, scale));
-
-  if ((scale | (mask >> 1)) == mask)
-    {
-      /* Scale is negative.  */
-      code = MINUS_EXPR;
-      scale = (-scale) & mask;
-    }
-  else
-    code = PLUS_EXPR;
-
-  elt = fold_build2 (MULT_EXPR, type, elt,
-                    build_int_cst_type (type, scale));
-  return fold_build2 (code, type, expr, elt);
-}
-
-/* Copies the tree elements of COMB to ensure that they are not shared.  */
-
-static void
-unshare_aff_combination (struct affine_tree_combination *comb)
-{
-  unsigned i;
-
-  for (i = 0; i < comb->n; i++)
-    comb->elts[i] = unshare_expr (comb->elts[i]);
-  if (comb->rest)
-    comb->rest = unshare_expr (comb->rest);
-}
-
-/* Makes tree from the affine combination COMB.  */
-
-static tree
-aff_combination_to_tree (struct affine_tree_combination *comb)
-{
-  tree type = comb->type;
-  tree expr = comb->rest;
-  unsigned i;
-  unsigned HOST_WIDE_INT off, sgn;
-
-  if (comb->n == 0 && comb->offset == 0)
-    {
-      if (expr)
-       {
-         /* Handle the special case produced by get_computation_aff when
-            the type does not fit in HOST_WIDE_INT.  */
-         return fold_convert (type, expr);
-       }
-      else
-       return build_int_cst (type, 0);
-    }
-
-  gcc_assert (comb->n == MAX_AFF_ELTS || comb->rest == NULL_TREE);
-
-  for (i = 0; i < comb->n; i++)
-    expr = add_elt_to_tree (expr, type, comb->elts[i], comb->coefs[i],
-                           comb->mask);
-
-  if ((comb->offset | (comb->mask >> 1)) == comb->mask)
-    {
-      /* Offset is negative.  */
-      off = (-comb->offset) & comb->mask;
-      sgn = comb->mask;
-    }
-  else
-    {
-      off = comb->offset;
-      sgn = 1;
-    }
-  return add_elt_to_tree (expr, type, build_int_cst_type (type, off), sgn,
-                         comb->mask);
-}
-
 /* Folds EXPR using the affine expressions framework.  */
 
 static tree
@@ -3039,16 +2641,11 @@ get_computation_aff (struct loop *loop,
   tree ubase = use->iv->base;
   tree ustep = use->iv->step;
   tree cbase = cand->iv->base;
-  tree cstep = cand->iv->step;
+  tree cstep = cand->iv->step, cstep_common;
   tree utype = TREE_TYPE (ubase), ctype = TREE_TYPE (cbase);
-  tree common_type;
+  tree common_type, var;
   tree uutype;
-  tree expr, delta;
-  tree ratio;
-  unsigned HOST_WIDE_INT ustepi, cstepi;
-  HOST_WIDE_INT ratioi;
-  struct affine_tree_combination cbase_aff, expr_aff;
-  tree cstep_orig = cstep, ustep_orig = ustep;
+  aff_tree cbase_aff, var_aff;
   double_int rat;
 
   if (TYPE_PRECISION (utype) > TYPE_PRECISION (ctype))
@@ -3057,65 +2654,19 @@ get_computation_aff (struct loop *loop,
       return false;
     }
 
-  expr = var_at_stmt (loop, cand, at);
-
-  if (TREE_TYPE (expr) != ctype)
-    {
-      /* This may happen with the original ivs.  */
-      expr = fold_convert (ctype, expr);
-    }
-
-  if (TYPE_UNSIGNED (utype))
-    uutype = utype;
-  else
-    {
-      uutype = unsigned_type_for (utype);
-      ubase = fold_convert (uutype, ubase);
-      ustep = fold_convert (uutype, ustep);
-    }
+  var = var_at_stmt (loop, cand, at);
+  uutype = unsigned_type_for (utype);
 
-  if (uutype != ctype)
+  /* If the conversion is not noop, perform it.  */
+  if (TYPE_PRECISION (utype) < TYPE_PRECISION (ctype))
     {
-      expr = fold_convert (uutype, expr);
-      cbase = fold_convert (uutype, cbase);
       cstep = fold_convert (uutype, cstep);
-
-      /* If the conversion is not noop, we must take it into account when
-        considering the value of the step.  */
-      if (TYPE_PRECISION (utype) < TYPE_PRECISION (ctype))
-       cstep_orig = cstep;
-    }
-
-  if (cst_and_fits_in_hwi (cstep_orig)
-      && cst_and_fits_in_hwi (ustep_orig))
-    {
-      ustepi = int_cst_value (ustep_orig);
-      cstepi = int_cst_value (cstep_orig);
-
-      if (!divide (TYPE_PRECISION (uutype), ustepi, cstepi, &ratioi))
-       {
-         /* TODO maybe consider case when ustep divides cstep and the ratio is
-            a power of 2 (so that the division is fast to execute)?  We would
-            need to be much more careful with overflows etc. then.  */
-         return false;
-       }
-
-      ratio = build_int_cst_type (uutype, ratioi);
+      cbase = fold_convert (uutype, cbase);
+      var = fold_convert (uutype, var);
     }
-  else
-    {
-      if (!constant_multiple_of (ustep_orig, cstep_orig, &rat))
-       return false;
-      ratio = double_int_to_tree (uutype, rat);
 
-      /* Ratioi is only used to detect special cases when the multiplicative
-        factor is 1 or -1, so if rat does not fit to HOST_WIDE_INT, we may
-        set it to 0.  */
-      if (double_int_fits_in_shwi_p (rat))
-       ratioi = double_int_to_shwi (rat);
-      else
-       ratioi = 0;
-    }
+  if (!constant_multiple_of (ustep, cstep, &rat))
+    return false;
 
   /* In case both UBASE and CBASE are shortened to UUTYPE from some common
      type, we achieve better folding by computing their difference in this
@@ -3124,73 +2675,32 @@ get_computation_aff (struct loop *loop,
      anyway.  */
   common_type = determine_common_wider_type (&ubase, &cbase);
 
-  /* We may need to shift the value if we are after the increment.  */
-  if (stmt_after_increment (loop, cand, at))
-    {
-      if (uutype != common_type)
-       cstep = fold_convert (common_type, cstep);
-      cbase = fold_build2 (PLUS_EXPR, common_type, cbase, cstep);
-    }
-
-  /* use = ubase - ratio * cbase + ratio * var.
-
-     In general case ubase + ratio * (var - cbase) could be better (one less
-     multiplication), but often it is possible to eliminate redundant parts
-     of computations from (ubase - ratio * cbase) term, and if it does not
-     happen, fold is able to apply the distributive law to obtain this form
-     anyway.  */
+  /* use = ubase - ratio * cbase + ratio * var.  */
+  tree_to_aff_combination (ubase, common_type, aff);
+  tree_to_aff_combination (cbase, common_type, &cbase_aff);
+  tree_to_aff_combination (var, uutype, &var_aff);
 
-  if (TYPE_PRECISION (common_type) > HOST_BITS_PER_WIDE_INT)
+  /* We need to shift the value if we are after the increment.  */
+  if (stmt_after_increment (loop, cand, at))
     {
-      /* Let's compute in trees and just return the result in AFF.  This case
-        should not be very common, and fold itself is not that bad either,
-        so making the aff. functions more complicated to handle this case
-        is not that urgent.  */
-      if (ratioi == 1)
-       {
-         delta = fold_build2 (MINUS_EXPR, common_type, ubase, cbase);
-         if (uutype != common_type)
-           delta = fold_convert (uutype, delta);
-         expr = fold_build2 (PLUS_EXPR, uutype, expr, delta);
-       }
-      else if (ratioi == -1)
-       {
-         delta = fold_build2 (PLUS_EXPR, common_type, ubase, cbase);
-         if (uutype != common_type)
-           delta = fold_convert (uutype, delta);
-         expr = fold_build2 (MINUS_EXPR, uutype, delta, expr);
-       }
+      aff_tree cstep_aff;
+  
+      if (common_type != uutype)
+       cstep_common = fold_convert (common_type, cstep);
       else
-       {
-         delta = fold_build2 (MULT_EXPR, common_type, cbase, ratio);
-         delta = fold_build2 (MINUS_EXPR, common_type, ubase, delta);
-         if (uutype != common_type)
-           delta = fold_convert (uutype, delta);
-         expr = fold_build2 (MULT_EXPR, uutype, ratio, expr);
-         expr = fold_build2 (PLUS_EXPR, uutype, delta, expr);
-       }
+       cstep_common = cstep;
 
-      aff->type = uutype;
-      aff->n = 0;
-      aff->offset = 0;
-      aff->mask = 0;
-      aff->rest = expr;
-      return true;
+      tree_to_aff_combination (cstep_common, common_type, &cstep_aff);
+      aff_combination_add (&cbase_aff, &cstep_aff);
     }
 
-  /* If we got here, the types fits in HOST_WIDE_INT, thus it must be
-     possible to compute ratioi.  */
-  gcc_assert (ratioi);
-
-  tree_to_aff_combination (ubase, common_type, aff);
-  tree_to_aff_combination (cbase, common_type, &cbase_aff);
-  tree_to_aff_combination (expr, uutype, &expr_aff);
-  aff_combination_scale (&cbase_aff, -ratioi);
-  aff_combination_scale (&expr_aff, ratioi);
+  aff_combination_scale (&cbase_aff, double_int_neg (rat));
   aff_combination_add (aff, &cbase_aff);
   if (common_type != uutype)
-    aff_combination_convert (uutype, aff);
-  aff_combination_add (aff, &expr_aff);
+    aff_combination_convert (aff, uutype);
+
+  aff_combination_scale (&var_aff, rat);
+  aff_combination_add (aff, &var_aff);
 
   return true;
 }
@@ -3202,7 +2712,7 @@ static tree
 get_computation_at (struct loop *loop,
                    struct iv_use *use, struct iv_cand *cand, tree at)
 {
-  struct affine_tree_combination aff;
+  aff_tree aff;
   tree type = TREE_TYPE (use->iv->base);
 
   if (!get_computation_aff (loop, use, cand, at, &aff))
@@ -3862,10 +3372,11 @@ get_computation_cost_at (struct ivopts_data *data,
   tree ubase = use->iv->base, ustep = use->iv->step;
   tree cbase, cstep;
   tree utype = TREE_TYPE (ubase), ctype;
-  unsigned HOST_WIDE_INT ustepi, cstepi, offset = 0;
+  unsigned HOST_WIDE_INT cstepi, offset = 0;
   HOST_WIDE_INT ratio, aratio;
   bool var_present, symbol_present;
   unsigned cost = 0, n_sums;
+  double_int rat;
 
   *depends_on = NULL;
 
@@ -3913,26 +3424,13 @@ get_computation_cost_at (struct ivopts_data *data,
   else
     cstepi = 0;
 
-  if (cst_and_fits_in_hwi (ustep)
-      && cst_and_fits_in_hwi (cstep))
-    {
-      ustepi = int_cst_value (ustep);
-
-      if (!divide (TYPE_PRECISION (utype), ustepi, cstepi, &ratio))
-       return INFTY;
-    }
-  else
-    {
-      double_int rat;
-      
-      if (!constant_multiple_of (ustep, cstep, &rat))
-       return INFTY;
+  if (!constant_multiple_of (ustep, cstep, &rat))
+    return INFTY;
     
-      if (double_int_fits_in_shwi_p (rat))
-       ratio = double_int_to_shwi (rat);
-      else
-       return INFTY;
-    }
+  if (double_int_fits_in_shwi_p (rat))
+    ratio = double_int_to_shwi (rat);
+  else
+    return INFTY;
 
   /* use = ubase + ratio * (var - cbase).  If either cbase is a constant
      or ratio == 1, it is better to handle this like
@@ -5427,7 +4925,10 @@ rewrite_use_nonlinear_expr (struct ivopts_data *data,
                                   unshare_expr (step)));
     }
   else
-    comp = get_computation (data->current_loop, use, cand);
+    {
+      comp = get_computation (data->current_loop, use, cand);
+      gcc_assert (comp != NULL_TREE);
+    }
 
   switch (TREE_CODE (use->stmt))
     {
@@ -5593,11 +5094,13 @@ static void
 rewrite_use_address (struct ivopts_data *data,
                     struct iv_use *use, struct iv_cand *cand)
 {
-  struct affine_tree_combination aff;
+  aff_tree aff;
   block_stmt_iterator bsi = bsi_for_stmt (use->stmt);
   tree ref;
+  bool ok;
 
-  get_computation_aff (data->current_loop, use, cand, use->stmt, &aff);
+  ok = get_computation_aff (data->current_loop, use, cand, use->stmt, &aff);
+  gcc_assert (ok);
   unshare_aff_combination (&aff);
 
   ref = create_mem_ref (&bsi, TREE_TYPE (*use->op_p), &aff);
@@ -5640,6 +5143,7 @@ rewrite_use_compare (struct ivopts_data *data,
   /* The induction variable elimination failed; just express the original
      giv.  */
   comp = get_computation (data->current_loop, use, cand);
+  gcc_assert (comp != NULL_TREE);
 
   cond = *use->op_p;
   op_p = &TREE_OPERAND (cond, 0);