diff options
Diffstat (limited to 'gcc/gimple-fold.cc')
-rw-r--r-- | gcc/gimple-fold.cc | 307 |
1 files changed, 96 insertions, 211 deletions
diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc index e63fd6f..c5c8e22 100644 --- a/gcc/gimple-fold.cc +++ b/gcc/gimple-fold.cc @@ -191,19 +191,6 @@ can_refer_decl_in_current_unit_p (tree decl, tree from_decl) return !node || !node->inlined_to; } -/* Create a temporary for TYPE for a statement STMT. If the current function - is in SSA form, a SSA name is created. Otherwise a temporary register - is made. */ - -tree -create_tmp_reg_or_ssa_name (tree type, gimple *stmt) -{ - if (gimple_in_ssa_p (cfun)) - return make_ssa_name (type, stmt); - else - return create_tmp_reg (type); -} - /* CVAL is value taken from DECL_INITIAL of variable. Try to transform it into acceptable form for is_gimple_min_invariant. FROM_DECL (if non-NULL) specify variable whose constructor contains CVAL. */ @@ -894,155 +881,6 @@ size_must_be_zero_p (tree size) return vr.zero_p (); } -/* Optimize - a = {}; - b = a; - into - a = {}; - b = {}; - Similarly for memset (&a, ..., sizeof (a)); instead of a = {}; - and/or memcpy (&b, &a, sizeof (a)); instead of b = a; */ - -static bool -optimize_memcpy_to_memset (gimple_stmt_iterator *gsip, tree dest, tree src, tree len) -{ - ao_ref read; - gimple *stmt = gsi_stmt (*gsip); - if (gimple_has_volatile_ops (stmt)) - return false; - - - tree src2 = NULL_TREE, len2 = NULL_TREE; - poly_int64 offset, offset2; - tree val = integer_zero_node; - bool len_was_null = len == NULL_TREE; - if (len == NULL_TREE) - len = (TREE_CODE (src) == COMPONENT_REF - ? DECL_SIZE_UNIT (TREE_OPERAND (src, 1)) - : TYPE_SIZE_UNIT (TREE_TYPE (src))); - if (len == NULL_TREE - || !poly_int_tree_p (len)) - return false; - - ao_ref_init (&read, src); - tree vuse = gimple_vuse (stmt); - gimple *defstmt; - do { - if (vuse == NULL || TREE_CODE (vuse) != SSA_NAME) - return false; - defstmt = SSA_NAME_DEF_STMT (vuse); - if (is_a <gphi*>(defstmt)) - return false; - - /* If the len was null, then we can use TBBA. */ - if (stmt_may_clobber_ref_p_1 (defstmt, &read, - /* tbaa_p = */ len_was_null)) - break; - vuse = gimple_vuse (defstmt); - } while (true); - - if (gimple_store_p (defstmt) - && gimple_assign_single_p (defstmt) - && TREE_CODE (gimple_assign_rhs1 (defstmt)) == STRING_CST - && !gimple_clobber_p (defstmt)) - { - tree str = gimple_assign_rhs1 (defstmt); - src2 = gimple_assign_lhs (defstmt); - /* The string must contain all null char's for now. */ - for (int i = 0; i < TREE_STRING_LENGTH (str); i++) - { - if (TREE_STRING_POINTER (str)[i] != 0) - { - src2 = NULL_TREE; - break; - } - } - } - else if (gimple_store_p (defstmt) - && gimple_assign_single_p (defstmt) - && TREE_CODE (gimple_assign_rhs1 (defstmt)) == CONSTRUCTOR - && !gimple_clobber_p (defstmt)) - src2 = gimple_assign_lhs (defstmt); - else if (gimple_call_builtin_p (defstmt, BUILT_IN_MEMSET) - && TREE_CODE (gimple_call_arg (defstmt, 0)) == ADDR_EXPR - && TREE_CODE (gimple_call_arg (defstmt, 1)) == INTEGER_CST) - { - src2 = TREE_OPERAND (gimple_call_arg (defstmt, 0), 0); - len2 = gimple_call_arg (defstmt, 2); - val = gimple_call_arg (defstmt, 1); - /* For non-0 val, we'd have to transform stmt from assignment - into memset (only if dest is addressable). */ - if (!integer_zerop (val) && is_gimple_assign (stmt)) - src2 = NULL_TREE; - } - - if (src2 == NULL_TREE) - return false; - - if (len2 == NULL_TREE) - len2 = (TREE_CODE (src2) == COMPONENT_REF - ? DECL_SIZE_UNIT (TREE_OPERAND (src2, 1)) - : TYPE_SIZE_UNIT (TREE_TYPE (src2))); - if (len2 == NULL_TREE - || !poly_int_tree_p (len2)) - return false; - - src = get_addr_base_and_unit_offset (src, &offset); - src2 = get_addr_base_and_unit_offset (src2, &offset2); - if (src == NULL_TREE - || src2 == NULL_TREE - || maybe_lt (offset, offset2)) - return false; - - if (!operand_equal_p (src, src2, 0)) - return false; - - /* [ src + offset2, src + offset2 + len2 - 1 ] is set to val. - Make sure that - [ src + offset, src + offset + len - 1 ] is a subset of that. */ - if (maybe_gt (wi::to_poly_offset (len) + (offset - offset2), - wi::to_poly_offset (len2))) - return false; - - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "Simplified\n "); - print_gimple_stmt (dump_file, stmt, 0, dump_flags); - fprintf (dump_file, "after previous\n "); - print_gimple_stmt (dump_file, defstmt, 0, dump_flags); - } - - /* For simplicity, don't change the kind of the stmt, - turn dest = src; into dest = {}; and memcpy (&dest, &src, len); - into memset (&dest, val, len); - In theory we could change dest = src into memset if dest - is addressable (maybe beneficial if val is not 0), or - memcpy (&dest, &src, len) into dest = {} if len is the size - of dest, dest isn't volatile. */ - if (is_gimple_assign (stmt)) - { - tree ctor = build_constructor (TREE_TYPE (dest), NULL); - gimple_assign_set_rhs_from_tree (gsip, ctor); - update_stmt (stmt); - } - else /* If stmt is memcpy, transform it into memset. */ - { - gcall *call = as_a <gcall *> (stmt); - tree fndecl = builtin_decl_implicit (BUILT_IN_MEMSET); - gimple_call_set_fndecl (call, fndecl); - gimple_call_set_fntype (call, TREE_TYPE (fndecl)); - gimple_call_set_arg (call, 1, val); - update_stmt (stmt); - } - - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "into\n "); - print_gimple_stmt (dump_file, stmt, 0, dump_flags); - } - return true; -} - /* Fold function call to builtin mem{{,p}cpy,move}. Try to detect and diagnose (otherwise undefined) overlapping copies without preventing folding. When folded, GCC guarantees that overlapping memcpy has @@ -1190,8 +1028,7 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi, { new_stmt = gimple_build_assign (NULL_TREE, srcmem); srcmem - = create_tmp_reg_or_ssa_name (TREE_TYPE (srcmem), - new_stmt); + = make_ssa_name (TREE_TYPE (srcmem), new_stmt); gimple_assign_set_lhs (new_stmt, srcmem); gimple_set_vuse (new_stmt, gimple_vuse (stmt)); gimple_set_location (new_stmt, loc); @@ -1322,15 +1159,6 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi, return false; } - /* Try to optimize the memcpy to memset if src and dest are addresses. */ - if (code != BUILT_IN_MEMPCPY - && TREE_CODE (dest) == ADDR_EXPR - && TREE_CODE (src) == ADDR_EXPR - && TREE_CODE (len) == INTEGER_CST - && optimize_memcpy_to_memset (gsi, TREE_OPERAND (dest, 0), - TREE_OPERAND (src, 0), len)) - return true; - if (!tree_fits_shwi_p (len)) return false; if (!srctype @@ -1469,8 +1297,7 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi, if (! is_gimple_min_invariant (srcvar)) { new_stmt = gimple_build_assign (NULL_TREE, srcvar); - srcvar = create_tmp_reg_or_ssa_name (TREE_TYPE (srcvar), - new_stmt); + srcvar = make_ssa_name (TREE_TYPE (srcvar), new_stmt); gimple_assign_set_lhs (new_stmt, srcvar); gimple_set_vuse (new_stmt, gimple_vuse (stmt)); gimple_set_location (new_stmt, loc); @@ -2442,7 +2269,7 @@ gimple_fold_builtin_strchr (gimple_stmt_iterator *gsi, bool is_strrchr) gimple_seq stmts = NULL; gimple *new_stmt = gimple_build_call (strlen_fn, 1, str); gimple_set_location (new_stmt, loc); - len = create_tmp_reg_or_ssa_name (size_type_node); + len = make_ssa_name (size_type_node); gimple_call_set_lhs (new_stmt, len); gimple_seq_add_stmt_without_update (&stmts, new_stmt); @@ -2588,7 +2415,7 @@ gimple_fold_builtin_strcat (gimple_stmt_iterator *gsi, tree dst, tree src) gimple_seq stmts = NULL, stmts2; gimple *repl = gimple_build_call (strlen_fn, 1, dst); gimple_set_location (repl, loc); - newdst = create_tmp_reg_or_ssa_name (size_type_node); + newdst = make_ssa_name (size_type_node); gimple_call_set_lhs (repl, newdst); gimple_seq_add_stmt_without_update (&stmts, repl); @@ -2821,7 +2648,7 @@ gimple_load_first_char (location_t loc, tree str, gimple_seq *stmts) tree temp = fold_build2_loc (loc, MEM_REF, cst_uchar_node, str, off0); gassign *stmt = gimple_build_assign (NULL_TREE, temp); - var = create_tmp_reg_or_ssa_name (cst_uchar_node, stmt); + var = make_ssa_name (cst_uchar_node, stmt); gimple_assign_set_lhs (stmt, var); gimple_seq_add_stmt_without_update (stmts, stmt); @@ -2992,7 +2819,7 @@ gimple_fold_builtin_string_compare (gimple_stmt_iterator *gsi) if (lhs) { - tree c = create_tmp_reg_or_ssa_name (integer_type_node); + tree c = make_ssa_name (integer_type_node); stmt = gimple_build_assign (c, NOP_EXPR, var); gimple_seq_add_stmt_without_update (&stmts, stmt); @@ -3014,11 +2841,11 @@ gimple_fold_builtin_string_compare (gimple_stmt_iterator *gsi) if (lhs) { - tree c1 = create_tmp_reg_or_ssa_name (integer_type_node); + tree c1 = make_ssa_name (integer_type_node); gassign *convert1 = gimple_build_assign (c1, NOP_EXPR, temp1); gimple_seq_add_stmt_without_update (&stmts, convert1); - tree c2 = create_tmp_reg_or_ssa_name (integer_type_node); + tree c2 = make_ssa_name (integer_type_node); gassign *convert2 = gimple_build_assign (c2, NOP_EXPR, temp2); gimple_seq_add_stmt_without_update (&stmts, convert2); @@ -4258,6 +4085,40 @@ gimple_fold_builtin_omp_is_initial_device (gimple_stmt_iterator *gsi) return false; } +/* omp_get_initial_device was in OpenMP 5.0/5.1 explicitly and in + 5.0 implicitly the same as omp_get_num_devices; since 6.0 it is + unspecified whether -1 or omp_get_num_devices() is returned. For + better backward compatibility, use omp_get_num_devices() on the + host - and -1 on the device (where the result is unspecified). */ + +static bool +gimple_fold_builtin_omp_get_initial_device (gimple_stmt_iterator *gsi) +{ +#if ACCEL_COMPILER + replace_call_with_value (gsi, build_int_cst (integer_type_node, -1)); +#else + if (!ENABLE_OFFLOADING) + replace_call_with_value (gsi, integer_zero_node); + else + { + tree fn = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_DEVICES); + gcall *repl = gimple_build_call (fn, 0); + replace_call_with_call_and_fold (gsi, repl); + } +#endif + return true; +} + +static bool +gimple_fold_builtin_omp_get_num_devices (gimple_stmt_iterator *gsi) +{ + if (!ENABLE_OFFLOADING) + { + replace_call_with_value (gsi, integer_zero_node); + return true; + } + return false; +} /* Fold a call to __builtin_acc_on_device. */ @@ -5502,6 +5363,12 @@ gimple_fold_builtin (gimple_stmt_iterator *gsi) case BUILT_IN_OMP_IS_INITIAL_DEVICE: return gimple_fold_builtin_omp_is_initial_device (gsi); + case BUILT_IN_OMP_GET_INITIAL_DEVICE: + return gimple_fold_builtin_omp_get_initial_device (gsi); + + case BUILT_IN_OMP_GET_NUM_DEVICES: + return gimple_fold_builtin_omp_get_num_devices (gsi); + case BUILT_IN_REALLOC: return gimple_fold_builtin_realloc (gsi); @@ -6178,7 +6045,7 @@ has_use_on_stmt (tree name, gimple *stmt) /* Add the lhs of each statement of SEQ to DCE_WORKLIST. */ -static void +void mark_lhs_in_seq_for_dce (bitmap dce_worklist, gimple_seq seq) { if (!dce_worklist) @@ -6239,8 +6106,9 @@ replace_stmt_with_simplification (gimple_stmt_iterator *gsi, auto code = tree_code (res_op->code); if (TREE_CODE_CLASS (code) == tcc_comparison /* GIMPLE_CONDs condition may not throw. */ - && (!flag_exceptions - || !cfun->can_throw_non_call_exceptions + && ((cfun + && (!flag_exceptions + || !cfun->can_throw_non_call_exceptions)) || !operation_could_trap_p (code, FLOAT_TYPE_P (TREE_TYPE (ops[0])), false, NULL_TREE))) @@ -6276,6 +6144,33 @@ replace_stmt_with_simplification (gimple_stmt_iterator *gsi, } else if (!inplace) { + /* For throwing comparisons, see if the GIMPLE_COND is the same as + the comparison would be. + This can happen due to the match pattern for + `(ne (cmp @0 @1) integer_zerop)` which creates a new expression + for the comparison. */ + if (TREE_CODE_CLASS (code) == tcc_comparison + && (!cfun + || (flag_exceptions + && cfun->can_throw_non_call_exceptions)) + && operation_could_trap_p (code, + FLOAT_TYPE_P (TREE_TYPE (ops[0])), + false, NULL_TREE)) + { + tree lhs = gimple_cond_lhs (cond_stmt); + if (gimple_cond_code (cond_stmt) == NE_EXPR + && TREE_CODE (lhs) == SSA_NAME + && INTEGRAL_TYPE_P (TREE_TYPE (lhs)) + && integer_zerop (gimple_cond_rhs (cond_stmt))) + { + gimple *s = SSA_NAME_DEF_STMT (lhs); + if (is_gimple_assign (s) + && gimple_assign_rhs_code (s) == code + && operand_equal_p (gimple_assign_rhs1 (s), ops[0]) + && operand_equal_p (gimple_assign_rhs2 (s), ops[1])) + return false; + } + } tree res = maybe_push_res_to_seq (res_op, seq); if (!res) return false; @@ -6706,16 +6601,6 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace, tree (*valueize) (tree), { case GIMPLE_ASSIGN: { - if (gimple_assign_load_p (stmt) && gimple_store_p (stmt)) - { - if (optimize_memcpy_to_memset (gsi, gimple_assign_lhs (stmt), - gimple_assign_rhs1 (stmt), - /* len = */NULL_TREE)) - { - changed = true; - break; - } - } /* Try to canonicalize for boolean-typed X the comparisons X == 0, X == 1, X != 0, and X != 1. */ if (gimple_assign_rhs_code (stmt) == EQ_EXPR @@ -10232,19 +10117,21 @@ fold_const_aggregate_ref_1 (tree t, tree (*valueize) (tree)) base = get_ref_base_and_extent (t, &offset, &size, &max_size, &reverse); ctor = get_base_constructor (base, &offset, valueize); + /* We cannot determine ctor. */ + if (!ctor) + return NULL_TREE; /* Empty constructor. Always fold to 0. */ if (ctor == error_mark_node) return build_zero_cst (TREE_TYPE (t)); - /* We do not know precise address. */ + /* We do not know precise access. */ if (!known_size_p (max_size) || maybe_ne (max_size, size)) return NULL_TREE; - /* We cannot determine ctor. */ - if (!ctor) - return NULL_TREE; - /* Out of bound array access. Value is undefined, but don't fold. */ if (maybe_lt (offset, 0)) return NULL_TREE; + /* Access with reverse storage order. */ + if (reverse) + return NULL_TREE; tem = fold_ctor_reference (TREE_TYPE (t), ctor, offset, size, base); if (tem) @@ -10264,7 +10151,6 @@ fold_const_aggregate_ref_1 (tree t, tree (*valueize) (tree)) && offset.is_constant (&coffset) && (coffset % BITS_PER_UNIT != 0 || csize % BITS_PER_UNIT != 0) - && !reverse && BYTES_BIG_ENDIAN == WORDS_BIG_ENDIAN) { poly_int64 bitoffset; @@ -10391,13 +10277,12 @@ gimple_get_virt_method_for_vtable (HOST_WIDE_INT token, access_index = offset / BITS_PER_UNIT / elt_size; gcc_checking_assert (offset % (elt_size * BITS_PER_UNIT) == 0); - /* The C++ FE can now produce indexed fields, and we check if the indexes - match. */ + /* This code makes an assumption that there are no + indexed fileds produced by C++ FE, so we can directly index the array. */ if (access_index < CONSTRUCTOR_NELTS (init)) { fn = CONSTRUCTOR_ELT (init, access_index)->value; - tree idx = CONSTRUCTOR_ELT (init, access_index)->index; - gcc_checking_assert (!idx || tree_to_uhwi (idx) == access_index); + gcc_checking_assert (!CONSTRUCTOR_ELT (init, access_index)->index); STRIP_NOPS (fn); } else @@ -10790,7 +10675,7 @@ gimple_build (gimple_stmt_iterator *gsi, gsi->bb ? follow_all_ssa_edges : gimple_build_valueize); if (!res) { - res = create_tmp_reg_or_ssa_name (type); + res = make_ssa_name (type); gimple *stmt; if (code == REALPART_EXPR || code == IMAGPART_EXPR @@ -10822,7 +10707,7 @@ gimple_build (gimple_stmt_iterator *gsi, gsi->bb ? follow_all_ssa_edges : gimple_build_valueize); if (!res) { - res = create_tmp_reg_or_ssa_name (type); + res = make_ssa_name (type); gimple *stmt = gimple_build_assign (res, code, op0, op1); gimple_set_location (stmt, loc); gimple_seq_add_stmt_without_update (&seq, stmt); @@ -10849,7 +10734,7 @@ gimple_build (gimple_stmt_iterator *gsi, gsi->bb ? follow_all_ssa_edges : gimple_build_valueize); if (!res) { - res = create_tmp_reg_or_ssa_name (type); + res = make_ssa_name (type); gimple *stmt; if (code == BIT_FIELD_REF) stmt = gimple_build_assign (res, code, @@ -10885,7 +10770,7 @@ gimple_build (gimple_stmt_iterator *gsi, } if (!VOID_TYPE_P (type)) { - res = create_tmp_reg_or_ssa_name (type); + res = make_ssa_name (type); gimple_call_set_lhs (stmt, res); } gimple_set_location (stmt, loc); @@ -10920,7 +10805,7 @@ gimple_build (gimple_stmt_iterator *gsi, } if (!VOID_TYPE_P (type)) { - res = create_tmp_reg_or_ssa_name (type); + res = make_ssa_name (type); gimple_call_set_lhs (stmt, res); } gimple_set_location (stmt, loc); @@ -10957,7 +10842,7 @@ gimple_build (gimple_stmt_iterator *gsi, } if (!VOID_TYPE_P (type)) { - res = create_tmp_reg_or_ssa_name (type); + res = make_ssa_name (type); gimple_call_set_lhs (stmt, res); } gimple_set_location (stmt, loc); @@ -10995,7 +10880,7 @@ gimple_build (gimple_stmt_iterator *gsi, } if (!VOID_TYPE_P (type)) { - res = create_tmp_reg_or_ssa_name (type); + res = make_ssa_name (type); gimple_call_set_lhs (stmt, res); } gimple_set_location (stmt, loc); |