This is the mail archive of the
mailing list for the GCC project.
[PATCH/RFC] Start to use VIEW_CONVERT_EXPR more and start to fix PR 26069
- From: Andrew Pinski <pinskia at physics dot uc dot edu>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 04 Sep 2006 17:17:30 -0700
- Subject: [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;
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;"
2 is important for the following testcase:
int f(short a)
unsigned short b;
*(short*)&b = a;
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.
* 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.
--- 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. */
+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
@@ -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) => __imag__ complexfoo */
--- gimplify.c (revision 116671)
+++ gimplify.c (working copy)
@@ -3519,6 +3519,26 @@ gimplify_modify_expr (tree *expr_p, tree
+ /* 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),
+ *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,
--- tree-ssa-operands.c (revision 116671)
+++ tree-ssa-operands.c (working copy)
@@ -1843,6 +1843,11 @@ get_expr_operands (tree stmt, tree *expr
+ case VIEW_CONVERT_EXPR:
+ if (flags & opf_is_def)
+ add_to_addressable_set (TREE_OPERAND (expr, 0), &s_ann->addresses_taken);
+ goto do_unary;
/* 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 VIEW_CONVERT_EXPR:
get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags);