aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/fold-const.c15
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/foldcast-1.c16
4 files changed, 44 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 35226d1..31f6974 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,15 @@
+2006-05-11 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/27529
+ * fold-const.c (fold_unary): Handle intermediate conversion
+ to a pointer type like intermediate conversion to an integer
+ type in folding of (T1)(T2)var to var.
+ Match the code to the comment in the final conversion for
+ (T1)(T2)var to (T1)var regarding to type precision. Rather
+ than disallow T1 being of pointer type, assert that both T1
+ and var are of pointer type or not. Make sure not to fall
+ over the frontends lazyness wrt array to pointer decay though.
+
2006-05-10 Richard Earnshaw <rearnsha@arm.com>
* arm.c (arm_struct_value_rtx): Delete.
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 030bcb1..ce68929 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -7323,7 +7323,8 @@ fold_unary (enum tree_code code, tree type, tree op0)
type via an object of identical or wider precision, neither
conversion is needed. */
if (TYPE_MAIN_VARIANT (inside_type) == TYPE_MAIN_VARIANT (type)
- && ((inter_int && final_int) || (inter_float && final_float))
+ && (((inter_int || inter_ptr) && final_int)
+ || (inter_float && final_float))
&& inter_prec >= final_prec)
return fold_build1 (code, type, TREE_OPERAND (op0, 0));
@@ -7362,10 +7363,13 @@ fold_unary (enum tree_code code, tree type, tree op0)
- the initial type is a pointer type and the precisions of the
intermediate and final types differ, or
- the final type is a pointer type and the precisions of the
- initial and intermediate types differ. */
+ initial and intermediate types differ.
+ - the final type is a pointer type and the initial type not
+ - the initial type is a pointer to an array and the final type
+ not. */
if (! inside_float && ! inter_float && ! final_float
&& ! inside_vec && ! inter_vec && ! final_vec
- && (inter_prec > inside_prec || inter_prec > final_prec)
+ && (inter_prec >= inside_prec || inter_prec >= final_prec)
&& ! (inside_int && inter_int
&& inter_unsignedp != inside_unsignedp
&& inter_prec < final_prec)
@@ -7375,7 +7379,10 @@ fold_unary (enum tree_code code, tree type, tree op0)
&& ! (final_ptr && inside_prec != inter_prec)
&& ! (final_prec != GET_MODE_BITSIZE (TYPE_MODE (type))
&& TYPE_MODE (type) == TYPE_MODE (inter_type))
- && ! final_ptr)
+ && final_ptr == inside_ptr
+ && ! (inside_ptr
+ && TREE_CODE (TREE_TYPE (inside_type)) == ARRAY_TYPE
+ && TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE))
return fold_build1 (code, type, TREE_OPERAND (op0, 0));
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 35fbf2d..418c671 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2006-05-11 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/27529
+ * gcc.dg/tree-ssa/foldcast-1.c: New testcase.
+
2006-05-10 Janis Johnson <janis187@us.ibm.com>
* lib/target-supports-dg.exp (check-flags): New.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/foldcast-1.c b/gcc/testsuite/gcc.dg/tree-ssa/foldcast-1.c
new file mode 100644
index 0000000..a0626ea
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/foldcast-1.c
@@ -0,0 +1,16 @@
+/* { dg-do "compile" } */
+/* { dg-options "-fdump-tree-original" } */
+
+typedef int ssize_t __attribute__((mode(pointer)));
+ssize_t foo (ssize_t x)
+{
+ return (ssize_t)(char *)x;
+}
+
+char *bar (char *x)
+{
+ return (char *)(ssize_t)x;
+}
+
+/* { dg-final { scan-tree-dump-times "return x;" 2 "original" } } */
+/* { dg-final { cleanup-tree-dump "original" } } */