OSDN Git Service

PR bootstrap/50665
[pf3gnuchains/gcc-fork.git] / gcc / gimplify.c
index 4ff7e93..9713218 100644 (file)
@@ -1329,8 +1329,9 @@ gimplify_vla_decl (tree decl, gimple_seq *seq_p)
   SET_DECL_VALUE_EXPR (decl, t);
   DECL_HAS_VALUE_EXPR_P (decl) = 1;
 
-  t = built_in_decls[BUILT_IN_ALLOCA];
-  t = build_call_expr (t, 1, DECL_SIZE_UNIT (decl));
+  t = built_in_decls[BUILT_IN_ALLOCA_WITH_ALIGN];
+  t = build_call_expr (t, 2, DECL_SIZE_UNIT (decl),
+                      size_int (DECL_ALIGN (decl)));
   /* The call has been built for a variable-sized object.  */
   CALL_ALLOCA_FOR_VAR_P (t) = 1;
   t = fold_convert (ptr_type, t);
@@ -1799,7 +1800,6 @@ canonicalize_addr_expr (tree *expr_p)
 static enum gimplify_status
 gimplify_conversion (tree *expr_p)
 {
-  tree tem;
   location_t loc = EXPR_LOCATION (*expr_p);
   gcc_assert (CONVERT_EXPR_P (*expr_p));
 
@@ -1810,17 +1810,6 @@ gimplify_conversion (tree *expr_p)
   if (tree_ssa_useless_type_conversion (*expr_p))
     *expr_p = TREE_OPERAND (*expr_p, 0);
 
-  /* Attempt to avoid NOP_EXPR by producing reference to a subtype.
-     For example this fold (subclass *)&A into &A->subclass avoiding
-     a need for statement.  */
-  if (CONVERT_EXPR_P (*expr_p)
-      && POINTER_TYPE_P (TREE_TYPE (*expr_p))
-      && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (*expr_p, 0)))
-      && (tem = maybe_fold_offset_to_address
-         (EXPR_LOCATION (*expr_p), TREE_OPERAND (*expr_p, 0),
-          integer_zero_node, TREE_TYPE (*expr_p))) != NULL_TREE)
-    *expr_p = tem;
-
   /* If we still have a conversion at the toplevel,
      then canonicalize some constructs.  */
   if (CONVERT_EXPR_P (*expr_p))
@@ -2208,7 +2197,7 @@ gimplify_self_mod_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
   /* For POINTERs increment, use POINTER_PLUS_EXPR.  */
   if (POINTER_TYPE_P (TREE_TYPE (lhs)))
     {
-      rhs = fold_convert_loc (loc, sizetype, rhs);
+      rhs = convert_to_ptrofftype_loc (loc, rhs);
       if (arith_code == MINUS_EXPR)
        rhs = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (rhs), rhs);
       arith_code = POINTER_PLUS_EXPR;
@@ -2860,18 +2849,23 @@ gimple_boolify (tree expr)
 
     case TRUTH_NOT_EXPR:
       TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
-      /* FALLTHRU */
 
-    case EQ_EXPR: case NE_EXPR:
-    case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:
       /* These expressions always produce boolean results.  */
-      TREE_TYPE (expr) = boolean_type_node;
+      if (TREE_CODE (type) != BOOLEAN_TYPE)
+       TREE_TYPE (expr) = boolean_type_node;
       return expr;
 
     default:
+      if (COMPARISON_CLASS_P (expr))
+       {
+         /* There expressions always prduce boolean results.  */
+         if (TREE_CODE (type) != BOOLEAN_TYPE)
+           TREE_TYPE (expr) = boolean_type_node;
+         return expr;
+       }
       /* Other expressions that get here must have boolean values, but
         might need to be converted to the appropriate mode.  */
-      if (type == boolean_type_node)
+      if (TREE_CODE (type) == BOOLEAN_TYPE)
        return expr;
       return fold_convert_loc (loc, boolean_type_node, expr);
     }
