aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/cp-gimplify.cc74
-rw-r--r--gcc/testsuite/g++.target/i386/pr118068.C17
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));
+}