aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2022-10-18 10:31:20 +0200
committerJakub Jelinek <jakub@redhat.com>2022-10-18 10:39:09 +0200
commit4dda30e9910c4f04a6258b053401249e213f29be (patch)
tree4c7ad9e81387b5f56bd856017a40638c32fdb033 /gcc/cp
parent5ad3cc1ecc3c7c61d5e319f74cb7287fb80944fd (diff)
downloadgcc-4dda30e9910c4f04a6258b053401249e213f29be.zip
gcc-4dda30e9910c4f04a6258b053401249e213f29be.tar.gz
gcc-4dda30e9910c4f04a6258b053401249e213f29be.tar.bz2
middle-end IFN_ASSUME support [PR106654]
My earlier patches gimplify the simplest non-side-effects assumptions into if (cond) ; else __builtin_unreachable (); and throw the rest on the floor. The following patch attempts to do something with the rest too. For -O0, it throws the more complex assumptions on the floor, we don't expect optimizations and the assumptions are there to allow optimizations. Otherwise arranges for the assumptions to be visible in the IL as .ASSUME (_Z2f4i._assume.0, i_1(D)); call where there is an artificial function like: bool _Z2f4i._assume.0 (int i) { bool _2; <bb 2> [local count: 1073741824]: _2 = i_1(D) == 43; return _2; } with the semantics that there is UB unless the assumption function would return true. Aldy, could ranger handle this? If it sees .ASSUME call, walk the body of such function from the edge(s) to exit with the assumption that the function returns true, so above set _2 [true, true] and from there derive that i_1(D) [43, 43] and then map the argument in the assumption function to argument passed to IFN_ASSUME (note, args there are shifted by 1)? During gimplification it actually gimplifies it into [[assume (D.2591)]] { { i = i + 1; D.2591 = i == 44; } } which is a new GIMPLE_ASSUME statement wrapping a GIMPLE_BIND and specifying a boolean_type_node variable which contains the result. The GIMPLE_ASSUME then survives just a couple of passes and is lowered during gimple lowering into an outlined separate function and IFN_ASSUME call. Variables declared inside of the condition (both static and automatic) just change context, automatic variables from the caller are turned into parameters (note, as the code is never executed, I handle this way even non-POD types, we don't need to bother pretending there would be user copy constructors etc. involved). The assume_function artificial functions are then optimized until the new assumptions pass which doesn't do much right now but I'd like to see there the backwards ranger walk and filling up of SSA_NAME_RANGE_INFO for the parameters. There are a few further changes I'd like to do, like ignoring the .ASSUME calls in inlining size estimations (but haven't figured out where it is done), or for LTO arrange for the assume functions to be emitted in all partitions that reference those (usually there will be just one, unless code with the assumption got inlined, versioned etc.). 2022-10-18 Jakub Jelinek <jakub@redhat.com> PR c++/106654 gcc/ * gimple.def (GIMPLE_ASSUME): New statement kind. * gimple.h (struct gimple_statement_assume): New type. (is_a_helper <gimple_statement_assume *>::test, is_a_helper <const gimple_statement_assume *>::test): New. (gimple_build_assume): Declare. (gimple_has_substatements): Return true for GIMPLE_ASSUME. (gimple_assume_guard, gimple_assume_set_guard, gimple_assume_guard_ptr, gimple_assume_body_ptr, gimple_assume_body): New inline functions. * gsstruct.def (GSS_ASSUME): New. * gimple.cc (gimple_build_assume): New function. (gimple_copy): Handle GIMPLE_ASSUME. * gimple-pretty-print.cc (dump_gimple_assume): New function. (pp_gimple_stmt_1): Handle GIMPLE_ASSUME. * gimple-walk.cc (walk_gimple_op): Handle GIMPLE_ASSUME. * omp-low.cc (WALK_SUBSTMTS): Likewise. (lower_omp_1): Likewise. * omp-oacc-kernels-decompose.cc (adjust_region_code_walk_stmt_fn): Likewise. * tree-cfg.cc (verify_gimple_stmt, verify_gimple_in_seq_2): Likewise. * function.h (struct function): Add assume_function bitfield. * gimplify.cc (gimplify_call_expr): If the assumption isn't simple enough, expand it into GIMPLE_ASSUME wrapped block or for -O0 drop it. * gimple-low.cc: Include attribs.h. (create_assumption_fn): New function. (struct lower_assumption_data): New type. (find_assumption_locals_r, assumption_copy_decl, adjust_assumption_stmt_r, adjust_assumption_stmt_op, lower_assumption): New functions. (lower_stmt): Handle GIMPLE_ASSUME. * tree-ssa-ccp.cc (pass_fold_builtins::execute): Remove IFN_ASSUME calls. * lto-streamer-out.cc (output_struct_function_base): Pack assume_function bit. * lto-streamer-in.cc (input_struct_function_base): And unpack it. * cgraphunit.cc (cgraph_node::expand): Don't verify assume_function has TREE_ASM_WRITTEN set and don't release its body. (symbol_table::compile): Allow assume functions not to have released body. * internal-fn.cc (expand_ASSUME): Remove gcc_unreachable. * passes.cc (execute_one_pass): For TODO_discard_function don't release body of assume functions. * cgraph.cc (cgraph_node::verify_node): Don't verify cgraph nodes of PROP_assumptions_done functions. * tree-pass.h (PROP_assumptions_done): Define. (TODO_discard_function): Adjust comment. (make_pass_assumptions): Declare. * passes.def (pass_assumptions): Add. * timevar.def (TV_TREE_ASSUMPTIONS): New. * tree-inline.cc (remap_gimple_stmt): Handle GIMPLE_ASSUME. * tree-vrp.cc (pass_data_assumptions): New variable. (pass_assumptions): New class. (make_pass_assumptions): New function. gcc/cp/ * cp-tree.h (build_assume_call): Declare. * parser.cc (cp_parser_omp_assumption_clauses): Use build_assume_call. * cp-gimplify.cc (build_assume_call): New function. (process_stmt_assume_attribute): Use build_assume_call. * pt.cc (tsubst_copy_and_build): Likewise. gcc/testsuite/ * g++.dg/cpp23/attr-assume5.C: New test. * g++.dg/cpp23/attr-assume6.C: New test. * g++.dg/cpp23/attr-assume7.C: New test.
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/cp-gimplify.cc15
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/parser.cc6
-rw-r--r--gcc/cp/pt.cc5
4 files changed, 15 insertions, 12 deletions
diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
index 2608475..28c3398 100644
--- a/gcc/cp/cp-gimplify.cc
+++ b/gcc/cp/cp-gimplify.cc
@@ -3101,6 +3101,17 @@ process_stmt_hotness_attribute (tree std_attrs, location_t attrs_loc)
return std_attrs;
}
+/* Build IFN_ASSUME internal call for assume condition ARG. */
+
+tree
+build_assume_call (location_t loc, tree arg)
+{
+ if (!processing_template_decl)
+ arg = fold_build_cleanup_point_expr (TREE_TYPE (arg), arg);
+ return build_call_expr_internal_loc (loc, IFN_ASSUME, void_type_node,
+ 1, arg);
+}
+
/* If [[assume (cond)]] appears on this statement, handle it. */
tree
@@ -3137,9 +3148,7 @@ process_stmt_assume_attribute (tree std_attrs, tree statement,
arg = contextual_conv_bool (arg, tf_warning_or_error);
if (error_operand_p (arg))
continue;
- statement = build_call_expr_internal_loc (attrs_loc, IFN_ASSUME,
- void_type_node, 1, arg);
- finish_expr_stmt (statement);
+ finish_expr_stmt (build_assume_call (attrs_loc, arg));
}
}
return remove_attribute ("gnu", "assume", std_attrs);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index e2607f0..60a2510 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -8280,6 +8280,7 @@ extern tree predeclare_vla (tree);
extern void clear_fold_cache (void);
extern tree lookup_hotness_attribute (tree);
extern tree process_stmt_hotness_attribute (tree, location_t);
+extern tree build_assume_call (location_t, tree);
extern tree process_stmt_assume_attribute (tree, tree, location_t);
extern bool simple_empty_class_p (tree, tree, tree_code);
extern tree fold_builtin_source_location (location_t);
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 9ddfb02..a39c5f0 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -46012,11 +46012,7 @@ cp_parser_omp_assumption_clauses (cp_parser *parser, cp_token *pragma_tok,
if (!type_dependent_expression_p (t))
t = contextual_conv_bool (t, tf_warning_or_error);
if (is_assume && !error_operand_p (t))
- {
- t = build_call_expr_internal_loc (eloc, IFN_ASSUME,
- void_type_node, 1, t);
- finish_expr_stmt (t);
- }
+ finish_expr_stmt (build_assume_call (eloc, t));
if (!parens.require_close (parser))
cp_parser_skip_to_closing_parenthesis (parser,
/*recovering=*/true,
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index e4dca9d..5eddad9 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -21140,10 +21140,7 @@ tsubst_copy_and_build (tree t,
ret = error_mark_node;
break;
}
- ret = build_call_expr_internal_loc (EXPR_LOCATION (t),
- IFN_ASSUME,
- void_type_node, 1,
- arg);
+ ret = build_assume_call (EXPR_LOCATION (t), arg);
RETURN (ret);
}
break;