Mercurial > hg > CbC > CbC_gcc
comparison gcc/trans-mem.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
comparison
equal
deleted
inserted
replaced
111:04ced10e8804 | 131:84e7813d76e9 |
---|---|
1 /* Passes for transactional memory support. | 1 /* Passes for transactional memory support. |
2 Copyright (C) 2008-2017 Free Software Foundation, Inc. | 2 Copyright (C) 2008-2018 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 |
233 /* A call to the irrevocable builtin is by definition, | 233 /* A call to the irrevocable builtin is by definition, |
234 irrevocable. */ | 234 irrevocable. */ |
235 if (TREE_CODE (x) == ADDR_EXPR) | 235 if (TREE_CODE (x) == ADDR_EXPR) |
236 x = TREE_OPERAND (x, 0); | 236 x = TREE_OPERAND (x, 0); |
237 if (TREE_CODE (x) == FUNCTION_DECL | 237 if (TREE_CODE (x) == FUNCTION_DECL |
238 && DECL_BUILT_IN_CLASS (x) == BUILT_IN_NORMAL | 238 && fndecl_built_in_p (x, BUILT_IN_TM_IRREVOCABLE)) |
239 && DECL_FUNCTION_CODE (x) == BUILT_IN_TM_IRREVOCABLE) | |
240 return true; | 239 return true; |
241 | 240 |
242 return false; | 241 return false; |
243 } | 242 } |
244 | 243 |
356 | 355 |
357 if (gimple_code (stmt) != GIMPLE_CALL) | 356 if (gimple_code (stmt) != GIMPLE_CALL) |
358 return false; | 357 return false; |
359 | 358 |
360 fndecl = gimple_call_fndecl (stmt); | 359 fndecl = gimple_call_fndecl (stmt); |
361 return (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL | 360 return (fndecl |
361 && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL) | |
362 && BUILTIN_TM_LOAD_P (DECL_FUNCTION_CODE (fndecl))); | 362 && BUILTIN_TM_LOAD_P (DECL_FUNCTION_CODE (fndecl))); |
363 } | 363 } |
364 | 364 |
365 /* Same as above, but for simple TM loads, that is, not the | 365 /* Same as above, but for simple TM loads, that is, not the |
366 after-write, after-read, etc optimized variants. */ | 366 after-write, after-read, etc optimized variants. */ |
372 | 372 |
373 if (gimple_code (stmt) != GIMPLE_CALL) | 373 if (gimple_code (stmt) != GIMPLE_CALL) |
374 return false; | 374 return false; |
375 | 375 |
376 fndecl = gimple_call_fndecl (stmt); | 376 fndecl = gimple_call_fndecl (stmt); |
377 if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL) | 377 if (fndecl && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)) |
378 { | 378 { |
379 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); | 379 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); |
380 return (fcode == BUILT_IN_TM_LOAD_1 | 380 return (fcode == BUILT_IN_TM_LOAD_1 |
381 || fcode == BUILT_IN_TM_LOAD_2 | 381 || fcode == BUILT_IN_TM_LOAD_2 |
382 || fcode == BUILT_IN_TM_LOAD_4 | 382 || fcode == BUILT_IN_TM_LOAD_4 |
400 | 400 |
401 if (gimple_code (stmt) != GIMPLE_CALL) | 401 if (gimple_code (stmt) != GIMPLE_CALL) |
402 return false; | 402 return false; |
403 | 403 |
404 fndecl = gimple_call_fndecl (stmt); | 404 fndecl = gimple_call_fndecl (stmt); |
405 return (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL | 405 return (fndecl |
406 && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL) | |
406 && BUILTIN_TM_STORE_P (DECL_FUNCTION_CODE (fndecl))); | 407 && BUILTIN_TM_STORE_P (DECL_FUNCTION_CODE (fndecl))); |
407 } | 408 } |
408 | 409 |
409 /* Same as above, but for simple TM stores, that is, not the | 410 /* Same as above, but for simple TM stores, that is, not the |
410 after-write, after-read, etc optimized variants. */ | 411 after-write, after-read, etc optimized variants. */ |
416 | 417 |
417 if (gimple_code (stmt) != GIMPLE_CALL) | 418 if (gimple_code (stmt) != GIMPLE_CALL) |
418 return false; | 419 return false; |
419 | 420 |
420 fndecl = gimple_call_fndecl (stmt); | 421 fndecl = gimple_call_fndecl (stmt); |
421 if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL) | 422 if (fndecl |
423 && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)) | |
422 { | 424 { |
423 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); | 425 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); |
424 return (fcode == BUILT_IN_TM_STORE_1 | 426 return (fcode == BUILT_IN_TM_STORE_1 |
425 || fcode == BUILT_IN_TM_STORE_2 | 427 || fcode == BUILT_IN_TM_STORE_2 |
426 || fcode == BUILT_IN_TM_STORE_4 | 428 || fcode == BUILT_IN_TM_STORE_4 |
438 /* Return true if FNDECL is BUILT_IN_TM_ABORT. */ | 440 /* Return true if FNDECL is BUILT_IN_TM_ABORT. */ |
439 | 441 |
440 static bool | 442 static bool |
441 is_tm_abort (tree fndecl) | 443 is_tm_abort (tree fndecl) |
442 { | 444 { |
443 return (fndecl | 445 return (fndecl && fndecl_built_in_p (fndecl, BUILT_IN_TM_ABORT)); |
444 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL | |
445 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_TM_ABORT); | |
446 } | 446 } |
447 | 447 |
448 /* Build a GENERIC tree for a user abort. This is called by front ends | 448 /* Build a GENERIC tree for a user abort. This is called by front ends |
449 while transforming the __tm_abort statement. */ | 449 while transforming the __tm_abort statement. */ |
450 | 450 |
2005 { | 2005 { |
2006 g = gsi_stmt (gsi); | 2006 g = gsi_stmt (gsi); |
2007 if (gimple_code (g) == GIMPLE_CALL) | 2007 if (gimple_code (g) == GIMPLE_CALL) |
2008 { | 2008 { |
2009 tree fn = gimple_call_fndecl (g); | 2009 tree fn = gimple_call_fndecl (g); |
2010 if (fn && DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL) | 2010 if (fn && fndecl_built_in_p (fn, BUILT_IN_NORMAL)) |
2011 { | 2011 { |
2012 if ((DECL_FUNCTION_CODE (fn) == BUILT_IN_TM_COMMIT | 2012 if ((DECL_FUNCTION_CODE (fn) == BUILT_IN_TM_COMMIT |
2013 || DECL_FUNCTION_CODE (fn) == BUILT_IN_TM_COMMIT_EH) | 2013 || DECL_FUNCTION_CODE (fn) == BUILT_IN_TM_COMMIT_EH) |
2014 && region->exit_blocks) | 2014 && region->exit_blocks) |
2015 { | 2015 { |
2580 location_t loc = gimple_location (stmt); | 2580 location_t loc = gimple_location (stmt); |
2581 edge fallthru_edge = NULL; | 2581 edge fallthru_edge = NULL; |
2582 gassign *assign_stmt; | 2582 gassign *assign_stmt; |
2583 | 2583 |
2584 /* Remember if the call was going to throw. */ | 2584 /* Remember if the call was going to throw. */ |
2585 if (stmt_can_throw_internal (stmt)) | 2585 if (stmt_can_throw_internal (cfun, stmt)) |
2586 { | 2586 { |
2587 edge_iterator ei; | 2587 edge_iterator ei; |
2588 edge e; | 2588 edge e; |
2589 basic_block bb = gimple_bb (stmt); | 2589 basic_block bb = gimple_bb (stmt); |
2590 | 2590 |
2930 edge ei = make_edge (transaction_bb, test_bb, EDGE_FALLTHRU); | 2930 edge ei = make_edge (transaction_bb, test_bb, EDGE_FALLTHRU); |
2931 edge et = make_edge (test_bb, code_bb, EDGE_TRUE_VALUE); | 2931 edge et = make_edge (test_bb, code_bb, EDGE_TRUE_VALUE); |
2932 edge ef = make_edge (test_bb, join_bb, EDGE_FALSE_VALUE); | 2932 edge ef = make_edge (test_bb, join_bb, EDGE_FALSE_VALUE); |
2933 redirect_edge_pred (fallthru_edge, join_bb); | 2933 redirect_edge_pred (fallthru_edge, join_bb); |
2934 | 2934 |
2935 join_bb->frequency = test_bb->frequency = transaction_bb->frequency; | |
2936 join_bb->count = test_bb->count = transaction_bb->count; | 2935 join_bb->count = test_bb->count = transaction_bb->count; |
2937 | 2936 |
2938 ei->probability = profile_probability::always (); | 2937 ei->probability = profile_probability::always (); |
2939 et->probability = profile_probability::likely (); | 2938 et->probability = profile_probability::likely (); |
2940 ef->probability = profile_probability::unlikely (); | 2939 ef->probability = profile_probability::unlikely (); |
2941 | 2940 |
2942 code_bb->count = et->count (); | 2941 code_bb->count = et->count (); |
2943 code_bb->frequency = EDGE_FREQUENCY (et); | |
2944 | 2942 |
2945 transaction_bb = join_bb; | 2943 transaction_bb = join_bb; |
2946 } | 2944 } |
2947 | 2945 |
2948 // If we have an ABORT edge, create a test to perform the abort. | 2946 // If we have an ABORT edge, create a test to perform the abort. |
2962 t2 = build_int_cst (tm_state_type, 0); | 2960 t2 = build_int_cst (tm_state_type, 0); |
2963 stmt = gimple_build_cond (NE_EXPR, t1, t2, NULL, NULL); | 2961 stmt = gimple_build_cond (NE_EXPR, t1, t2, NULL, NULL); |
2964 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING); | 2962 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING); |
2965 | 2963 |
2966 edge ei = make_edge (transaction_bb, test_bb, EDGE_FALLTHRU); | 2964 edge ei = make_edge (transaction_bb, test_bb, EDGE_FALLTHRU); |
2967 test_bb->frequency = transaction_bb->frequency; | |
2968 test_bb->count = transaction_bb->count; | 2965 test_bb->count = transaction_bb->count; |
2969 ei->probability = profile_probability::always (); | 2966 ei->probability = profile_probability::always (); |
2970 | 2967 |
2971 // Not abort edge. If both are live, chose one at random as we'll | 2968 // Not abort edge. If both are live, chose one at random as we'll |
2972 // we'll be fixing that up below. | 2969 // we'll be fixing that up below. |
3004 // Create the edge into test_bb first, as we want to copy values | 3001 // Create the edge into test_bb first, as we want to copy values |
3005 // out of the fallthru edge. | 3002 // out of the fallthru edge. |
3006 edge e = make_edge (transaction_bb, test_bb, fallthru_edge->flags); | 3003 edge e = make_edge (transaction_bb, test_bb, fallthru_edge->flags); |
3007 e->probability = fallthru_edge->probability; | 3004 e->probability = fallthru_edge->probability; |
3008 test_bb->count = fallthru_edge->count (); | 3005 test_bb->count = fallthru_edge->count (); |
3009 test_bb->frequency = EDGE_FREQUENCY (e); | |
3010 | 3006 |
3011 // Now update the edges to the inst/uninist implementations. | 3007 // Now update the edges to the inst/uninist implementations. |
3012 // For now assume that the paths are equally likely. When using HTM, | 3008 // For now assume that the paths are equally likely. When using HTM, |
3013 // we'll try the uninst path first and fallback to inst path if htm | 3009 // we'll try the uninst path first and fallback to inst path if htm |
3014 // buffers are exceeded. Without HTM we start with the inst path and | 3010 // buffers are exceeded. Without HTM we start with the inst path and |
5067 gsi = gsi_after_labels (bb); | 5063 gsi = gsi_after_labels (bb); |
5068 gsi_insert_before (&gsi, g, GSI_SAME_STMT); | 5064 gsi_insert_before (&gsi, g, GSI_SAME_STMT); |
5069 | 5065 |
5070 node->create_edge (cgraph_node::get_create | 5066 node->create_edge (cgraph_node::get_create |
5071 (builtin_decl_explicit (BUILT_IN_TM_IRREVOCABLE)), | 5067 (builtin_decl_explicit (BUILT_IN_TM_IRREVOCABLE)), |
5072 g, gimple_bb (g)->count, | 5068 g, gimple_bb (g)->count); |
5073 compute_call_stmt_bb_frequency (node->decl, | |
5074 gimple_bb (g))); | |
5075 } | 5069 } |
5076 | 5070 |
5077 /* Construct a call to TM_GETTMCLONE and insert it before GSI. */ | 5071 /* Construct a call to TM_GETTMCLONE and insert it before GSI. */ |
5078 | 5072 |
5079 static bool | 5073 static bool |
5118 ret = make_ssa_name (ret, g); | 5112 ret = make_ssa_name (ret, g); |
5119 gimple_call_set_lhs (g, ret); | 5113 gimple_call_set_lhs (g, ret); |
5120 | 5114 |
5121 gsi_insert_before (gsi, g, GSI_SAME_STMT); | 5115 gsi_insert_before (gsi, g, GSI_SAME_STMT); |
5122 | 5116 |
5123 node->create_edge (cgraph_node::get_create (gettm_fn), g, gimple_bb (g)->count, | 5117 node->create_edge (cgraph_node::get_create (gettm_fn), g, gimple_bb (g)->count); |
5124 compute_call_stmt_bb_frequency (node->decl, | |
5125 gimple_bb (g))); | |
5126 | 5118 |
5127 /* Cast return value from tm_gettmclone* into appropriate function | 5119 /* Cast return value from tm_gettmclone* into appropriate function |
5128 pointer. */ | 5120 pointer. */ |
5129 callfn = create_tmp_var (TREE_TYPE (old_fn)); | 5121 callfn = create_tmp_var (TREE_TYPE (old_fn)); |
5130 g2 = gimple_build_assign (callfn, | 5122 g2 = gimple_build_assign (callfn, |