OSDN Git Service

Use PIP to determine the integer feasibility of a constraint system.
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-sccvn.c
index ed56d1d..e37668e 100644 (file)
@@ -644,10 +644,11 @@ copy_reference_ops_from_ref (tree ref, VEC(vn_reference_op_s, heap) **result)
                  {
                    double_int off
                      = double_int_add (tree_to_double_int (this_offset),
-                                       double_int_sdiv
+                                       double_int_rshift
                                          (tree_to_double_int (bit_offset),
-                                          uhwi_to_double_int (BITS_PER_UNIT),
-                                          TRUNC_DIV_EXPR));
+                                          BITS_PER_UNIT == 8
+                                          ? 3 : exact_log2 (BITS_PER_UNIT),
+                                          HOST_BITS_PER_DOUBLE_INT, true));
                    if (double_int_fits_in_shwi_p (off))
                      temp.off = off.low;
                  }
@@ -1242,6 +1243,7 @@ vn_reference_lookup_1 (vn_reference_t vr, vn_reference_t *vnresult)
 }
 
 static tree *last_vuse_ptr;
+static vn_lookup_kind vn_walk_kind;
 
 /* Callback for walk_non_aliased_vuses.  Adjusts the vn_reference_t VR_
    with the current VUSE and performs the expression lookup.  */
@@ -1288,21 +1290,25 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_)
   tree fndecl;
   tree base;
   HOST_WIDE_INT offset, maxsize;
+  static VEC (vn_reference_op_s, heap) *lhs_ops = NULL;
+  ao_ref lhs_ref;
+  bool lhs_ref_ok = false;
 
   /* First try to disambiguate after value-replacing in the definitions LHS.  */
   if (is_gimple_assign (def_stmt))
     {
+      VEC (vn_reference_op_s, heap) *tem;
       tree lhs = gimple_assign_lhs (def_stmt);
-      ao_ref ref1;
-      VEC (vn_reference_op_s, heap) *operands = NULL;
-      bool res = true;
-      copy_reference_ops_from_ref (lhs, &operands);
-      operands = valueize_refs (operands);
-      if (ao_ref_init_from_vn_reference (&ref1, get_alias_set (lhs),
-                                        TREE_TYPE (lhs), operands))
-       res = refs_may_alias_p_1 (ref, &ref1, true);
-      VEC_free (vn_reference_op_s, heap, operands);
-      if (!res)
+      /* Avoid re-allocation overhead.  */
+      VEC_truncate (vn_reference_op_s, lhs_ops, 0);
+      copy_reference_ops_from_ref (lhs, &lhs_ops);
+      tem = lhs_ops;
+      lhs_ops = valueize_refs (lhs_ops);
+      gcc_assert (lhs_ops == tem);
+      lhs_ref_ok = ao_ref_init_from_vn_reference (&lhs_ref, get_alias_set (lhs),
+                                                 TREE_TYPE (lhs), lhs_ops);
+      if (lhs_ref_ok
+         && !refs_may_alias_p_1 (ref, &lhs_ref, true))
        return NULL;
     }
 
