From 125e025e06060daa5583d98cf47c209dfbef95e4 Mon Sep 17 00:00:00 2001 From: Richard Guenther Date: Thu, 10 Jan 2008 14:28:40 +0000 Subject: [PATCH] re PR tree-optimization/34651 (ICE in set_value_range, at tree-vrp.c:321) 2008-01-10 Richard Guenther PR tree-optimization/34651 * tree-sra.c (sra_build_assignment): Sanitize. Use the correct types and ordering for masking and converting. * g++.dg/torture/pr34651.C: New testcase. From-SVN: r131442 --- gcc/ChangeLog | 6 ++ gcc/testsuite/ChangeLog | 5 + gcc/testsuite/g++.dg/torture/pr34651.C | 25 +++++ gcc/tree-sra.c | 138 +++++++++++-------------- 4 files changed, 96 insertions(+), 78 deletions(-) create mode 100644 gcc/testsuite/g++.dg/torture/pr34651.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0748d1575a2a..cc61c7050ba3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2008-01-10 Richard Guenther + + PR tree-optimization/34651 + * tree-sra.c (sra_build_assignment): Sanitize. Use the correct + types and ordering for masking and converting. + 2008-01-09 Sebastian Pop PR tree-optimization/34017 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8730974a7a78..496ef45a8f0a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2008-01-10 Richard Guenther + + PR tree-optimization/34651 + * g++.dg/torture/pr34651.C: New testcase. + 2008-01-09 Sebastian Pop PR tree-optimization/34017 diff --git a/gcc/testsuite/g++.dg/torture/pr34651.C b/gcc/testsuite/g++.dg/torture/pr34651.C new file mode 100644 index 000000000000..2fce4d7a1af7 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr34651.C @@ -0,0 +1,25 @@ +/* { dg-do compile } */ + +typedef bool Bool; +struct CString { + CString (const char * =__null); + CString & operator += (const CString &); +}; +struct THotKey { + short Key; + Bool Control; + Bool Shift; + Bool Alt; +}; +THotKey m_HotKey; +THotKey GetHotKey () { return m_HotKey; } +void Serialize () +{ + THotKey inHotKey (GetHotKey()); + CString outCombinaison (inHotKey.Control + ? ((inHotKey.Alt || inHotKey.Shift) + ? "ctrl+" : "ctrl") + : __null); + outCombinaison += inHotKey.Alt ? inHotKey.Shift ? "alt+" : "alt" : ""; + outCombinaison += inHotKey.Shift ? "shift" : ""; +} diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index 9128677dde04..df6c6dc7be65 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -2127,30 +2127,37 @@ static tree sra_build_assignment (tree dst, tree src) { /* Turning BIT_FIELD_REFs into bit operations enables other passes - to do a much better job at optimizing the code. */ + to do a much better job at optimizing the code. + From dst = BIT_FIELD_REF we produce + + SR.1 = (scalar type) var; + SR.2 = SR.1 >> off; + SR.3 = SR.2 & ((1 << sz) - 1); + ... possible sign extension of SR.3 ... + dst = (destination type) SR.3; + */ if (scalar_bitfield_p (src)) { - tree cst, cst2, mask, minshift, maxshift; - tree tmp, var, utype, stype; + tree var, shift, width; + tree utype, stype, stmp, utmp; tree list, stmt; bool unsignedp = BIT_FIELD_REF_UNSIGNED (src); var = TREE_OPERAND (src, 0); - cst = TREE_OPERAND (src, 2); - cst2 = size_binop (PLUS_EXPR, TREE_OPERAND (src, 1), - TREE_OPERAND (src, 2)); - + width = TREE_OPERAND (src, 1); + /* The offset needs to be adjusted to a right shift quantity + depending on the endianess. */ if (BYTES_BIG_ENDIAN) { - maxshift = size_binop (MINUS_EXPR, TYPE_SIZE (TREE_TYPE (var)), cst); - minshift = size_binop (MINUS_EXPR, TYPE_SIZE (TREE_TYPE (var)), cst2); + tree tmp = size_binop (PLUS_EXPR, width, TREE_OPERAND (src, 2)); + shift = size_binop (MINUS_EXPR, TYPE_SIZE (TREE_TYPE (var)), tmp); } else - { - maxshift = cst2; - minshift = cst; - } + shift = TREE_OPERAND (src, 2); + /* In weird cases we have non-integral types for the source or + destination object. + ??? For unknown reasons we also want an unsigned scalar type. */ stype = TREE_TYPE (var); if (!INTEGRAL_TYPE_P (stype)) stype = lang_hooks.types.type_for_size (TREE_INT_CST_LOW @@ -2166,117 +2173,92 @@ sra_build_assignment (tree dst, tree src) utype = unsigned_type_for (utype); list = NULL; + stmp = make_rename_temp (stype, "SR"); - cst2 = size_binop (MINUS_EXPR, maxshift, minshift); - if (TREE_INT_CST_LOW (cst2) == TYPE_PRECISION (utype)) - { - unsignedp = true; - mask = NULL_TREE; - } - else - { - mask = build_int_cst_wide (utype, 1, 0); - cst = int_const_binop (LSHIFT_EXPR, mask, cst2, true); - mask = int_const_binop (MINUS_EXPR, cst, mask, true); - } - - tmp = make_rename_temp (stype, "SR"); - if (TYPE_MAIN_VARIANT (TREE_TYPE (var)) != TYPE_MAIN_VARIANT (stype)) + /* Convert the base var of the BIT_FIELD_REF to the scalar type + we use for computation if we cannot use it directly. */ + if (!useless_type_conversion_p (stype, TREE_TYPE (var))) { if (INTEGRAL_TYPE_P (TREE_TYPE (var))) - stmt = build_gimple_modify_stmt (tmp, + stmt = build_gimple_modify_stmt (stmp, fold_convert (stype, var)); else - stmt = build_gimple_modify_stmt (tmp, + stmt = build_gimple_modify_stmt (stmp, fold_build1 (VIEW_CONVERT_EXPR, stype, var)); append_to_statement_list (stmt, &list); - - var = tmp; + var = stmp; } - if (!integer_zerop (minshift)) + if (!integer_zerop (shift)) { - tmp = make_rename_temp (stype, "SR"); - stmt = build_gimple_modify_stmt (tmp, + stmt = build_gimple_modify_stmt (stmp, fold_build2 (RSHIFT_EXPR, stype, - var, minshift)); + var, shift)); append_to_statement_list (stmt, &list); - - var = tmp; + var = stmp; } - if (TYPE_MAIN_VARIANT (utype) != TYPE_MAIN_VARIANT (stype)) + /* If we need a masking operation, produce one. */ + if (TREE_INT_CST_LOW (width) == TYPE_PRECISION (stype)) + unsignedp = true; + else { - if (!mask && unsignedp - && (TYPE_MAIN_VARIANT (utype) - == TYPE_MAIN_VARIANT (TREE_TYPE (dst)))) - tmp = dst; - else - tmp = make_rename_temp (utype, "SR"); + tree one = build_int_cst_wide (stype, 1, 0); + tree mask = int_const_binop (LSHIFT_EXPR, one, width, 0); + mask = int_const_binop (MINUS_EXPR, mask, one, 0); - stmt = build_gimple_modify_stmt (tmp, fold_convert (utype, var)); + stmt = build_gimple_modify_stmt (stmp, + fold_build2 (BIT_AND_EXPR, stype, + var, mask)); append_to_statement_list (stmt, &list); - - var = tmp; + var = stmp; } - if (mask) + /* After shifting and masking, convert to the target type. */ + utmp = stmp; + if (!useless_type_conversion_p (utype, stype)) { - if (!unsignedp - || (TYPE_MAIN_VARIANT (TREE_TYPE (dst)) - != TYPE_MAIN_VARIANT (utype))) - tmp = make_rename_temp (utype, "SR"); - else - tmp = dst; + utmp = make_rename_temp (utype, "SR"); - stmt = build_gimple_modify_stmt (tmp, - fold_build2 (BIT_AND_EXPR, utype, - var, mask)); + stmt = build_gimple_modify_stmt (utmp, fold_convert (utype, var)); append_to_statement_list (stmt, &list); - var = tmp; + var = utmp; } + /* Perform sign extension, if required. + ??? This should never be necessary. */ if (!unsignedp) { tree signbit = int_const_binop (LSHIFT_EXPR, build_int_cst_wide (utype, 1, 0), - size_binop (MINUS_EXPR, cst2, - bitsize_int (1)), - true); + size_binop (MINUS_EXPR, width, + bitsize_int (1)), 0); - tmp = make_rename_temp (utype, "SR"); - stmt = build_gimple_modify_stmt (tmp, + stmt = build_gimple_modify_stmt (utmp, fold_build2 (BIT_XOR_EXPR, utype, var, signbit)); append_to_statement_list (stmt, &list); - var = tmp; - - if (TYPE_MAIN_VARIANT (TREE_TYPE (dst)) != TYPE_MAIN_VARIANT (utype)) - tmp = make_rename_temp (utype, "SR"); - else - tmp = dst; - - stmt = build_gimple_modify_stmt (tmp, + stmt = build_gimple_modify_stmt (utmp, fold_build2 (MINUS_EXPR, utype, - var, signbit)); + utmp, signbit)); append_to_statement_list (stmt, &list); - var = tmp; + var = utmp; } - if (var != dst) + /* Finally, move and convert to the destination. */ + if (!useless_type_conversion_p (TREE_TYPE (dst), TREE_TYPE (var))) { if (INTEGRAL_TYPE_P (TREE_TYPE (dst))) var = fold_convert (TREE_TYPE (dst), var); else var = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (dst), var); - - stmt = build_gimple_modify_stmt (dst, var); - append_to_statement_list (stmt, &list); } + stmt = build_gimple_modify_stmt (dst, var); + append_to_statement_list (stmt, &list); return list; } -- 2.47.2