diff options
author | Martin Liska <mliska@suse.cz> | 2021-11-23 11:28:31 +0100 |
---|---|---|
committer | Martin Liska <mliska@suse.cz> | 2021-11-23 11:28:31 +0100 |
commit | e6cf319354390ac1720646654f50d72dde3fa618 (patch) | |
tree | bca470dd5247aa7c9cb7eebba8e56de892ee58fa /gcc | |
parent | 44a06feaf84111c298bb906b4906b54073fc61d5 (diff) | |
parent | d3f22853d18195b6ef4c9e26298befa55402eb4a (diff) | |
download | gcc-e6cf319354390ac1720646654f50d72dde3fa618.zip gcc-e6cf319354390ac1720646654f50d72dde3fa618.tar.gz gcc-e6cf319354390ac1720646654f50d72dde3fa618.tar.bz2 |
Merge branch 'master' into devel/sphinx
Diffstat (limited to 'gcc')
44 files changed, 942 insertions, 133 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1e94c54..b70adbd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,39 @@ +2021-11-22 Roger Sayle <roger@nextmovesoftware.com> + + PR tree-optimization/98953 + PR tree-optimization/103345 + * gimple-ssa-store-merging.c (find_bswap_or_nop_1): Handle + BIT_XOR_EXPR and PLUS_EXPR the same as BIT_IOR_EXPR. + (pass_optimize_bswap::execute): Likewise. + +2021-11-22 Martin Liska <mliska@suse.cz> + + * doc/invoke.texi: Remove duplicate documentation for 3 params. + +2021-11-22 Richard Biener <rguenther@suse.de> + + PR tree-optimization/103351 + * tree-ssa-dce.c (sort_phi_args): Sort after e->dest_idx as + second key. + +2021-11-22 liuhongt <hongtao.liu@intel.com> + + PR target/103275 + * config/i386/constraints.md (Bk): New + define_memory_constraint. + * config/i386/i386-protos.h (ix86_gpr_tls_address_pattern_p): + Declare. + * config/i386/i386.c (ix86_gpr_tls_address_pattern_p): New + function. + * config/i386/i386.md (*movsi_internal): Don't allow + mask/sse/mmx move in TLS code sequences. + (*movdi_internal): Ditto. + +2021-11-22 Kewen Lin <linkw@linux.ibm.com> + + * config/xtensa/xtensa.md (movdi_internal, movdf_internal): Fix split + condition. + 2021-11-21 Jakub Jelinek <jakub@redhat.com> PR c++/101180 diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 7e15177..e45f2d0 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20211122 +20211123 diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 50d7010..b71358e 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -13848,7 +13848,6 @@ c_clone_omp_udr (tree stmt, tree omp_decl1, tree omp_decl2, id.transform_call_graph_edges = CB_CGE_DUPLICATE; id.transform_new_cfg = true; id.transform_return_to_modify = false; - id.transform_lang_insert_block = NULL; id.eh_lp_nr = 0; walk_tree (&stmt, copy_tree_body_r, &id, NULL); return stmt; diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md index a057218..ef43211 100644 --- a/gcc/config/rs6000/altivec.md +++ b/gcc/config/rs6000/altivec.md @@ -3984,12 +3984,43 @@ DONE; }) +;; Vector reverse elements for V16QI V8HI V4SI V4SF (define_expand "altivec_vreve<mode>2" - [(set (match_operand:VEC_A 0 "register_operand" "=v") - (unspec:VEC_A [(match_operand:VEC_A 1 "register_operand" "v")] + [(set (match_operand:VEC_K 0 "register_operand" "=v") + (unspec:VEC_K [(match_operand:VEC_K 1 "register_operand" "v")] UNSPEC_VREVEV))] "TARGET_ALTIVEC" { + if (TARGET_P9_VECTOR) + { + if (<MODE>mode == V16QImode) + emit_insn (gen_p9_xxbrq_v16qi (operands[0], operands[1])); + else if (<MODE>mode == V8HImode) + { + rtx subreg1 = simplify_gen_subreg (V1TImode, operands[1], + <MODE>mode, 0); + rtx temp = gen_reg_rtx (V1TImode); + emit_insn (gen_p9_xxbrq_v1ti (temp, subreg1)); + rtx subreg2 = simplify_gen_subreg (<MODE>mode, temp, + V1TImode, 0); + emit_insn (gen_p9_xxbrh_v8hi (operands[0], subreg2)); + } + else /* V4SI and V4SF. */ + { + rtx subreg1 = simplify_gen_subreg (V1TImode, operands[1], + <MODE>mode, 0); + rtx temp = gen_reg_rtx (V1TImode); + emit_insn (gen_p9_xxbrq_v1ti (temp, subreg1)); + rtx subreg2 = simplify_gen_subreg (<MODE>mode, temp, + V1TImode, 0); + if (<MODE>mode == V4SImode) + emit_insn (gen_p9_xxbrw_v4si (operands[0], subreg2)); + else + emit_insn (gen_p9_xxbrw_v4sf (operands[0], subreg2)); + } + DONE; + } + int i, j, size, num_elements; rtvec v = rtvec_alloc (16); rtx mask = gen_reg_rtx (V16QImode); @@ -4008,6 +4039,17 @@ DONE; }) +;; Vector reverse elements for V2DI V2DF +(define_expand "altivec_vreve<mode>2" + [(set (match_operand:VEC_64 0 "register_operand" "=v") + (unspec:VEC_64 [(match_operand:VEC_64 1 "register_operand" "v")] + UNSPEC_VREVEV))] + "TARGET_ALTIVEC" +{ + emit_insn (gen_xxswapd_<mode> (operands[0], operands[1])); + DONE; +}) + ;; Vector SIMD PEM v2.06c defines LVLX, LVLXL, LVRX, LVRXL, ;; STVLX, STVLXL, STVVRX, STVRXL are available only on Cell. (define_insn "altivec_lvlx" diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 205416f..836ab86 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,27 @@ +2021-11-22 Jason Merrill <jason@redhat.com> + + * typeck.c (build_x_unary_op): Set address location. + (convert_member_func_to_ptr): Handle location wrapper. + * pt.c (convert_nontype_argument): Likewise. + +2021-11-22 Jason Merrill <jason@redhat.com> + + * typeck.c (check_return_expr): Only strip location wrapper during + NRV handling. + +2021-11-22 Jakub Jelinek <jakub@redhat.com> + + PR c++/101731 + * parser.c (cp_parser_late_parsing_oacc_routine): Set + parser->oacc_routine->fndecl_seen here, rather than ... + (cp_finalize_oacc_routine): ... here. Don't error if + parser->oacc_routine->fndecl_seen is set for FUNCTION_DECLs. + +2021-11-22 Jakub Jelinek <jakub@redhat.com> + + PR c++/103349 + * constexpr.c (potential_constant_expression_1): Punt on OMP_MASKED. + 2021-11-19 Jakub Jelinek <jakub@redhat.com> PR c++/101180 diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c index 22ed7d3..e6fd27f 100644 --- a/gcc/cp/optimize.c +++ b/gcc/cp/optimize.c @@ -103,7 +103,6 @@ clone_body (tree clone, tree fn, void *arg_map) id.transform_call_graph_edges = CB_CGE_DUPLICATE; id.transform_new_cfg = true; id.transform_return_to_modify = false; - id.transform_lang_insert_block = NULL; /* We're not inside any EH region. */ id.eh_lp_nr = 0; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index c73e035..288625e 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -7267,6 +7267,8 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain) const bool val_dep_p = value_dependent_expression_p (expr); if (val_dep_p) expr = canonicalize_expr_argument (expr, complain); + else + STRIP_ANY_LOCATION_WRAPPER (expr); /* 14.3.2/5: The null pointer{,-to-member} conversion is applied to a non-type argument of "nullptr". */ diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index d962b29..79b8162 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -6066,7 +6066,6 @@ clone_omp_udr (tree stmt, tree omp_decl1, tree omp_decl2, id.transform_call_graph_edges = CB_CGE_DUPLICATE; id.transform_new_cfg = true; id.transform_return_to_modify = false; - id.transform_lang_insert_block = NULL; id.eh_lp_nr = 0; walk_tree (&stmt, copy_tree_body_r, &id, NULL); return stmt; diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 58919aa..84dcb6f 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -6492,6 +6492,11 @@ build_x_unary_op (location_t loc, enum tree_code code, cp_expr xarg, } exp = cp_build_addr_expr_strict (xarg, complain); + + if (TREE_CODE (exp) == PTRMEM_CST) + exp = maybe_wrap_with_location (exp, loc); + else + protected_set_expr_location (exp, loc); } if (processing_template_decl && exp != error_mark_node) @@ -8179,10 +8184,14 @@ convert_member_func_to_ptr (tree type, tree expr, tsubst_flags_t complain) if (!(complain & tf_warning_or_error)) return error_mark_node; + location_t loc = cp_expr_loc_or_input_loc (expr); + if (pedantic || warn_pmf2ptr) - pedwarn (input_location, pedantic ? OPT_Wpedantic : OPT_Wpmf_conversions, + pedwarn (loc, pedantic ? OPT_Wpedantic : OPT_Wpmf_conversions, "converting from %qH to %qI", intype, type); + STRIP_ANY_LOCATION_WRAPPER (expr); + if (TREE_CODE (intype) == METHOD_TYPE) expr = build_addr_func (expr, complain); else if (TREE_CODE (expr) == PTRMEM_CST) @@ -8197,7 +8206,9 @@ convert_member_func_to_ptr (tree type, tree expr, tsubst_flags_t complain) if (expr == error_mark_node) return error_mark_node; - return build_nop (type, expr); + expr = build_nop (type, expr); + SET_EXPR_LOCATION (expr, loc); + return expr; } /* Build a NOP_EXPR to TYPE, but mark it as a reinterpret_cast so that @@ -10545,19 +10556,20 @@ check_return_expr (tree retval, bool *no_warning) this restriction, anyway. (jason 2000-11-19) See finish_function and finalize_nrv for the rest of this optimization. */ + tree bare_retval = NULL_TREE; if (retval) { retval = maybe_undo_parenthesized_ref (retval); - STRIP_ANY_LOCATION_WRAPPER (retval); + bare_retval = tree_strip_any_location_wrapper (retval); } - bool named_return_value_okay_p = can_do_nrvo_p (retval, functype); + bool named_return_value_okay_p = can_do_nrvo_p (bare_retval, functype); if (fn_returns_value_p && flag_elide_constructors) { if (named_return_value_okay_p && (current_function_return_value == NULL_TREE - || current_function_return_value == retval)) - current_function_return_value = retval; + || current_function_return_value == bare_retval)) + current_function_return_value = bare_retval; else current_function_return_value = error_mark_node; } @@ -10571,7 +10583,7 @@ check_return_expr (tree retval, bool *no_warning) maybe_warn_pessimizing_move (retval, functype); /* Do any required conversions. */ - if (retval == result || DECL_CONSTRUCTOR_P (current_function_decl)) + if (bare_retval == result || DECL_CONSTRUCTOR_P (current_function_decl)) /* No conversions are required. */ ; else diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 34484f6..97b6c99 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -14754,14 +14754,6 @@ Maximum number of arrays per scop. @item max-vartrack-reverse-op-size Max. size of loc list for which reverse ops should be added. -@item tracer-dynamic-coverage-feedback -The percentage of function, weighted by execution frequency, -that must be covered by trace formation. -Used when profile feedback is available. - -@item max-inline-recursive-depth-auto -The maximum depth of recursive inlining for non-inline functions. - @item fsm-scale-path-stmts Scale factor to apply to the number of statements in a threading path when comparing to the number of (scaled) blocks. diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index ad9703e..73f090b 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -6061,6 +6061,28 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace, tree (*valueize) (tree)) if (REFERENCE_CLASS_P (*lhs) && maybe_canonicalize_mem_ref_addr (lhs)) changed = true; + /* Canonicalize &MEM[ssa_n, CST] to ssa_n p+ CST. + This cannot be done in maybe_canonicalize_mem_ref_addr + as the gimple now has two operands rather than one. + The same reason why this can't be done in + maybe_canonicalize_mem_ref_addr is the same reason why + this can't be done inplace. */ + if (!inplace && TREE_CODE (*rhs) == ADDR_EXPR) + { + tree inner = TREE_OPERAND (*rhs, 0); + if (TREE_CODE (inner) == MEM_REF + && TREE_CODE (TREE_OPERAND (inner, 0)) == SSA_NAME + && TREE_CODE (TREE_OPERAND (inner, 1)) == INTEGER_CST) + { + tree ptr = TREE_OPERAND (inner, 0); + tree addon = TREE_OPERAND (inner, 1); + addon = fold_convert (sizetype, addon); + gimple_assign_set_rhs_with_ops (gsi, POINTER_PLUS_EXPR, + ptr, addon); + changed = true; + stmt = gsi_stmt (*gsi); + } + } } else { diff --git a/gcc/gimple-loop-jam.c b/gcc/gimple-loop-jam.c index 666f740..933a4e0 100644 --- a/gcc/gimple-loop-jam.c +++ b/gcc/gimple-loop-jam.c @@ -402,10 +402,10 @@ adjust_unroll_factor (class loop *inner, struct data_dependence_relation *ddr, a >= N, or b > 0, or b is zero and a > 0. Otherwise the unroll factor needs to be limited so that the first condition holds. That may limit the factor down to zero in the worst case. */ - int dist = dist_v[0]; + lambda_int dist = dist_v[0]; if (dist < 0) gcc_unreachable (); - else if ((unsigned)dist >= *unroll) + else if (dist >= (lambda_int)*unroll) ; else if (lambda_vector_zerop (dist_v + 1, DDR_NB_LOOPS (ddr) - 1)) { diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c index 4efa200..1740c9e 100644 --- a/gcc/gimple-ssa-store-merging.c +++ b/gcc/gimple-ssa-store-merging.c @@ -742,10 +742,7 @@ find_bswap_or_nop_1 (gimple *stmt, struct symbolic_number *n, int limit) struct symbolic_number n1, n2; gimple *source_stmt, *source_stmt2; - if (code != BIT_IOR_EXPR) - return NULL; - - if (TREE_CODE (rhs2) != SSA_NAME) + if (!rhs2 || TREE_CODE (rhs2) != SSA_NAME) return NULL; rhs2_stmt = SSA_NAME_DEF_STMT (rhs2); @@ -753,6 +750,8 @@ find_bswap_or_nop_1 (gimple *stmt, struct symbolic_number *n, int limit) switch (code) { case BIT_IOR_EXPR: + case BIT_XOR_EXPR: + case PLUS_EXPR: source_stmt1 = find_bswap_or_nop_1 (rhs1_stmt, &n1, limit - 1); if (!source_stmt1) @@ -1495,6 +1494,8 @@ pass_optimize_bswap::execute (function *fun) continue; /* Fall through. */ case BIT_IOR_EXPR: + case BIT_XOR_EXPR: + case PLUS_EXPR: break; case CONSTRUCTOR: { diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 467b135..816cdaf 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -13128,21 +13128,15 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) /* Helper for gimplify_omp_loop, called through walk_tree. */ static tree -replace_reduction_placeholders (tree *tp, int *walk_subtrees, void *data) +note_no_context_vars (tree *tp, int *, void *data) { - if (DECL_P (*tp)) + if (VAR_P (*tp) + && DECL_CONTEXT (*tp) == NULL_TREE + && !is_global_var (*tp)) { - tree *d = (tree *) data; - if (*tp == OMP_CLAUSE_REDUCTION_PLACEHOLDER (d[0])) - { - *tp = OMP_CLAUSE_REDUCTION_PLACEHOLDER (d[1]); - *walk_subtrees = 0; - } - else if (*tp == OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (d[0])) - { - *tp = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (d[1]); - *walk_subtrees = 0; - } + vec<tree> *d = (vec<tree> *) data; + d->safe_push (*tp); + DECL_CONTEXT (*tp) = current_function_decl; } return NULL_TREE; } @@ -13312,7 +13306,8 @@ gimplify_omp_loop (tree *expr_p, gimple_seq *pre_p) { if (pass == 2) { - tree bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL); + tree bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, + make_node (BLOCK)); append_to_statement_list (*expr_p, &BIND_EXPR_BODY (bind)); *expr_p = make_node (OMP_PARALLEL); TREE_TYPE (*expr_p) = void_type_node; @@ -13379,25 +13374,63 @@ gimplify_omp_loop (tree *expr_p, gimple_seq *pre_p) *pc = copy_node (c); OMP_CLAUSE_DECL (*pc) = unshare_expr (OMP_CLAUSE_DECL (c)); TREE_TYPE (*pc) = unshare_expr (TREE_TYPE (c)); - OMP_CLAUSE_REDUCTION_INIT (*pc) - = unshare_expr (OMP_CLAUSE_REDUCTION_INIT (c)); - OMP_CLAUSE_REDUCTION_MERGE (*pc) - = unshare_expr (OMP_CLAUSE_REDUCTION_MERGE (c)); if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (*pc)) { + auto_vec<tree> no_context_vars; + int walk_subtrees = 0; + note_no_context_vars (&OMP_CLAUSE_REDUCTION_PLACEHOLDER (c), + &walk_subtrees, &no_context_vars); + if (tree p = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)) + note_no_context_vars (&p, &walk_subtrees, &no_context_vars); + walk_tree_without_duplicates (&OMP_CLAUSE_REDUCTION_INIT (c), + note_no_context_vars, + &no_context_vars); + walk_tree_without_duplicates (&OMP_CLAUSE_REDUCTION_MERGE (c), + note_no_context_vars, + &no_context_vars); + OMP_CLAUSE_REDUCTION_PLACEHOLDER (*pc) = copy_node (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)); if (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (*pc)) OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (*pc) = copy_node (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)); - tree nc = *pc; - tree data[2] = { c, nc }; - walk_tree_without_duplicates (&OMP_CLAUSE_REDUCTION_INIT (nc), - replace_reduction_placeholders, - data); - walk_tree_without_duplicates (&OMP_CLAUSE_REDUCTION_MERGE (nc), - replace_reduction_placeholders, - data); + + hash_map<tree, tree> decl_map; + decl_map.put (OMP_CLAUSE_DECL (c), OMP_CLAUSE_DECL (c)); + decl_map.put (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c), + OMP_CLAUSE_REDUCTION_PLACEHOLDER (*pc)); + if (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (*pc)) + decl_map.put (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c), + OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (*pc)); + + copy_body_data id; + memset (&id, 0, sizeof (id)); + id.src_fn = current_function_decl; + id.dst_fn = current_function_decl; + id.src_cfun = cfun; + id.decl_map = &decl_map; + id.copy_decl = copy_decl_no_change; + id.transform_call_graph_edges = CB_CGE_DUPLICATE; + id.transform_new_cfg = true; + id.transform_return_to_modify = false; + id.eh_lp_nr = 0; + walk_tree (&OMP_CLAUSE_REDUCTION_INIT (*pc), copy_tree_body_r, + &id, NULL); + walk_tree (&OMP_CLAUSE_REDUCTION_MERGE (*pc), copy_tree_body_r, + &id, NULL); + + for (tree d : no_context_vars) + { + DECL_CONTEXT (d) = NULL_TREE; + DECL_CONTEXT (*decl_map.get (d)) = NULL_TREE; + } + } + else + { + OMP_CLAUSE_REDUCTION_INIT (*pc) + = unshare_expr (OMP_CLAUSE_REDUCTION_INIT (c)); + OMP_CLAUSE_REDUCTION_MERGE (*pc) + = unshare_expr (OMP_CLAUSE_REDUCTION_MERGE (c)); } pc = &OMP_CLAUSE_CHAIN (*pc); break; diff --git a/gcc/match.pd b/gcc/match.pd index f059b47..886f807 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -242,6 +242,14 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (mult @0 integer_zerop@1) @1) +/* -x == x -> x == 0 */ +(for cmp (eq ne) + (simplify + (cmp:c @0 (negate @0)) + (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0)) + && !TYPE_OVERFLOW_WRAPS (TREE_TYPE(@0))) + (cmp @0 { build_zero_cst (TREE_TYPE(@0)); })))) + /* Maybe fold x * 0 to 0. The expressions aren't the same when x is NaN, since x * 0 is also NaN. Nor are they the same in modes with signed zeros, since multiplying a @@ -643,6 +651,12 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if (INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type)) (convert (trunc_mod @0 @1)))) +/* x * (1 + y / x) - y -> x - y % x */ +(simplify + (minus (mult:cs @0 (plus:s (trunc_div:s @1 @0) integer_onep)) @1) + (if (INTEGRAL_TYPE_P (type)) + (minus @0 (trunc_mod @1 @0)))) + /* Optimize TRUNC_MOD_EXPR by a power of two into a BIT_AND_EXPR, i.e. "X % C" into "X & (C - 1)", if X and C are positive. Also optimize A % (C << N) where C is a power of 2, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9872619..cdf542e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,49 @@ +2021-11-22 Jason Merrill <jason@redhat.com> + + * g++.dg/template/crash106.C: Adjust. + * g++.dg/diagnostic/ptrtomem3.C: New test. + +2021-11-22 Jason Merrill <jason@redhat.com> + + * g++.dg/cpp0x/pr65327.C: Adjust location. + * g++.dg/cpp23/constexpr-nonlit4.C: Likewise. + * g++.dg/cpp23/constexpr-nonlit5.C: Likewise. + * g++.dg/cpp2a/constexpr-init1.C: Likewise. + +2021-11-22 Jakub Jelinek <jakub@redhat.com> + Tobias Burnus <tobias@codesourcery.com> + + PR preprocessor/103165 + * c-c++-common/gomp/pragma-3.c: New test. + * c-c++-common/gomp/pragma-4.c: New test. + * c-c++-common/gomp/pragma-5.c: New test. + +2021-11-22 Roger Sayle <roger@nextmovesoftware.com> + + PR tree-optimization/98953 + PR tree-optimization/103345 + * gcc.dg/tree-ssa/pr98953.c: New test case. + * gcc.dg/tree-ssa/pr103345.c: New test case. + +2021-11-22 Jakub Jelinek <jakub@redhat.com> + + PR c++/101731 + * c-c++-common/goacc/routine-6.c: New test. + +2021-11-22 Richard Biener <rguenther@suse.de> + + PR tree-optimization/103351 + * g++.dg/torture/pr103351.C: New testcase. + +2021-11-22 Jakub Jelinek <jakub@redhat.com> + + PR c++/103349 + * g++.dg/gomp/masked-1.C: New test. + +2021-11-22 liuhongt <hongtao.liu@intel.com> + + * gcc.target/i386/pr103275.c: New test. + 2021-11-21 Jakub Jelinek <jakub@redhat.com> PR c++/101180 diff --git a/gcc/testsuite/c-c++-common/gomp/pr102431.c b/gcc/testsuite/c-c++-common/gomp/pr102431.c new file mode 100644 index 0000000..bf4f3cb --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/pr102431.c @@ -0,0 +1,16 @@ +/* PR middle-end/102431 */ + +struct S { int s; } s; +void add (struct S *, struct S *); +void init (struct S *); +void bar (int i, struct S *); +#pragma omp declare reduction (+:struct S:add (&omp_out, &omp_in)) initializer (init (&omp_priv)) + +void +foo (void) +{ + int i; + #pragma omp loop bind(teams) reduction(+:s) + for (i = 0; i < 8; i++) + bar (i, &s); +} diff --git a/gcc/testsuite/c-c++-common/gomp/pragma-3.c b/gcc/testsuite/c-c++-common/gomp/pragma-3.c new file mode 100644 index 0000000..c1dee1b --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/pragma-3.c @@ -0,0 +1,20 @@ +/* { dg-additional-options "-fdump-tree-original" } */ +/* PR preprocessor/103165 */ + +#define inner(...) #__VA_ARGS__ ; _Pragma("omp error severity(warning) message (\"Test\") at(compilation)") +#define outer(...) inner(__VA_ARGS__) + +void +f (void) +{ + const char *str = outer(inner(1,2)); /* { dg-warning "'pragma omp error' encountered: Test" } */ +} + +#if 0 +After preprocessing, the expected result are the following three lines: + const char *str = "\"1,2\" ; _Pragma(\"omp error severity(warning) message (\\\"Test\\\") at(compilation)\")" ; +#pragma omp error severity(warning) message ("Test") at(compilation) + ; +#endif + +/* { dg-final { scan-tree-dump "const char \\* str = \\(const char \\*\\) \"\\\\\"1,2\\\\\" ; _Pragma\\(\\\\\"omp error severity\\(warning\\) message \\(\\\\\\\\\\\\\"Test\\\\\\\\\\\\\"\\) at\\(compilation\\)\\\\\"\\)\";" "original" } } */ diff --git a/gcc/testsuite/c-c++-common/gomp/pragma-4.c b/gcc/testsuite/c-c++-common/gomp/pragma-4.c new file mode 100644 index 0000000..419c4ac --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/pragma-4.c @@ -0,0 +1,20 @@ +/* { dg-additional-options "-fdump-tree-original -save-temps" } */ +/* PR preprocessor/103165 */ + +#define inner(...) #__VA_ARGS__ ; _Pragma("omp error severity(warning) message (\"Test\") at(compilation)") +#define outer(...) inner(__VA_ARGS__) + +void +f (void) +{ + const char *str = outer(inner(1,2)); /* { dg-warning "'pragma omp error' encountered: Test" } */ +} + +#if 0 +After preprocessing, the expected result are the following three lines: + const char *str = "\"1,2\" ; _Pragma(\"omp error severity(warning) message (\\\"Test\\\") at(compilation)\")" ; +#pragma omp error severity(warning) message ("Test") at(compilation) + ; +#endif + +/* { dg-final { scan-tree-dump "const char \\* str = \\(const char \\*\\) \"\\\\\"1,2\\\\\" ; _Pragma\\(\\\\\"omp error severity\\(warning\\) message \\(\\\\\\\\\\\\\"Test\\\\\\\\\\\\\"\\) at\\(compilation\\)\\\\\"\\)\";" "original" } } */ diff --git a/gcc/testsuite/c-c++-common/gomp/pragma-5.c b/gcc/testsuite/c-c++-common/gomp/pragma-5.c new file mode 100644 index 0000000..af54b68 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/pragma-5.c @@ -0,0 +1,20 @@ +/* { dg-additional-options "-fdump-tree-original" } */ +/* PR preprocessor/103165 */ + +#define inner(...) #__VA_ARGS__ ; _Pragma ( " omp error severity (warning) message (\"Test\") at(compilation)" ) +#define outer(...) inner(__VA_ARGS__) + +void +f (void) +{ + const char *str = outer(inner(1,2)); /* { dg-warning "'pragma omp error' encountered: Test" } */ +} + +#if 0 +After preprocessing, the expected result are the following three lines: + const char *str = "\"1,2\" ; _Pragma ( \" omp error severity (warning) message (\\\"Test\\\") at(compilation)\" )" ; +#pragma omp error severity(warning) message ("Test") at(compilation) + ; +#endif + +/* { dg-final { scan-tree-dump "const char \\* str = \\(const char \\*\\) \"\\\\\"1,2\\\\\" ; _Pragma \\( \\\\\" omp\\\\t\\\\terror severity \\(warning\\)\\\\tmessage \\(\\\\\\\\\\\\\"Test\\\\\\\\\\\\\"\\) at\\(compilation\\)\\\\\" \\)\";" "original" } } */ diff --git a/gcc/testsuite/g++.dg/cpp0x/pr65327.C b/gcc/testsuite/g++.dg/cpp0x/pr65327.C index 6e888eb..e814995 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr65327.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr65327.C @@ -14,5 +14,5 @@ foo () constexpr volatile int // { dg-warning "deprecated" "" { target c++2a } } bar () { - return i; -} // { dg-error "lvalue-to-rvalue conversion of a volatile lvalue" } + return i; // { dg-error "lvalue-to-rvalue conversion of a volatile lvalue" } +} diff --git a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit4.C b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit4.C index e4ed2e3..bdc97a9 100644 --- a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit4.C +++ b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit4.C @@ -34,7 +34,7 @@ baz (int x) { static const int v = qux (); // { dg-message "'v' was not initialized with a constant expression" } case 12: - return v; + return v; // { dg-error "the value of 'v' is not usable in a constant expression" } } return 0; } @@ -46,12 +46,12 @@ corge (int x) { const thread_local int v = qux (); // { dg-message "'v' was not initialized with a constant expression" } case 12: - return v; + return v; // { dg-error "the value of 'v' is not usable in a constant expression" } } return 0; } constexpr int a = foo (12); constexpr int b = bar (12); -constexpr int c = baz (12); // { dg-error "the value of 'v' is not usable in a constant expression" } -constexpr int d = corge (12); // { dg-error "the value of 'v' is not usable in a constant expression" } +constexpr int c = baz (12); +constexpr int d = corge (12); diff --git a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit5.C b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit5.C index 838f282..86d5dba 100644 --- a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit5.C +++ b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit5.C @@ -34,7 +34,7 @@ baz (int x) { static int v = 6; // { dg-message "int v' is not const" } case 12: - return v; + return v; // { dg-error "the value of 'v' is not usable in a constant expression" } } return 0; } @@ -46,12 +46,12 @@ corge (int x) { thread_local int v = 6; // { dg-message "int v' is not const" } case 12: - return v; + return v; // { dg-error "the value of 'v' is not usable in a constant expression" } } return 0; } constexpr int a = foo (12); constexpr int b = bar (12); -constexpr int c = baz (12); // { dg-error "the value of 'v' is not usable in a constant expression" } -constexpr int d = corge (12); // { dg-error "the value of 'v' is not usable in a constant expression" } +constexpr int c = baz (12); +constexpr int d = corge (12); diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-init1.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-init1.C index 75984a2..e56ecfe 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-init1.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-init1.C @@ -73,11 +73,11 @@ fn7 (bool b) int a; // { dg-message ".int a. is not const" } if (b) a = 42; - return a; + return a; // { dg-error "the value of .a. is not usable" } } static_assert (fn7 (true) == 42); -static_assert (fn7 (false) == 42); // { dg-error "non-constant condition|the value of .a. is not usable" } +static_assert (fn7 (false) == 42); // { dg-error "non-constant condition" } // { dg-message "in .constexpr. expansion of" "" { target *-*-* } .-1 } constexpr int diff --git a/gcc/testsuite/g++.dg/diagnostic/ptrtomem3.C b/gcc/testsuite/g++.dg/diagnostic/ptrtomem3.C new file mode 100644 index 0000000..6096a98 --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/ptrtomem3.C @@ -0,0 +1,14 @@ +// Check that the diagnostic for a pointer-to-member expression has the caret +// at the &. + +struct A +{ + int i; +}; + +void f(); + +int main() +{ + return &A::i; // { dg-error "10:cannot convert" } +} diff --git a/gcc/testsuite/g++.dg/gomp/pr102431.C b/gcc/testsuite/g++.dg/gomp/pr102431.C new file mode 100644 index 0000000..7db36f4 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/pr102431.C @@ -0,0 +1,13 @@ +// PR middle-end/102431 + +struct S { S (); ~S (); S (const S &); void add (const S &); int s; } s; +void bar (int, S &); +#pragma omp declare reduction (+:S:omp_out.add (omp_in)) + +void +foo () +{ + #pragma omp loop bind(teams) reduction(+:s) + for (int i = 0; i < 8; i++) + bar (i, s); +} diff --git a/gcc/testsuite/g++.dg/template/crash106.C b/gcc/testsuite/g++.dg/template/crash106.C index f904bd4..35cedb5 100644 --- a/gcc/testsuite/g++.dg/template/crash106.C +++ b/gcc/testsuite/g++.dg/template/crash106.C @@ -7,6 +7,6 @@ struct A template<T> void foo(); // { dg-error "type" "" { target c++17_down } } }; -template<T N = 0.0, void (A::*)() = &A::foo<N> > struct B {}; // { dg-error "type|declared" "" { target c++17_down } } +template<T N = 0.0, void (A::*)() = &A::foo<N> > struct B {}; // { dg-error "type|declared|could not convert" "" { target c++17_down } } -B<> b; // { dg-error "(could not convert|no matches)" "" { target c++17_down } } +B<> b; // { dg-message "" "" { target c++17_down } } diff --git a/gcc/testsuite/g++.dg/torture/pr103361.C b/gcc/testsuite/g++.dg/torture/pr103361.C new file mode 100644 index 0000000..ec1d6e1 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr103361.C @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-floop-unroll-and-jam" } */ + +char a, b; +extern unsigned short c[]; +extern bool d[]; +const unsigned short &e(const unsigned short &f, const unsigned short &g) { + if (g < f) + return g; + return f; +} +void k() { + for (int h = 0; b; h += 3) + for (unsigned long i = 0; i < 11104842004558084287ULL; + i += -11104842004558084300ULL) + for (bool j(e(6, e(6, c[h + i]))); j < (bool)a; j = 7) + d[7] = 0; +} diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr102216-1.C b/gcc/testsuite/g++.dg/tree-ssa/pr102216-1.C new file mode 100644 index 0000000..21f7f67 --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/pr102216-1.C @@ -0,0 +1,21 @@ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +void link_error (); +void g () +{ + const char **language_names; + + language_names = new const char *[6]; + + const char **language_names_p = language_names; + + language_names_p++; + language_names_p++; + language_names_p++; + + if ( (language_names_p) - (language_names+3) != 0) + link_error(); + delete[] language_names; +} +/* We should have removed the link_error on the gimple level as GCC should + be able to tell that language_names_p is the same as language_names+3. */ +/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized" } } */ diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr102216-2.C b/gcc/testsuite/g++.dg/tree-ssa/pr102216-2.C new file mode 100644 index 0000000..8d351a9 --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/pr102216-2.C @@ -0,0 +1,45 @@ +/* { dg-options "-O2 -Wall" } */ +#include <algorithm> + +static inline bool +compare_cstrings (const char *str1, const char *str2) +{ + return str1 < str2; +} + +void +add_set_language_command () +{ + static const char **language_names; + + language_names = new const char *[6]; + + language_names[0] = "auto"; + language_names[1] = "local"; + language_names[2] = "unknown"; + + const char **language_names_p = language_names; + /* language_names_p == &language_names[0]. */ + language_names_p++; + /* language_names_p == &language_names[1]. */ + language_names_p++; + /* language_names_p == &language_names[2]. */ + language_names_p++; + /* language_names_p == &language_names[3]. */ + + const char **sort_begin; + + if (0) + sort_begin = &language_names[3]; + else + sort_begin = language_names_p; + + language_names[3] = ""; + language_names[4] = ""; + language_names[5] = NULL; + + /* There should be no warning associated with this std::sort as + sort_begin != &language_names[5] and GCC should be able to figure + that out. */ + std::sort (sort_begin, &language_names[5], compare_cstrings); +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/modref-dse-4.c b/gcc/testsuite/gcc.dg/tree-ssa/modref-dse-4.c index 81aa7dc..19e91b0 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/modref-dse-4.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/modref-dse-4.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-dse2-details" } */ +/* { dg-options "-O2 -fdump-tree-dse1-details" } */ struct a {int a,b,c;}; __attribute__ ((noinline)) void @@ -23,4 +23,4 @@ set (struct a *a) my_pleasure (a); a->b=1; } -/* { dg-final { scan-tree-dump "Deleted dead store: kill_me" "dse2" } } */ +/* { dg-final { scan-tree-dump "Deleted dead store: kill_me" "dse1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/modref-dse-5.c b/gcc/testsuite/gcc.dg/tree-ssa/modref-dse-5.c index ad35b70..dc2c289 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/modref-dse-5.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/modref-dse-5.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-dse2-details" } */ +/* { dg-options "-O2 -fdump-tree-dse1-details" } */ struct a {int a,b,c;}; __attribute__ ((noinline)) void @@ -36,8 +36,7 @@ set (struct a *a) { wrap (0, a); int ret = wrap2 (0, a); - //int ret = my_pleasure (a); a->b=1; return ret; } -/* { dg-final { scan-tree-dump "Deleted dead store: wrap" "dse2" } } */ +/* { dg-final { scan-tree-dump "Deleted dead store: wrap" "dse1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr102232.c b/gcc/testsuite/gcc.dg/tree-ssa/pr102232.c new file mode 100644 index 0000000..62bca69 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr102232.c @@ -0,0 +1,52 @@ +/* PR tree-optimization/102232 */ +/* { dg-do run } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +int __attribute__ ((noipa)) foo (int a, int b) +{ + return b * (1 + a / b) - a; +} + +int +main (void) +{ + // few randomly generated test cases + if (foo (71856034, 238) != 212) + { + __builtin_abort (); + } + if (foo (71856034, 10909) != 1549) + { + __builtin_abort (); + } + if (foo (20350, 1744) != 578) + { + __builtin_abort (); + } + if (foo (444813, 88563) != 86565) + { + __builtin_abort (); + } + if (foo (112237, 63004) != 13771) + { + __builtin_abort (); + } + if (foo (68268386, 787116) != 210706) + { + __builtin_abort (); + } + if (foo (-444813, 88563) != 90561) + { + __builtin_abort (); + } + if (foo (-68268386, 787116) != 1363526) + { + __builtin_abort (); + } + + return 0; +} + +/* Verify that multiplication and division has been removed. */ +/* { dg-final { scan-tree-dump-not " \\* " "optimized" } } */ +/* { dg-final { scan-tree-dump-not " / " "optimized" } } */
\ No newline at end of file diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr103345.c b/gcc/testsuite/gcc.dg/tree-ssa/pr103345.c new file mode 100644 index 0000000..94388b5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr103345.c @@ -0,0 +1,53 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-bswap-details" } */ + +typedef unsigned int uint32_t; +typedef unsigned char uint8_t; + +uint32_t load_le_32_or(const uint8_t *ptr) +{ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + return ((uint32_t)ptr[0]) | + ((uint32_t)ptr[1] << 8) | + ((uint32_t)ptr[2] << 16) | + ((uint32_t)ptr[3] << 24); +#else + return ((uint32_t)ptr[3]) | + ((uint32_t)ptr[2] << 8) | + ((uint32_t)ptr[1] << 16) | + ((uint32_t)ptr[0] << 24); +#endif +} + +uint32_t load_le_32_add(const uint8_t *ptr) +{ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + return ((uint32_t)ptr[0]) + + ((uint32_t)ptr[1] << 8) + + ((uint32_t)ptr[2] << 16) + + ((uint32_t)ptr[3] << 24); +#else + return ((uint32_t)ptr[3]) + + ((uint32_t)ptr[2] << 8) + + ((uint32_t)ptr[1] << 16) + + ((uint32_t)ptr[0] << 24); +#endif +} + +uint32_t load_le_32_xor(const uint8_t *ptr) +{ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + return ((uint32_t)ptr[0]) ^ + ((uint32_t)ptr[1] << 8) ^ + ((uint32_t)ptr[2] << 16) ^ + ((uint32_t)ptr[3] << 24); +#else + return ((uint32_t)ptr[0]) ^ + ((uint32_t)ptr[1] << 8) ^ + ((uint32_t)ptr[2] << 16) ^ + ((uint32_t)ptr[3] << 24); +#endif +} + +/* { dg-final { scan-tree-dump-times "32 bit load in target endianness found" 3 "bswap" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr96779-disabled.c b/gcc/testsuite/gcc.dg/tree-ssa/pr96779-disabled.c new file mode 100644 index 0000000..205133d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr96779-disabled.c @@ -0,0 +1,84 @@ +/* PR tree-optimization/96779 */ +/* { dg-do run } */ +/* { dg-options "-O -fdump-tree-optimized -fwrapv" } */ + +#include <stdbool.h> + +bool __attribute__ ((noipa)) f_func(int a) +{ + return -a == a; +} + +bool __attribute__ ((noipa)) g_func(unsigned int a) +{ + return -a == a; +} + +bool __attribute__ ((noipa)) h_func(short a) +{ + return -a == a; +} + +bool __attribute__ ((noipa)) k_func(long a) +{ + return -a == a; +} + +int +main (void) +{ + // few randomly generated test cases + if (f_func (71856034)) + { + __builtin_abort (); + } + if (g_func (71856034)) + { + __builtin_abort (); + } + if (h_func (1744)) + { + __builtin_abort (); + } + if (k_func (68268386)) + { + __builtin_abort (); + } + if (f_func (-112237)) + { + __builtin_abort (); + } + if (g_func (-787116)) + { + __builtin_abort (); + } + if (h_func (-863)) + { + __builtin_abort (); + } + if (k_func (-787116)) + { + __builtin_abort (); + } + if (!f_func (0)) + { + __builtin_abort (); + } + if (!g_func (0)) + { + __builtin_abort (); + } + if (!h_func (0)) + { + __builtin_abort (); + } + if (!k_func (0)) + { + __builtin_abort (); + } + + return 0; +} + +/* Verify that we have *not* transfered "= -" pattern in any of those functions. */ +/* { dg-final { scan-tree-dump-times "= -" 4 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr96779.c b/gcc/testsuite/gcc.dg/tree-ssa/pr96779.c new file mode 100644 index 0000000..0d46e8e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr96779.c @@ -0,0 +1,79 @@ +/* PR tree-optimization/96779 */ +/* { dg-do run } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +#include <stdbool.h> + +bool __attribute__ ((noipa)) f_func(int a) +{ + return -a == a; +} + +bool __attribute__ ((noipa)) h_func(short a) +{ + return -a == a; +} + +bool __attribute__ ((noipa)) k_func(long a) +{ + return -a == a; +} + +int +main (void) +{ + // few randomly generated test cases + if (f_func (71856034)) + { + __builtin_abort (); + } + if (f_func (71856034)) + { + __builtin_abort (); + } + if (h_func (1744)) + { + __builtin_abort (); + } + if (k_func (68268386)) + { + __builtin_abort (); + } + if (f_func (-112237)) + { + __builtin_abort (); + } + if (f_func (-787116)) + { + __builtin_abort (); + } + if (h_func (-863)) + { + __builtin_abort (); + } + if (k_func (-787116)) + { + __builtin_abort (); + } + if (!f_func (0)) + { + __builtin_abort (); + } + if (!f_func (0)) + { + __builtin_abort (); + } + if (!h_func (0)) + { + __builtin_abort (); + } + if (!k_func (0)) + { + __builtin_abort (); + } + + return 0; +} + +/* Verify that we transfered to "= -" pattern from "_2 = -_1;". */ +/* { dg-final { scan-tree-dump-not "= -" "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr98953.c b/gcc/testsuite/gcc.dg/tree-ssa/pr98953.c new file mode 100644 index 0000000..7687dc2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr98953.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-bswap-details" } */ + +int foo(unsigned char *ptr) +{ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + return ptr[0] + (ptr[1] << 8); +#else + return ptr[1] + (ptr[0] << 8); +#endif +} + +/* { dg-final { scan-tree-dump "16 bit load in target endianness found" "bswap" } } */ + diff --git a/gcc/testsuite/gcc.target/powerpc/vec_reve_1.c b/gcc/testsuite/gcc.target/powerpc/vec_reve_1.c new file mode 100644 index 0000000..120c318 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/vec_reve_1.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target powerpc_altivec_ok } */ +/* { dg-options "-O2 -maltivec" } */ + +#include <altivec.h> + +vector double foo1 (vector double a) +{ + return vec_reve (a); +} + +vector long long foo2 (vector long long a) +{ + return vec_reve (a); +} + +/* { dg-final { scan-assembler-times {\mxxpermdi\M} 2 } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/vec_reve_2.c b/gcc/testsuite/gcc.target/powerpc/vec_reve_2.c new file mode 100644 index 0000000..9661939 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/vec_reve_2.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target powerpc_p9vector_ok } */ +/* { dg-options "-mdejagnu-cpu=power9 -O2" } */ + +#include <altivec.h> + +vector int foo1 (vector int a) +{ + return vec_reve (a); +} + +vector float foo2 (vector float a) +{ + return vec_reve (a); +} + +vector short foo3 (vector short a) +{ + return vec_reve (a); +} + +vector char foo4 (vector char a) +{ + return vec_reve (a); +} + +/* { dg-final { scan-assembler-times {\mxxbrq\M} 4 } } */ +/* { dg-final { scan-assembler-times {\mxxbrw\M} 2 } } */ +/* { dg-final { scan-assembler-times {\mxxbrh\M} 1 } } */ diff --git a/gcc/testsuite/gfortran.dg/gomp/pr102431.f90 b/gcc/testsuite/gfortran.dg/gomp/pr102431.f90 new file mode 100644 index 0000000..71efed8 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/pr102431.f90 @@ -0,0 +1,10 @@ +! PR middle-end/102431 + +program pr102431 + integer :: a(2) + a(:) = 0 + !$omp parallel loop reduction(+:a) + do i = 1, 8 + a = a + 1 + end do +end diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c index 46f4ffe..9b6ca1a 100644 --- a/gcc/tree-data-ref.c +++ b/gcc/tree-data-ref.c @@ -388,7 +388,7 @@ print_lambda_vector (FILE * outfile, lambda_vector vector, int n) int i; for (i = 0; i < n; i++) - fprintf (outfile, "%3d ", (int)vector[i]); + fprintf (outfile, HOST_WIDE_INT_PRINT_DEC " ", vector[i]); fprintf (outfile, "\n"); } diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 8c108d8..bc5ff0b 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -823,9 +823,6 @@ remap_block (tree *block, copy_body_data *id) &BLOCK_NONLOCALIZED_VARS (new_block), id); - if (id->transform_lang_insert_block) - id->transform_lang_insert_block (new_block); - /* Remember the remapped block. */ insert_decl_map (id, old_block, new_block); } @@ -5473,7 +5470,6 @@ optimize_inline_calls (tree fn) id.transform_new_cfg = false; id.transform_return_to_modify = true; id.transform_parameter = true; - id.transform_lang_insert_block = NULL; id.statements_to_fold = new hash_set<gimple *>; push_gimplify_context (); @@ -5857,7 +5853,6 @@ copy_gimple_seq_and_replace_locals (gimple_seq seq) id.transform_new_cfg = false; id.transform_return_to_modify = false; id.transform_parameter = false; - id.transform_lang_insert_block = NULL; /* Walk the tree once to find local labels. */ memset (&wi, 0, sizeof (wi)); @@ -6252,7 +6247,6 @@ tree_function_versioning (tree old_decl, tree new_decl, id.transform_new_cfg = true; id.transform_return_to_modify = false; id.transform_parameter = false; - id.transform_lang_insert_block = NULL; old_entry_block = ENTRY_BLOCK_PTR_FOR_FN (DECL_STRUCT_FUNCTION (old_decl)); @@ -6541,7 +6535,6 @@ maybe_inline_call_in_expr (tree exp) id.transform_new_cfg = false; id.transform_return_to_modify = true; id.transform_parameter = true; - id.transform_lang_insert_block = NULL; /* Make sure not to unshare trees behind the front-end's back since front-end specific mechanisms may rely on sharing. */ @@ -6613,7 +6606,6 @@ copy_fn (tree fn, tree& parms, tree& result) id.transform_new_cfg = false; id.transform_return_to_modify = false; id.transform_parameter = true; - id.transform_lang_insert_block = NULL; /* Make sure not to unshare trees behind the front-end's back since front-end specific mechanisms may rely on sharing. */ diff --git a/gcc/tree-inline.h b/gcc/tree-inline.h index ec0e82f..e9d21a4 100644 --- a/gcc/tree-inline.h +++ b/gcc/tree-inline.h @@ -133,9 +133,6 @@ struct copy_body_data and only in that case will actually remap the type. */ bool dont_remap_vla_if_no_change; - /* A function to be called when duplicating BLOCK nodes. */ - void (*transform_lang_insert_block) (tree); - /* Statements that might be possibly folded. */ hash_set<gimple *> *statements_to_fold; diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c index 9531d89..8717d65 100644 --- a/gcc/tree-ssa-dse.c +++ b/gcc/tree-ssa-dse.c @@ -156,57 +156,137 @@ initialize_ao_ref_for_dse (gimple *stmt, ao_ref *write) } /* Given REF from the alias oracle, return TRUE if it is a valid - memory reference for dead store elimination, false otherwise. + kill memory reference for dead store elimination, false otherwise. In particular, the reference must have a known base, known maximum size, start at a byte offset and have a size that is one or more bytes. */ static bool -valid_ao_ref_for_dse (ao_ref *ref) +valid_ao_ref_kill_for_dse (ao_ref *ref) { return (ao_ref_base (ref) && known_size_p (ref->max_size) && maybe_ne (ref->size, 0) && known_eq (ref->max_size, ref->size) - && known_ge (ref->offset, 0) - && multiple_p (ref->offset, BITS_PER_UNIT) - && multiple_p (ref->size, BITS_PER_UNIT)); + && known_ge (ref->offset, 0)); +} + +/* Given REF from the alias oracle, return TRUE if it is a valid + load or store memory reference for dead store elimination, false otherwise. + + Unlike for valid_ao_ref_kill_for_dse we can accept writes where max_size + is not same as size since we can handle conservatively the larger range. */ + +static bool +valid_ao_ref_for_dse (ao_ref *ref) +{ + return (ao_ref_base (ref) + && known_size_p (ref->max_size) + && known_ge (ref->offset, 0)); +} + +/* Initialize OFFSET and SIZE to a range known to contain REF + where the boundaries are divisible by BITS_PER_UNIT (bit still in bits). + Return false if this is impossible. */ + +static bool +get_byte_aligned_range_containing_ref (ao_ref *ref, poly_int64 *offset, + HOST_WIDE_INT *size) +{ + if (!known_size_p (ref->max_size)) + return false; + *offset = aligned_lower_bound (ref->offset, BITS_PER_UNIT); + poly_int64 end = aligned_upper_bound (ref->offset + ref->max_size, + BITS_PER_UNIT); + return (end - *offset).is_constant (size); +} + +/* Initialize OFFSET and SIZE to a range known to be contained REF + where the boundaries are divisible by BITS_PER_UNIT (but still in bits). + Return false if this is impossible. */ + +static bool +get_byte_aligned_range_contained_in_ref (ao_ref *ref, poly_int64 *offset, + HOST_WIDE_INT *size) +{ + if (!known_size_p (ref->size) + || !known_eq (ref->size, ref->max_size)) + return false; + *offset = aligned_upper_bound (ref->offset, BITS_PER_UNIT); + poly_int64 end = aligned_lower_bound (ref->offset + ref->max_size, + BITS_PER_UNIT); + /* For bit accesses we can get -1 here, but also 0 sized kill is not + useful. */ + if (!known_gt (end, *offset)) + return false; + return (end - *offset).is_constant (size); } -/* Try to normalize COPY (an ao_ref) relative to REF. Essentially when we are - done COPY will only refer bytes found within REF. Return true if COPY - is known to intersect at least one byte of REF. */ +/* Compute byte range (returned iN REF_OFFSET and RET_SIZE) for access COPY + inside REF. If KILL is true, then COPY represent a kill and the byte range + needs to be fully contained in bit range given by COPY. If KILL is false + then the byte range returned must contain the range of COPY. */ static bool -normalize_ref (ao_ref *copy, ao_ref *ref) +get_byte_range (ao_ref *copy, ao_ref *ref, bool kill, + HOST_WIDE_INT *ret_offset, HOST_WIDE_INT *ret_size) { - if (!ordered_p (copy->offset, ref->offset)) + HOST_WIDE_INT copy_size, ref_size; + poly_int64 copy_offset, ref_offset; + HOST_WIDE_INT diff; + + /* First translate from bits to bytes, rounding to bigger or smaller ranges + as needed. Kills needs to be always rounded to smaller ranges while + uses and stores to larger ranges. */ + if (kill) + { + if (!get_byte_aligned_range_contained_in_ref (copy, ©_offset, + ©_size)) + return false; + } + else + { + if (!get_byte_aligned_range_containing_ref (copy, ©_offset, + ©_size)) + return false; + } + + if (!get_byte_aligned_range_containing_ref (ref, &ref_offset, &ref_size) + || !ordered_p (copy_offset, ref_offset)) return false; + /* Switch sizes from bits to bytes so we do not need to care about + overflows. Offset calculation needs to stay in bits until we compute + the difference and can switch to HOST_WIDE_INT. */ + copy_size /= BITS_PER_UNIT; + ref_size /= BITS_PER_UNIT; + /* If COPY starts before REF, then reset the beginning of COPY to match REF and decrease the size of COPY by the number of bytes removed from COPY. */ - if (maybe_lt (copy->offset, ref->offset)) + if (maybe_lt (copy_offset, ref_offset)) { - poly_int64 diff = ref->offset - copy->offset; - if (maybe_le (copy->size, diff)) + if (!(ref_offset - copy_offset).is_constant (&diff) + || copy_size < diff / BITS_PER_UNIT) return false; - copy->size -= diff; - copy->offset = ref->offset; + copy_size -= diff / BITS_PER_UNIT; + copy_offset = ref_offset; } - poly_int64 diff = copy->offset - ref->offset; - if (maybe_le (ref->size, diff)) + if (!(copy_offset - ref_offset).is_constant (&diff) + || ref_size <= diff / BITS_PER_UNIT) return false; /* If COPY extends beyond REF, chop off its size appropriately. */ - poly_int64 limit = ref->size - diff; - if (!ordered_p (limit, copy->size)) - return false; + HOST_WIDE_INT limit = ref_size - diff / BITS_PER_UNIT; - if (maybe_gt (copy->size, limit)) - copy->size = limit; + if (copy_size > limit) + copy_size = limit; + *ret_size = copy_size; + if (!(copy_offset - ref_offset).is_constant (ret_offset)) + return false; + *ret_offset /= BITS_PER_UNIT; return true; } @@ -214,20 +294,14 @@ normalize_ref (ao_ref *copy, ao_ref *ref) Verify we have the same base memory address, the write has a known size and overlaps with REF. */ static void -clear_live_bytes_for_ref (sbitmap live_bytes, ao_ref *ref, ao_ref write) +clear_live_bytes_for_ref (sbitmap live_bytes, ao_ref *ref, ao_ref *write) { HOST_WIDE_INT start, size; - if (valid_ao_ref_for_dse (&write) - && operand_equal_p (write.base, ref->base, OEP_ADDRESS_OF) - && known_eq (write.size, write.max_size) - /* normalize_ref modifies write and for that reason write is not - passed by reference. */ - && normalize_ref (&write, ref) - && (write.offset - ref->offset).is_constant (&start) - && write.size.is_constant (&size)) - bitmap_clear_range (live_bytes, start / BITS_PER_UNIT, - size / BITS_PER_UNIT); + if (valid_ao_ref_kill_for_dse (write) + && operand_equal_p (write->base, ref->base, OEP_ADDRESS_OF) + && get_byte_range (write, ref, true, &start, &size)) + bitmap_clear_range (live_bytes, start, size); } /* Clear any bytes written by STMT from the bitmap LIVE_BYTES. The base @@ -250,12 +324,12 @@ clear_bytes_written_by (sbitmap live_bytes, gimple *stmt, ao_ref *ref) if (summary && !interposed) for (auto kill : summary->kills) if (kill.get_ao_ref (as_a <gcall *> (stmt), &write)) - clear_live_bytes_for_ref (live_bytes, ref, write); + clear_live_bytes_for_ref (live_bytes, ref, &write); } if (!initialize_ao_ref_for_dse (stmt, &write)) return; - clear_live_bytes_for_ref (live_bytes, ref, write); + clear_live_bytes_for_ref (live_bytes, ref, &write); } /* REF is a memory write. Extract relevant information from it and @@ -267,9 +341,11 @@ setup_live_bytes_from_ref (ao_ref *ref, sbitmap live_bytes) { HOST_WIDE_INT const_size; if (valid_ao_ref_for_dse (ref) - && ref->size.is_constant (&const_size) - && (const_size / BITS_PER_UNIT - <= param_dse_max_object_size)) + && ((aligned_upper_bound (ref->offset + ref->max_size, BITS_PER_UNIT) + - aligned_lower_bound (ref->offset, + BITS_PER_UNIT)).is_constant (&const_size)) + && (const_size / BITS_PER_UNIT <= param_dse_max_object_size) + && const_size > 1) { bitmap_clear (live_bytes); bitmap_set_range (live_bytes, 0, const_size / BITS_PER_UNIT); @@ -645,24 +721,21 @@ maybe_trim_partially_dead_store (ao_ref *ref, sbitmap live, gimple *stmt) location. So callers do not see those modifications. */ static bool -live_bytes_read (ao_ref use_ref, ao_ref *ref, sbitmap live) +live_bytes_read (ao_ref *use_ref, ao_ref *ref, sbitmap live) { /* We have already verified that USE_REF and REF hit the same object. Now verify that there's actually an overlap between USE_REF and REF. */ HOST_WIDE_INT start, size; - if (normalize_ref (&use_ref, ref) - && (use_ref.offset - ref->offset).is_constant (&start) - && use_ref.size.is_constant (&size)) + if (get_byte_range (use_ref, ref, false, &start, &size)) { /* If USE_REF covers all of REF, then it will hit one or more live bytes. This avoids useless iteration over the bitmap below. */ - if (start == 0 && known_eq (size, ref->size)) + if (start == 0 && known_eq (size * 8, ref->size)) return true; /* Now check if any of the remaining bits in use_ref are set in LIVE. */ - return bitmap_bit_in_range_p (live, start / BITS_PER_UNIT, - (start + size - 1) / BITS_PER_UNIT); + return bitmap_bit_in_range_p (live, start, (start + size - 1)); } return true; } @@ -861,16 +934,18 @@ dse_classify_store (ao_ref *ref, gimple *stmt, { /* Handle common cases where we can easily build an ao_ref structure for USE_STMT and in doing so we find that the - references hit non-live bytes and thus can be ignored. */ + references hit non-live bytes and thus can be ignored. + + TODO: We can also use modref summary to handle calls. */ if (byte_tracking_enabled && is_gimple_assign (use_stmt)) { ao_ref use_ref; ao_ref_init (&use_ref, gimple_assign_rhs1 (use_stmt)); if (valid_ao_ref_for_dse (&use_ref) - && use_ref.base == ref->base - && known_eq (use_ref.size, use_ref.max_size) - && !live_bytes_read (use_ref, ref, live_bytes)) + && operand_equal_p (use_ref.base, ref->base, + OEP_ADDRESS_OF) + && !live_bytes_read (&use_ref, ref, live_bytes)) { /* If this is a store, remember it as we possibly need to walk the defs uses. */ |