@@ -3731,9 +3725,8 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
     case ARRAY_TYPE:
       {
        struct gimplify_init_ctor_preeval_data preeval_data;
-       HOST_WIDE_INT num_type_elements, num_ctor_elements;
-       HOST_WIDE_INT num_nonzero_elements;
-       bool cleared, valid_const_initializer;
+       HOST_WIDE_INT num_ctor_elements, num_nonzero_elements;
+       bool cleared, complete_p, valid_const_initializer;
 
        /* Aggregate types must lower constructors to initialization of
           individual elements.  The exception is that a CONSTRUCTOR node
@@ -3750,7 +3743,7 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
           can only do so if it known to be a valid constant initializer.  */
        valid_const_initializer
          = categorize_ctor_elements (ctor, &num_nonzero_elements,
-                                     &num_ctor_elements, &cleared);
+                                     &num_ctor_elements, &complete_p);
 
        /* If a const aggregate variable is being initialized, then it
           should never be a lose to promote the variable to be static.  */
@@ -3788,26 +3781,29 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
           parts in, then generate code for the non-constant parts.  */
        /* TODO.  There's code in cp/typeck.c to do this.  */
 
-       num_type_elements = count_type_elements (type, true);
-
-       /* If count_type_elements could not determine number of type elements
-          for a constant-sized object, assume clearing is needed.
-          Don't do this for variable-sized objects, as store_constructor
-          will ignore the clearing of variable-sized objects.  */
-       if (num_type_elements < 0 && int_size_in_bytes (type) >= 0)
+       if (int_size_in_bytes (TREE_TYPE (ctor)) < 0)
+         /* store_constructor will ignore the clearing of variable-sized
+            objects.  Initializers for such objects must explicitly set
+            every field that needs to be set.  */
+         cleared = false;
+       else if (!complete_p)
+         /* If the constructor isn't complete, clear the whole object
+            beforehand.
+
+            ??? This ought not to be needed.  For any element not present
+            in the initializer, we should simply set them to zero.  Except
+            we'd need to *find* the elements that are not present, and that
+            requires trickery to avoid quadratic compile-time behavior in
+            large cases or excessive memory use in small cases.  */
          cleared = true;
-       /* If there are "lots" of zeros, then block clear the object first.  */
-       else if (num_type_elements - num_nonzero_elements
+       else if (num_ctor_elements - num_nonzero_elements
                 > CLEAR_RATIO (optimize_function_for_speed_p (cfun))
-                && num_nonzero_elements < num_type_elements/4)
-         cleared = true;
-       /* ??? This bit ought not be needed.  For any element not present
-          in the initializer, we should simply set them to zero.  Except
-          we'd need to *find* the elements that are not present, and that
-          requires trickery to avoid quadratic compile-time behavior in
-          large cases or excessive memory use in small cases.  */
-       else if (num_ctor_elements < num_type_elements)
+                && num_nonzero_elements < num_ctor_elements / 4)
+         /* If there are "lots" of zeros, it's more efficient to clear
+            the memory and then set the nonzero elements.  */
          cleared = true;
+       else
+         cleared = false;
 
        /* If there are "lots" of initialized elements, and all of them
           are valid address constants, then the entire initializer can
@@ -4476,6 +4472,7 @@ gimplify_modify_expr_complex_part (tree *expr_p, gimple_seq *pre_p,
 
   ocode = code == REALPART_EXPR ? IMAGPART_EXPR : REALPART_EXPR;
   other = build1 (ocode, TREE_TYPE (rhs), lhs);
+  TREE_NO_WARNING (other) = 1;
   other = get_formal_tmp_var (other, pre_p);
 
   realpart = code == REALPART_EXPR ? rhs : other;
@@ -5925,6 +5922,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
            }
          break;
 
+       case OMP_CLAUSE_FINAL:
        case OMP_CLAUSE_IF:
          OMP_CLAUSE_OPERAND (c, 0)
            = gimple_boolify (OMP_CLAUSE_OPERAND (c, 0));
@@ -5941,6 +5939,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
        case OMP_CLAUSE_ORDERED:
        case OMP_CLAUSE_UNTIED:
        case OMP_CLAUSE_COLLAPSE:
+       case OMP_CLAUSE_MERGEABLE:
          break;
 
        case OMP_CLAUSE_DEFAULT:
@@ -6081,6 +6080,8 @@ gimplify_adjust_omp_clauses (tree *list_p)
        case OMP_CLAUSE_DEFAULT:
        case OMP_CLAUSE_UNTIED:
        case OMP_CLAUSE_COLLAPSE:
+       case OMP_CLAUSE_FINAL:
+       case OMP_CLAUSE_MERGEABLE:
          break;
 
        default:
@@ -6451,6 +6452,13 @@ goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr,
          saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
                                         lhs_addr, lhs_var);
          break;
+       case COMPOUND_EXPR:
+         /* Break out any preevaluations from cp_build_modify_expr.  */
+         for (; TREE_CODE (expr) == COMPOUND_EXPR;
+              expr = TREE_OPERAND (expr, 1))
+           gimplify_stmt (&TREE_OPERAND (expr, 0), pre_p);
+         *expr_p = expr;
+         return goa_stabilize_expr (expr_p, pre_p, lhs_addr, lhs_var);
        default:
          break;
        }
