This is the mail archive of the 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]

[PATCH/RFC] Start to use VIEW_CONVERT_EXPR more and start to fix PR 26069

The problem with PR 26069 is that we removed address_of rtl which
removed a small set of optimizations which were done.
One example is:
int f(short a)
  unsigned short b = *(unsigned short*)&a;
  return b;
We don't really need to store a in memory to get the value from a.

What this patch is three things:
1) Add to fold_indirect_ref_1, folding of *(unsigned short*)&a into
   VIEW_CONVERT<unsigned short>a when the type sizes are the same and
   the aliasing sets are the same.
2) Have the gimplifier swap which side of a MODIFY_EXPR, the VIEW_CONVERT_EXPR
   is on.  This helps because otherwise a in "VIEW_CONVERT_EXPR<int> a = b;" needs
   to be addressable.
3) Fix a bug in tree-ssa-operands which does not mark a in "VIEW_CONVERT <int> a = b;"
   as addressable.

2 is important for the following testcase:
int f(short a)
  unsigned short b;
  *(short*)&b = a;
  return b;

If we don't have 2 here, then we lose and still make b addressable
and store it to the stack.

The one question I have about 1 is should we ignore the aliasing set and always
do this transformation even though we know we turn undefined code into defined code?
Right now I check the aliasing sets but I don't see there is a good reason to.

This is only a small step in getting PR 26069 fixed because that bug has different
sizes when dealing with the types.

OK for the mainline (yes the testcases above are a regression from 3.4.0)?
Bootstrapped and tested on i686-linux-gnu.

Andrew Pinski

	* fold-const.c (fold_indirect_ref_to_vce): New function.
	(fold_indirect_ref_1): Use it.
	* gimplify.c (gimplify_modify_expr): Fold the indirect ref in lhs.
	If we have a VIEW_CONVERT_EXPR on the lhs, try to move it to the
	* tree-ssa-operands (get_expr_operands <case VIEW_CONVERT_EXPR>):
	If the flags include opf_is_def, mark the first operand as addressable.

Index: fold-const.c
--- fold-const.c	(revision 116671)
+++ fold-const.c	(working copy)
@@ -12647,6 +12647,33 @@ build_fold_addr_expr (tree t)
   return build_fold_addr_expr_with_type (t, build_pointer_type (TREE_TYPE (t)));
+/* Given an addr_expr of INNEREXPR, try to convert an indirect reference of
+   this with a type of OUTERTYPE into a view_convert_expr.  */
+static tree
+fold_indirect_ref_to_vce (tree outertype, tree innerexpr)
+  tree innertype = TREE_TYPE (innerexpr);
+  tree sizeouter = TYPE_SIZE (outertype);
+  tree sizeinner = TYPE_SIZE (innertype);
+  if (sizeouter == NULL_TREE
+      || sizeinner == NULL_TREE)
+    return NULL_TREE;
+  /* FIXME: Should we really take into aliasing sets? */
+  /* Simple conversion, the types sizes are the same and so are the
+     aliasing sets or the outer's aliasing set is 0.  */
+  if (!TYPE_VOLATILE (outertype)
+      && simple_cst_equal (sizeouter, sizeinner)
+      && (!get_alias_set (outertype)
+          || get_alias_set (outertype) == get_alias_set (innertype)))
+    return fold_build1 (VIEW_CONVERT_EXPR, outertype, innerexpr);
+  return NULL_TREE;
 /* Given a pointer value OP0 and a type TYPE, return a simplified version
    of an indirection through OP0, or NULL_TREE if no simplification is
    possible.  */
@@ -12666,6 +12693,7 @@ fold_indirect_ref_1 (tree type, tree op0
       tree op = TREE_OPERAND (sub, 0);
       tree optype = TREE_TYPE (op);
+      tree tmp;
       /* *&p => p;  make sure to handle *&"str"[cst] here.  */
       if (type == optype)
@@ -12689,6 +12717,8 @@ fold_indirect_ref_1 (tree type, tree op0
       else if (TREE_CODE (optype) == COMPLEX_TYPE
 	       && type == TREE_TYPE (optype))
 	return fold_build1 (REALPART_EXPR, type, op);
+      else if ((tmp = fold_indirect_ref_to_vce (type, op)) != NULL_TREE)
+	return tmp;
   /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */
Index: gimplify.c
--- gimplify.c	(revision 116671)
+++ gimplify.c	(working copy)
@@ -3519,6 +3519,26 @@ gimplify_modify_expr (tree *expr_p, tree
       return GS_ALL_DONE;
+  /* Do the folding of the indirect reference so we can try to optimize
+     VCEs.  */
+  if (TREE_CODE (*to_p) == INDIRECT_REF)
+      *to_p = fold_indirect_ref (*to_p);
+  /*  For VCE<type> a = b, it is better that we have a = VCE<othertype> b.
+      Do this for types which don't have placeholder expressions in them.  */
+  if (TREE_CODE (*to_p) == VIEW_CONVERT_EXPR 
+      && !type_contains_placeholder_p (TREE_TYPE (TREE_OPERAND (*to_p, 0)))
+      && simple_cst_equal (TYPE_SIZE (TREE_TYPE (*to_p)),
+			   TYPE_SIZE (TREE_TYPE (TREE_OPERAND (*to_p, 0)))))
+    {
+      tree inner = TREE_OPERAND (*to_p, 0);
+      tree otherside = *from_p;
+      otherside = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (inner),
+			       otherside);
+      *to_p = inner;
+      *from_p = otherside;
+    }
   /* See if any simplifications can be done based on what the RHS is.  */
   ret = gimplify_modify_expr_rhs (expr_p, from_p, to_p, pre_p, post_p,
Index: tree-ssa-operands.c
--- tree-ssa-operands.c	(revision 116671)
+++ tree-ssa-operands.c	(working copy)
@@ -1843,6 +1843,11 @@ get_expr_operands (tree stmt, tree *expr
   switch (code)
+      if (flags & opf_is_def)
+        add_to_addressable_set (TREE_OPERAND (expr, 0), &s_ann->addresses_taken);
+      goto do_unary;
     case ADDR_EXPR:
       /* Taking the address of a variable does not represent a
 	 reference to it, but the fact that the statement takes its
@@ -2018,7 +2023,6 @@ get_expr_operands (tree stmt, tree *expr
       /* Fallthru  */
     case TRUTH_NOT_EXPR:
       get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags);

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