aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2016-06-28 10:27:18 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2016-06-28 10:27:18 +0200
commit849a76a5a20db3830b3a627aae1b8c7eb0f1623d (patch)
tree532f4d56f6e6da5f9c6f2a7cf4ae65a7b9a8342d /gcc/tree-ssa.c
parenta826405801ce4e28d534e3f693f236405d886caf (diff)
downloadgcc-849a76a5a20db3830b3a627aae1b8c7eb0f1623d.zip
gcc-849a76a5a20db3830b3a627aae1b8c7eb0f1623d.tar.gz
gcc-849a76a5a20db3830b3a627aae1b8c7eb0f1623d.tar.bz2
re PR middle-end/66867 (Suboptimal code generation for atomic_compare_exchange)
PR middle-end/66867 * builtins.c (expand_ifn_atomic_compare_exchange_into_call, expand_ifn_atomic_compare_exchange): New functions. * internal-fn.c (expand_ATOMIC_COMPARE_EXCHANGE): New function. * tree.h (build_call_expr_internal_loc): Rename to ... (build_call_expr_internal_loc_array): ... this. Fix up type of last argument. * internal-fn.def (ATOMIC_COMPARE_EXCHANGE): New internal fn. * predict.c (expr_expected_value_1): Handle IMAGPART_EXPR of ATOMIC_COMPARE_EXCHANGE result. * builtins.h (expand_ifn_atomic_compare_exchange): New prototype. * gimple-fold.h (optimize_atomic_compare_exchange_p, fold_builtin_atomic_compare_exchange): New prototypes. * gimple-fold.c (optimize_atomic_compare_exchange_p, fold_builtin_atomic_compare_exchange): New functions.. * tree-ssa.c (execute_update_addresses_taken): If optimize_atomic_compare_exchange_p, ignore &var in 2nd argument of call when finding addressable vars, and if such var becomes non-addressable, call fold_builtin_atomic_compare_exchange. From-SVN: r237814
Diffstat (limited to 'gcc/tree-ssa.c')
-rw-r--r--gcc/tree-ssa.c27
1 files changed, 25 insertions, 2 deletions
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index 247fa07..fd742f2 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -1414,8 +1414,21 @@ execute_update_addresses_taken (void)
enum gimple_code code = gimple_code (stmt);
tree decl;
- /* Note all addresses taken by the stmt. */
- gimple_ior_addresses_taken (addresses_taken, stmt);
+ if (code == GIMPLE_CALL
+ && optimize_atomic_compare_exchange_p (stmt))
+ {
+ /* For __atomic_compare_exchange_N if the second argument
+ is &var, don't mark var addressable;
+ if it becomes non-addressable, we'll rewrite it into
+ ATOMIC_COMPARE_EXCHANGE call. */
+ tree arg = gimple_call_arg (stmt, 1);
+ gimple_call_set_arg (stmt, 1, null_pointer_node);
+ gimple_ior_addresses_taken (addresses_taken, stmt);
+ gimple_call_set_arg (stmt, 1, arg);
+ }
+ else
+ /* Note all addresses taken by the stmt. */
+ gimple_ior_addresses_taken (addresses_taken, stmt);
/* If we have a call or an assignment, see if the lhs contains
a local decl that requires not to be a gimple register. */
@@ -1657,6 +1670,16 @@ execute_update_addresses_taken (void)
else if (gimple_code (stmt) == GIMPLE_CALL)
{
unsigned i;
+ if (optimize_atomic_compare_exchange_p (stmt))
+ {
+ tree expected = gimple_call_arg (stmt, 1);
+ if (bitmap_bit_p (suitable_for_renaming,
+ DECL_UID (TREE_OPERAND (expected, 0))))
+ {
+ fold_builtin_atomic_compare_exchange (&gsi);
+ continue;
+ }
+ }
for (i = 0; i < gimple_call_num_args (stmt); ++i)
{
tree *argp = gimple_call_arg_ptr (stmt, i);