@@ -6476,24 +6484,45 @@ static enum gimplify_status
 gimplify_omp_atomic (tree *expr_p, gimple_seq *pre_p)
 {
   tree addr = TREE_OPERAND (*expr_p, 0);
-  tree rhs = TREE_OPERAND (*expr_p, 1);
+  tree rhs = TREE_CODE (*expr_p) == OMP_ATOMIC_READ
+            ? NULL : TREE_OPERAND (*expr_p, 1);
   tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
   tree tmp_load;
+  gimple loadstmt, storestmt;
 
-   tmp_load = create_tmp_reg (type, NULL);
-   if (goa_stabilize_expr (&rhs, pre_p, addr, tmp_load) < 0)
-     return GS_ERROR;
+  tmp_load = create_tmp_reg (type, NULL);
+  if (rhs && goa_stabilize_expr (&rhs, pre_p, addr, tmp_load) < 0)
+    return GS_ERROR;
 
-   if (gimplify_expr (&addr, pre_p, NULL, is_gimple_val, fb_rvalue)
-       != GS_ALL_DONE)
-     return GS_ERROR;
+  if (gimplify_expr (&addr, pre_p, NULL, is_gimple_val, fb_rvalue)
+      != GS_ALL_DONE)
+    return GS_ERROR;
 
-   gimplify_seq_add_stmt (pre_p, gimple_build_omp_atomic_load (tmp_load, addr));
-   if (gimplify_expr (&rhs, pre_p, NULL, is_gimple_val, fb_rvalue)
-       != GS_ALL_DONE)
-     return GS_ERROR;
-   gimplify_seq_add_stmt (pre_p, gimple_build_omp_atomic_store (rhs));
-   *expr_p = NULL;
+  loadstmt = gimple_build_omp_atomic_load (tmp_load, addr);
+  gimplify_seq_add_stmt (pre_p, loadstmt);
+  if (rhs && gimplify_expr (&rhs, pre_p, NULL, is_gimple_val, fb_rvalue)
+      != GS_ALL_DONE)
+    return GS_ERROR;
+
+  if (TREE_CODE (*expr_p) == OMP_ATOMIC_READ)
+    rhs = tmp_load;
+  storestmt = gimple_build_omp_atomic_store (rhs);
+  gimplify_seq_add_stmt (pre_p, storestmt);
+  switch (TREE_CODE (*expr_p))
+    {
+    case OMP_ATOMIC_READ:
+    case OMP_ATOMIC_CAPTURE_OLD:
+      *expr_p = tmp_load;
+      gimple_omp_atomic_set_need_value (loadstmt);
+      break;
+    case OMP_ATOMIC_CAPTURE_NEW:
+      *expr_p = rhs;
+      gimple_omp_atomic_set_need_value (storestmt);
+      break;
+    default:
+      *expr_p = NULL;
+      break;
+    }
 
    return GS_ALL_DONE;
 }
@@ -6764,13 +6793,13 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
               source location of the outer expression.  */
            tree org_type = TREE_TYPE (*expr_p);
            *expr_p = gimple_boolify (*expr_p);
