diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/cp-gimplify.cc | 74 | ||||
-rw-r--r-- | gcc/testsuite/g++.target/i386/pr118068.C | 17 |
2 files changed, 52 insertions, 39 deletions
diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc index 04e4308..550cea29 100644 --- a/gcc/cp/cp-gimplify.cc +++ b/gcc/cp/cp-gimplify.cc @@ -519,7 +519,7 @@ cp_fold_immediate (tree *tp, mce_value manifestly_const_eval, cp_fold_data data (flags); int save_errorcount = errorcount; - tree r = cp_walk_tree_without_duplicates (tp, cp_fold_immediate_r, &data); + tree r = cp_walk_tree (tp, cp_fold_immediate_r, &data, NULL); if (errorcount > save_errorcount) return integer_one_node; return r; @@ -1204,7 +1204,8 @@ cp_build_init_expr_for_ctor (tree call, tree init) return init; } -/* A subroutine of cp_fold_r to handle immediate functions. */ +/* A walk_tree callback for cp_fold_function and cp_fully_fold_init to handle + immediate functions. */ static tree cp_fold_immediate_r (tree *stmt_p, int *walk_subtrees, void *data_) @@ -1250,7 +1251,19 @@ cp_fold_immediate_r (tree *stmt_p, int *walk_subtrees, void *data_) if (!ADDR_EXPR_DENOTES_CALL_P (stmt)) decl = TREE_OPERAND (stmt, 0); break; + case IF_STMT: + if (IF_STMT_CONSTEVAL_P (stmt)) + { + if (!data->pset.add (stmt)) + cp_walk_tree (&ELSE_CLAUSE (stmt), cp_fold_immediate_r, data_, + NULL); + *walk_subtrees = 0; + return NULL_TREE; + } + /* FALLTHRU */ default: + if (data->pset.add (stmt)) + *walk_subtrees = 0; return NULL_TREE; } @@ -1370,45 +1383,8 @@ cp_fold_r (tree *stmt_p, int *walk_subtrees, void *data_) tree stmt = *stmt_p; enum tree_code code = TREE_CODE (stmt); - if (cxx_dialect >= cxx20) - { - /* Unfortunately we must handle code like - false ? bar () : 42 - where we have to check bar too. The cp_fold call below could - fold the ?: into a constant before we've checked it. */ - if (code == COND_EXPR) - { - auto then_fn = cp_fold_r, else_fn = cp_fold_r; - /* See if we can figure out if either of the branches is dead. If it - is, we don't need to do everything that cp_fold_r does. */ - cp_walk_tree (&TREE_OPERAND (stmt, 0), cp_fold_r, data, nullptr); - if (integer_zerop (TREE_OPERAND (stmt, 0))) - then_fn = cp_fold_immediate_r; - else if (integer_nonzerop (TREE_OPERAND (stmt, 0))) - else_fn = cp_fold_immediate_r; - - if (TREE_OPERAND (stmt, 1)) - cp_walk_tree (&TREE_OPERAND (stmt, 1), then_fn, data, - nullptr); - if (TREE_OPERAND (stmt, 2)) - cp_walk_tree (&TREE_OPERAND (stmt, 2), else_fn, data, - nullptr); - *walk_subtrees = 0; - /* Don't return yet, still need the cp_fold below. */ - } - else - cp_fold_immediate_r (stmt_p, walk_subtrees, data); - } - *stmt_p = stmt = cp_fold (*stmt_p, data->flags); - /* For certain trees, like +foo(), the cp_fold above will remove the +, - and the subsequent tree walk would go straight down to the CALL_EXPR's - operands, meaning that cp_fold_immediate_r would never see the - CALL_EXPR. Ew :(. */ - if (TREE_CODE (stmt) == CALL_EXPR && code != CALL_EXPR) - cp_fold_immediate_r (stmt_p, walk_subtrees, data); - if (data->pset.add (stmt)) { /* Don't walk subtrees of stmts we've already walked once, otherwise @@ -1537,6 +1513,16 @@ cp_fold_function (tree fndecl) been constant-evaluated already if possible, so we can safely pass ff_mce_false. */ cp_fold_data data (ff_genericize | ff_mce_false); + /* Do cp_fold_immediate_r in separate whole IL walk instead of during + cp_fold_r, as otherwise expressions using results of immediate functions + might not be folded as cp_fold is called on those before cp_fold_r is + called on their argument. */ + if (cxx_dialect >= cxx20) + { + cp_walk_tree (&DECL_SAVED_TREE (fndecl), cp_fold_immediate_r, + &data, NULL); + data.pset.empty (); + } cp_walk_tree (&DECL_SAVED_TREE (fndecl), cp_fold_r, &data, NULL); /* This is merely an optimization: if FNDECL has no i-e expressions, @@ -1717,6 +1703,11 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) case RETURN_EXPR: if (TREE_OPERAND (stmt, 0)) { + if (error_operand_p (TREE_OPERAND (stmt, 0)) + && warn_return_type) + /* Suppress -Wreturn-type for this function. */ + suppress_warning (current_function_decl, OPT_Wreturn_type); + if (is_invisiref_parm (TREE_OPERAND (stmt, 0))) /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR. */ @@ -2922,6 +2913,11 @@ cp_fully_fold_init (tree x) return x; x = cp_fully_fold (x, mce_false); cp_fold_data data (ff_mce_false); + if (cxx_dialect >= cxx20) + { + cp_walk_tree (&x, cp_fold_immediate_r, &data, NULL); + data.pset.empty (); + } cp_walk_tree (&x, cp_fold_r, &data, NULL); return x; } diff --git a/gcc/testsuite/g++.target/i386/pr118068.C b/gcc/testsuite/g++.target/i386/pr118068.C new file mode 100644 index 0000000..c5cc61f --- /dev/null +++ b/gcc/testsuite/g++.target/i386/pr118068.C @@ -0,0 +1,17 @@ +// PR target/118068 +// { dg-do compile { target c++20 } } +// { dg-options "-O0 -mavx" } + +typedef float V __attribute__((vector_size (32))); + +consteval unsigned char +foo (int x) +{ + return x; +} + +V +bar (V x, V y) +{ + return __builtin_ia32_blendps256 (x, y, (int) foo (0x23)); +} |