From 4b8d544bc69dca9cd1afe0905a2f7816aa0cdbe3 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 4 Apr 2005 10:50:35 +0200 Subject: [PATCH] re PR rtl-optimization/16104 (ICE in reload_cse_simplify_operands, at postreload.c:378 with SSE2 code on -O2) PR rtl-optimization/16104 * fold-const.c (fold_unary): Fix folding of vector conversions. * gcc.c-torture/execute/20050316-1.c: New test. From-SVN: r97529 --- gcc/ChangeLog | 6 ++ gcc/fold-const.c | 14 +++- gcc/testsuite/ChangeLog | 5 ++ .../gcc.c-torture/execute/20050316-1.c | 69 +++++++++++++++++++ 4 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/20050316-1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4fc4bea315c..fe589da8458 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2005-04-04 Richard Henderson + Jakub Jelinek + + PR rtl-optimization/16104 + * fold-const.c (fold_unary): Fix folding of vector conversions. + 2005-04-04 Richard Sandiford * config.gcc (xstormy16-*-elf): Set extra_options. diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 0b9a71f09f7..efbf8ed5c78 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -6772,16 +6772,19 @@ fold_unary (enum tree_code code, tree type, tree op0) int inside_int = INTEGRAL_TYPE_P (inside_type); int inside_ptr = POINTER_TYPE_P (inside_type); int inside_float = FLOAT_TYPE_P (inside_type); + int inside_vec = TREE_CODE (inside_type) == VECTOR_TYPE; unsigned int inside_prec = TYPE_PRECISION (inside_type); int inside_unsignedp = TYPE_UNSIGNED (inside_type); int inter_int = INTEGRAL_TYPE_P (inter_type); int inter_ptr = POINTER_TYPE_P (inter_type); int inter_float = FLOAT_TYPE_P (inter_type); + int inter_vec = TREE_CODE (inter_type) == VECTOR_TYPE; unsigned int inter_prec = TYPE_PRECISION (inter_type); int inter_unsignedp = TYPE_UNSIGNED (inter_type); int final_int = INTEGRAL_TYPE_P (type); int final_ptr = POINTER_TYPE_P (type); int final_float = FLOAT_TYPE_P (type); + int final_vec = TREE_CODE (type) == VECTOR_TYPE; unsigned int final_prec = TYPE_PRECISION (type); int final_unsignedp = TYPE_UNSIGNED (type); @@ -6801,12 +6804,15 @@ fold_unary (enum tree_code code, tree type, tree op0) since then we sometimes need the inner conversion. Likewise if the outer has a precision not equal to the size of its mode. */ if ((((inter_int || inter_ptr) && (inside_int || inside_ptr)) - || (inter_float && inside_float)) + || (inter_float && inside_float) + || (inter_vec && inside_vec)) && inter_prec >= inside_prec - && (inter_float || inter_unsignedp == inside_unsignedp) + && (inter_float || inter_vec + || inter_unsignedp == inside_unsignedp) && ! (final_prec != GET_MODE_BITSIZE (TYPE_MODE (type)) && TYPE_MODE (type) == TYPE_MODE (inter_type)) - && ! final_ptr) + && ! final_ptr + && (! final_vec || inter_prec == inside_prec)) return fold_build1 (code, type, TREE_OPERAND (op0, 0)); /* If we have a sign-extension of a zero-extended value, we can @@ -6818,6 +6824,7 @@ fold_unary (enum tree_code code, tree type, tree op0) /* Two conversions in a row are not needed unless: - some conversion is floating-point (overstrict for now), or + - some conversion is a vector (overstrict for now), or - the intermediate type is narrower than both initial and final, or - the intermediate type and innermost type differ in signedness, @@ -6827,6 +6834,7 @@ fold_unary (enum tree_code code, tree type, tree op0) - the final type is a pointer type and the precisions of the initial and intermediate types differ. */ if (! inside_float && ! inter_float && ! final_float + && ! inside_vec && ! inter_vec && ! final_vec && (inter_prec > inside_prec || inter_prec > final_prec) && ! (inside_int && inter_int && inter_unsignedp != inside_unsignedp diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a3691a6c495..4abe23ea4de 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2005-04-04 Jakub Jelinek + + PR rtl-optimization/16104 + * gcc.c-torture/execute/20050316-1.c: New test. + 2005-04-04 Nathan Sidwell * g++.dg/template/spec23.C: Fix dg-error text. diff --git a/gcc/testsuite/gcc.c-torture/execute/20050316-1.c b/gcc/testsuite/gcc.c-torture/execute/20050316-1.c new file mode 100644 index 00000000000..2a1c6254dfa --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/20050316-1.c @@ -0,0 +1,69 @@ +/* PR rtl-optimization/16104 */ + +extern void abort (void); + +typedef int V2SI __attribute__ ((vector_size (8))); +typedef unsigned int V2USI __attribute__ ((vector_size (8))); +typedef short V2HI __attribute__ ((vector_size (4))); +typedef unsigned int V2UHI __attribute__ ((vector_size (4))); + +int +test1 (void) +{ + return (long long) (V2SI) 0LL; +} + +int +test2 (V2SI x) +{ + return (long long) x; +} + +V2SI +test3 (void) +{ + return (V2SI) (long long) (int) (V2HI) 0; +} + +V2SI +test4 (V2HI x) +{ + return (V2SI) (long long) (int) x; +} + +V2SI +test5 (V2USI x) +{ + return (V2SI) x; +} + +int +main (void) +{ + if (sizeof (short) != 2 || sizeof (int) != 4 || sizeof (long long) != 8) + return 0; + + if (test1 () != 0) + abort (); + + V2SI x = { 2, 2 }; + if (test2 (x) != 2) + abort (); + + union { V2SI x; int y[2]; V2USI z; long long l; } u; + u.x = test3 (); + if (u.y[0] != 0 || u.y[1] != 0) + abort (); + + V2HI y = { 4, 4 }; + union { V2SI x; long long y; } v; + v.x = test4 (y); + if (v.y != 0x40004) + abort (); + + V2USI z = { 6, 6 }; + u.x = test5 (z); + if (u.y[0] != 6 || u.y[1] != 6) + abort (); + return 0; +} -- 2.30.2