-           *expr_p = build3_loc (saved_location, COND_EXPR,
+           *expr_p = build3_loc (input_location, COND_EXPR,
                                  org_type, *expr_p,
                                  fold_convert_loc
-                                   (saved_location,
+                                   (input_location,
                                     org_type, boolean_true_node),
                                  fold_convert_loc
-                                   (saved_location,
+                                   (input_location,
                                     org_type, boolean_false_node));
            ret = GS_OK;
            break;
@@ -6778,22 +6807,27 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 
        case TRUTH_NOT_EXPR:
          {
-           tree org_type = TREE_TYPE (*expr_p);
-
+           tree type = TREE_TYPE (*expr_p);
+           /* The parsers are careful to generate TRUTH_NOT_EXPR
+              only with operands that are always zero or one.
+              We do not fold here but handle the only interesting case
+              manually, as fold may re-introduce the TRUTH_NOT_EXPR.  */
            *expr_p = gimple_boolify (*expr_p);
-           if (org_type != boolean_type_node)
-             {
-               *expr_p = fold_convert (org_type, *expr_p);
-               ret = GS_OK;
-               break;
-             }
+           if (TYPE_PRECISION (TREE_TYPE (*expr_p)) == 1)
+             *expr_p = build1_loc (input_location, BIT_NOT_EXPR,
+                                   TREE_TYPE (*expr_p),
+                                   TREE_OPERAND (*expr_p, 0));
+           else
+             *expr_p = build2_loc (input_location, BIT_XOR_EXPR,
+                                   TREE_TYPE (*expr_p),
+                                   TREE_OPERAND (*expr_p, 0),
+                                   build_int_cst (TREE_TYPE (*expr_p), 1));
+           if (!useless_type_conversion_p (type, TREE_TYPE (*expr_p)))
+             *expr_p = fold_convert_loc (input_location, type, *expr_p);
+           ret = GS_OK;
+           break;
          }
 
-         ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
-                              is_gimple_val, fb_rvalue);
-         recalculate_side_effects (*expr_p);
-         break;
-
        case ADDR_EXPR:
          ret = gimplify_addr_expr (expr_p, pre_p, post_p);
          break;
@@ -7211,6 +7245,9 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
          }
 
        case OMP_ATOMIC:
+       case OMP_ATOMIC_READ:
+       case OMP_ATOMIC_CAPTURE_OLD:
+       case OMP_ATOMIC_CAPTURE_NEW:
          ret = gimplify_omp_atomic (expr_p, pre_p);
          break;
 
@@ -7218,76 +7255,70 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
        case TRUTH_OR_EXPR:
        case TRUTH_XOR_EXPR:
          {
-           tree org_type = TREE_TYPE (*expr_p);
-           
+           tree orig_type = TREE_TYPE (*expr_p);
            *expr_p = gimple_boolify (*expr_p);
-
-           /* This shouldn't happen, but due fold-const (and here especially
-              fold_truth_not_expr) happily uses operand type and doesn't
-              automatically uses boolean_type as result, we need to keep
-              orignal type.  */
-           if (org_type != boolean_type_node)
+           if (!useless_type_conversion_p (orig_type, TREE_TYPE (*expr_p)))
              {
-               *expr_p = fold_convert (org_type, *expr_p);
+               *expr_p = fold_convert_loc (input_location, orig_type, *expr_p);
                ret = GS_OK;
                break;
              }
-         }
 
-         /* With two-valued operand types binary truth expressions are
-            semantically equivalent to bitwise binary expressions.  Canonicalize
-            them to the bitwise variant.  */   switch (TREE_CODE (*expr_p))
-         {
-         case TRUTH_AND_EXPR:
-           TREE_SET_CODE (*expr_p, BIT_AND_EXPR);
-           break;
-         case TRUTH_OR_EXPR:
-           TREE_SET_CODE (*expr_p, BIT_IOR_EXPR);
-           break;
-         case TRUTH_XOR_EXPR:
-           TREE_SET_CODE (*expr_p, BIT_XOR_EXPR);
-           break;
-         default:
-           break;
+         /* Boolified binary truth expressions are semantically equivalent
+            to bitwise binary expressions.  Canonicalize them to the
+            bitwise variant.  */
+           switch (TREE_CODE (*expr_p))
+             {
+             case TRUTH_AND_EXPR:
+               TREE_SET_CODE (*expr_p, BIT_AND_EXPR);
+               break;
+             case TRUTH_OR_EXPR:
+               TREE_SET_CODE (*expr_p, BIT_IOR_EXPR);
+               break;
+             case TRUTH_XOR_EXPR:
+               TREE_SET_CODE (*expr_p, BIT_XOR_EXPR);
+               break;
+             default:
+               break;
+             }
+
+           /* Continue classified as tcc_binary.  */
+           goto expr_2;
          }
-         /* Classified as tcc_expression.  */
-         goto expr_2;
 
        case FMA_EXPR:
+       case VEC_PERM_EXPR:
          /* Classified as tcc_expression.  */
          goto expr_3;
 
        case POINTER_PLUS_EXPR:
-          /* Convert ((type *)A)+offset into &A->field_of_type_and_offset.
-            The second is gimple immediate saving a need for extra statement.
-          */
-         if (TREE_CODE (TREE_OPERAND (*expr_p, 1)) == INTEGER_CST
-             && (tmp = maybe_fold_offset_to_address
-                 (EXPR_LOCATION (*expr_p),
-                  TREE_OPERAND (*expr_p, 0), TREE_OPERAND (*expr_p, 1),
-                  TREE_TYPE (*expr_p))))
-           {
-             *expr_p = tmp;
-             ret = GS_OK;
-             break;
-           }
-         /* Convert (void *)&a + 4 into (void *)&a[1].  */
-         if (TREE_CODE (TREE_OPERAND (*expr_p, 0)) == NOP_EXPR
-             && TREE_CODE (TREE_OPERAND (*expr_p, 1)) == INTEGER_CST
-             && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (*expr_p,
-                                                                       0),0)))
-             && (tmp = maybe_fold_offset_to_address
-                 (EXPR_LOCATION (*expr_p),
-                  TREE_OPERAND (TREE_OPERAND (*expr_p, 0), 0),
-                  TREE_OPERAND (*expr_p, 1),
-                  TREE_TYPE (TREE_OPERAND (TREE_OPERAND (*expr_p, 0),
-                                           0)))))
-            {
-               *expr_p = fold_convert (TREE_TYPE (*expr_p), tmp);
-              ret = GS_OK;
-              break;
-            }
-          /* FALLTHRU */
+         {
+           enum gimplify_status r0, r1;
+           r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
+                               post_p, is_gimple_val, fb_rvalue);
+           r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
+                               post_p, is_gimple_val, fb_rvalue);
+           recalculate_side_effects (*expr_p);
+           ret = MIN (r0, r1);
+           /* Convert &X + CST to invariant &MEM[&X, CST].  Do this
+              after gimplifying operands - this is similar to how
+              it would be folding all gimplified stmts on creation
+              to have them canonicalized, which is what we eventually
+              should do anyway.  */
+           if (TREE_CODE (TREE_OPERAND (*expr_p, 1)) == INTEGER_CST
+               && is_gimple_min_invariant (TREE_OPERAND (*expr_p, 0)))
+             {
+               *expr_p = build_fold_addr_expr_with_type_loc
+                  (input_location,
+                   fold_build2 (MEM_REF, TREE_TYPE (TREE_TYPE (*expr_p)),
+                                TREE_OPERAND (*expr_p, 0),
+                                fold_convert (ptr_type_node,
+                                              TREE_OPERAND (*expr_p, 1))),
+                   TREE_TYPE (*expr_p));
+               ret = MIN (ret, GS_OK);
+             }
+           break;
+         }
 
        default:
          switch (TREE_CODE_CLASS (TREE_CODE (*expr_p)))
@@ -7305,8 +7336,23 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
                {
                  tree type = TREE_TYPE (TREE_OPERAND (*expr_p, 1));
 
-                 if (!AGGREGATE_TYPE_P (type))
+                 /* Vector comparisons need no boolification.  */
+                 if (TREE_CODE (type) == VECTOR_TYPE)
                    goto expr_2;
+                 else if (!AGGREGATE_TYPE_P (type))
+                   {
+                     tree org_type = TREE_TYPE (*expr_p);
+                     *expr_p = gimple_boolify (*expr_p);
+                     if (!useless_type_conversion_p (org_type,
+                                                     TREE_TYPE (*expr_p)))
+                       {
+                         *expr_p = fold_convert_loc (input_location,
+                                                     org_type, *expr_p);
+                         ret = GS_OK;
+                       }
+                     else
+                       goto expr_2;
+                   }
                  else if (TYPE_MODE (type) != BLKmode)
                    ret = gimplify_scalar_mode_aggregate_compare (expr_p);
                  else