Mercurial > hg > CbC > CbC_gcc
comparison gcc/trans-mem.c @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | 84e7813d76e9 |
children |
comparison
equal
deleted
inserted
replaced
131:84e7813d76e9 | 145:1830386684a0 |
---|---|
1 /* Passes for transactional memory support. | 1 /* Passes for transactional memory support. |
2 Copyright (C) 2008-2018 Free Software Foundation, Inc. | 2 Copyright (C) 2008-2020 Free Software Foundation, Inc. |
3 Contributed by Richard Henderson <rth@redhat.com> | 3 Contributed by Richard Henderson <rth@redhat.com> |
4 and Aldy Hernandez <aldyh@redhat.com>. | 4 and Aldy Hernandez <aldyh@redhat.com>. |
5 | 5 |
6 This file is part of GCC. | 6 This file is part of GCC. |
7 | 7 |
44 #include "tree-into-ssa.h" | 44 #include "tree-into-ssa.h" |
45 #include "tree-inline.h" | 45 #include "tree-inline.h" |
46 #include "demangle.h" | 46 #include "demangle.h" |
47 #include "output.h" | 47 #include "output.h" |
48 #include "trans-mem.h" | 48 #include "trans-mem.h" |
49 #include "params.h" | |
50 #include "langhooks.h" | 49 #include "langhooks.h" |
51 #include "cfgloop.h" | 50 #include "cfgloop.h" |
52 #include "tree-ssa-address.h" | 51 #include "tree-ssa-address.h" |
53 #include "stringpool.h" | 52 #include "stringpool.h" |
54 #include "attribs.h" | 53 #include "attribs.h" |
263 /* Return true if CALL is const, or tm_pure. */ | 262 /* Return true if CALL is const, or tm_pure. */ |
264 | 263 |
265 static bool | 264 static bool |
266 is_tm_pure_call (gimple *call) | 265 is_tm_pure_call (gimple *call) |
267 { | 266 { |
268 if (gimple_call_internal_p (call)) | 267 return (gimple_call_flags (call) & (ECF_CONST | ECF_TM_PURE)) != 0; |
269 return (gimple_call_flags (call) & (ECF_CONST | ECF_TM_PURE)) != 0; | |
270 | |
271 tree fn = gimple_call_fn (call); | |
272 | |
273 if (TREE_CODE (fn) == ADDR_EXPR) | |
274 { | |
275 fn = TREE_OPERAND (fn, 0); | |
276 gcc_assert (TREE_CODE (fn) == FUNCTION_DECL); | |
277 } | |
278 else | |
279 fn = TREE_TYPE (fn); | |
280 | |
281 return is_tm_pure (fn); | |
282 } | 268 } |
283 | 269 |
284 /* Return true if X has been marked TM_CALLABLE. */ | 270 /* Return true if X has been marked TM_CALLABLE. */ |
285 | 271 |
286 static bool | 272 static bool |
765 /* ??? We ought to come up with a way to add attributes to | 751 /* ??? We ought to come up with a way to add attributes to |
766 asm statements, and then add "transaction_safe" to it. | 752 asm statements, and then add "transaction_safe" to it. |
767 Either that or get the language spec to resurrect __tm_waiver. */ | 753 Either that or get the language spec to resurrect __tm_waiver. */ |
768 if (d->block_flags & DIAG_TM_SAFE) | 754 if (d->block_flags & DIAG_TM_SAFE) |
769 error_at (gimple_location (stmt), | 755 error_at (gimple_location (stmt), |
770 "asm not allowed in atomic transaction"); | 756 "%<asm%> not allowed in atomic transaction"); |
771 else if (d->func_flags & DIAG_TM_SAFE) | 757 else if (d->func_flags & DIAG_TM_SAFE) |
772 error_at (gimple_location (stmt), | 758 error_at (gimple_location (stmt), |
773 "asm not allowed in %<transaction_safe%> function"); | 759 "%<asm%> not allowed in %<transaction_safe%> function"); |
774 break; | 760 break; |
775 | 761 |
776 case GIMPLE_TRANSACTION: | 762 case GIMPLE_TRANSACTION: |
777 { | 763 { |
778 gtransaction *trans_stmt = as_a <gtransaction *> (stmt); | 764 gtransaction *trans_stmt = as_a <gtransaction *> (stmt); |
1119 if (entry_block | 1105 if (entry_block |
1120 && transaction_invariant_address_p (lp->addr, entry_block) | 1106 && transaction_invariant_address_p (lp->addr, entry_block) |
1121 && TYPE_SIZE_UNIT (type) != NULL | 1107 && TYPE_SIZE_UNIT (type) != NULL |
1122 && tree_fits_uhwi_p (TYPE_SIZE_UNIT (type)) | 1108 && tree_fits_uhwi_p (TYPE_SIZE_UNIT (type)) |
1123 && ((HOST_WIDE_INT) tree_to_uhwi (TYPE_SIZE_UNIT (type)) | 1109 && ((HOST_WIDE_INT) tree_to_uhwi (TYPE_SIZE_UNIT (type)) |
1124 < PARAM_VALUE (PARAM_TM_MAX_AGGREGATE_SIZE)) | 1110 < param_tm_max_aggregate_size) |
1125 /* We must be able to copy this type normally. I.e., no | 1111 /* We must be able to copy this type normally. I.e., no |
1126 special constructors and the like. */ | 1112 special constructors and the like. */ |
1127 && !TREE_ADDRESSABLE (type)) | 1113 && !TREE_ADDRESSABLE (type)) |
1128 { | 1114 { |
1129 lp->save_var = create_tmp_reg (TREE_TYPE (lp->addr), "tm_save"); | 1115 lp->save_var = create_tmp_reg (TREE_TYPE (lp->addr), "tm_save"); |
2552 if (repl) | 2538 if (repl) |
2553 { | 2539 { |
2554 gimple_call_set_fndecl (stmt, repl); | 2540 gimple_call_set_fndecl (stmt, repl); |
2555 update_stmt (stmt); | 2541 update_stmt (stmt); |
2556 node = cgraph_node::create (repl); | 2542 node = cgraph_node::create (repl); |
2557 node->local.tm_may_enter_irr = false; | 2543 node->tm_may_enter_irr = false; |
2558 return expand_call_tm (region, gsi); | 2544 return expand_call_tm (region, gsi); |
2559 } | 2545 } |
2560 gcc_unreachable (); | 2546 gcc_unreachable (); |
2561 } | 2547 } |
2562 if (node->local.tm_may_enter_irr) | 2548 if (node->tm_may_enter_irr) |
2563 transaction_subcode_ior (region, GTMA_MAY_ENTER_IRREVOCABLE); | 2549 transaction_subcode_ior (region, GTMA_MAY_ENTER_IRREVOCABLE); |
2564 | 2550 |
2565 if (is_tm_abort (fn_decl)) | 2551 if (is_tm_abort (fn_decl)) |
2566 { | 2552 { |
2567 transaction_subcode_ior (region, GTMA_HAVE_ABORT); | 2553 transaction_subcode_ior (region, GTMA_HAVE_ABORT); |
3248 call_stmt = dyn_cast <gcall *> (stmt); | 3234 call_stmt = dyn_cast <gcall *> (stmt); |
3249 if ((!call_stmt) | 3235 if ((!call_stmt) |
3250 || (gimple_call_flags (call_stmt) & ECF_TM_BUILTIN) == 0) | 3236 || (gimple_call_flags (call_stmt) & ECF_TM_BUILTIN) == 0) |
3251 continue; | 3237 continue; |
3252 | 3238 |
3253 if (DECL_FUNCTION_CODE (gimple_call_fndecl (call_stmt)) | 3239 if (gimple_call_builtin_p (call_stmt, BUILT_IN_TM_ABORT)) |
3254 == BUILT_IN_TM_ABORT) | |
3255 { | 3240 { |
3256 // If we have a ``_transaction_cancel [[outer]]'', there is only | 3241 // If we have a ``_transaction_cancel [[outer]]'', there is only |
3257 // one abnormal edge: to the transaction marked OUTER. | 3242 // one abnormal edge: to the transaction marked OUTER. |
3258 // All compiler-generated instances of BUILT_IN_TM_ABORT have a | 3243 // All compiler-generated instances of BUILT_IN_TM_ABORT have a |
3259 // constant argument, which we can examine here. Users invoking | 3244 // constant argument, which we can examine here. Users invoking |
3719 bool changed; | 3704 bool changed; |
3720 | 3705 |
3721 /* Allocate a worklist array/queue. Entries are only added to the | 3706 /* Allocate a worklist array/queue. Entries are only added to the |
3722 list if they were not already on the list. So the size is | 3707 list if they were not already on the list. So the size is |
3723 bounded by the number of basic blocks in the region. */ | 3708 bounded by the number of basic blocks in the region. */ |
3709 gcc_assert (!blocks.is_empty ()); | |
3724 qlen = blocks.length () - 1; | 3710 qlen = blocks.length () - 1; |
3725 qin = qout = worklist = | 3711 qin = qout = worklist = XNEWVEC (basic_block, qlen); |
3726 XNEWVEC (basic_block, qlen); | |
3727 | 3712 |
3728 /* Put every block in the region on the worklist. */ | 3713 /* Put every block in the region on the worklist. */ |
3729 for (i = 0; blocks.iterate (i, &bb); ++i) | 3714 for (i = 0; blocks.iterate (i, &bb); ++i) |
3730 { | 3715 { |
3731 /* Seed AVAIL_OUT with the LOCAL set. */ | 3716 /* Seed AVAIL_OUT with the LOCAL set. */ |
4425 yet implemented, so we can't check for it. */ | 4410 yet implemented, so we can't check for it. */ |
4426 if (is_tm_safe (current_function_decl)) | 4411 if (is_tm_safe (current_function_decl)) |
4427 { | 4412 { |
4428 tree t = build1 (NOP_EXPR, void_type_node, size_zero_node); | 4413 tree t = build1 (NOP_EXPR, void_type_node, size_zero_node); |
4429 SET_EXPR_LOCATION (t, gimple_location (stmt)); | 4414 SET_EXPR_LOCATION (t, gimple_location (stmt)); |
4430 error ("%Kasm not allowed in %<transaction_safe%> function", t); | 4415 error ("%K%<asm%> not allowed in %<transaction_safe%> function", |
4416 t); | |
4431 } | 4417 } |
4432 return true; | 4418 return true; |
4433 | 4419 |
4434 default: | 4420 default: |
4435 break; | 4421 break; |
4733 if (d->irrevocable_blocks_clone) | 4719 if (d->irrevocable_blocks_clone) |
4734 return true; | 4720 return true; |
4735 | 4721 |
4736 /* We may have previously marked this function as tm_may_enter_irr; | 4722 /* We may have previously marked this function as tm_may_enter_irr; |
4737 see pass_diagnose_tm_blocks. */ | 4723 see pass_diagnose_tm_blocks. */ |
4738 if (node->local.tm_may_enter_irr) | 4724 if (node->tm_may_enter_irr) |
4739 return true; | 4725 return true; |
4740 | 4726 |
4741 /* Recurse on the main body for aliases. In general, this will | 4727 /* Recurse on the main body for aliases. In general, this will |
4742 result in one of the bits above being set so that we will not | 4728 result in one of the bits above being set so that we will not |
4743 have to recurse next time. */ | 4729 have to recurse next time. */ |
4757 { | 4743 { |
4758 struct cgraph_edge *e; | 4744 struct cgraph_edge *e; |
4759 | 4745 |
4760 for (e = node->callees; e ; e = e->next_callee) | 4746 for (e = node->callees; e ; e = e->next_callee) |
4761 if (!is_tm_callable (e->callee->decl) | 4747 if (!is_tm_callable (e->callee->decl) |
4762 && e->callee->local.tm_may_enter_irr) | 4748 && e->callee->tm_may_enter_irr) |
4763 error_at (gimple_location (e->call_stmt), | 4749 error_at (gimple_location (e->call_stmt), |
4764 "unsafe function call %qD within " | 4750 "unsafe function call %qD within " |
4765 "%<transaction_safe%> function", e->callee->decl); | 4751 "%<transaction_safe%> function", e->callee->decl); |
4766 } | 4752 } |
4767 | 4753 |
4799 tree fndecl; | 4785 tree fndecl; |
4800 | 4786 |
4801 if (gimple_code (stmt) == GIMPLE_ASM) | 4787 if (gimple_code (stmt) == GIMPLE_ASM) |
4802 { | 4788 { |
4803 error_at (gimple_location (stmt), | 4789 error_at (gimple_location (stmt), |
4804 "asm not allowed in atomic transaction"); | 4790 "%<asm%> not allowed in atomic transaction"); |
4805 continue; | 4791 continue; |
4806 } | 4792 } |
4807 | 4793 |
4808 if (!is_gimple_call (stmt)) | 4794 if (!is_gimple_call (stmt)) |
4809 continue; | 4795 continue; |
4825 if (is_tm_pure_call (stmt)) | 4811 if (is_tm_pure_call (stmt)) |
4826 continue; | 4812 continue; |
4827 if (is_tm_callable (fndecl)) | 4813 if (is_tm_callable (fndecl)) |
4828 continue; | 4814 continue; |
4829 | 4815 |
4830 if (cgraph_node::local_info (fndecl)->tm_may_enter_irr) | 4816 if (cgraph_node::local_info_node (fndecl)->tm_may_enter_irr) |
4831 error_at (gimple_location (stmt), | 4817 error_at (gimple_location (stmt), |
4832 "unsafe function call %qD within " | 4818 "unsafe function call %qD within " |
4833 "atomic transaction", fndecl); | 4819 "atomic transaction", fndecl); |
4834 } | 4820 } |
4835 | 4821 |
4857 old_asm_name = IDENTIFIER_POINTER (old_asm_id); | 4843 old_asm_name = IDENTIFIER_POINTER (old_asm_id); |
4858 dc = cplus_demangle_v3_components (old_asm_name, DMGL_NO_OPTS, &alloc); | 4844 dc = cplus_demangle_v3_components (old_asm_name, DMGL_NO_OPTS, &alloc); |
4859 | 4845 |
4860 if (dc == NULL) | 4846 if (dc == NULL) |
4861 { | 4847 { |
4862 char length[8]; | 4848 char length[12]; |
4863 | 4849 |
4864 do_unencoded: | 4850 do_unencoded: |
4865 sprintf (length, "%u", IDENTIFIER_LENGTH (old_asm_id)); | 4851 sprintf (length, "%u", IDENTIFIER_LENGTH (old_asm_id)); |
4866 tm_name = concat ("_ZGTt", length, old_asm_name, NULL); | 4852 tm_name = concat ("_ZGTt", length, old_asm_name, NULL); |
4867 } | 4853 } |
5000 varpool_node::get (new_decl)->set_comdat_group | 4986 varpool_node::get (new_decl)->set_comdat_group |
5001 (tm_mangle (DECL_COMDAT_GROUP (old_decl))); | 4987 (tm_mangle (DECL_COMDAT_GROUP (old_decl))); |
5002 | 4988 |
5003 gcc_assert (!old_node->ipa_transforms_to_apply.exists ()); | 4989 gcc_assert (!old_node->ipa_transforms_to_apply.exists ()); |
5004 new_node = old_node->create_version_clone (new_decl, vNULL, NULL); | 4990 new_node = old_node->create_version_clone (new_decl, vNULL, NULL); |
5005 new_node->local.local = false; | 4991 new_node->local = false; |
5006 new_node->externally_visible = old_node->externally_visible; | 4992 new_node->externally_visible = old_node->externally_visible; |
5007 new_node->lowered = true; | 4993 new_node->lowered = true; |
5008 new_node->tm_clone = 1; | 4994 new_node->tm_clone = 1; |
5009 if (!old_node->implicit_section) | 4995 if (!old_node->implicit_section) |
5010 new_node->set_section (old_node->get_section ()); | 4996 new_node->set_section (old_node->get_section ()); |
5020 TREE_PUBLIC (new_decl) = 0; | 5006 TREE_PUBLIC (new_decl) = 0; |
5021 DECL_WEAK (new_decl) = 0; | 5007 DECL_WEAK (new_decl) = 0; |
5022 } | 5008 } |
5023 | 5009 |
5024 tree_function_versioning (old_decl, new_decl, | 5010 tree_function_versioning (old_decl, new_decl, |
5025 NULL, false, NULL, | 5011 NULL, NULL, false, NULL, NULL); |
5026 false, NULL, NULL); | |
5027 } | 5012 } |
5028 | 5013 |
5029 record_tm_clone_pair (old_decl, new_decl); | 5014 record_tm_clone_pair (old_decl, new_decl); |
5030 | 5015 |
5031 symtab->call_cgraph_insertion_hooks (new_node); | 5016 symtab->call_cgraph_insertion_hooks (new_node); |
5221 /* ??? This seems broken. How is it that we're marking the | 5206 /* ??? This seems broken. How is it that we're marking the |
5222 CALLEE as may_enter_irr? Surely we should be marking the | 5207 CALLEE as may_enter_irr? Surely we should be marking the |
5223 CALLER. Also note that find_tm_replacement_function also | 5208 CALLER. Also note that find_tm_replacement_function also |
5224 contains mappings into the TM runtime, e.g. memcpy. These | 5209 contains mappings into the TM runtime, e.g. memcpy. These |
5225 we know won't go irrevocable. */ | 5210 we know won't go irrevocable. */ |
5226 new_node->local.tm_may_enter_irr = 1; | 5211 new_node->tm_may_enter_irr = 1; |
5227 } | 5212 } |
5228 else | 5213 else |
5229 { | 5214 { |
5230 struct tm_ipa_cg_data *d; | 5215 struct tm_ipa_cg_data *d; |
5231 struct cgraph_node *tnode = e->callee; | 5216 struct cgraph_node *tnode = e->callee; |
5429 /* ... marked tm_pure, record that fact for the runtime by | 5414 /* ... marked tm_pure, record that fact for the runtime by |
5430 indicating that the pure function is its own tm_callable. | 5415 indicating that the pure function is its own tm_callable. |
5431 No need to do this if the function's address can't be taken. */ | 5416 No need to do this if the function's address can't be taken. */ |
5432 if (is_tm_pure (node->decl)) | 5417 if (is_tm_pure (node->decl)) |
5433 { | 5418 { |
5434 if (!node->local.local) | 5419 if (!node->local) |
5435 record_tm_clone_pair (node->decl, node->decl); | 5420 record_tm_clone_pair (node->decl, node->decl); |
5436 continue; | 5421 continue; |
5437 } | 5422 } |
5438 | 5423 |
5439 push_cfun (DECL_STRUCT_FUNCTION (node->decl)); | 5424 push_cfun (DECL_STRUCT_FUNCTION (node->decl)); |
5556 } | 5541 } |
5557 | 5542 |
5558 node = irr_worklist[i]; | 5543 node = irr_worklist[i]; |
5559 d = get_cg_data (&node, true); | 5544 d = get_cg_data (&node, true); |
5560 d->in_worklist = false; | 5545 d->in_worklist = false; |
5561 node->local.tm_may_enter_irr = true; | 5546 node->tm_may_enter_irr = true; |
5562 | 5547 |
5563 /* Propagate back to normal callers. */ | 5548 /* Propagate back to normal callers. */ |
5564 for (e = node->callers; e ; e = e->next_caller) | 5549 for (e = node->callers; e ; e = e->next_caller) |
5565 { | 5550 { |
5566 caller = e->caller; | 5551 caller = e->caller; |
5567 if (!is_tm_safe_or_pure (caller->decl) | 5552 if (!is_tm_safe_or_pure (caller->decl) |
5568 && !caller->local.tm_may_enter_irr) | 5553 && !caller->tm_may_enter_irr) |
5569 { | 5554 { |
5570 d = get_cg_data (&caller, true); | 5555 d = get_cg_data (&caller, true); |
5571 maybe_push_queue (caller, &irr_worklist, &d->in_worklist); | 5556 maybe_push_queue (caller, &irr_worklist, &d->in_worklist); |
5572 } | 5557 } |
5573 } | 5558 } |
5574 | 5559 |
5575 /* Propagate back to referring aliases as well. */ | 5560 /* Propagate back to referring aliases as well. */ |
5576 FOR_EACH_ALIAS (node, ref) | 5561 FOR_EACH_ALIAS (node, ref) |
5577 { | 5562 { |
5578 caller = dyn_cast<cgraph_node *> (ref->referring); | 5563 caller = dyn_cast<cgraph_node *> (ref->referring); |
5579 if (!caller->local.tm_may_enter_irr) | 5564 if (!caller->tm_may_enter_irr) |
5580 { | 5565 { |
5581 /* ?? Do not traverse aliases here. */ | 5566 /* ?? Do not traverse aliases here. */ |
5582 d = get_cg_data (&caller, false); | 5567 d = get_cg_data (&caller, false); |
5583 maybe_push_queue (caller, &irr_worklist, &d->in_worklist); | 5568 maybe_push_queue (caller, &irr_worklist, &d->in_worklist); |
5584 } | 5569 } |