a-clrefi.adb, [...]: New files
[gcc.git] / gcc / gimplify.c
index 0b6ec34d97471dc946aba2fc54bff697b7f2fa28..e73e00ae9ae959eafd11ee571b0b256600dc83dd 100644 (file)
@@ -1617,6 +1617,7 @@ canonicalize_addr_expr (tree *expr_p)
 static enum gimplify_status
 gimplify_conversion (tree *expr_p)
 {
+  tree tem;
   gcc_assert (TREE_CODE (*expr_p) == NOP_EXPR
              || TREE_CODE (*expr_p) == CONVERT_EXPR);
   
@@ -1627,6 +1628,17 @@ 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 (TREE_CODE (*expr_p) == NOP_EXPR
+      && POINTER_TYPE_P (TREE_TYPE (*expr_p))
+      && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (*expr_p, 0)))
+      && (tem = maybe_fold_offset_to_reference
+                 (TREE_OPERAND (*expr_p, 0),
+                  integer_zero_node, TREE_TYPE (TREE_TYPE (*expr_p)))))
+    *expr_p = build_fold_addr_expr_with_type (tem, TREE_TYPE (*expr_p));
+
   /* If we still have a conversion at the toplevel,
      then canonicalize some constructs.  */
   if (TREE_CODE (*expr_p) == NOP_EXPR || TREE_CODE (*expr_p) == CONVERT_EXPR)
@@ -5296,7 +5308,8 @@ gimplify_omp_atomic_pipeline (tree *expr_p, tree *pre_p, tree addr,
      floating point.  This allows the atomic operation to properly 
      succeed even with NaNs and -0.0.  */
   x = build3 (COND_EXPR, void_type_node,
-             build2 (NE_EXPR, boolean_type_node, oldival, oldival2),
+             build2 (NE_EXPR, boolean_type_node,
+                     fold_convert (itype, oldival), oldival2),
              build1 (GOTO_EXPR, void_type_node, label), NULL);
   gimplify_and_add (x, pre_p);
 
@@ -5857,6 +5870,38 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
          ret = GS_ALL_DONE;
          break;
 
+       case 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 (POINTER_TYPE_P (TREE_TYPE (*expr_p))
+             && TREE_CODE (TREE_OPERAND (*expr_p, 1)) == INTEGER_CST
+             && (tmp = maybe_fold_offset_to_reference
+                        (TREE_OPERAND (*expr_p, 0), TREE_OPERAND (*expr_p, 1),
+                         TREE_TYPE (TREE_TYPE (*expr_p)))))
+            {
+               *expr_p = build_fold_addr_expr_with_type (tmp,
+                                                        TREE_TYPE (*expr_p));
+              break;
+            }
+         /* Convert (void *)&a + 4 into (void *)&a[1].  */
+         if (POINTER_TYPE_P (TREE_TYPE (*expr_p))
+             && 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_reference
+                        (TREE_OPERAND (TREE_OPERAND (*expr_p, 0), 0),
+                         TREE_OPERAND (*expr_p, 1),
+                         TREE_TYPE (TREE_TYPE
+                                 (TREE_OPERAND (TREE_OPERAND (*expr_p, 0),
+                                                0))))))
+            {
+               tmp = build_fold_addr_expr (tmp);
+               *expr_p = fold_convert (TREE_TYPE (*expr_p), tmp);
+              break;
+            }
+          /* FALLTHRU */
        default:
          switch (TREE_CODE_CLASS (TREE_CODE (*expr_p)))
            {