@@ -1334,11 +1340,12 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_)
       size2 = TREE_INT_CST_LOW (gimple_call_arg (def_stmt, 2)) * 8;
       if ((unsigned HOST_WIDE_INT)size2 / 8
          == TREE_INT_CST_LOW (gimple_call_arg (def_stmt, 2))
+         && maxsize2 != -1
          && operand_equal_p (base, base2, 0)
          && offset2 <= offset
          && offset2 + size2 >= offset + maxsize)
        {
-         tree val = fold_convert (vr->type, integer_zero_node);
+         tree val = build_zero_cst (vr->type);
          unsigned int value_id = get_or_alloc_constant_value_id (val);
          return vn_reference_insert_pieces (vuse, vr->set, vr->type,
                                             VEC_copy (vn_reference_op_s,
@@ -1357,11 +1364,12 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_)
       HOST_WIDE_INT offset2, size2, maxsize2;
       base2 = get_ref_base_and_extent (gimple_assign_lhs (def_stmt),
                                       &offset2, &size2, &maxsize2);
-      if (operand_equal_p (base, base2, 0)
+      if (maxsize2 != -1
+         && operand_equal_p (base, base2, 0)
          && offset2 <= offset
          && offset2 + size2 >= offset + maxsize)
        {
-         tree val = fold_convert (vr->type, integer_zero_node);
+         tree val = build_zero_cst (vr->type);
          unsigned int value_id = get_or_alloc_constant_value_id (val);
          return vn_reference_insert_pieces (vuse, vr->set, vr->type,
                                             VEC_copy (vn_reference_op_s,
@@ -1372,7 +1380,8 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_)
 
   /* For aggregate copies translate the reference through them if
      the copy kills ref.  */
-  else if (gimple_assign_single_p (def_stmt)
+  else if (vn_walk_kind == VN_WALKREWRITE
+          && gimple_assign_single_p (def_stmt)
           && (DECL_P (gimple_assign_rhs1 (def_stmt))
               || TREE_CODE (gimple_assign_rhs1 (def_stmt)) == MEM_REF
               || handled_component_p (gimple_assign_rhs1 (def_stmt))))
@@ -1380,32 +1389,37 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_)
       tree base2;
       HOST_WIDE_INT offset2, size2, maxsize2;
       int i, j;
-      VEC (vn_reference_op_s, heap) *lhs = NULL, *rhs = NULL;
+      VEC (vn_reference_op_s, heap) *rhs = NULL;
       vn_reference_op_t vro;
       ao_ref r;
 
+      if (!lhs_ref_ok)
+       return (void *)-1;
+
       /* See if the assignment kills REF.  */
-      base2 = get_ref_base_and_extent (gimple_assign_lhs (def_stmt),
-                                      &offset2, &size2, &maxsize2);
-      if (!operand_equal_p (base, base2, 0)
+      base2 = ao_ref_base (&lhs_ref);
+      offset2 = lhs_ref.offset;
+      size2 = lhs_ref.size;
+      maxsize2 = lhs_ref.max_size;
+      if (maxsize2 == -1
+         || (base != base2 && !operand_equal_p (base, base2, 0))
          || offset2 > offset
          || offset2 + size2 < offset + maxsize)
        return (void *)-1;
 
-      /* Find the common base of ref and the lhs.  */
-      copy_reference_ops_from_ref (gimple_assign_lhs (def_stmt), &lhs);
+      /* Find the common base of ref and the lhs.  lhs_ops already
+         contains valueized operands for the lhs.  */
       i = VEC_length (vn_reference_op_s, vr->operands) - 1;
-      j = VEC_length (vn_reference_op_s, lhs) - 1;
+      j = VEC_length (vn_reference_op_s, lhs_ops) - 1;
       while (j >= 0 && i >= 0
             && vn_reference_op_eq (VEC_index (vn_reference_op_s,
                                               vr->operands, i),
-                                   VEC_index (vn_reference_op_s, lhs, j)))
+                                   VEC_index (vn_reference_op_s, lhs_ops, j)))
        {
          i--;
          j--;
        }
 
-      VEC_free (vn_reference_op_s, heap, lhs);
       /* i now points to the first additional op.
         ???  LHS may not be completely contained in VR, one or more
         VIEW_CONVERT_EXPRs could be in its way.  We could at least
@@ -1461,7 +1475,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_)
 tree
 vn_reference_lookup_pieces (tree vuse, alias_set_type set, tree type,
                            VEC (vn_reference_op_s, heap) *operands,
-                           vn_reference_t *vnresult, bool maywalk)
+                           vn_reference_t *vnresult, vn_lookup_kind kind)
 {
   struct vn_reference_s vr1;
   vn_reference_t tmp;
@@ -1489,10 +1503,11 @@ vn_reference_lookup_pieces (tree vuse, alias_set_type set, tree type,
 
   vn_reference_lookup_1 (&vr1, vnresult);
   if (!*vnresult
-      && maywalk
+      && kind != VN_NOWALK
       && vr1.vuse)
     {
       ao_ref r;
+      vn_walk_kind = kind;
       if (ao_ref_init_from_vn_reference (&r, set, type, vr1.operands))
        *vnresult =
          (vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse,
@@ -1515,7 +1530,7 @@ vn_reference_lookup_pieces (tree vuse, alias_set_type set, tree type,
    stored in the hashtable if one exists.  */
 
 tree
-vn_reference_lookup (tree op, tree vuse, bool maywalk,
+vn_reference_lookup (tree op, tree vuse, vn_lookup_kind kind,
                     vn_reference_t *vnresult)
 {
   VEC (vn_reference_op_s, heap) *operands;
@@ -1533,12 +1548,13 @@ vn_reference_lookup (tree op, tree vuse, bool maywalk,
   if ((cst = fully_constant_vn_reference_p (&vr1)))
     return cst;
 
-  if (maywalk
+  if (kind != VN_NOWALK
       && vr1.vuse)
     {
       vn_reference_t wvnresult;
       ao_ref r;
       ao_ref_init (&r, op);
+      vn_walk_kind = kind;
       wvnresult =
        (vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse,
                                                vn_reference_lookup_2,
@@ -1708,10 +1724,16 @@ init_vn_nary_op_from_pieces (vn_nary_op_t vno, unsigned int length,
   vno->opcode = code;
   vno->length = length;
   vno->type = type;
-  vno->op[0] = op0;
-  vno->op[1] = op1;
-  vno->op[2] = op2;
-  vno->op[3] = op3;
+  switch (length)
+    {
+      /* The fallthrus here are deliberate.  */
+    case 4: vno->op[3] = op3;
+    case 3: vno->op[2] = op2;
+    case 2: vno->op[1] = op1;
+    case 1: vno->op[0] = op0;
+    default:
+      break;
+    }
 }
 
 /* Initialize VNO from OP.  */
@@ -2161,41 +2183,17 @@ visit_copy (tree lhs, tree rhs)
   return set_ssa_val_to (lhs, rhs);
 }
 
-/* Visit a unary operator RHS, value number it, and return true if the
+/* Visit a nary operator RHS, value number it, and return true if the
    value number of LHS has changed as a result.  */
 
 static bool
-visit_unary_op (tree lhs, gimple stmt)
+visit_nary_op (tree lhs, gimple stmt)
 {
   bool changed = false;
   tree result = vn_nary_op_lookup_stmt (stmt, NULL);
 
   if (result)
-    {
-      changed = set_ssa_val_to (lhs, result);
-    }
-  else
-    {
-      changed = set_ssa_val_to (lhs, lhs);
-      vn_nary_op_insert_stmt (stmt, lhs);
-    }
-
-  return changed;
-}
-
-/* Visit a binary operator RHS, value number it, and return true if the
-   value number of LHS has changed as a result.  */
-
-static bool
-visit_binary_op (tree lhs, gimple stmt)
-{
-  bool changed = false;
-  tree result = vn_nary_op_lookup_stmt (stmt, NULL);
-
-  if (result)
-    {
-      changed = set_ssa_val_to (lhs, result);
-    }
+    changed = set_ssa_val_to (lhs, result);
   else
     {
       changed = set_ssa_val_to (lhs, lhs);
@@ -2263,14 +2261,14 @@ visit_reference_op_load (tree lhs, tree op, gimple stmt)
 
   last_vuse = gimple_vuse (stmt);
   last_vuse_ptr = &last_vuse;
-  result = vn_reference_lookup (op, gimple_vuse (stmt), true, NULL);
+  result = vn_reference_lookup (op, gimple_vuse (stmt), VN_WALKREWRITE, NULL);
   last_vuse_ptr = NULL;
 
   /* If we have a VCE, try looking up its operand as it might be stored in
      a different type.  */
   if (!result && TREE_CODE (op) == VIEW_CONVERT_EXPR)
     result = vn_reference_lookup (TREE_OPERAND (op, 0), gimple_vuse (stmt),
-                                 true, NULL);
+                                 VN_WALKREWRITE, NULL);
 
   /* We handle type-punning through unions by value-numbering based
      on offset and size of the access.  Be prepared to handle a
@@ -2381,7 +2379,7 @@ visit_reference_op_store (tree lhs, tree op, gimple stmt)
      Otherwise, the vdefs for the store are used when inserting into
      the table, since the store generates a new memory state.  */
 
-  result = vn_reference_lookup (lhs, gimple_vuse (stmt), false, NULL);
+  result = vn_reference_lookup (lhs, gimple_vuse (stmt), VN_NOWALK, NULL);
 
   if (result)
     {
@@ -2903,10 +2901,9 @@ visit_use (tree use)
                  switch (get_gimple_rhs_class (gimple_assign_rhs_code (stmt)))
                    {
                    case GIMPLE_UNARY_RHS:
-                     changed = visit_unary_op (lhs, stmt);
-                     break;
                    case GIMPLE_BINARY_RHS:
-                     changed = visit_binary_op (lhs, stmt);
+                   case GIMPLE_TERNARY_RHS:
+                     changed = visit_nary_op (lhs, stmt);
                      break;
                    case GIMPLE_SINGLE_RHS:
                      switch (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)))
@@ -2915,10 +2912,10 @@ visit_use (tree use)
                          /* VOP-less references can go through unary case.  */
                          if ((gimple_assign_rhs_code (stmt) == REALPART_EXPR
                               || gimple_assign_rhs_code (stmt) == IMAGPART_EXPR
-                              || gimple_assign_rhs_code (stmt) == VIEW_CONVERT_EXPR )
+                              || gimple_assign_rhs_code (stmt) == VIEW_CONVERT_EXPR)
                              && TREE_CODE (TREE_OPERAND (gimple_assign_rhs1 (stmt), 0)) == SSA_NAME)
                            {
-                             changed = visit_unary_op (lhs, stmt);
+                             changed = visit_nary_op (lhs, stmt);
                              break;
                            }
                          /* Fallthrough.  */
@@ -2929,7 +2926,7 @@ visit_use (tree use)
                        case tcc_expression:
                          if (gimple_assign_rhs_code (stmt) == ADDR_EXPR)
                            {
-                             changed = visit_unary_op (lhs, stmt);
+                             changed = visit_nary_op (lhs, stmt);
                              break;
                            }
                          /* Fallthrough.  */
@@ -3038,10 +3035,7 @@ compare_ops (const void *pa, const void *pb)
 static void
 sort_scc (VEC (tree, heap) *scc)
 {
-  qsort (VEC_address (tree, scc),
-        VEC_length (tree, scc),
-        sizeof (tree),
-        compare_ops);
+  VEC_qsort (tree, scc, compare_ops);
 }
 
 /* Insert the no longer used nary ONARY to the hash INFO.  */
@@ -3105,9 +3099,20 @@ process_scc (VEC (tree, heap) *scc)
   if (VEC_length (tree, scc) == 1)
     {
       tree use = VEC_index (tree, scc, 0);
-      if (!VN_INFO (use)->use_processed)
-       visit_use (use);
-      return;
+      if (VN_INFO (use)->use_processed)
+       return;
+      /* We need to make sure it doesn't form a cycle itself, which can
+        happen for self-referential PHI nodes.  In that case we would
+        end up inserting an expression with VN_TOP operands into the
+        valid table which makes us derive bogus equivalences later.
+        The cheapest way to check this is to assume it for all PHI nodes.  */
+      if (gimple_code (SSA_NAME_DEF_STMT (use)) == GIMPLE_PHI)
+       /* Fallthru to iteration.  */ ;
+      else
+       {
+         visit_use (use);
+         return;
+       }
     }
 
   /* Iterate over the SCC with the optimistic table until it stops