aboutsummaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2005-07-26 07:34:58 +0000
committerRichard Guenther <rguenther@suse.de>2005-07-26 07:34:58 +0000
commitaa55d12948e62c67539b091832ccaa5d10a26d13 (patch)
tree0c96be52bba7fbb40aef73b7e70cfd92198df875 /gcc/fold-const.c
parent60368d8a9f15cfed3699a822b11abe8b6aa70583 (diff)
2005-07-26 Richard Guenther <rguenther@suse.de>
PR tree-optimization/22486 * fold-const.c (fold_unary): Fold away useless component references of the form (T *)&T.x, if the address doesn't change. * gcc.dg/tree-ssa/upcast-1.c: New testcase. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@102381 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 9a9ea2246c0..bdda6001078 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -6711,6 +6711,29 @@ fold_unary (enum tree_code code, tree type, tree op0)
return fold_build1 (code, type, TREE_OPERAND (op0, 0));
}
+ /* Handle (T *)&A.B.C for A being of type T and B and C
+ living at offset zero. This occours frequently in
+ C++ upcasting and then accessing the base. */
+ if (TREE_CODE (op0) == ADDR_EXPR
+ && POINTER_TYPE_P (type)
+ && handled_component_p (TREE_OPERAND (op0, 0)))
+ {
+ HOST_WIDE_INT bitsize, bitpos;
+ tree offset;
+ enum machine_mode mode;
+ int unsignedp, volatilep;
+ tree base = TREE_OPERAND (op0, 0);
+ base = get_inner_reference (base, &bitsize, &bitpos, &offset,
+ &mode, &unsignedp, &volatilep, false);
+ /* If the reference was to a (constant) zero offset, we can use
+ the address of the base if it has the same base type
+ as the result type. */
+ if (! offset && bitpos == 0
+ && TYPE_MAIN_VARIANT (TREE_TYPE (type))
+ == TYPE_MAIN_VARIANT (TREE_TYPE (base)))
+ return fold_convert (type, build_fold_addr_expr (base));
+ }
+
if (TREE_CODE (op0) == MODIFY_EXPR
&& TREE_CONSTANT (TREE_OPERAND (op0, 1))
/* Detect assigning a bitfield. */