diff options
author | Martin Liska <mliska@suse.cz> | 2021-05-25 15:01:25 +0200 |
---|---|---|
committer | Martin Liska <mliska@suse.cz> | 2021-05-25 15:01:25 +0200 |
commit | 2f7ea01554b7d202f169fc4268d8c9ee2fabbad2 (patch) | |
tree | 430d16cc500688b1ca0788dcbe2e5a904dca2182 | |
parent | d5bc4d65275781ea5cf0f7f89b9bde629d744bda (diff) | |
parent | ebd5e86c0f41dc1d692f9b2b68a510b1f6835a3e (diff) | |
download | gcc-2f7ea01554b7d202f169fc4268d8c9ee2fabbad2.zip gcc-2f7ea01554b7d202f169fc4268d8c9ee2fabbad2.tar.gz gcc-2f7ea01554b7d202f169fc4268d8c9ee2fabbad2.tar.bz2 |
Merge branch 'master' into devel/sphinx
131 files changed, 7245 insertions, 1370 deletions
diff --git a/c++tools/Makefile.in b/c++tools/Makefile.in index afc87d0..83a6ae5 100644 --- a/c++tools/Makefile.in +++ b/c++tools/Makefile.in @@ -1,5 +1,5 @@ # Makefile for c++tools -# Copyright 2020 Free Software Foundation, Inc. +# Copyright (C) 2020-2021 Free Software Foundation, Inc. # # This file is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/c++tools/configure b/c++tools/configure index 3f511b2..a288f7a 100755 --- a/c++tools/configure +++ b/c++tools/configure @@ -2978,9 +2978,9 @@ else fi case "$enable_maintainer_mode" in - ("yes") maintainer_mode=yes ;; - ("no") maintainer=no ;; - (*) as_fn_error $? "unknown maintainer mode $enable_maintainer_mode" "$LINENO" 5 ;; + yes) maintainer_mode=yes ;; + no) maintainer_mode=no ;; + *) as_fn_error $? "unknown maintainer mode $enable_maintainer_mode" "$LINENO" 5 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking maintainer-mode" >&5 $as_echo_n "checking maintainer-mode... " >&6; } diff --git a/c++tools/configure.ac b/c++tools/configure.ac index 5771f2a..70fcb64 100644 --- a/c++tools/configure.ac +++ b/c++tools/configure.ac @@ -1,5 +1,5 @@ # Configure script for c++tools -# Copyright (C) 2020 Free Software Foundation, Inc. +# Copyright (C) 2020-2021 Free Software Foundation, Inc. # Written by Nathan Sidwell <nathan@acm.org> while at FaceBook # # This file is free software; you can redistribute it and/or modify it @@ -58,9 +58,9 @@ AS_HELP_STRING([--enable-maintainer-mode], [enable maintainer mode. Add rules to rebuild configurey bits]),, [enable_maintainer_mode=no]) case "$enable_maintainer_mode" in - ("yes") maintainer_mode=yes ;; - ("no") maintainer=no ;; - (*) AC_MSG_ERROR([unknown maintainer mode $enable_maintainer_mode]) ;; + yes) maintainer_mode=yes ;; + no) maintainer_mode=no ;; + *) AC_MSG_ERROR([unknown maintainer mode $enable_maintainer_mode]) ;; esac AC_MSG_CHECKING([maintainer-mode]) AC_MSG_RESULT([$maintainer_mode]) diff --git a/c++tools/resolver.cc b/c++tools/resolver.cc index ef08de5..edd4624 100644 --- a/c++tools/resolver.cc +++ b/c++tools/resolver.cc @@ -1,5 +1,5 @@ /* C++ modules. Experimental! -*- c++ -*- - Copyright (C) 2017-2020 Free Software Foundation, Inc. + Copyright (C) 2017-2021 Free Software Foundation, Inc. Written by Nathan Sidwell <nathan@acm.org> while at FaceBook This file is part of GCC. diff --git a/c++tools/resolver.h b/c++tools/resolver.h index a9547bf..b2f4381 100644 --- a/c++tools/resolver.h +++ b/c++tools/resolver.h @@ -1,5 +1,5 @@ /* C++ modules. Experimental! -*- c++ -*- - Copyright (C) 2017-2020 Free Software Foundation, Inc. + Copyright (C) 2017-2021 Free Software Foundation, Inc. Written by Nathan Sidwell <nathan@acm.org> while at FaceBook This file is part of GCC. diff --git a/c++tools/server.cc b/c++tools/server.cc index 21c7d46..709955e 100644 --- a/c++tools/server.cc +++ b/c++tools/server.cc @@ -1,5 +1,5 @@ /* C++ modules. Experimental! - Copyright (C) 2018-2020 Free Software Foundation, Inc. + Copyright (C) 2018-2021 Free Software Foundation, Inc. Written by Nathan Sidwell <nathan@acm.org> while at FaceBook This file is part of GCC. @@ -290,7 +290,7 @@ static void ATTRIBUTE_NORETURN print_version (void) { fnotice (stdout, "%s %s%s\n", progname, pkgversion_string, version_string); - fprintf (stdout, "Copyright %s 2018-2020 Free Software Foundation, Inc.\n", + fprintf (stdout, "Copyright %s 2018-2021 Free Software Foundation, Inc.\n", ("(C)")); fnotice (stdout, ("This is free software; see the source for copying conditions.\n" diff --git a/contrib/ChangeLog b/contrib/ChangeLog index 0b4cf14..0498c0f 100644 --- a/contrib/ChangeLog +++ b/contrib/ChangeLog @@ -1,3 +1,9 @@ +2021-05-24 Martin Liska <mliska@suse.cz> + + * gcc-changelog/git_commit.py: Add note that ChangeLog entries + are added automatically. + * gcc-changelog/test_email.py: Update test. + 2021-05-18 Jonathan Wakely <jwakely@redhat.com> * gcc-changelog/git_email.py: Remove use of non-strict mode. diff --git a/contrib/update-copyright.py b/contrib/update-copyright.py index 83c761a..2b2bb11 100755 --- a/contrib/update-copyright.py +++ b/contrib/update-copyright.py @@ -735,6 +735,7 @@ class GCCCmdLine (CmdLine): self.add_dir ('.', TopLevelFilter()) # boehm-gc is imported from upstream. + self.add_dir ('c++tools') self.add_dir ('config', ConfigFilter()) # contrib isn't really part of GCC. self.add_dir ('fixincludes') @@ -770,6 +771,7 @@ class GCCCmdLine (CmdLine): # zlib is imported from upstream. self.default_dirs = [ + 'c++tools', 'gcc', 'include', 'libada', diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5cf4824..d3c90e2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,51 @@ +2021-05-24 Aaron Sawdey <acsawdey@linux.ibm.com> + + * config/rs6000/genfusion.pl (gen_logical_addsubf): Refactor to + add generation of logical-add and add-logical fusion pairs. + * config/rs6000/rs6000-cpus.def: Add new fusion to ISA 3.1 mask + and powerpc mask. + * config/rs6000/rs6000.c (rs6000_option_override_internal): Turn on + logical-add and add-logical fusion by default. + * config/rs6000/rs6000.opt: Add -mpower10-fusion-logical-add and + -mpower10-fusion-add-logical options. + * config/rs6000/fusion.md: Regenerate file. + +2021-05-24 Aldy Hernandez <aldyh@redhat.com> + + * value-range.cc (irange::legacy_equal_p): Check type when + comparing VR_VARYING types. + (range_tests_legacy): Test comparing VARYING ranges of different + sizes. + +2021-05-24 Wilco Dijkstra <wdijkstr@arm.com> + + * config/aarch64/aarch64.c (neoversen1_tunings): + Enable AARCH64_EXTRA_TUNE_CHEAP_SHIFT_EXTEND. + +2021-05-24 Wilco Dijkstra <wdijkstr@arm.com> + + * config/aarch64/aarch64.c (aarch64_classify_symbol): Use GOT for + extern weak symbols. Limit symbol offsets for non-GOT symbols with + PIC/PIE. + +2021-05-24 Christophe Lyon <christophe.lyon@linaro.org> + + * config/arm/neon.md (vec_load_lanesxi<mode>) + (vec_store_lanexoi<mode>): Move ... + * config/arm/vec-common.md: here. + +2021-05-24 Christophe Lyon <christophe.lyon@linaro.org> + + * config/arm/neon.md (vec_load_lanesoi<mode>) + (vec_store_lanesoi<mode>): Move ... + * config/arm/vec-common.md: here. + +2021-05-24 liuhongt <hongtao.liu@intel.com> + + PR target/100660 + * config/i386/i386.c (ix86_gimple_fold_builtin): Replacing + stmt with GIMPLE_NOP when lhs doesn't exist. + 2021-05-23 Uroš Bizjak <ubizjak@gmail.com> PR target/100722 diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index e2a9538..e64bfab 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20210524 +20210525 diff --git a/gcc/ada/doc/share/conf.py b/gcc/ada/doc/share/conf.py index 755c3a6..0f7f963 100644 --- a/gcc/ada/doc/share/conf.py +++ b/gcc/ada/doc/share/conf.py @@ -144,5 +144,5 @@ texinfo_documents = [ def setup(app): - app.add_lexer('ada', ada_pygments.AdaLexer()) - app.add_lexer('gpr', ada_pygments.GNATProjectLexer()) + app.add_lexer('ada', ada_pygments.AdaLexer) + app.add_lexer('gpr', ada_pygments.GNATProjectLexer) @@ -249,4 +249,14 @@ sanitize_flags_p (unsigned int flag, const_tree fn = current_function_decl) return result_flags; } +/* Return true when coverage sanitization should happend for FN function. */ + +static inline bool +sanitize_coverage_p (const_tree fn = current_function_decl) +{ + return (flag_sanitize_coverage + && lookup_attribute ("no_sanitize_coverage", + DECL_ATTRIBUTES (fn)) == NULL_TREE); +} + #endif /* TREE_ASAN */ diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c index ccf9e4c..804374d 100644 --- a/gcc/c-family/c-attribs.c +++ b/gcc/c-family/c-attribs.c @@ -62,6 +62,8 @@ static tree handle_no_address_safety_analysis_attribute (tree *, tree, tree, int, bool *); static tree handle_no_sanitize_undefined_attribute (tree *, tree, tree, int, bool *); +static tree handle_no_sanitize_coverage_attribute (tree *, tree, tree, int, + bool *); static tree handle_asan_odr_indicator_attribute (tree *, tree, tree, int, bool *); static tree handle_stack_protect_attribute (tree *, tree, tree, int, bool *); @@ -449,6 +451,8 @@ const struct attribute_spec c_common_attribute_table[] = handle_no_sanitize_thread_attribute, NULL }, { "no_sanitize_undefined", 0, 0, true, false, false, false, handle_no_sanitize_undefined_attribute, NULL }, + { "no_sanitize_coverage", 0, 0, true, false, false, false, + handle_no_sanitize_coverage_attribute, NULL }, { "asan odr indicator", 0, 0, true, false, false, false, handle_asan_odr_indicator_attribute, NULL }, { "warning", 1, 1, true, false, false, false, @@ -1211,6 +1215,22 @@ handle_no_sanitize_undefined_attribute (tree *node, tree name, tree, int, return NULL_TREE; } +/* Handle a "no_sanitize_coverage" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_no_sanitize_coverage_attribute (tree *node, tree name, tree, int, + bool *no_add_attrs) +{ + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + /* Handle an "asan odr indicator" attribute; arguments as in struct attribute_spec.handler. */ @@ -5363,6 +5383,8 @@ handle_optimize_attribute (tree *node, tree name, tree args, /* Save current options. */ cl_optimization_save (&cur_opts, &global_options, &global_options_set); + tree prev_target_node = build_target_option_node (&global_options, + &global_options_set); /* If we previously had some optimization options, use them as the default. */ @@ -5381,10 +5403,17 @@ handle_optimize_attribute (tree *node, tree name, tree args, parse_optimize_options (args, true); DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node) = build_optimization_node (&global_options, &global_options_set); + tree target_node = build_target_option_node (&global_options, + &global_options_set); + if (prev_target_node != target_node) + DECL_FUNCTION_SPECIFIC_TARGET (*node) = target_node; /* Restore current options. */ cl_optimization_restore (&global_options, &global_options_set, &cur_opts); + cl_target_option_restore (&global_options, &global_options_set, + TREE_TARGET_OPTION (prev_target_node)); + if (saved_global_options != NULL) { cl_optimization_compare (saved_global_options, &global_options); diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c index 0945a1e..1b4a112 100644 --- a/gcc/c-family/c-omp.c +++ b/gcc/c-family/c-omp.c @@ -2059,6 +2059,23 @@ c_omp_split_clauses (location_t loc, enum tree_code code, OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP]; cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP] = c; } + else if ((mask & (OMP_CLAUSE_MASK_1 + << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) != 0) + { + c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses), + OMP_CLAUSE_REDUCTION); + OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses); + OMP_CLAUSE_REDUCTION_CODE (c) + = OMP_CLAUSE_REDUCTION_CODE (clauses); + OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) + = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses); + OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) + = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses); + OMP_CLAUSE_REDUCTION_INSCAN (c) + = OMP_CLAUSE_REDUCTION_INSCAN (clauses); + OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS]; + cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c; + } s = C_OMP_CLAUSE_SPLIT_SIMD; } else diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c index 4f8e8e0..7f658ea 100644 --- a/gcc/c-family/c-pragma.c +++ b/gcc/c-family/c-pragma.c @@ -918,6 +918,12 @@ handle_pragma_target(cpp_reader *ARG_UNUSED(dummy)) if (targetm.target_option.pragma_parse (args, NULL_TREE)) current_target_pragma = chainon (current_target_pragma, args); + + /* A target pragma can also influence optimization options. */ + tree current_optimize + = build_optimization_node (&global_options, &global_options_set); + if (current_optimize != optimization_current_node) + optimization_current_node = current_optimize; } } @@ -1078,12 +1084,14 @@ handle_pragma_pop_options (cpp_reader *ARG_UNUSED(dummy)) target_option_current_node = p->target_binary; } + /* Always restore optimization options as optimization_current_node is + * overwritten by invoke_set_current_function_hook. */ + cl_optimization_restore (&global_options, &global_options_set, + TREE_OPTIMIZATION (p->optimize_binary)); + if (p->optimize_binary != optimization_current_node) { - tree old_optimize = optimization_current_node; - cl_optimization_restore (&global_options, &global_options_set, - TREE_OPTIMIZATION (p->optimize_binary)); - c_cpp_builtins_optimize_pragma (parse_in, old_optimize, + c_cpp_builtins_optimize_pragma (parse_in, optimization_current_node, p->optimize_binary); optimization_current_node = p->optimize_binary; } diff --git a/gcc/calls.c b/gcc/calls.c index f3da183..dd8ff2a 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -2397,7 +2397,8 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED, already in memory, instead of making a copy. Likewise if we want to make the copy in the callee instead of the caller. */ if ((call_from_thunk_p || callee_copies) - && (base = get_base_address (args[i].tree_value)) + && TREE_CODE (args[i].tree_value) != WITH_SIZE_EXPR + && ((base = get_base_address (args[i].tree_value)), true) && TREE_CODE (base) != SSA_NAME && (!DECL_P (base) || MEM_P (DECL_RTL (base)))) { diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index c1e451e..2753c85 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -1659,7 +1659,7 @@ static const struct tune_params neoversen1_tunings = 2, /* min_div_recip_mul_df. */ 0, /* max_case_values. */ tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ - (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ + (AARCH64_EXTRA_TUNE_CHEAP_SHIFT_EXTEND), /* tune_flags. */ &generic_prefetch_tune }; @@ -17902,7 +17902,14 @@ aarch64_classify_symbol (rtx x, HOST_WIDE_INT offset) switch (aarch64_cmodel) { + case AARCH64_CMODEL_TINY_PIC: case AARCH64_CMODEL_TINY: + /* With -fPIC non-local symbols use the GOT. For orthogonality + always use the GOT for extern weak symbols. */ + if ((flag_pic || SYMBOL_REF_WEAK (x)) + && !aarch64_symbol_binds_local_p (x)) + return SYMBOL_TINY_GOT; + /* When we retrieve symbol + offset address, we have to make sure the offset does not cause overflow of the final address. But we have no way of knowing the address of symbol at compile time @@ -17910,42 +17917,30 @@ aarch64_classify_symbol (rtx x, HOST_WIDE_INT offset) symbol + offset is outside the addressible range of +/-1MB in the TINY code model. So we limit the maximum offset to +/-64KB and assume the offset to the symbol is not larger than +/-(1MB - 64KB). - If offset_within_block_p is true we allow larger offsets. - Furthermore force to memory if the symbol is a weak reference to - something that doesn't resolve to a symbol in this module. */ - - if (SYMBOL_REF_WEAK (x) && !aarch64_symbol_binds_local_p (x)) - return SYMBOL_FORCE_TO_MEM; + If offset_within_block_p is true we allow larger offsets. */ if (!(IN_RANGE (offset, -0x10000, 0x10000) || offset_within_block_p (x, offset))) return SYMBOL_FORCE_TO_MEM; return SYMBOL_TINY_ABSOLUTE; + + case AARCH64_CMODEL_SMALL_SPIC: + case AARCH64_CMODEL_SMALL_PIC: case AARCH64_CMODEL_SMALL: + if ((flag_pic || SYMBOL_REF_WEAK (x)) + && !aarch64_symbol_binds_local_p (x)) + return aarch64_cmodel == AARCH64_CMODEL_SMALL_SPIC + ? SYMBOL_SMALL_GOT_28K : SYMBOL_SMALL_GOT_4G; + /* Same reasoning as the tiny code model, but the offset cap here is 1MB, allowing +/-3.9GB for the offset to the symbol. */ - - if (SYMBOL_REF_WEAK (x) && !aarch64_symbol_binds_local_p (x)) - return SYMBOL_FORCE_TO_MEM; if (!(IN_RANGE (offset, -0x100000, 0x100000) || offset_within_block_p (x, offset))) return SYMBOL_FORCE_TO_MEM; return SYMBOL_SMALL_ABSOLUTE; - case AARCH64_CMODEL_TINY_PIC: - if (!aarch64_symbol_binds_local_p (x)) - return SYMBOL_TINY_GOT; - return SYMBOL_TINY_ABSOLUTE; - - case AARCH64_CMODEL_SMALL_SPIC: - case AARCH64_CMODEL_SMALL_PIC: - if (!aarch64_symbol_binds_local_p (x)) - return (aarch64_cmodel == AARCH64_CMODEL_SMALL_SPIC - ? SYMBOL_SMALL_GOT_28K : SYMBOL_SMALL_GOT_4G); - return SYMBOL_SMALL_ABSOLUTE; - case AARCH64_CMODEL_LARGE: /* This is alright even in PIC code as the constant pool reference is always PC relative and within diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md index cc82d06..977adef 100644 --- a/gcc/config/arm/neon.md +++ b/gcc/config/arm/neon.md @@ -5066,13 +5066,6 @@ if (BYTES_BIG_ENDIAN) (const_string "neon_load2_2reg<q>")))] ) -(define_expand "vec_load_lanesoi<mode>" - [(set (match_operand:OI 0 "s_register_operand") - (unspec:OI [(match_operand:OI 1 "neon_struct_operand") - (unspec:VQ2 [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] - UNSPEC_VLD2))] - "TARGET_NEON") - (define_insn "neon_vld2<mode>" [(set (match_operand:OI 0 "s_register_operand" "=w") (unspec:OI [(match_operand:OI 1 "neon_struct_operand" "Um") @@ -5200,13 +5193,6 @@ if (BYTES_BIG_ENDIAN) (const_string "neon_store2_one_lane<q>")))] ) -(define_expand "vec_store_lanesoi<mode>" - [(set (match_operand:OI 0 "neon_struct_operand") - (unspec:OI [(match_operand:OI 1 "s_register_operand") - (unspec:VQ2 [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] - UNSPEC_VST2))] - "TARGET_NEON") - (define_insn "neon_vst2<mode>" [(set (match_operand:OI 0 "neon_struct_operand" "=Um") (unspec:OI [(match_operand:OI 1 "s_register_operand" "w") @@ -5634,16 +5620,6 @@ if (BYTES_BIG_ENDIAN) (const_string "neon_load4_4reg<q>")))] ) -(define_expand "vec_load_lanesxi<mode>" - [(match_operand:XI 0 "s_register_operand") - (match_operand:XI 1 "neon_struct_operand") - (unspec:VQ2 [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] - "TARGET_NEON" -{ - emit_insn (gen_neon_vld4<mode> (operands[0], operands[1])); - DONE; -}) - (define_expand "neon_vld4<mode>" [(match_operand:XI 0 "s_register_operand") (match_operand:XI 1 "neon_struct_operand") @@ -5835,16 +5811,6 @@ if (BYTES_BIG_ENDIAN) (const_string "neon_store4_4reg<q>")))] ) -(define_expand "vec_store_lanesxi<mode>" - [(match_operand:XI 0 "neon_struct_operand") - (match_operand:XI 1 "s_register_operand") - (unspec:VQ2 [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] - "TARGET_NEON" -{ - emit_insn (gen_neon_vst4<mode> (operands[0], operands[1])); - DONE; -}) - (define_expand "neon_vst4<mode>" [(match_operand:XI 0 "neon_struct_operand") (match_operand:XI 1 "s_register_operand") diff --git a/gcc/config/arm/vec-common.md b/gcc/config/arm/vec-common.md index 265fa40..e8b2901 100644 --- a/gcc/config/arm/vec-common.md +++ b/gcc/config/arm/vec-common.md @@ -483,6 +483,59 @@ } else gcc_unreachable (); + DONE; +}) + +(define_expand "vec_load_lanesoi<mode>" + [(set (match_operand:OI 0 "s_register_operand") + (unspec:OI [(match_operand:OI 1 "neon_struct_operand") + (unspec:VQ2 [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] + UNSPEC_VLD2))] + "TARGET_NEON || TARGET_HAVE_MVE" +{ + if (TARGET_NEON) + emit_insn (gen_neon_vld2<mode> (operands[0], operands[1])); + else + emit_insn (gen_mve_vld2q<mode> (operands[0], operands[1])); + DONE; +}) +(define_expand "vec_store_lanesoi<mode>" + [(set (match_operand:OI 0 "neon_struct_operand") + (unspec:OI [(match_operand:OI 1 "s_register_operand") + (unspec:VQ2 [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] + UNSPEC_VST2))] + "TARGET_NEON || TARGET_HAVE_MVE" +{ + if (TARGET_NEON) + emit_insn (gen_neon_vst2<mode> (operands[0], operands[1])); + else + emit_insn (gen_mve_vst2q<mode> (operands[0], operands[1])); + DONE; +}) + +(define_expand "vec_load_lanesxi<mode>" + [(match_operand:XI 0 "s_register_operand") + (match_operand:XI 1 "neon_struct_operand") + (unspec:VQ2 [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] + "TARGET_NEON || TARGET_HAVE_MVE" +{ + if (TARGET_NEON) + emit_insn (gen_neon_vld4<mode> (operands[0], operands[1])); + else + emit_insn (gen_mve_vld4q<mode> (operands[0], operands[1])); + DONE; +}) + +(define_expand "vec_store_lanesxi<mode>" + [(match_operand:XI 0 "neon_struct_operand") + (match_operand:XI 1 "s_register_operand") + (unspec:VQ2 [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] + "TARGET_NEON || TARGET_HAVE_MVE" +{ + if (TARGET_NEON) + emit_insn (gen_neon_vst4<mode> (operands[0], operands[1])); + else + emit_insn (gen_mve_vst4q<mode> (operands[0], operands[1])); DONE; }) diff --git a/gcc/config/csky/constraints.md b/gcc/config/csky/constraints.md index 6067d3d..c9bc9f2 100644 --- a/gcc/config/csky/constraints.md +++ b/gcc/config/csky/constraints.md @@ -24,8 +24,6 @@ (define_register_constraint "b" "LOW_REGS" "r0 - r15") (define_register_constraint "c" "C_REGS" "C register") (define_register_constraint "y" "HILO_REGS" "HI and LO registers") -(define_register_constraint "l" "LO_REGS" "LO register") -(define_register_constraint "h" "HI_REGS" "HI register") (define_register_constraint "v" "V_REGS" "vector registers") (define_register_constraint "z" "SP_REGS" "SP register") @@ -34,7 +32,11 @@ (define_memory_constraint "Q" "Memory operands with base register, index register and short displacement for FPUV2" - (match_test "csky_valid_fpuv2_mem_operand (op)")) + (match_test "csky_valid_mem_constraint_operand (op, \"Q\")")) + +(define_memory_constraint "W" + "Memory operands with base register, index register" + (match_test "csky_valid_mem_constraint_operand (op, \"W\")")) (define_constraint "R" "Memory operands whose address is a label_ref" @@ -172,3 +174,10 @@ "Constant in range [-8, -1]" (and (match_code "const_int") (match_test "CSKY_CONST_OK_FOR_US (ival)"))) + +(define_constraint "Dv" + "@VFPv3 + A const_double which can be used with a VFP fmovi + instruction." + (and (match_code "const_double") + (match_test "fpuv3_const_double_rtx (op)"))) diff --git a/gcc/config/csky/csky-modes.def b/gcc/config/csky/csky-modes.def new file mode 100644 index 0000000..109ee51 --- /dev/null +++ b/gcc/config/csky/csky-modes.def @@ -0,0 +1,22 @@ +/* C-SKY extra machine modes. + Copyright (C) 2018-2021 Free Software Foundation, Inc. + Contributed by C-SKY Microsystems and Mentor Graphics. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +/* Float modes. */ +FLOAT_MODE (HF, 2, ieee_half_format); /* Half-precision floating point */ diff --git a/gcc/config/csky/csky-protos.h b/gcc/config/csky/csky-protos.h index 7a2e23e..7c6528b 100644 --- a/gcc/config/csky/csky-protos.h +++ b/gcc/config/csky/csky-protos.h @@ -30,7 +30,7 @@ extern void csky_cpu_cpp_builtins (cpp_reader *); extern bool csky_inlinable_constant (HOST_WIDE_INT value); extern bool csky_shifted_imm8_constant (unsigned HOST_WIDE_INT, unsigned int *, unsigned int *); -extern bool csky_valid_fpuv2_mem_operand (rtx); +extern bool csky_valid_mem_constraint_operand (rtx, const char*); extern bool csky_minipool_load_p (rtx_insn *); extern const char *csky_output_move (rtx insn, rtx *, machine_mode); @@ -70,4 +70,9 @@ extern int csky_default_branch_cost (bool, bool); extern bool csky_default_logical_op_non_short_circuit (void); extern void csky_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree); +extern int csky_get_movedouble_length(rtx operands[]); + +/* The functions was used for fpuv3. */ +extern const char *fpuv3_output_move (rtx *operands); +extern int fpuv3_const_double_rtx (rtx); #endif /* GCC_CSKY_PROTOS_H */ diff --git a/gcc/config/csky/csky.c b/gcc/config/csky/csky.c index cdb95fe..7f2af82 100644 --- a/gcc/config/csky/csky.c +++ b/gcc/config/csky/csky.c @@ -112,7 +112,7 @@ enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER] = /* Reserved. */ RESERVE_REGS, /* CC,HI,LO registers. */ - C_REGS, HI_REGS, LO_REGS, + C_REGS, HILO_REGS, HILO_REGS, /* Reserved. */ RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, @@ -126,7 +126,46 @@ enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER] = /* Reserved. */ RESERVE_REGS, RESERVE_REGS, /* Register epc. */ - OTHER_REGS + OTHER_REGS, + /* Vec registers. */ + V_REGS, V_REGS, V_REGS, V_REGS, + V_REGS, V_REGS, V_REGS, V_REGS, + V_REGS, V_REGS, V_REGS, V_REGS, + V_REGS, V_REGS, V_REGS, V_REGS, + /* Reserved. */ + RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, + RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, + RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, + RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, + /* Reserved. */ + RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, + RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, + RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, + RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, + RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, + RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, + RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, + RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, + + RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, + RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, + RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, + RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, + RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, + RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, + RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, + RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, + + RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, + RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, + RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, + RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, + RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, + RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, + RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, + RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, + + RESERVE_REGS, RESERVE_REGS, RESERVE_REGS }; /* Arrays that map GCC register numbers to debugger register numbers, @@ -138,11 +177,34 @@ const int csky_dbx_regno[FIRST_PSEUDO_REGISTER] = 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - -1, -1, 36, 37, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, -1, -1, 72 + -1, -1, 36, 37, + 75, 79, 83, 87, 91, 95, 99, 103, + 107, 111, 115, 119, 123, 127, 131, 135, + 74, 78, 82, 86, 90, 94, 98, 102, + 106, 110, 114, 118, 122, 126, 130, 134, + -1, -1, 72, + /* vr: 71 - 86 */ + 139, 143, 147, 151, 155, 159, 163, 167, + 171, 175, 179, 183, 187, 191, 195, 199, + 138, 142, 146, 150, 154, 158, 162, 166, + 170, 174, 178, 182, 186, 190, 194, 198, + /* resereved */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + + -1, -1, -1 }; /* Table of machine attributes. */ @@ -351,6 +413,12 @@ csky_cpu_cpp_builtins (cpp_reader *pfile) builtin_define ("__CSKY_FPUV2__"); } + if (TARGET_SUPPORT_FPV3) + { + builtin_define ("__csky_fpuv3__"); + builtin_define ("__CSKY_FPUV3__"); + } + if (TARGET_ELRW) { builtin_define ("__csky_elrw__"); @@ -408,7 +476,6 @@ csky_cpu_cpp_builtins (cpp_reader *pfile) * Storage Layout * ******************************************************************/ - #undef TARGET_PROMOTE_FUNCTION_MODE #define TARGET_PROMOTE_FUNCTION_MODE \ default_promote_function_mode_always_promote @@ -416,6 +483,9 @@ csky_cpu_cpp_builtins (cpp_reader *pfile) #undef TARGET_CONSTANT_ALIGNMENT #define TARGET_CONSTANT_ALIGNMENT csky_constant_alignment +#undef TARGET_MANGLE_TYPE +#define TARGET_MANGLE_TYPE csky_mangle_type + /****************************************************************** * Stack Layout and Calling Conventions * @@ -692,6 +762,15 @@ csky_default_logical_op_non_short_circuit (void) #define TARGET_SCHED_ADJUST_COST csky_sched_adjust_cost +/****************************************************************** + * Builtin * + ******************************************************************/ + + +#undef TARGET_INIT_BUILTINS +#define TARGET_INIT_BUILTINS csky_init_builtins + + /* The declaration of functions. */ static void push_csky_minipool_fix (rtx_insn *, HOST_WIDE_INT, rtx *, machine_mode, rtx); @@ -837,6 +916,7 @@ Mfix *minipool_fix_tail; Mfix *minipool_barrier; /* Allow GC scanning of the minipool obstack. */ + static void csky_add_gc_roots (void) { @@ -846,6 +926,7 @@ csky_add_gc_roots (void) /* Implement TARGET_CONSTANT_ALIGNMENT. Make strings word-aligned so strcpy from constants will be faster. */ + static HOST_WIDE_INT csky_constant_alignment (const_tree exp, HOST_WIDE_INT align) { @@ -1109,6 +1190,7 @@ get_csky_barrier_cost (rtx_insn *insn) (FIX->address,MAX_ADDRESS) to forcibly insert a minipool barrier. Create the barrier by inserting a jump and add a new fix entry for it. */ + static Mfix * create_csky_fix_barrier (Mfix *fix, Mfix *fix_next, HOST_WIDE_INT max_address) @@ -1455,6 +1537,7 @@ csky_compute_pushpop_length (rtx *operands) } /* Emit constant pools for -mconstpool. */ + static void csky_emit_constant_pools (void) { @@ -1668,12 +1751,12 @@ get_csky_live_regs (int *count) save = true; /* Frame pointer marked used. */ - else if (frame_pointer_needed && reg == FRAME_POINTER_REGNUM) + else if (frame_pointer_needed && reg == HARD_FRAME_POINTER_REGNUM) save = true; /* This is required for CK801/802 where FP is a fixed reg, otherwise we end up with no FP value available to the DWARF-2 unwinder. */ - else if (crtl->calls_eh_return && reg == FRAME_POINTER_REGNUM) + else if (crtl->calls_eh_return && reg == HARD_FRAME_POINTER_REGNUM) save = true; /* CK801/802 also need special handling for LR because it's clobbered @@ -1749,6 +1832,8 @@ csky_layout_stack_frame (void) static bool csky_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to) { + if (to == FRAME_POINTER_REGNUM) + return from != ARG_POINTER_REGNUM; if (to == STACK_POINTER_REGNUM) return !frame_pointer_needed; return true; @@ -1769,6 +1854,7 @@ csky_initial_elimination_offset (int from, int to) switch (from) { case FRAME_POINTER_REGNUM: + case HARD_FRAME_POINTER_REGNUM: offset = cfun->machine->reg_offset; break; @@ -1783,7 +1869,7 @@ csky_initial_elimination_offset (int from, int to) /* If we are asked for the offset to the frame pointer instead, then subtract the difference between the frame pointer and stack pointer. */ - if (to == FRAME_POINTER_REGNUM) + if (to == FRAME_POINTER_REGNUM || to == HARD_FRAME_POINTER_REGNUM) offset -= cfun->machine->reg_offset; return offset; } @@ -1796,6 +1882,7 @@ csky_initial_elimination_offset (int from, int to) CUM is a variable of type CUMULATIVE_ARGS which gives info about the preceding args and about the function being called. ARG is a description of the argument. */ + static rtx csky_function_arg (cumulative_args_t pcum_v, const function_arg_info &arg) { @@ -1921,6 +2008,7 @@ csky_function_value (const_tree type, const_tree func, /* Implement TARGET_LIBCALL_VALUE. */ + static rtx csky_libcall_value (machine_mode mode, const_rtx libcall ATTRIBUTE_UNUSED) @@ -1949,6 +2037,7 @@ csky_function_value_regno_p (const unsigned int regno) /* Return an RTX indicating where the return address to the calling function can be found. */ + rtx csky_return_addr (int count, rtx frame ATTRIBUTE_UNUSED) { @@ -1964,6 +2053,7 @@ csky_return_addr (int count, rtx frame ATTRIBUTE_UNUSED) that must be put in registers. The value must be zero for arguments that are passed entirely in registers or that are entirely pushed on the stack. */ + static int csky_arg_partial_bytes (cumulative_args_t pcum_v, const function_arg_info &arg) { @@ -2180,7 +2270,19 @@ csky_conditional_register_usage (void) int regno; for (regno = CSKY_FIRST_VFP_REGNUM; - regno <= CSKY_LAST_VFP_REGNUM; regno++) + regno <= CSKY_LAST_VFP3_REGNUM; regno++) + { + fixed_regs[regno] = 1; + call_used_regs[regno] = 1; + } + } + + if (!TARGET_SUPPORT_FPV3) + { + int regno; + + for (regno = CSKY_FIRST_VFP3_REGNUM; + regno <= CSKY_LAST_VFP3_REGNUM; regno++) { fixed_regs[regno] = 1; call_used_regs[regno] = 1; @@ -2198,6 +2300,7 @@ csky_conditional_register_usage (void) } /* Implement TARGET_HARD_REGNO_NREGS. */ + static unsigned int csky_hard_regno_nregs (unsigned int regno, machine_mode mode) { @@ -2261,6 +2364,7 @@ csky_hard_regno_mode_ok (unsigned int regno, machine_mode mode) /* Implement TARGET_MODES_TIEABLE_P. We can't tie DFmode with other modes when V_REGs might be in use because those registers mess with the stored bits. */ + static bool csky_modes_tieable_p (machine_mode mode1, machine_mode mode2) { @@ -2272,6 +2376,7 @@ csky_modes_tieable_p (machine_mode mode1, machine_mode mode2) /* Implement TARGET_CAN_CHANGE_MODE_CLASS. V_REG registers can't do subreg as all values are reformatted to internal precision. */ + static bool csky_can_change_mode_class (machine_mode from, machine_mode to, @@ -2375,8 +2480,7 @@ csky_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x, /* We always require a general register when copying anything to HI/LO_REGNUM, except when copying an SImode value from HI/LO_REGNUM to a general register, or when copying from register 0. */ - if ((rclass == HILO_REGS || rclass == LO_REGS || rclass == HI_REGS) - && !CSKY_GENERAL_REGNO_P (regno)) + if (rclass == HILO_REGS && !CSKY_GENERAL_REGNO_P (regno)) return GENERAL_REGS; if (rclass == V_REGS && !CSKY_GENERAL_REGNO_P (regno)) @@ -2406,6 +2510,7 @@ csky_spill_class (reg_class_t rclass, machine_mode mode ATTRIBUTE_UNUSED) /* Convert a static initializer array of feature bits to sbitmap representation. */ + static void csky_initialize_isa (sbitmap isa, const enum csky_isa_feature *isa_bits) { @@ -2417,6 +2522,7 @@ csky_initialize_isa (sbitmap isa, const enum csky_isa_feature *isa_bits) /* Configure a build target TARGET from the user-specified options OPTS and OPTS_SET. */ + static void csky_configure_build_target (struct csky_build_target *target, struct cl_target_option *opts, @@ -2508,7 +2614,9 @@ csky_option_override (void) csky_base_arch = csky_active_target.base_arch; - if (flag_pic && !(CSKY_TARGET_ARCH (CK810) || CSKY_TARGET_ARCH (CK807))) + if (flag_pic && !(CSKY_TARGET_ARCH (CK807) + || CSKY_TARGET_ARCH (CK810) + || CSKY_TARGET_ARCH (CK860))) { flag_pic = 0; warning (0, "%qs is not supported by arch %s", @@ -2526,19 +2634,21 @@ csky_option_override (void) bool ok; int fpu_index; -#ifdef CSKY_FPUTYPE_DEFAULT - target_fpu_name = CSKY_FPUTYPE_DEFAULT; -#else - target_fpu_name = "fpv2"; -#endif - if (csky_active_target.core_name != NULL && !strchr (csky_active_target.core_name, 'f')) target_fpu_name = "auto"; else if (CSKY_TARGET_ARCH (CK803) || !TARGET_DOUBLE_FLOAT) target_fpu_name = "fpv2_sf"; + else if (CSKY_TARGET_ARCH (CK860)) + target_fpu_name = "fpv3"; else if (TARGET_DOUBLE_FLOAT && TARGET_FDIVDU) target_fpu_name = "fpv2_divd"; + else +#ifdef CSKY_FPUTYPE_DEFAULT + target_fpu_name = CSKY_FPUTYPE_DEFAULT; +#else + target_fpu_name = "fpv2"; +#endif ok = opt_enum_arg_to_value (OPT_mfpu_, target_fpu_name, &fpu_index, CL_TARGET); @@ -2573,6 +2683,18 @@ csky_option_override (void) TARGET_FDIVDU = 0; } + /* Initialize boolean versions of the architectural flags, for use + in the .md file. */ + +#undef CSKY_ISA +#define CSKY_ISA(IDENT, DESC) \ + { \ + csky_arch_isa_features[CSKY_ISA_FEATURE_GET (IDENT)] = \ + bitmap_bit_p (csky_active_target.isa, CSKY_ISA_FEATURE_GET (IDENT)); \ + } +#include "csky_isa.def" +#undef CSKY_ISA + /* Extended LRW instructions are enabled by default on CK801, disabled otherwise. */ if (TARGET_ELRW == -1) @@ -2645,18 +2767,6 @@ csky_option_override (void) TARGET_MULTIPLE_STLD = 0; } - /* Initialize boolean versions of the architectural flags, for use - in the .md file. */ - -#undef CSKY_ISA -#define CSKY_ISA(IDENT, DESC) \ - { \ - csky_arch_isa_features[CSKY_ISA_FEATURE_GET (IDENT)] = \ - bitmap_bit_p (csky_active_target.isa, CSKY_ISA_FEATURE_GET (IDENT)); \ - } -#include "csky_isa.def" -#undef CSKY_ISA - /* TODO */ /* Resynchronize the saved target options. */ @@ -3020,10 +3130,8 @@ ck810_legitimate_index_p (machine_mode mode, rtx index, int strict_p) { enum rtx_code code = GET_CODE (index); - if (TARGET_HARD_FLOAT - && (mode == SFmode || mode == DFmode)) - return (code == CONST_INT && INTVAL (index) < 1024 - && INTVAL (index) >= 0 + if (code == CONST_INT && TARGET_HARD_FLOAT && CSKY_VREG_MODE_P (mode)) + return (INTVAL (index) < 1024 && INTVAL (index) >= 0 && (INTVAL (index) & 3) == 0); if (code == CONST_INT) @@ -3183,7 +3291,7 @@ static bool decompose_csky_address (rtx addr, struct csky_address *out) { rtx base = NULL_RTX, index = NULL_RTX, disp = NULL_RTX; - HOST_WIDE_INT scale = 1; + HOST_WIDE_INT scale = 0; rtx scale_rtx = NULL_RTX; int i; @@ -3231,7 +3339,10 @@ decompose_csky_address (rtx addr, struct csky_address *out) if (!base) base = op; else if (!index) - index = op; + { + index = op; + scale = 1; + } else return false; break; @@ -3259,7 +3370,7 @@ decompose_csky_address (rtx addr, struct csky_address *out) scale_rtx = XEXP (op, 1); if (!CONST_INT_P (scale_rtx)) return false; - scale = scale << INTVAL (scale_rtx); + scale = 1 << INTVAL (scale_rtx); break; default: return false; @@ -3484,6 +3595,14 @@ csky_print_operand (FILE *stream, rtx x, int code) case UNSPEC: csky_output_pic_addr_const (stream, x, code); break; + case CONST_DOUBLE: + { + char fpstr[20]; + real_to_decimal ( fpstr, CONST_DOUBLE_REAL_VALUE (x), + sizeof (fpstr), 0, 1); + fprintf (stream, "%s", fpstr); + } + break; default: output_addr_const (stream, x); break; @@ -3997,17 +4116,37 @@ csky_output_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[], return "mfhi\t%0"; } - if (CSKY_VREG_P (dstreg) && CSKY_VREG_P (srcreg)) - return "fmovs\t%0, %1"; - if (CSKY_VREG_P (dstreg)) - return "fmtvrl\t%0, %1"; - if (CSKY_VREG_P (srcreg)) - return "fmfvrl\t%0, %1"; - - if (REGNO (src) == CSKY_CC_REGNUM) - return "mvc\t%0"; - else - return "mov\t%0, %1"; + if (CSKY_VREG_P (dstreg) && CSKY_VREG_P (srcreg)) + { + if (CSKY_ISA_FEATURE (fpv2_sf)) + return "fmovs\t%0, %1"; + else if (CSKY_ISA_FEATURE (fpv3_sf)) + return "fmov.32\t%0, %1"; + else + gcc_unreachable (); + } + if (CSKY_VREG_P (dstreg)) + { + if (CSKY_ISA_FEATURE (fpv2_sf)) + return "fmtvrl\t%0, %1"; + else if (CSKY_ISA_FEATURE (fpv3_sf)) + return "fmtvr.32.1\t%0, %1"; + else + gcc_unreachable (); + } + if (CSKY_VREG_P (srcreg)) + { + if (CSKY_ISA_FEATURE (fpv2_sf)) + return "fmfvrl\t%0, %1"; + else if (CSKY_ISA_FEATURE (fpv3_sf)) + return "fmfvr.32.1\t%0, %1"; + else + gcc_unreachable (); + } + if (REGNO (src) == CSKY_CC_REGNUM) + return "mvc\t%0"; + else + return "mov\t%0, %1"; } /* The situation mov memory to reg. */ else if (GET_CODE (src) == MEM) @@ -4018,13 +4157,21 @@ csky_output_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[], switch (GET_MODE (src)) { case E_HImode: + case E_HFmode: return "ldr.h\t%0, %1"; case E_QImode: return "ldr.b\t%0, %1"; case E_SImode: case E_SFmode: if (CSKY_VREG_P (REGNO (dst))) - return "fldrs\t%0, %1"; + { + if (CSKY_ISA_FEATURE(fpv2_sf)) + return "fldrs\t%0, %1"; + else if (CSKY_ISA_FEATURE(fpv3_sf)) + return "fldr.32\t%0, %1"; + else + gcc_unreachable (); + } else return "ldr.w\t%0, %1"; default: @@ -4042,13 +4189,21 @@ csky_output_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[], switch (GET_MODE (src)) { case E_HImode: + case E_HFmode: return "ld.h\t%0, %1"; case E_QImode: return "ld.b\t%0, %1"; case E_SFmode: case E_SImode: if (CSKY_VREG_P (REGNO (dst))) - return "flds\t%0, %1"; + { + if (CSKY_ISA_FEATURE(fpv2_sf)) + return "flds\t%0, %1"; + else if (CSKY_ISA_FEATURE(fpv3_sf)) + return "fld.32\t%0, %1"; + else + gcc_unreachable (); + } else return "ld.w\t%0, %1"; default: @@ -4106,7 +4261,14 @@ csky_output_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[], case E_SFmode: case E_SImode: if (CSKY_VREG_P (REGNO (src))) - return "fstrs\t%1, %0"; + { + if (CSKY_ISA_FEATURE(fpv2_sf)) + return "fstrs\t%1, %0"; + else if (CSKY_ISA_FEATURE(fpv3_sf)) + return "fstr.32\t%1, %0"; + else + gcc_unreachable (); + } else return "str.w\t%1, %0"; default: @@ -4122,7 +4284,14 @@ csky_output_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[], case E_SImode: case E_SFmode: if (CSKY_VREG_P (REGNO (src))) - return "fsts\t%1, %0"; + { + if (CSKY_ISA_FEATURE(fpv2_sf)) + return "fsts\t%1, %0"; + else if (CSKY_ISA_FEATURE(fpv3_sf)) + return "fst.32\t%1, %0"; + else + gcc_unreachable (); + } else return "st.w\t%1, %0"; default: @@ -4261,7 +4430,14 @@ csky_output_movedouble (rtx operands[], return "mthi\t%R1\n\tmtlo\t%1"; } else if (CSKY_VREG_P (srcreg) && CSKY_VREG_P (dstreg)) - return "fmovd\t%0, %1"; + { + if (CSKY_ISA_FEATURE(fpv2_df)) + return "fmovd\t%0, %1"; + else if (CSKY_ISA_FEATURE(fpv3_df)) + return "fmov.64\t%0, %1"; + else + gcc_unreachable (); + } else if (CSKY_VREG_P (srcreg)) { /* Since the vector registers in fpuv2_soft processors @@ -4270,18 +4446,46 @@ csky_output_movedouble (rtx operands[], if (TARGET_SOFT_FPU) return "fmfvrl\t%0, %1"; else if (TARGET_BIG_ENDIAN) - return "fmfvrh\t%0, %1\n\tfmfvrl\t%R0, %1"; + { + if (CSKY_ISA_FEATURE(fpv2_df)) + return "fmfvrh\t%0, %1\n\tfmfvrl\t%R0, %1"; + else if (CSKY_ISA_FEATURE(fpv3_df)) + return "fmfvr.64\t%R0, %0, %1"; + else + gcc_unreachable (); + } else - return "fmfvrh\t%R0, %1\n\tfmfvrl\t%0, %1"; + { + if (CSKY_ISA_FEATURE(fpv2_df)) + return "fmfvrh\t%R0, %1\n\tfmfvrl\t%0, %1"; + else if (CSKY_ISA_FEATURE(fpv3_df)) + return "fmfvr.64\t%0, %R0, %1"; + else + gcc_unreachable (); + } } else if (CSKY_VREG_P (dstreg)) { if (TARGET_SOFT_FPU) return "fmtvrl\t%0, %1"; else if (TARGET_BIG_ENDIAN) - return "fmtvrh\t%0, %1\n\tfmtvrl\t%0, %R1"; + { + if (CSKY_ISA_FEATURE(fpv2_df)) + return "fmtvrh\t%0, %1\n\tfmtvrl\t%0, %R1"; + else if (CSKY_ISA_FEATURE(fpv3_df)) + return "fmtvr.64\t%0, %R1, %1"; + else + gcc_unreachable (); + } else - return "fmtvrh\t%0, %R1\n\tfmtvrl\t%0, %1"; + { + if (CSKY_ISA_FEATURE(fpv2_df)) + return "fmtvrh\t%0, %R1\n\tfmtvrl\t%0, %1"; + else if (CSKY_ISA_FEATURE(fpv3_df)) + return "fmtvr.64\t%0, %1, %R1"; + else + gcc_unreachable (); + } } /* Ensure the second source not overwritten. */ @@ -4323,9 +4527,23 @@ csky_output_movedouble (rtx operands[], if (CSKY_VREG_P (dstreg)) { if (op0.index) - return "fldrd\t%0, %1"; + { + if (CSKY_ISA_FEATURE(fpv2_df)) + return "fldrd\t%0, %1"; + else if (CSKY_ISA_FEATURE(fpv3_df)) + return "fldr.64\t%0, %1"; + else + gcc_unreachable (); + } else - return "fldd\t%0, %1"; + { + if (CSKY_ISA_FEATURE(fpv2_df)) + return "fldd\t%0, %1"; + else if (CSKY_ISA_FEATURE(fpv3_df)) + return "fld.64\t%0, %1"; + else + gcc_unreachable (); + } } /* FIXME length attribute is wrong here. */ if (dstreg == basereg) @@ -4389,9 +4607,23 @@ csky_output_movedouble (rtx operands[], if (CSKY_VREG_P (srcreg)) { if (op0.index) - return "fstrd\t%1, %0"; + { + if (CSKY_ISA_FEATURE(fpv2_df)) + return "fstrd\t%1, %0"; + else if (CSKY_ISA_FEATURE(fpv3_df)) + return "fstr.64\t%1, %0"; + else + gcc_unreachable (); + } else - return "fstd\t%1, %0"; + { + if (CSKY_ISA_FEATURE(fpv2_df)) + return "fstd\t%1, %0"; + else if (CSKY_ISA_FEATURE(fpv3_df)) + return "fst.64\t%1, %0"; + else + gcc_unreachable (); + } } /* FIXME length attribute is wrong here. */ if (srcreg == basereg) @@ -4518,9 +4750,181 @@ csky_output_ck801_movedouble (rtx operands[], gcc_unreachable (); } +/* Calculate the instruction's length for moving double-word data. */ + +int +csky_get_movedouble_length(rtx operands[]) +{ + rtx dst = operands[0]; + rtx src = operands[1]; + + if (REG_P (dst)) + { + if (REG_P (src)) + { + int dstreg = REGNO (dst); + int srcreg = REGNO (src); + + if (CSKY_VREG_P (srcreg) && CSKY_VREG_P (dstreg)) + return 4; + else + return 8; + } + else if (GET_CODE (src) == MEM) + { + rtx memexp = XEXP (src, 0); + int dstreg = REGNO (dst); + struct csky_address op0; + decompose_csky_address (XEXP (src, 0), &op0); + + if (GET_CODE (memexp) == LABEL_REF) + return 8; + if (CSKY_VREG_P (dstreg)) + return 4; + return 8; + } + else if (GET_CODE (src) == CONST_INT || GET_CODE (src) == CONST_DOUBLE) + { + split_double (src, operands + 2, operands + 3); + if (CSKY_CONST_OK_FOR_N (INTVAL (operands[2]) + 1) + && CSKY_CONST_OK_FOR_N (INTVAL (operands[3]) + 1) + && REGNO (operands[0]) < 6) + return 4; + else + return 8; + } + } + else if (GET_CODE (dst) == MEM && GET_CODE (src) == REG) + { + rtx memexp = XEXP (dst, 0); + int srcreg = REGNO (src); + int offset = -1; + if (CSKY_VREG_P (srcreg)) + return 4; + + if (GET_CODE (memexp) == REG) + offset = 0; + else if (GET_CODE (memexp) == PLUS) + { + if (GET_CODE (XEXP (memexp, 0)) == REG) + offset = INTVAL (XEXP (memexp, 1)); + else if (GET_CODE (XEXP (memexp, 1)) == REG) + offset = INTVAL (XEXP (memexp, 0)); + else + gcc_unreachable (); + } + else + gcc_unreachable (); + + if (srcreg <= 6 && offset <= 1020) + return 4; + else if ((srcreg == 7 && offset <= 1024) || (srcreg <= 7 && offset == 1024)) + return 6; + else + return 8; + } + else + gcc_unreachable (); + + return 0; +} + +/* Output float point load/store instructions for fpuv3. */ + +const char * +fpuv3_output_move (rtx *operands) +{ + rtx reg, mem, addr, ops[2]; + bool isload = REG_P (operands[0]); + + const char *templ = "f%s%s.%s\t%%0, %%1"; + char buff[50]; + machine_mode mode; + + reg = operands[isload ? 0 : 1]; + mem = operands[isload ? 1 : 0]; + + gcc_assert (REG_P (reg)); + gcc_assert (CSKY_VREG_P (REGNO (reg))); + gcc_assert (MEM_P (mem)); + + mode = GET_MODE (reg); + const char *type = mode == DFmode ? "64" : + mode == SFmode ? "32" : + mode == HFmode ? "16" : + NULL; + gcc_assert(type != NULL); + + addr = XEXP (mem, 0); + struct csky_address caddr; + decompose_csky_address (addr, &caddr); + + ops[0] = reg; + ops[1] = mem; + sprintf (buff, templ, + isload ? "ld" : "st", + caddr.index ? "r" : "", + type); + output_asm_insn (buff, ops); + + return ""; +} + +/* Check if a const_double can be used by a VFP fmovi instruction. */ + +int +fpuv3_const_double_rtx (rtx x) +{ + REAL_VALUE_TYPE r, m; + r = *CONST_DOUBLE_REAL_VALUE (x); + + /* Fpuv3 doesn't support the following values. */ + if (REAL_VALUE_ISINF (r) || REAL_VALUE_ISNAN (r) || REAL_VALUE_MINUS_ZERO (r) + || r.cl == rvc_zero) + return 0; + + /* Extract sign, exponent and mantissa. */ + int exponent; + r = real_value_abs (&r); + exponent = REAL_EXP (&r); + + bool fail; + unsigned HOST_WIDE_INT mantissa, mant_hi; + unsigned HOST_WIDE_INT mask; + int point_pos = 2 * HOST_BITS_PER_WIDE_INT - 1; + real_ldexp (&m, &r, point_pos - exponent); + wide_int w = real_to_integer (&m, &fail, HOST_BITS_PER_WIDE_INT * 2); + mantissa = w.elt (0); + mant_hi = w.elt (1); + + exponent -= 1; + + if (!IN_RANGE (exponent, -4, 11)) + return 0; + + /* If there are bits set in the low part of the mantissa, these values are + not supported. */ + if (mantissa != 0) + return 0; + + /* Now, make the mantissa contain the most-significant bits, and the + point_pos indicates the number of these bits. */ + point_pos -= HOST_BITS_PER_WIDE_INT; + mantissa = mant_hi; + + /* We can only allow a mantissa of 9 significant digits, top of which is always 1. */ + mask = ((unsigned HOST_WIDE_INT)1 << (point_pos - 9)) - 1; + if ((mantissa & mask) != 0) + return 0; + + return 1; +} + + /* Split operands for an AND expression when OPERANDS[2] is a constant. Note operands[0] is marked earlyclobber in this case and can be overwritten. Return true if "DONE", false otherwise. */ + bool csky_split_and (rtx *operands) { @@ -4650,6 +5054,7 @@ csky_split_and (rtx *operands) /* Split operands for an IOR expression when OPERANDS[2] is a constant. Note operands[0] is marked earlyclobber in this case and can be overwritten. Return true if "DONE", false otherwise. */ + bool csky_split_ior (rtx *operands) { @@ -4717,6 +5122,7 @@ csky_split_ior (rtx *operands) /* Split operands for an XOR expression when OPERANDS[2] is a constant. Note operands[0] is marked earlyclobber in this case and can be overwritten. Return true if "DONE", false otherwise. */ + bool csky_split_xor (rtx *operands) { @@ -4765,6 +5171,7 @@ csky_split_xor (rtx *operands) /* Return true if X is an address form involving a symbol or label ref. */ + bool csky_symbolic_address_p (rtx x) { @@ -4793,6 +5200,9 @@ csky_emit_compare (enum rtx_code code, rtx op0, rtx op1) bool invert; rtx cc_reg = gen_rtx_REG (CCmode, CSKY_CC_REGNUM); + if (GET_MODE_CLASS(GET_MODE (op0)) == MODE_FLOAT) + return csky_emit_compare_float(code, op0, op1); + if (GET_CODE (op1) == CONST_INT) { HOST_WIDE_INT val = INTVAL (op1); @@ -5378,7 +5788,7 @@ csky_expand_prologue (void) of the register save area. */ if (frame_pointer_needed) { - insn = emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx)); + insn = emit_insn (gen_movsi (hard_frame_pointer_rtx, stack_pointer_rtx)); RTX_FRAME_RELATED_P (insn) = 1; } @@ -5441,7 +5851,7 @@ csky_expand_epilogue (void) /* Restore the SP to the base of the register save area. */ if (frame_pointer_needed) { - insn = emit_move_insn (stack_pointer_rtx, frame_pointer_rtx); + insn = emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx); RTX_FRAME_RELATED_P (insn) = 1; } else @@ -5597,7 +6007,7 @@ csky_set_eh_return_address (rtx source, rtx scratch) if (frame_pointer_needed) { - basereg = frame_pointer_rtx; + basereg = hard_frame_pointer_rtx; delta = 0; } else @@ -5707,6 +6117,7 @@ tls_unspec_mentioned_p (rtx x) /* Implement LEGITIMATE_PIC_OPERAND_P. */ + bool csky_legitimate_pic_operand_p (rtx x) { @@ -5938,33 +6349,20 @@ csky_emit_compare_float (enum rtx_code code, rtx op0, rtx op1) op1 = force_reg (mode, op1); invert = false; + switch (code) { case EQ: code = NE; invert = true; break; - - case NE: - break; - case LE: - if (op1 == CONST0_RTX (mode)) - op1 = force_reg (mode, op1); - break; case GT: - if (op1 == CONST0_RTX (mode)) - op1 = force_reg (mode, op1); - break; - case GE: - break; case LT: - if (op1 == CONST0_RTX (mode)) - { - code = GE; - invert = true; - } - break; - case UNORDERED: + case LE: + if (op1 == CONST0_RTX (mode) && (CSKY_ISA_FEATURE_GET(fpv2_sf) + || CSKY_ISA_FEATURE_GET(fpv2_df) + || CSKY_ISA_FEATURE_GET(fpv2_divd))) + op1 = force_reg (mode, op1); break; case ORDERED: code = UNORDERED; @@ -5980,10 +6378,11 @@ csky_emit_compare_float (enum rtx_code code, rtx op0, rtx op1) return invert; } -/* Support for the Q memory constraint. Returns true if OP is a MEM RTX - with an address consisting of base + index or base + displacement. */ +/* Support for the Q or W memory constraint. Returns true if OP is a MEM + RTX with an address consisting of base + index or base + displacement. */ + bool -csky_valid_fpuv2_mem_operand (rtx op) +csky_valid_mem_constraint_operand (rtx op, const char *constraint) { struct csky_address addr; @@ -5998,7 +6397,7 @@ csky_valid_fpuv2_mem_operand (rtx op) return false; /* Verify index operand. */ - if (addr.index) + if (addr.index && (constraint[0] == 'Q' || constraint[0] == 'W')) { if (!is_csky_address_register_rtx_p (addr.index, 0)) return false; @@ -6010,7 +6409,7 @@ csky_valid_fpuv2_mem_operand (rtx op) return false; } /* Verify disp operand. */ - else if (addr.disp) + else if (addr.disp && constraint[0] == 'Q') { rtx disp = addr.disp; @@ -6023,7 +6422,11 @@ csky_valid_fpuv2_mem_operand (rtx op) return false; } - return true; + else if (constraint[0] == 'Q') + /* Single reg is valid for 'Q'. */ + return true; + + return false; } @@ -6145,7 +6548,7 @@ csky_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED, || (CLASS) == LOW_REGS) #define HILO_REG_CLASS_P(CLASS) \ - ((CLASS) == HI_REGS || (CLASS) == LO_REGS || (CLASS) == HILO_REGS) + ((CLASS) == HILO_REGS) #define V_REG_CLASS_P(CLASS) \ ((CLASS) == V_REGS) @@ -6442,7 +6845,7 @@ ck803_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, } } -/* TARGET_RTX_COSTS helper for ck807+ arches. */ +/* TARGET_RTX_COSTS helper for ck807/ck810 arches. */ static bool ck807_ck810_rtx_costs (rtx x, int code, @@ -6473,6 +6876,52 @@ ck807_ck810_rtx_costs (rtx x, int code, } } +/* TARGET_RTX_COSTS helper for ck860 arches. */ + +static bool +ck860_rtx_costs (rtx x, int code, machine_mode mode, + int outer_code ATTRIBUTE_UNUSED, + int *total, bool speed ATTRIBUTE_UNUSED) +{ + switch (code) + { + case PLUS: + /* The costs of mula is 1 more than mult. */ + if (GET_CODE (XEXP (x, 0)) == MULT && REG_P (XEXP (x, 1)) && speed) + { + rtx mul_op0 = XEXP (XEXP (x, 0), 0); + rtx mul_op1 = XEXP (XEXP (x, 0), 1); + if (REG_P (mul_op0) && REG_P (mul_op1)) + { + *total = COSTS_N_INSNS (1); + *total += rtx_cost (XEXP (x, 0), mode, + (enum rtx_code) code, 0, speed); + return true; + } + } + return false; + case MULT: + if (REG_P (XEXP (x, 0)) && CONST_INT_P (XEXP (x, 1))) + { + HOST_WIDE_INT val = INTVAL (XEXP (x, 1)); + if (val % 2 == 0 && val < 0xffffffff && val > 0) + { + *total = COSTS_N_INSNS (1); + return true; + } + } + return false; + + case CONST: + case LABEL_REF: + case SYMBOL_REF: + *total = COSTS_N_INSNS (3); + return true; + default: + return false; + } +} + /* Implement TARGET_RTX_COSTS, to compute a (partial) cost for rtx X. Return true if the complete cost has been computed, and false if @@ -6491,6 +6940,8 @@ csky_rtx_costs (rtx x, machine_mode mode ATTRIBUTE_UNUSED, int outer_code, return ck803_rtx_costs (x, code, outer_code, total, speed); else if (CSKY_TARGET_ARCH (CK807) || CSKY_TARGET_ARCH (CK810)) return ck807_ck810_rtx_costs (x, code, outer_code, total, speed); + else if (CSKY_TARGET_ARCH (CK860)) + return ck860_rtx_costs (x, code, mode, outer_code, total, speed); else gcc_unreachable (); } @@ -6633,6 +7084,7 @@ csky_warn_func_return (tree decl) /* Implement TARGET_RETURN_IN_MEMORY to decide whether TYPE should be returned in memory (true) or in a register (false). FNTYPE is the type of the function making the call. */ + static bool csky_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) @@ -6646,6 +7098,7 @@ csky_return_in_memory (const_tree type, Dwarf models VFP registers as 64-bit or 128-bit registers default. GCC models tham as 32-bit registers, so we need to describe this to the DWARF generation code. Other registers can use the default. */ + static rtx csky_dwarf_register_span (rtx rtl) { @@ -6659,11 +7112,15 @@ csky_dwarf_register_span (rtx rtl) if (!CSKY_VREG_P (regno)) return NULL_RTX; + if (CSKY_VREG_HI_P (regno)) + regno += 16; + mode = GET_MODE (rtl); if (GET_MODE_SIZE (mode) < 8) return NULL_RTX; - if (TARGET_SOFT_FPU) + + if (TARGET_SINGLE_FPU) { nregs = GET_MODE_SIZE (mode) / 4; for (i = 0; i < nregs; i += 2) @@ -6684,9 +7141,18 @@ csky_dwarf_register_span (rtx rtl) as the CPU bit width. Transform the 64-bit FPU registers to 32 bits here, and we will modify the unwind processing to fit CSKY architecture later. */ - nregs = GET_MODE_SIZE (mode) / 8; - for (i = 0; i < nregs; i++) - parts[i] = gen_rtx_REG (SImode, regno + i); + nregs = GET_MODE_SIZE (mode) / 4; + for (i = 0; i < nregs; i += 2) + if (TARGET_BIG_ENDIAN) + { + parts[i] = gen_rtx_REG (SImode, regno + i - 16); + parts[i + 1] = gen_rtx_REG (SImode, regno + i); + } + else + { + parts[i] = gen_rtx_REG (SImode, regno + i); + parts[i + 1] = gen_rtx_REG (SImode, regno + i - 16); + } } return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nregs , parts)); @@ -6847,6 +7313,34 @@ csky_init_cumulative_args (CUMULATIVE_ARGS *pcum, tree fntype, pcum->is_stdarg = true; } + +/* Implement the TARGET_INIT_BUILTINS target macro. */ + +void +csky_init_builtins (void) +{ + /* Inint fp16. */ + static tree csky_floatHF_type_node = make_node (REAL_TYPE); + TYPE_PRECISION (csky_floatHF_type_node) = GET_MODE_PRECISION (HFmode); + layout_type (csky_floatHF_type_node); + (*lang_hooks.types.register_builtin_type) (csky_floatHF_type_node, "__fp16"); +} + + +/* Implement TARGET_MANGLE_TYPE. */ + +static const char * +csky_mangle_type (const_tree type) +{ + if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL + && DECL_NAME (TYPE_NAME (type)) + && !strcmp (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))), "__fp16")) + return "__fp16"; + + /* Use the default mangling. */ + return NULL; +} + struct gcc_target targetm = TARGET_INITIALIZER; #include "gt-csky.h" diff --git a/gcc/config/csky/csky.h b/gcc/config/csky/csky.h index c7590ab..f2b0d1c 100644 --- a/gcc/config/csky/csky.h +++ b/gcc/config/csky/csky.h @@ -28,8 +28,17 @@ #define CSKY_GENERAL_REGNO_P(N) \ ((N) < CSKY_NGPR_REGS && (int)(N) >= 0) -#define CSKY_VREG_P(N) \ - ((N) >= CSKY_FIRST_VFP_REGNUM && (N) <= CSKY_LAST_VFP_REGNUM) +#define CSKY_VREG_LO_P(N) \ + ((N) >= CSKY_FIRST_VFP_REGNUM \ + && (N) <= CSKY_LAST_VFP_REGNUM) + + #define CSKY_VREG_HI_P(N) \ + ((N) >= CSKY_FIRST_VFP3_REGNUM \ + && (N) <= CSKY_LAST_VFP3_REGNUM) + + #define CSKY_VREG_P(N) \ + (CSKY_VREG_LO_P(N) \ + || CSKY_VREG_HI_P(N)) #define CSKY_HILO_REG_P(N) \ ((N) == CSKY_HI_REGNUM || (N) == CSKY_LO_REGNUM) @@ -124,7 +133,7 @@ (optimize_size && TARGET_CONSTANT_POOL \ && (CSKY_TARGET_ARCH (CK801) || CSKY_TARGET_ARCH (CK802))) #define TARGET_TLS \ - (CSKY_TARGET_ARCH (CK807) || CSKY_TARGET_ARCH (CK810)) + (CSKY_TARGET_ARCH (CK807) || CSKY_TARGET_ARCH (CK810) || CSKY_TARGET_ARCH (CK860)) /* Run-time Target Specification. */ #define TARGET_SOFT_FLOAT (csky_float_abi == CSKY_FLOAT_ABI_SOFT) @@ -133,7 +142,9 @@ /* Use hardware floating point calling convention. */ #define TARGET_HARD_FLOAT_ABI (csky_float_abi == CSKY_FLOAT_ABI_HARD) -#define TARGET_SINGLE_FPU (csky_fpu_index == TARGET_FPU_fpv2_sf) +#define TARGET_SINGLE_FPU (csky_fpu_index == TARGET_FPU_fpv2_sf \ + || csky_fpu_index == TARGET_FPU_fpv3_hsf \ + || csky_fpu_index == TARGET_FPU_fpv3_hf) #define TARGET_DOUBLE_FPU (TARGET_HARD_FLOAT && !TARGET_SINGLE_FPU) #define FUNCTION_VARG_REGNO_P(REGNO) \ @@ -142,13 +153,18 @@ CSKY_FIRST_VFP_REGNUM + CSKY_NPARM_FREGS - 1)) #define CSKY_VREG_MODE_P(mode) \ - ((mode) == SFmode || (mode) == DFmode) + ((mode) == SFmode || (mode) == DFmode \ + || (CSKY_ISA_FEATURE(fpv3_hf) && (mode) == HFmode)) #define FUNCTION_VARG_MODE_P(mode) \ (TARGET_HARD_FLOAT_ABI \ && CSKY_VREG_MODE_P(mode) \ && !(mode == DFmode && TARGET_SINGLE_FPU)) +#define TARGET_SUPPORT_FPV3 (CSKY_ISA_FEATURE (fpv3_hf) \ + || CSKY_ISA_FEATURE (fpv3_sf) \ + || CSKY_ISA_FEATURE (fpv3_df)) + /* Number of loads/stores handled by ldm/stm. */ #define CSKY_MIN_MULTIPLE_STLD 3 #define CSKY_MAX_MULTIPLE_STLD 12 @@ -326,7 +342,8 @@ extern int csky_arch_isa_features[]; #define STACK_POINTER_REGNUM CSKY_SP_REGNUM /* Base register for access to local variables of the function. */ -#define FRAME_POINTER_REGNUM 8 +#define FRAME_POINTER_REGNUM 36 +#define HARD_FRAME_POINTER_REGNUM 8 /* Base register for access to arguments of the function. This is a fake register that is always eliminated. */ @@ -354,7 +371,9 @@ extern int csky_arch_isa_features[]; #define ELIMINABLE_REGS \ {{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM },\ { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM },\ - { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM }} + { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM },\ + { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM },\ + { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM }} /* Define the offset between two registers, one to be eliminated, and the other its replacement, at the start of a routine. */ @@ -427,7 +446,7 @@ typedef struct ******************************************************************/ -#define FIRST_PSEUDO_REGISTER 71 +#define FIRST_PSEUDO_REGISTER 202 /* 1 for registers that have pervasive standard uses and are not available for the register allocator. @@ -456,7 +475,31 @@ typedef struct /* reserved */ \ 1, 1, \ /* epc */ \ - 1 \ + 1, \ + /* vr16 vr17 vr18 vr19 vr20 vr21 vr22 vr23 */ \ + 0, 0, 0, 0, 0, 0, 0, 0, \ + /* vr24 vr25 vr26 vr27 vr28 vr29 vr30 vr31 */ \ + 0, 0, 0, 0, 0, 0, 0, 0 , \ + /* reserved */ \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + /* reserved */ \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + \ + 1, 1, 1 \ } /* Like `CALL_USED_REGISTERS' but used to overcome a historical @@ -487,7 +530,31 @@ typedef struct /* reserved */ \ 1, 1, \ /* epc */ \ - 1 \ + 1, \ + /* vr16 vr17 vr18 vr19 vr20 vr21 vr22 vr23*/ \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + /* vr24 vr25 vr26 vr27 vr28 vr29 vr30 vr31 */ \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + /* reserved */ \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + /* reserved */ \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + \ + 1, 1, 1 \ } #define REGISTER_NAMES \ @@ -510,7 +577,37 @@ typedef struct "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7", \ "vr8", "vr9", "vr10", "vr11", "vr12", "vr13", "vr14", "vr15", \ "reserved", "reserved", \ - "epc" \ + "epc", \ + /* V registers: 71~86 */ \ + "vr16", "vr17", "vr18", "vr19", "vr20", "vr21", "vr22", "vr23", \ + "vr24", "vr25", "vr26", "vr27", "vr28", "vr29", "vr30", "vr31", \ + "reserved", "reserved", "reserved", "reserved", "reserved", \ + "reserved", "reserved", "reserved", "reserved", "reserved", \ + "reserved", "reserved", "reserved", "reserved", "reserved", \ + "reserved", \ + /* reserved: 87~201*/ \ + "reserved", "reserved", "reserved", "reserved", "reserved", \ + "reserved", "reserved", "reserved", "reserved", "reserved", \ + "reserved", "reserved", "reserved", "reserved", "reserved", \ + "reserved", "reserved", "reserved", "reserved", "reserved", \ + "reserved", "reserved", "reserved", "reserved", "reserved", \ + "reserved", "reserved", "reserved", "reserved", "reserved", \ + "reserved", "reserved", \ + "reserved", "reserved", "reserved", "reserved", "reserved", \ + "reserved", "reserved", "reserved", "reserved", "reserved", \ + "reserved", "reserved", "reserved", "reserved", "reserved", \ + "reserved", "reserved", "reserved", "reserved", "reserved", \ + "reserved", "reserved", "reserved", "reserved", "reserved", \ + "reserved", "reserved", "reserved", "reserved", "reserved", \ + "reserved", "reserved", \ + "reserved", "reserved", "reserved", "reserved", "reserved", \ + "reserved", "reserved", "reserved", "reserved", "reserved", \ + "reserved", "reserved", "reserved", "reserved", "reserved", \ + "reserved", "reserved", "reserved", "reserved", "reserved", \ + "reserved", "reserved", "reserved", "reserved", "reserved", \ + "reserved", "reserved", "reserved", "reserved", "reserved", \ + "reserved", "reserved", \ + "reserved", "reserved", "reserved" \ } /* Table of additional register names to use in user input. */ @@ -569,9 +666,16 @@ typedef struct 52, 53, 54, 55, 56, 57, 58, 59, \ /* vr8 vr9 vr10 vr11 vr12 vr13 vr14 vr15 */ \ 60, 61, 62, 63, 64, 65, 66, 67, \ +/* vr16 vr17 vr18 vr18 vr20 vr21 vr22 vr23 */ \ + 71, 72, 73, 74, 75, 76, 77, 78, \ +/* vr24 vr25 vr26 vr27 vr28 vr28 vr30 vr31 */ \ + 79, 80, 81, 82, 83, 84, 85, 86, \ /* reserved */ \ 36, 37, 38, 39, 40, 41, 42, 43, \ 44, 45, 46, 47, 48, 49, 50, 51, \ +/* reserved */ \ + 87, 88, 89, 90, 91, 92, 93, 94, \ + 95, 96, 97, 98, 99, 100, 101, 102, \ /* sp tls reserved c reserved epc */ \ 14, 31, 32, 33, 68, 69, 70 } @@ -584,8 +688,6 @@ enum reg_class LOW_REGS, GENERAL_REGS, C_REGS, - HI_REGS, - LO_REGS, HILO_REGS, V_REGS, OTHER_REGS, @@ -605,8 +707,6 @@ enum reg_class "LOW_REGS", \ "GENERAL_REGS", \ "C_REGS", \ - "HI_REGS", \ - "LO_REGS", \ "HILO_REGS", \ "V_REGS", \ "OTHER_REGS", \ @@ -616,21 +716,30 @@ enum reg_class /* Define which registers fit in which classes. This is an initializer for a vector of HARD_REG_SET of length N_REG_CLASSES. */ -#define REG_CLASS_CONTENTS \ -{ \ - {0x00000000, 0x00000000, 0x00000000 }, /* NO_REGS */ \ - {0x000000FF, 0x00000000, 0x00000000 }, /* MINI_REGS */ \ - {0x00004000, 0x00000000, 0x00000000 }, /* SP_REGS */ \ - {0x0000FFFF, 0x00000000, 0x00000000 }, /* LOW_REGS */ \ - {0xFFFFFFFF, 0x00000000, 0x00000000 }, /* GENERAL_REGS */ \ - {0x00000000, 0x00000002, 0x00000000 }, /* C_REGS */ \ - {0x00000000, 0x00000004, 0x00000000 }, /* HI_REG */ \ - {0x00000000, 0x00000008, 0x00000000 }, /* LO_REG */ \ - {0x00000000, 0x0000000c, 0x00000000 }, /* HILO_REGS */ \ - {0x00000000, 0xFFF00000, 0x0000000F }, /* V_REGS */ \ - {0x00000000, 0x00000000, 0x00000040 }, /* OTHER_REGS */ \ - {0x00000000, 0x0FF00001, 0x00000030 }, /* RESERVE_REGS */ \ - {0xFFFFFFFF, 0xFFFFFFFF, 0x0000007F }, /* ALL_REGS */ \ +#define REG_CLASS_CONTENTS \ +{ \ + {0x00000000, 0x00000000, 0x00000000, 0x00000000, \ + 0x00000000, 0x00000000, 0x00000000}, /* NO_REGS */ \ + {0x000000FF, 0x00000000, 0x00000000, 0x00000000, \ + 0x00000000, 0x00000000, 0x00000000}, /* MINI_REGS */ \ + {0x00004000, 0x00000000, 0x00000000, 0x00000000, \ + 0x00000000, 0x00000000, 0x00000000}, /* SP_REGS */ \ + {0x0000FFFF, 0x00000000, 0x00000000, 0x00000000, \ + 0x00000000, 0x00000000, 0x00000000}, /* LOW_REGS */ \ + {0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000, \ + 0x00000000, 0x00000000, 0x00000000}, /* GENERAL_REGS */ \ + {0x00000000, 0x00000002, 0x00000000, 0x00000000, \ + 0x00000000, 0x00000000, 0x00000000}, /* C_REGS */ \ + {0x00000000, 0x0000000c, 0x00000000, 0x00000000, \ + 0x00000000, 0x00000000, 0x00000000}, /* HILO_REGS */ \ + {0x00000000, 0xFFF00000, 0x007FFF8F, 0x00000000, \ + 0x00000000, 0x00000000, 0x00000000}, /* V_REGS */ \ + {0x00000000, 0x00000000, 0x00000040, 0x00000000, \ + 0x00000000, 0x00000000, 0x00000000}, /* OTHER_REGS */ \ + {0x00000000, 0x000FFFF1, 0xFF800030, 0xFFFFFFFF, \ + 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF}, /* RESERVE_REGS */ \ + {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \ + 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF}, /* ALL_REGS */ \ } /* Return register class from regno. */ diff --git a/gcc/config/csky/csky.md b/gcc/config/csky/csky.md index 8bb3b2b..c27d627 100644 --- a/gcc/config/csky/csky.md +++ b/gcc/config/csky/csky.md @@ -32,6 +32,8 @@ (CSKY_FIRST_RET_REGNUM 0) (CSKY_FIRST_VFP_REGNUM 52) (CSKY_LAST_VFP_REGNUM 67) + (CSKY_FIRST_VFP3_REGNUM 71) + (CSKY_LAST_VFP3_REGNUM 86) (CSKY_FIRST_HIGH_REGNUM 16) (CSKY_LAST_HIGH_REGNUM 31) (CSKY_FIRST_MINI_REGNUM 0) @@ -423,85 +425,6 @@ (set_attr "type" "alu,alu,alu,load,load,store")] ) -;; Float mov instructions. - -(define_expand "movsf" - [(set (match_operand:SF 0 "general_operand" "") - (match_operand:SF 1 "general_operand" ""))] - "" - " - if (GET_CODE (operands[0]) == MEM && can_create_pseudo_p ()) - operands[1] = force_reg (SFmode, operands[1]); - " -) - -;; FIXME: maybe the vreg load/stores should have their own type attr. -(define_insn "*csky_movsf_fpv2" - [(set (match_operand:SF 0 "nonimmediate_operand" "=b,r,v,r,r,r, m,Q,v,v,v") - (match_operand:SF 1 "general_operand" " b,r,r,v,m,mF,r,v,Q,v,m"))] - "CSKY_ISA_FEATURE (fpv2_sf)" - "* return csky_output_move (insn, operands, SFmode);" - [(set_attr "length" "2,4,4,4,4,4,4,4,4,4,4") - (set_attr "type" "alu,alu,alu,alu,load,load,store,alu,alu,alu,alu")] -) - -(define_insn "*ck801_movsf" - [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r, m") - (match_operand:SF 1 "general_operand" " r,m,mF,r"))] - "CSKY_ISA_FEATURE (E1)" - "* return csky_output_ck801_move (insn, operands, SFmode);" - [(set_attr "length" "2,4,4,4") - (set_attr "type" "alu,load,load,store")] -) - -(define_insn "*csky_movsf" - [(set (match_operand:SF 0 "nonimmediate_operand" "=b,r,r,r, m") - (match_operand:SF 1 "general_operand" " b,r,m,mF,r"))] - "CSKY_ISA_FEATURE (E2) && !CSKY_ISA_FEATURE (fpv2_sf)" - "* return csky_output_move (insn, operands, SFmode);" - [(set_attr "length" "2,4,4,4,4") - (set_attr "type" "alu,alu,load,load,store")] -) - - -(define_expand "movdf" - [(set (match_operand:DF 0 "general_operand" "") - (match_operand:DF 1 "general_operand" ""))] - "" - " - if (GET_CODE (operands[0]) == MEM && can_create_pseudo_p ()) - operands[1] = force_reg (DFmode, operands[1]); - " -) - -;; FIXME: maybe the vreg load/stores should have their own type attr. -(define_insn "*csky_movdf_fpv2" - [(set (match_operand:DF 0 "nonimmediate_operand" "=b,r,v,r,r,r, m,Q,v,v,v") - (match_operand:DF 1 "general_operand" "b,r,r,v,m,mF,r,v,Q,v,m"))] - "CSKY_ISA_FEATURE (fpv2_df)" - "* return csky_output_movedouble (operands, DFmode);" - [(set_attr "length" "4,8,8,8,8,8,8,8,8,8,8") - (set_attr "type" "alu,alu,alu,alu,load,load,store,alu,alu,alu,alu")] -) - -(define_insn "*ck801_movdf" - [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,r, m") - (match_operand:DF 1 "general_operand" " r,m,mF,r"))] - "CSKY_ISA_FEATURE (E1)" - "* return csky_output_ck801_movedouble (operands, DFmode);" - [(set_attr "length" "4,8,8,8") - (set_attr "type" "alu,load,load,store")] -) - -(define_insn "*csky_movdf" - [(set (match_operand:DF 0 "nonimmediate_operand" "=b,r,r,r, m") - (match_operand:DF 1 "general_operand" " b,r,m,mF,r"))] - "CSKY_ISA_FEATURE (E2) && !CSKY_ISA_FEATURE (fpv2_df)" - "* return csky_output_movedouble (operands, DFmode);" - [(set_attr "length" "4,8,8,8,8") - (set_attr "type" "alu,alu,load,load,store")] -) - ;; The only CCmode move supported is a nop. Without this pattern, ;; CSE is unable to eliminate redundant comparisons in conditional ;; execution expressions. @@ -522,7 +445,7 @@ (define_expand "movsicc" [(set (match_operand 0 "register_operand" "") - (if_then_else:SI (match_operand 1 "ordered_comparison_operator" "") + (if_then_else:SI (match_operand 1 "comparison_operator" "") (match_operand:SI 2 "register_operand" "") (match_operand:SI 3 "register_operand" "")))] "CSKY_ISA_FEATURE (E2)" @@ -1321,7 +1244,7 @@ (define_expand "addsicc" [(match_operand:SI 0 "register_operand" "") - (match_operand 1 "ordered_comparison_operator" "") + (match_operand 1 "comparison_operator" "") (match_operand:SI 2 "register_operand" "") (match_operand:SI 3 "csky_literal_K_Uh_operand" "")] "CSKY_ISA_FEATURE (E2)" @@ -3316,9 +3239,9 @@ (define_expand "untyped_call" [(parallel [(call (match_operand 0 "" "") - (const_int 0)) - (match_operand 1 "" "") - (match_operand 2 "" "")])] + (const_int 0)) + (match_operand 1 "" "") + (match_operand 2 "" "")])] "" { int i; @@ -3349,11 +3272,25 @@ "" [(set_attr "length" "0")]) -(define_insn "*call_value_internal_vs" - [(set (match_operand:SF 0 "register_operand" "=v,v,v") +(define_insn "*call_value_internal_vh" + [(set (match_operand:HF 0 "register_operand" "=v,v,v") (call (mem:SI (match_operand:SI 1 "csky_call_address_operand" "b, r,S")) (match_operand 2 "" ""))) (clobber (reg:SI CSKY_LR_REGNUM))] + "TARGET_HARD_FLOAT_ABI && CSKY_ISA_FEATURE (fpv3_hf)" + "@ + jsr\t%1 + jsr\t%1 + jbsr\t%1" + [(set_attr "length" "2,4,4") + (set_attr "type" "call_jsr,call_jsr,call")] +) + +(define_insn "*call_value_internal_vs" + [(set (match_operand:SF 0 "register_operand" "=v,v,v") + (call (mem:SI (match_operand:SI 1 "csky_call_address_operand" "b, r,S")) + (match_operand 2 "" ""))) + (clobber (reg:SI CSKY_LR_REGNUM))] "TARGET_HARD_FLOAT_ABI" "@ jsr\t%1 @@ -3364,9 +3301,9 @@ ) (define_insn "*call_value_internal_vd" - [(set (match_operand:DF 0 "register_operand" "=v,v,v") - (call (mem:SI (match_operand:SI 1 "csky_call_address_operand" "b, r,S")) - (match_operand 2 "" ""))) + [(set (match_operand:DF 0 "register_operand" "=v,v,v") + (call (mem:SI (match_operand:SI 1 "csky_call_address_operand" "b, r,S")) + (match_operand 2 "" ""))) (clobber (reg:SI CSKY_LR_REGNUM))] "TARGET_HARD_FLOAT_ABI && TARGET_DOUBLE_FPU" "@ @@ -3378,18 +3315,18 @@ ) (define_insn "*call_value_internal_pic_vs" - [(set (match_operand:SF 0 "register_operand" "=v") - (call (mem:SI (match_operand:SI 1 "csky_unspec_operand" "X")) - (match_operand 2 "" ""))) + [(set (match_operand:SF 0 "register_operand" "=v") + (call (mem:SI (match_operand:SI 1 "csky_unspec_operand" "X")) + (match_operand 2 "" ""))) (clobber (reg:SI CSKY_LR_REGNUM))] "flag_pic && TARGET_HARD_FLOAT_ABI" "* return csky_output_call (operands, 1);" ) (define_insn "*call_value_internal_pic_vd" - [(set (match_operand:DF 0 "register_operand" "=v") - (call (mem:SI (match_operand:SI 1 "csky_unspec_operand" "X")) - (match_operand 2 "" ""))) + [(set (match_operand:DF 0 "register_operand" "=v") + (call (mem:SI (match_operand:SI 1 "csky_unspec_operand" "X")) + (match_operand 2 "" ""))) (clobber (reg:SI CSKY_LR_REGNUM))] "flag_pic && TARGET_HARD_FLOAT_ABI && TARGET_DOUBLE_FPU" "* return csky_output_call (operands, 1);" diff --git a/gcc/config/csky/csky_cores.def b/gcc/config/csky/csky_cores.def index 8309e99..fcf42a4 100644 --- a/gcc/config/csky/csky_cores.def +++ b/gcc/config/csky/csky_cores.def @@ -38,6 +38,8 @@ CSKY_ARCH ("ck807", ck807, CK807, CSKY_ISA_FEAT (CSKY_ISA_CK807) CSKY_ISA_FEAT (CSKY_ISA_DSP)) CSKY_ARCH ("ck810", ck810, CK810, CSKY_ISA_FEAT (CSKY_ISA_CK810) CSKY_ISA_FEAT (CSKY_ISA_DSP)) +CSKY_ARCH ("ck860", ck860, CK860, + CSKY_ISA_FEAT (CSKY_ISA_CK860)) #endif @@ -181,6 +183,12 @@ CSKY_CORE ("ck810ft", ck810ff, ck810ft, CK810, CSKY_ISA_FEAT_NONE) CSKY_CORE ("ck810ftv", ck810ftv, ck810ftv, CK810, CSKY_ISA_FEAT_NONE) + +/* ck860 Architecture Processors */ +CSKY_CORE("ck860", ck860, ck860, CK860, + CSKY_ISA_FEAT_NONE) +CSKY_CORE("ck860f", ck860f, ck860f, CK860, + CSKY_ISA_FEAT_NONE) #endif @@ -196,4 +204,9 @@ CSKY_CORE ("ck810ftv", ck810ftv, ck810ftv, CK810, CSKY_FPU ("fpv2_sf", fpv2_sf, CSKY_ISA_FEAT (CSKY_ISA_FPv2_SF)) CSKY_FPU ("fpv2", fpv2, CSKY_ISA_FEAT (CSKY_ISA_FPv2)) CSKY_FPU ("fpv2_divd", fpv2_divd, CSKY_ISA_FEAT (CSKY_ISA_FPv2_DIVD)) + +CSKY_FPU ("fpv3_hf", fpv3_hf, CSKY_ISA_FEAT (CSKY_ISA_FPv3_HF)) +CSKY_FPU ("fpv3_hsf", fpv3_hsf, CSKY_ISA_FEAT (CSKY_ISA_FPv3_HSF)) +CSKY_FPU ("fpv3_sdf", fpv3_sdf, CSKY_ISA_FEAT (CSKY_ISA_FPv3_SDF)) +CSKY_FPU ("fpv3", fpv3, CSKY_ISA_FEAT (CSKY_ISA_FPv3)) #endif diff --git a/gcc/config/csky/csky_insn_fpu.md b/gcc/config/csky/csky_insn_fpu.md index c1e78af..e0d01ab 100644 --- a/gcc/config/csky/csky_insn_fpu.md +++ b/gcc/config/csky/csky_insn_fpu.md @@ -18,528 +18,314 @@ ;; along with GCC; see the file COPYING3. If not see ;; <http://www.gnu.org/licenses/>. */ -;; ------------------------------------------------------------------------- -;; Float Abs instructions -;; ------------------------------------------------------------------------- +(define_c_enum "unspec" [ + UNSPEC_FLOOR + UNSPEC_CEIL + UNSPEC_BTRUNC + UNSPEC_RINT +]) -(define_insn "abssf2" - [(set (match_operand:SF 0 "register_operand" "=v,r") - (abs:SF (match_operand:SF 1 "register_operand" "v, r")))] - "CSKY_ISA_FEATURE (fpv2_sf)" - "@ - fabss\t%0, %1 - bclri\t%0, %1, 31") +(define_c_enum "unspecv" [ + VUNSPEC_GET_FCR ; Represent fetch of FCR content. + VUNSPEC_SET_FCR ; Represent assign of FCR content. + VUNSPEC_INS_FCR ; Represent insert of FCR content. +]) -(define_insn "absdf2" - [(set (match_operand:DF 0 "register_operand" "=v") - (abs:DF (match_operand:DF 1 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_df)" - "fabsd\t%0, %1") +(define_mode_iterator F3ANY [HF SF DF]) +(define_mode_attr f3t [(HF "16") (SF "32") (DF "64")]) +(define_mode_iterator SFDF [SF DF]) +(define_mode_attr f2t [(SF "32") (DF "64")]) -;; ------------------------------------------------------------------------- -;; Float Neg instructions -;; ------------------------------------------------------------------------- +(define_code_iterator FCMPZ [ne ge lt gt le]) +(define_code_attr zero_inst [(ne "nez") (ge "hsz") (lt "ltz") (gt "hz") (le "lsz")]) -(define_insn "negsf2" - [(set (match_operand:SF 0 "register_operand" "=v") - (neg:SF (match_operand:SF 1 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_sf)" - "fnegs\t%0, %1") +(define_code_iterator FCMP [ne ge lt]) +(define_code_attr reg_inst [(ne "ne") (ge "hs") (lt "lt")]) -(define_insn "negdf2" - [(set (match_operand:DF 0 "register_operand" "=v") - (neg:DF (match_operand:DF 1 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_df)" - "fnegd\t%0, %1") +(define_code_iterator FIX_SU [fix unsigned_fix]) +(define_code_attr fixsuop [(fix "") (unsigned_fix "uns")]) +(define_code_attr fixsu [(fix "s") (unsigned_fix "u")]) +(define_code_iterator FLOAT_SU [float unsigned_float]) +(define_code_attr floatsuop [(float "") (unsigned_float "uns")]) +(define_code_attr floatsu [(float "s") (unsigned_float "u")]) -;; ------------------------------------------------------------------------- -;; Float Sqrt instructions -;; ------------------------------------------------------------------------- +(define_int_iterator FRM [UNSPEC_FLOOR + UNSPEC_CEIL UNSPEC_RINT]) -(define_insn "sqrtsf2" - [(set (match_operand:SF 0 "register_operand" "=v") - (sqrt:SF (match_operand:SF 1 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_sf)" - "fsqrts\t%0, %1") +(define_int_iterator FRMF [UNSPEC_FLOOR + UNSPEC_CEIL UNSPEC_BTRUNC]) -(define_insn "sqrtdf2" - [(set (match_operand:DF 0 "register_operand" "=v") - (sqrt:DF (match_operand:DF 1 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_divd)" - "fsqrtd\t%0, %1") +(define_int_attr frm_pattern [(UNSPEC_FLOOR "floor") + (UNSPEC_CEIL "ceil") (UNSPEC_BTRUNC "btrunc") + (UNSPEC_RINT "rint")]) + +(define_int_attr rm [(UNSPEC_FLOOR ".rni") + (UNSPEC_CEIL ".rpi") (UNSPEC_BTRUNC ".rz") + (UNSPEC_RINT "")]) ;; ------------------------------------------------------------------------- -;; Float Add instructions +;; Float mov instructions ;; ------------------------------------------------------------------------- -(define_insn "addsf3" - [(set (match_operand:SF 0 "register_operand" "=v") - (plus:SF (match_operand:SF 1 "register_operand" "v") - (match_operand:SF 2 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_sf)" - "fadds\t%0, %1, %2") +(define_expand "movhf" + [(set (match_operand:HF 0 "general_operand" "") + (match_operand:HF 1 "general_operand" ""))] + "CSKY_ISA_FEATURE(fpv3_hf)" + " + { + if (GET_CODE(operands[0]) == MEM && can_create_pseudo_p ()) + { + operands[1] = force_reg (HFmode, operands[1]); + } + } +") + +(define_expand "mov<mode>" + [(set (match_operand:SFDF 0 "general_operand" "") + (match_operand:SFDF 1 "general_operand" ""))] + "CSKY_ISA_FEATURE(fpv2_<mode>) + || CSKY_ISA_FEATURE(fpv3_<mode>)" + " + { + if (GET_CODE(operands[0]) == MEM && can_create_pseudo_p ()) + { + operands[1] = force_reg (<MODE>mode, operands[1]); + } + } +") + +;; Move float value with general register. + +(define_insn "*e2_movsf" + [(set (match_operand:SF 0 "nonimmediate_operand" "=b,r,r,r, m") + (match_operand:SF 1 "general_operand" " b,r,m,mF,r"))] + "CSKY_ISA_FEATURE (E2) + && !CSKY_ISA_FEATURE (fpv2_sf) + && !CSKY_ISA_FEATURE (fpv3_sf)" + "* return csky_output_move (insn, operands, SFmode);" + [(set_attr "length" "2,4,4,4,4") + (set_attr "type" "alu,alu,load,load,store")] +) + +(define_insn "*e2_movdf" + [(set (match_operand:DF 0 "nonimmediate_operand" "=b,r,r,r, m") + (match_operand:DF 1 "general_operand" " b,r,m,mF,r"))] + "CSKY_ISA_FEATURE (E2) + && !CSKY_ISA_FEATURE (fpv2_df) + && !CSKY_ISA_FEATURE (fpv3_df)" + "* return csky_output_movedouble (operands, DFmode);" + [(set_attr "length" "4,8,8,8,8") + (set_attr "type" "alu,alu,load,load,store")] +) -(define_insn "adddf3" - [(set (match_operand:DF 0 "register_operand" "=v") - (plus:DF (match_operand:DF 1 "register_operand" "v") - (match_operand:DF 2 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_df)" - "faddd\t%0, %1, %2") +(define_insn "*e1_movsf" + [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r, m") + (match_operand:SF 1 "general_operand" " r,m,mF,r"))] + "CSKY_ISA_FEATURE (E1)" + "* return csky_output_ck801_move (insn, operands, SFmode);" + [(set_attr "length" "2,4,4,4") + (set_attr "type" "alu,load,load,store")] +) +(define_insn "*e1_movdf" + [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,r, m") + (match_operand:DF 1 "general_operand" " r,m,mF,r"))] + "CSKY_ISA_FEATURE (E1)" + "* return csky_output_ck801_movedouble (operands, DFmode);" + [(set_attr "length" "4,8,8,8") + (set_attr "type" "alu,load,load,store")] +) ;; ------------------------------------------------------------------------- -;; Float Sub instructions +;; Float Mul instructions ;; ------------------------------------------------------------------------- -(define_insn "subsf3" - [(set (match_operand:SF 0 "register_operand" "=v") - (minus:SF (match_operand:SF 1 "register_operand" "v") - (match_operand:SF 2 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_sf)" - "fsubs\t%0, %1, %2") +(define_expand "mulhf3" + [(set (match_operand:HF 0 "register_operand" "=v") + (mult:HF (match_operand:HF 1 "register_operand" "v") + (match_operand:HF 2 "register_operand" "v")))] + "CSKY_ISA_FEATURE(fpv3_hf)" + "") -(define_insn "subdf3" - [(set (match_operand:DF 0 "register_operand" "=v") - (minus:DF (match_operand:DF 1 "register_operand" "v") - (match_operand:DF 2 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_df)" - "fsubd\t%0, %1, %2") +(define_expand "mul<mode>3" + [(set (match_operand:SFDF 0 "register_operand" "=v") + (mult:SFDF (match_operand:SFDF 1 "register_operand" "v") + (match_operand:SFDF 2 "register_operand" "v")))] + "CSKY_ISA_FEATURE(fpv2_<mode>) + || CSKY_ISA_FEATURE(fpv3_<mode>)" + "") +(define_expand "fma<mode>4" + [(set (match_operand:F3ANY 0 "register_operand" "=v") + (fma:F3ANY (match_operand:F3ANY 1 "register_operand" "v") + (match_operand:F3ANY 2 "register_operand" "v") + (match_operand:F3ANY 3 "register_operand" "0")))] + "CSKY_ISA_FEATURE(fpv3_<mode>)" + "") ;; ------------------------------------------------------------------------- -;; Float Mul instructions +;; Float ADD SUB NEG ABS instructions ;; ------------------------------------------------------------------------- -(define_insn "mulsf3" - [(set (match_operand:SF 0 "register_operand" "=v") - (mult:SF (match_operand:SF 1 "register_operand" "v") - (match_operand:SF 2 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_sf)" - "fmuls\t%0, %1, %2") - -(define_insn "muldf3" - [(set (match_operand:DF 0 "register_operand" "=v") - (mult:DF (match_operand:DF 1 "register_operand" "v") - (match_operand:DF 2 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_df)" - "fmuld\t%0, %1, %2") - -(define_insn "*fpuv2_nmulsf3_1" - [(set (match_operand:SF 0 "register_operand" "=v") - (mult:SF (neg:SF (match_operand:SF 1 "register_operand" "%v")) - (match_operand:SF 2 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_sf) && !flag_rounding_math" - "fnmuls\t%0, %1, %2") - -(define_insn "*fpuv2_nmulsf3_2" - [(set (match_operand:SF 0 "register_operand" "=v") - (neg:SF (mult:SF (match_operand:SF 1 "register_operand" "v") - (match_operand:SF 2 "register_operand" "v"))))] - "CSKY_ISA_FEATURE (fpv2_sf)" - "fnmuls\t%0, %1, %2") - -(define_insn "*fpuv2_nmuldf3_1" - [(set (match_operand:DF 0 "register_operand" "=v") - (mult:DF (neg:DF (match_operand:DF 1 "register_operand" "%v")) - (match_operand:DF 2 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_df) && !flag_rounding_math" - "fnmuld\t%0, %1, %2") - -(define_insn "*fpuv2_nmuldf3_2" - [(set (match_operand:DF 0 "register_operand" "=v") - (neg:DF (mult:DF (match_operand:DF 1 "register_operand" "v") - (match_operand:DF 2 "register_operand" "v"))))] - "CSKY_ISA_FEATURE (fpv2_df)" - "fnmuld\t%0, %1, %2") +(define_expand "addhf3" + [(set (match_operand:HF 0 "register_operand" "") + (plus:HF (match_operand:HF 1 "register_operand" "") + (match_operand:HF 2 "register_operand" "")))] + "CSKY_ISA_FEATURE(fpv3_hf)" + "" +) + +(define_expand "add<mode>3" + [(set (match_operand:SFDF 0 "register_operand" "") + (plus:SFDF (match_operand:SFDF 1 "register_operand" "") + (match_operand:SFDF 2 "register_operand" "")))] + "CSKY_ISA_FEATURE(fpv2_<mode>) || CSKY_ISA_FEATURE(fpv3_<mode>)" + "" +) +(define_expand "subhf3" + [(set (match_operand:HF 0 "register_operand" "") + (minus:HF (match_operand:HF 1 "register_operand" "") + (match_operand:HF 2 "register_operand" "")))] + "CSKY_ISA_FEATURE(fpv3_hf)" + "" +) -;; ------------------------------------------------------------------------- -;; Float Div instructions -;; ------------------------------------------------------------------------- +(define_expand "sub<mode>3" + [(set (match_operand:SFDF 0 "register_operand" "") + (minus:SFDF (match_operand:SFDF 1 "register_operand" "") + (match_operand:SFDF 2 "register_operand" "")))] + "CSKY_ISA_FEATURE(fpv2_<mode>) || CSKY_ISA_FEATURE(fpv3_<mode>)" + "" +) -(define_expand "divsf3" - [(set (match_operand:SF 0 "register_operand" "") - (div:SF (match_operand:SF 1 "csky_arith_float1_operand" "") - (match_operand:SF 2 "register_operand" "")))] - "CSKY_ISA_FEATURE (fpv2_sf)" - "") +(define_expand "abshf2" + [(set (match_operand:HF 0 "register_operand" "") + (abs:HF (match_operand:HF 1 "register_operand" "")))] + "CSKY_ISA_FEATURE(fpv3_hf)" + "" +) -(define_insn "*fpuv2_divsf3" - [(set (match_operand:SF 0 "register_operand" "=v") - (div:SF (match_operand:SF 1 "register_operand" "v") - (match_operand:SF 2 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_sf)" - "fdivs\t%0, %1, %2") - -(define_insn "*fpuv2_1_divsf3" - [(set (match_operand:SF 0 "register_operand" "=v") - (div:SF (match_operand:SF 1 "csky_const_float1_operand" "i") - (match_operand:SF 2 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_sf)" - "frecips\t%0, %2") - - -(define_expand "divdf3" - [(set (match_operand:DF 0 "register_operand" "") - (div:DF (match_operand:DF 1 "csky_arith_float1_operand" "") - (match_operand:DF 2 "register_operand" "")))] - "CSKY_ISA_FEATURE (fpv2_divd)" - "") +(define_expand "abs<mode>2" + [(set (match_operand:SFDF 0 "register_operand" "") + (abs:SFDF (match_operand:SFDF 1 "register_operand" "")))] + "CSKY_ISA_FEATURE(fpv2_<mode>) || CSKY_ISA_FEATURE(fpv3_<mode>)" + "" +) -(define_insn "*fpuv2_divdf3" - [(set (match_operand:DF 0 "register_operand" "=v") - (div:DF (match_operand:DF 1 "register_operand" "v") - (match_operand:DF 2 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_divd)" - "fdivd\t%0, %1, %2") +(define_expand "neghf2" + [(set (match_operand:HF 0 "register_operand" "") + (neg:HF (match_operand:HF 1 "register_operand" "")))] + "CSKY_ISA_FEATURE(fpv3_hf)" + "" +) -(define_insn "*fpuv2_1_divdf3" - [(set (match_operand:DF 0 "register_operand" "=v") - (div:DF (match_operand:DF 1 "csky_const_float1_operand" "i") - (match_operand:DF 2 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_divd)" - "frecipd\t%0, %2") +(define_expand "neg<mode>2" + [(set (match_operand:SFDF 0 "register_operand" "") + (neg:SFDF (match_operand:SFDF 1 "register_operand" "")))] + "CSKY_ISA_FEATURE(fpv2_<mode>) || CSKY_ISA_FEATURE(fpv3_<mode>)" + "" +) +(define_expand "sqrthf2" + [(set (match_operand:HF 0 "register_operand" "") + (sqrt:HF (match_operand:HF 1 "register_operand" "")))] + "CSKY_ISA_FEATURE(fpv3_hf)" + "" +) + +(define_expand "sqrt<mode>2" + [(set (match_operand:SFDF 0 "register_operand" "") + (sqrt:SFDF (match_operand:SFDF 1 "register_operand" "")))] + "CSKY_ISA_FEATURE(fpv2_<mode>) || CSKY_ISA_FEATURE(fpv3_<mode>)" + "" +) ;; ------------------------------------------------------------------------- -;; Float add(sub) with mult instructions +;; Float div instructions ;; ------------------------------------------------------------------------- -;; vrz <= vrz + vrx * vry -(define_insn "*fpuv2_fmacs" - [(set (match_operand:SF 0 "register_operand" "=v") - (plus:SF (mult:SF (match_operand:SF 1 "register_operand" "v") - (match_operand:SF 2 "register_operand" "v")) - (match_operand:SF 3 "register_operand" "0")))] - "CSKY_ISA_FEATURE (fpv2_sf)" - "fmacs\t%0, %1, %2") - -(define_insn "*fpuv2_fmacd" - [(set (match_operand:DF 0 "register_operand" "=v") - (plus:DF (mult:DF (match_operand:DF 1 "register_operand" "v") - (match_operand:DF 2 "register_operand" "v")) - (match_operand:DF 3 "register_operand" "0")))] - "CSKY_ISA_FEATURE (fpv2_df)" - "fmacd\t%0, %1, %2") - -;; vrz <= vrz - vrx * vry -(define_insn "*fpuv2_fnmacs" - [(set (match_operand:SF 0 "register_operand" "=v") - (minus:SF (match_operand:SF 1 "register_operand" "0") - (mult:SF (match_operand:SF 2 "register_operand" "v") - (match_operand:SF 3 "register_operand" "v"))))] - "CSKY_ISA_FEATURE (fpv2_sf)" - "fnmacs\t%0, %2, %3") - -(define_insn "*fpuv2_fnmacd" - [(set (match_operand:DF 0 "register_operand" "=v") - (minus:DF (match_operand:DF 1 "register_operand" "0") - (mult:DF (match_operand:DF 2 "register_operand" "v") - (match_operand:DF 3 "register_operand" "v"))))] - "CSKY_ISA_FEATURE (fpv2_df)" - "fnmacd\t%0, %2, %3") - -;; vrz <= vrx * vry - vrz -(define_insn "*fpuv2_fmscs" - [(set (match_operand:SF 0 "register_operand" "=v") - (minus:SF (mult:SF (match_operand:SF 1 "register_operand" "v") - (match_operand:SF 2 "register_operand" "v")) - (match_operand:SF 3 "register_operand" "0")))] - "CSKY_ISA_FEATURE (fpv2_sf)" - "fmscs\t%0, %1, %2") - -(define_insn "*fpuv2_fmscd" - [(set (match_operand:DF 0 "register_operand" "=v") - (minus:DF (mult:DF (match_operand:DF 1 "register_operand" "v") - (match_operand:DF 2 "register_operand" "v")) - (match_operand:DF 3 "register_operand" "0")))] - "CSKY_ISA_FEATURE (fpv2_df)" - "fmscd\t%0, %1, %2") - -;; vrz = - (vrz + vrx * vry) -(define_insn "*fpuv2_fnmscs_1" - [(set (match_operand:SF 0 "register_operand" "=v") - (minus:SF (mult:SF (neg:SF (match_operand:SF 1 "register_operand" "%v")) - (match_operand:SF 2 "register_operand" "v")) - (match_operand:SF 3 "register_operand" "0")))] - "CSKY_ISA_FEATURE (fpv2_sf)" - "fnmscs\t%0, %1, %2") - -(define_insn "*fpuv2_fnmscs_2" - [(set (match_operand:SF 0 "register_operand" "=v") - (neg:SF (plus:SF (mult:SF (match_operand:SF 1 "register_operand" "v") - (match_operand:SF 2 "register_operand" "v")) - (match_operand:SF 3 "register_operand" "0"))))] - "CSKY_ISA_FEATURE (fpv2_sf)" - "fnmscs\t%0, %1, %2") - -(define_insn "*fpuv2_fnmscd_1" - [(set (match_operand:DF 0 "register_operand" "=v") - (minus:DF (mult:DF (neg:DF (match_operand:DF 1 "register_operand" "%v")) - (match_operand:DF 2 "register_operand" "v")) - (match_operand:DF 3 "register_operand" "0")))] - "CSKY_ISA_FEATURE (fpv2_df)" - "fnmscd\t%0, %1, %2") - -(define_insn "*fpuv2_fnmscd_2" - [(set (match_operand:DF 0 "register_operand" "=v") - (neg:DF (plus:DF (mult:DF (match_operand:DF 1 "register_operand" "v") - (match_operand:DF 2 "register_operand" "v")) - (match_operand:DF 3 "register_operand" "0"))))] - "CSKY_ISA_FEATURE (fpv2_df)" - "fnmscd\t%0, %1, %2") +(define_expand "div<mode>3" + [(set (match_operand:SFDF 0 "register_operand" "") + (div:SFDF (match_operand:SFDF 1 "csky_arith_float1_operand" "") + (match_operand:SFDF 2 "register_operand" "")))] + "CSKY_ISA_FEATURE(fpv2_<mode>) || CSKY_ISA_FEATURE(fpv3_<mode>)" + "") +(define_expand "divhf3" + [(set (match_operand:HF 0 "register_operand" "") + (div:HF (match_operand:HF 1 "csky_arith_float1_operand" "") + (match_operand:HF 2 "register_operand" "")))] + "CSKY_ISA_FEATURE(fpv3_hf)" + "") ;; ------------------------------------------------------------------------- ;; Float compare instructions ;; ------------------------------------------------------------------------- -(define_expand "cbranchsf4" +(define_expand "cbranch<mode>4" [(set (pc) (if_then_else (match_operator 0 "csky_float_comparison_operator" - [(match_operand:SF 1 "register_operand") - (match_operand:SF 2 "csky_compare_operand_float")]) + [(match_operand:SFDF 1 "register_operand") + (match_operand:SFDF 2 "csky_compare_operand_float")]) (label_ref (match_operand 3 "")) (pc)))] - "CSKY_ISA_FEATURE (fpv2_sf)" - " - { - enum rtx_code code = GET_CODE (operands[0]); - bool invert = csky_emit_compare_float (code, operands[1], operands[2]); +"CSKY_ISA_FEATURE(fpv2_<mode>) || CSKY_ISA_FEATURE(fpv3_<mode>)" +"{ + enum rtx_code code = GET_CODE (operands[0]); + bool invert; - if (invert) - emit_jump_insn (gen_csky_jbf (operands[3])); - else - emit_jump_insn (gen_csky_jbt (operands[3])); + invert = csky_emit_compare_float (code, operands[1], operands[2]); - DONE; - }") - -(define_insn "*fpuv2_unordered" - [(set (reg:CC 33) (unordered:CC (match_operand:SF 0 "register_operand" "v") - (match_operand:SF 1 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_sf)" - "fcmpuos\t%0, %1") - -(define_insn "*fpuv2_unordered_zero" - [(set (reg:CC 33) (unordered:CC (match_operand:SF 0 "register_operand" "v") - (match_operand:SF 1 "csky_const_float0_operand" "i")))] - "CSKY_ISA_FEATURE (fpv2_sf)" - "fcmpuos\t%0, %0") - -(define_insn "*fpuv2_ne" - [(set (reg:CC 33) (ne:CC (match_operand:SF 0 "register_operand" "v") - (match_operand:SF 1 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_sf)" - "fcmpnes\t%0, %1") - -(define_insn "*fpuv2_gt" - [(set (reg:CC 33) (gt:CC (match_operand:SF 0 "register_operand" "v") - (match_operand:SF 1 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_sf)" - "fcmplts\t%1, %0") - -(define_insn "*fpuv2_ge" - [(set (reg:CC 33) (ge:CC (match_operand:SF 0 "register_operand" "v") - (match_operand:SF 1 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_sf)" - "fcmphss\t%0, %1") - -(define_insn "*fpuv2_lt" - [(set (reg:CC 33) (lt:CC (match_operand:SF 0 "register_operand" "v") - (match_operand:SF 1 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_sf)" - "fcmplts\t%0, %1") - -(define_insn "*fpuv2_le" - [(set (reg:CC 33) (le:CC (match_operand:SF 0 "register_operand" "v") - (match_operand:SF 1 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_sf)" - "fcmphss\t%1, %0") - -(define_insn "*fpuv2_gez" - [(set (reg:CC 33) (ge:CC (match_operand:SF 0 "register_operand" "v") - (match_operand:SF 1 "csky_const_float0_operand" "i")))] - "CSKY_ISA_FEATURE (fpv2_sf)" - "fcmpzhss\t%0") - -(define_insn "*fpuv2_nez" - [(set (reg:CC 33) (ne:CC (match_operand:SF 0 "register_operand" "v") - (match_operand:SF 1 "csky_const_float0_operand" "i")))] - "CSKY_ISA_FEATURE (fpv2_sf)" - "fcmpznes\t%0") - - -(define_expand "cbranchdf4" - [(set (pc) (if_then_else (match_operator 0 "csky_float_comparison_operator" - [(match_operand:DF 1 "register_operand") - (match_operand:DF 2 "csky_compare_operand_float")]) - (label_ref (match_operand 3 "")) - (pc)))] - "CSKY_ISA_FEATURE (fpv2_df)" - " - { - enum rtx_code code = GET_CODE (operands[0]); - bool invert = csky_emit_compare_float (code, operands[1], operands[2]); + if (invert) + emit_jump_insn (gen_csky_jbf (operands[3])); + else + emit_jump_insn (gen_csky_jbt (operands[3])); - if (invert) - emit_jump_insn (gen_csky_jbf (operands[3])); - else - emit_jump_insn (gen_csky_jbt (operands[3])); + DONE; - DONE; }") -(define_insn "*fpuv2_dunordered" - [(set (reg:CC 33) (unordered:CC (match_operand:DF 0 "register_operand" "v") - (match_operand:DF 1 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_df)" - "fcmpuod\t%0, %1") - -(define_insn "*fpuv2_dunordered_zero" - [(set (reg:CC 33) (unordered:CC (match_operand:DF 0 "register_operand" "v") - (match_operand:DF 1 "csky_const_float0_operand" "i")))] - "CSKY_ISA_FEATURE (fpv2_df)" - "fcmpuod\t%0, %0") - -(define_insn "*fpuv2_dne" - [(set (reg:CC 33) (ne:CC (match_operand:DF 0 "register_operand" "v") - (match_operand:DF 1 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_df)" - "fcmpned\t%0, %1") - -(define_insn "*fpuv2_dgt" - [(set (reg:CC 33) (gt:CC (match_operand:DF 0 "register_operand" "v") - (match_operand:DF 1 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_df)" - "fcmpltd\t%1, %0") - -(define_insn "*fpuv2_dge" - [(set (reg:CC 33) (ge:CC (match_operand:DF 0 "register_operand" "v") - (match_operand:DF 1 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_df)" - "fcmphsd\t%0, %1") - -(define_insn "*fpuv2_dlt" - [(set (reg:CC 33) (lt:CC (match_operand:DF 0 "register_operand" "v") - (match_operand:DF 1 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_df)" - "fcmpltd\t%0, %1") - -(define_insn "*fpuv2_dle" - [(set (reg:CC 33) (le:CC (match_operand:DF 0 "register_operand" "v") - (match_operand:DF 1 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_df)" - "fcmphsd\t%1, %0") - -(define_insn "*fpuv2_dgez" - [(set (reg:CC 33) (ge:CC (match_operand:DF 0 "register_operand" "v") - (match_operand:DF 1 "csky_const_float0_operand" "i")))] - "CSKY_ISA_FEATURE (fpv2_df)" - "fcmpzhsd\t%0") - -(define_insn "*fpuv2_dnez" - [(set (reg:CC 33) (ne:CC (match_operand:DF 0 "register_operand" "v") - (match_operand:DF 1 "csky_const_float0_operand" "i")))] - "CSKY_ISA_FEATURE (fpv2_df)" - "fcmpzned\t%0") +(define_expand "cbranchhf4" + [(set (pc) (if_then_else (match_operator 0 "csky_float_comparison_operator" + [(match_operand:HF 1 "register_operand") + (match_operand:HF 2 "csky_compare_operand_float")]) + (label_ref (match_operand 3 "")) + (pc)))] +"CSKY_ISA_FEATURE(fpv3_hf)" +"{ + enum rtx_code code = GET_CODE (operands[0]); + bool invert; + invert = csky_emit_compare_float (code, operands[1], operands[2]); -;; ------------------------------------------------------------------------- -;; Float convert instructions -;; ------------------------------------------------------------------------- + if (invert) + emit_jump_insn (gen_csky_jbf (operands[3])); + else + emit_jump_insn (gen_csky_jbt (operands[3])); -;; DF <- SF -(define_insn "extendsfdf2" - [(set (match_operand:DF 0 "register_operand" "=v") - (float_extend:DF (match_operand:SF 1 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_df)" - "fstod\t%0, %1") - -;; SF <- DF -(define_insn "truncdfsf2" - [(set (match_operand:SF 0 "register_operand" "=v") - (float_truncate:SF (match_operand:DF 1 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_df)" - "fdtos\t%0, %1") - -;; SF <- SI -(define_insn "floatsisf2" - [(set (match_operand:SF 0 "register_operand" "=v") - (float:SF (match_operand:SI 1 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_sf)" - "fsitos\t%0, %1") - -;; DF <- SI -(define_insn "floatsidf2" - [(set (match_operand:DF 0 "register_operand" "=v") - (float:DF (match_operand:SI 1 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_df)" - "fsitod\t%0, %1") - -;; SF <- unsigned SI -(define_insn "floatunssisf2" - [(set (match_operand:SF 0 "register_operand" "=v") - (unsigned_float:SF (match_operand:SI 1 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_sf)" - "fuitos\t%0, %1") - -;; DF <- unsigned SI -(define_insn "floatunssidf2" - [(set (match_operand:DF 0 "register_operand" "=v") - (unsigned_float:DF (match_operand:SI 1 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_df)" - "fuitod\t%0, %1") - -;; SI <- SF -(define_insn "fix_truncsfsi2" - [(set (match_operand:SI 0 "register_operand" "=v") - (fix:SI (match_operand:SF 1 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_sf)" - "fstosi.rz\t%0, %1") - -;; SI <- DF -(define_insn "fix_truncdfsi2" - [(set (match_operand:SI 0 "register_operand" "=v") - (fix:SI (match_operand:DF 1 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_df)" - "fdtosi.rz\t%0, %1") - -;; unsigned SI <- SF -(define_insn "fixuns_truncsfsi2" - [(set (match_operand:SI 0 "register_operand" "=v") - (unsigned_fix:SI (match_operand:SF 1 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_sf)" - "fstoui.rz\t%0, %1") - -;; unsigned SI <- DF -(define_insn "fixuns_truncdfsi2" - [(set (match_operand:SI 0 "register_operand" "=v") - (unsigned_fix:SI (match_operand:DF 1 "register_operand" "v")))] - "CSKY_ISA_FEATURE (fpv2_df)" - "fdtoui.rz\t%0, %1") + DONE; +}") ;; ------------------------------------------------------------------------- -;; Float mov instructions +;; Instructions for float cstore ;; ------------------------------------------------------------------------- -;; Note: movsf and movdf patterns are in csky.md. - -;; cstore SF -(define_expand "cstoresf4" +(define_expand "cstore<mode>4" [(set (match_operand:SI 0 "register_operand" "") - (match_operator 1 "ordered_comparison_operator" - [(match_operand:SF 2 "register_operand" "") - (match_operand:SF 3 "csky_compare_operand_float" "")]))] - "CSKY_ISA_FEATURE (fpv2_sf)" - " - { - bool invert = csky_emit_compare_float (GET_CODE (operands[1]), - operands[2], operands[3]); - if (invert) + (match_operator 1 "csky_float_comparison_operator" + [(match_operand:SFDF 2 "register_operand" "") + (match_operand:SFDF 3 "csky_compare_operand_float" "")]))] + "CSKY_ISA_FEATURE (fpv2_<mode>) || CSKY_ISA_FEATURE(fpv3_<mode>)" + "{ + bool invert; + + invert = csky_emit_compare_float (GET_CODE (operands[1]), + operands[2], operands[3]); + if(invert) emit_insn (gen_mvcv (operands[0])); else emit_insn (gen_mvc (operands[0])); @@ -547,21 +333,91 @@ }" ) -;; cstore DF -(define_expand "cstoredf4" +(define_expand "cstorehf4" [(set (match_operand:SI 0 "register_operand" "") - (match_operator 1 "ordered_comparison_operator" - [(match_operand:DF 2 "register_operand" "") - (match_operand:DF 3 "csky_compare_operand_float" "")]))] - "CSKY_ISA_FEATURE (fpv2_df)" - " - { - bool invert = csky_emit_compare_float (GET_CODE (operands[1]), - operands[2], operands[3]); - if (invert) + (match_operator 1 "csky_float_comparison_operator" + [(match_operand:HF 2 "register_operand" "") + (match_operand:HF 3 "csky_compare_operand_float" "")]))] + "CSKY_ISA_FEATURE(fpv3_hf)" + "{ + bool invert; + + invert = csky_emit_compare_float (GET_CODE (operands[1]), + operands[2], operands[3]); + if(invert) emit_insn (gen_mvcv (operands[0])); else emit_insn (gen_mvc (operands[0])); DONE; }" ) + +;; ------------------------------------------------------------------------- +;; Float convert instructions +;; ------------------------------------------------------------------------- + +;; SF <- HF +(define_expand "extendhfsf2" + [(set (match_operand:SF 0 "register_operand" "") + (float_extend:SF (match_operand:HF 1 "register_operand" "")))] + "CSKY_ISA_FEATURE(fpv3_hf)" + "") + +;; HF <- SF +(define_expand "truncsfhf2" + [(set (match_operand:HF 0 "register_operand" "") + (float_truncate:HF (match_operand:SF 1 "register_operand" "")))] + "CSKY_ISA_FEATURE(fpv3_hf)" + "") + +;; DF <- SF +(define_expand "extendsfdf2" + [(set (match_operand:DF 0 "register_operand" "") + (float_extend:DF (match_operand:SF 1 "register_operand" "")))] + "CSKY_ISA_FEATURE(fpv2_df) || CSKY_ISA_FEATURE(fpv3_df)" + "") + +;; SF <- DF +(define_expand "truncdfsf2" + [(set (match_operand:SF 0 "register_operand" "") + (float_truncate:SF (match_operand:DF 1 "register_operand" "")))] + "CSKY_ISA_FEATURE(fpv2_df) || CSKY_ISA_FEATURE(fpv3_df)" + "") + +;; HF <- unsigned SI,SI +(define_expand "float<floatsuop>sihf2" + [(set (match_operand:HF 0 "register_operand" "") + (FLOAT_SU:HF (match_operand:SI 1 "register_operand" "")))] + "CSKY_ISA_FEATURE(fpv3_hf)" + "") + +;; DF,SF <- unsigned SI,SI +(define_expand "float<floatsuop>si<mode>2" + [(set (match_operand:SFDF 0 "register_operand" "") + (FLOAT_SU:SFDF (match_operand:SI 1 "register_operand" "")))] + "CSKY_ISA_FEATURE(fpv2_<mode>) || CSKY_ISA_FEATURE(fpv3_<mode>)" + "") + +;; HF <- unsigned HI,HI +(define_expand "float<floatsuop>hihf2" + [(set (match_operand:HF 0 "register_operand" "") + (FLOAT_SU:HF (match_operand:HI 1 "register_operand" "")))] + "CSKY_ISA_FEATURE(fpv3_hi) && CSKY_ISA_FEATURE(fpv3_hf)" + "") + +;; unsigned SI,SI <- HF +(define_expand "fix<fixsuop>_trunchfsi2" + [(set (match_operand:SI 0 "register_operand" "") + (FIX_SU:SI (fix:HF (match_operand:HF 1 "register_operand" ""))))] + "CSKY_ISA_FEATURE(fpv3_hf)" + "") + +;; unsigned SI,SI <- DF,SF +(define_expand "fix<fixsuop>_trunc<mode>si2" + [(set (match_operand:SI 0 "register_operand" "") + (FIX_SU:SI (fix:SFDF (match_operand:SFDF 1 "register_operand" ""))))] + "CSKY_ISA_FEATURE(fpv2_<mode>) || CSKY_ISA_FEATURE(fpv3_<mode>)" + "") + +(include "csky_insn_fpuv3.md") +(include "csky_insn_fpuv2.md") diff --git a/gcc/config/csky/csky_insn_fpuv2.md b/gcc/config/csky/csky_insn_fpuv2.md new file mode 100644 index 0000000..d56b61f --- /dev/null +++ b/gcc/config/csky/csky_insn_fpuv2.md @@ -0,0 +1,489 @@ +;; C-SKY FPUV2 instruction descriptions. +;; Copyright (C) 2018-2021 Free Software Foundation, Inc. +;; Contributed by C-SKY Microsystems and Mentor Graphics. +;; +;; This file is part of GCC. +;; +;; GCC is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; GCC is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING3. If not see +;; <http://www.gnu.org/licenses/>. */ + +;; ------------------------------------------------------------------------- +;; Float Abs instructions +;; ------------------------------------------------------------------------- + +(define_insn "*fpuv2_abssf2" + [(set (match_operand:SF 0 "register_operand" "=v,a,r") + (abs:SF (match_operand:SF 1 "register_operand" "v, 0,r")))] + "CSKY_ISA_FEATURE (fpv2_sf)" + "@ + fabss\t%0, %1 + bclri\t%0, %1, 31 + bclri\t%0, %1, 31" + [(set_attr "length" "4,2,4")]) + +(define_insn "*fpuv2_absdf2" + [(set (match_operand:DF 0 "register_operand" "=v") + (abs:DF (match_operand:DF 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_df)" + "fabsd\t%0, %1") + + +;; ------------------------------------------------------------------------- +;; Float Neg instructions +;; ------------------------------------------------------------------------- + +(define_insn "*fpuv2_negsf2" + [(set (match_operand:SF 0 "register_operand" "=v") + (neg:SF (match_operand:SF 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_sf)" + "fnegs\t%0, %1") + +(define_insn "*fpuv2_negdf2" + [(set (match_operand:DF 0 "register_operand" "=v") + (neg:DF (match_operand:DF 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_df)" + "fnegd\t%0, %1") + + +;; ------------------------------------------------------------------------- +;; Float Sqrt instructions +;; ------------------------------------------------------------------------- + +(define_insn "*fpuv2_sqrtsf2" + [(set (match_operand:SF 0 "register_operand" "=v") + (sqrt:SF (match_operand:SF 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_sf)" + "fsqrts\t%0, %1") + +(define_insn "*fpuv2_sqrtdf2" + [(set (match_operand:DF 0 "register_operand" "=v") + (sqrt:DF (match_operand:DF 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_divd)" + "fsqrtd\t%0, %1") + + +;; ------------------------------------------------------------------------- +;; Float Add instructions +;; ------------------------------------------------------------------------- + +(define_insn "*fpuv2_addsf3" + [(set (match_operand:SF 0 "register_operand" "=v") + (plus:SF (match_operand:SF 1 "register_operand" "v") + (match_operand:SF 2 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_sf)" + "fadds\t%0, %1, %2") + +(define_insn "*fpuv2_adddf3" + [(set (match_operand:DF 0 "register_operand" "=v") + (plus:DF (match_operand:DF 1 "register_operand" "v") + (match_operand:DF 2 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_df)" + "faddd\t%0, %1, %2") + + +;; ------------------------------------------------------------------------- +;; Float Sub instructions +;; ------------------------------------------------------------------------- + +(define_insn "*fpuv2_subsf3" + [(set (match_operand:SF 0 "register_operand" "=v") + (minus:SF (match_operand:SF 1 "register_operand" "v") + (match_operand:SF 2 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_sf)" + "fsubs\t%0, %1, %2") + +(define_insn "*fpuv2_subdf3" + [(set (match_operand:DF 0 "register_operand" "=v") + (minus:DF (match_operand:DF 1 "register_operand" "v") + (match_operand:DF 2 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_df)" + "fsubd\t%0, %1, %2") + + +;; ------------------------------------------------------------------------- +;; Float Mul instructions +;; ------------------------------------------------------------------------- + +(define_insn "*fpv2_mulsf3" + [(set (match_operand:SF 0 "register_operand" "=v") + (mult:SF (match_operand:SF 1 "register_operand" "v") + (match_operand:SF 2 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_sf)" + "fmuls\t%0, %1, %2") + +(define_insn "*fpv2_muldf3" + [(set (match_operand:DF 0 "register_operand" "=v") + (mult:DF (match_operand:DF 1 "register_operand" "v") + (match_operand:DF 2 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_df)" + "fmuld\t%0, %1, %2") + +(define_insn "*fpuv2_nmulsf3_1" + [(set (match_operand:SF 0 "register_operand" "=v") + (mult:SF (neg:SF (match_operand:SF 1 "register_operand" "%v")) + (match_operand:SF 2 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_sf) && !flag_rounding_math" + "fnmuls\t%0, %1, %2") + +(define_insn "*fpuv2_nmulsf3_2" + [(set (match_operand:SF 0 "register_operand" "=v") + (neg:SF (mult:SF (match_operand:SF 1 "register_operand" "v") + (match_operand:SF 2 "register_operand" "v"))))] + "CSKY_ISA_FEATURE (fpv2_sf)" + "fnmuls\t%0, %1, %2") + +(define_insn "*fpuv2_nmuldf3_1" + [(set (match_operand:DF 0 "register_operand" "=v") + (mult:DF (neg:DF (match_operand:DF 1 "register_operand" "%v")) + (match_operand:DF 2 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_df) && !flag_rounding_math" + "fnmuld\t%0, %1, %2") + +(define_insn "*fpuv2_nmuldf3_2" + [(set (match_operand:DF 0 "register_operand" "=v") + (neg:DF (mult:DF (match_operand:DF 1 "register_operand" "v") + (match_operand:DF 2 "register_operand" "v"))))] + "CSKY_ISA_FEATURE (fpv2_df)" + "fnmuld\t%0, %1, %2") + + +;; ------------------------------------------------------------------------- +;; Float Div instructions +;; ------------------------------------------------------------------------- + +(define_insn "*fpuv2_divsf3" + [(set (match_operand:SF 0 "register_operand" "=v") + (div:SF (match_operand:SF 1 "register_operand" "v") + (match_operand:SF 2 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_sf)" + "fdivs\t%0, %1, %2") + +(define_insn "*fpuv2_1_divsf3" + [(set (match_operand:SF 0 "register_operand" "=v") + (div:SF (match_operand:SF 1 "csky_const_float1_operand" "i") + (match_operand:SF 2 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_sf)" + "frecips\t%0, %2") + +(define_insn "*fpuv2_divdf3" + [(set (match_operand:DF 0 "register_operand" "=v") + (div:DF (match_operand:DF 1 "register_operand" "v") + (match_operand:DF 2 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_divd)" + "fdivd\t%0, %1, %2") + +(define_insn "*fpuv2_1_divdf3" + [(set (match_operand:DF 0 "register_operand" "=v") + (div:DF (match_operand:DF 1 "csky_const_float1_operand" "i") + (match_operand:DF 2 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_divd)" + "frecipd\t%0, %2") + + +;; ------------------------------------------------------------------------- +;; Float add(sub) with mult instructions +;; ------------------------------------------------------------------------- + +;; vrz <= vrz + vrx * vry +(define_insn "*fpuv2_fmacs" + [(set (match_operand:SF 0 "register_operand" "=v") + (plus:SF (mult:SF (match_operand:SF 1 "register_operand" "v") + (match_operand:SF 2 "register_operand" "v")) + (match_operand:SF 3 "register_operand" "0")))] + "CSKY_ISA_FEATURE (fpv2_sf)" + "fmacs\t%0, %1, %2") + +(define_insn "*fpuv2_fmacd" + [(set (match_operand:DF 0 "register_operand" "=v") + (plus:DF (mult:DF (match_operand:DF 1 "register_operand" "v") + (match_operand:DF 2 "register_operand" "v")) + (match_operand:DF 3 "register_operand" "0")))] + "CSKY_ISA_FEATURE (fpv2_df)" + "fmacd\t%0, %1, %2") + +;; vrz <= vrz - vrx * vry +(define_insn "*fpuv2_fnmacs" + [(set (match_operand:SF 0 "register_operand" "=v") + (minus:SF (match_operand:SF 1 "register_operand" "0") + (mult:SF (match_operand:SF 2 "register_operand" "v") + (match_operand:SF 3 "register_operand" "v"))))] + "CSKY_ISA_FEATURE (fpv2_sf)" + "fnmacs\t%0, %2, %3") + +(define_insn "*fpuv2_fnmacd" + [(set (match_operand:DF 0 "register_operand" "=v") + (minus:DF (match_operand:DF 1 "register_operand" "0") + (mult:DF (match_operand:DF 2 "register_operand" "v") + (match_operand:DF 3 "register_operand" "v"))))] + "CSKY_ISA_FEATURE (fpv2_df)" + "fnmacd\t%0, %2, %3") + +;; vrz <= vrx * vry - vrz +(define_insn "*fpuv2_fmscs" + [(set (match_operand:SF 0 "register_operand" "=v") + (minus:SF (mult:SF (match_operand:SF 1 "register_operand" "v") + (match_operand:SF 2 "register_operand" "v")) + (match_operand:SF 3 "register_operand" "0")))] + "CSKY_ISA_FEATURE (fpv2_sf)" + "fmscs\t%0, %1, %2") + +(define_insn "*fpuv2_fmscd" + [(set (match_operand:DF 0 "register_operand" "=v") + (minus:DF (mult:DF (match_operand:DF 1 "register_operand" "v") + (match_operand:DF 2 "register_operand" "v")) + (match_operand:DF 3 "register_operand" "0")))] + "CSKY_ISA_FEATURE (fpv2_df)" + "fmscd\t%0, %1, %2") + +;; vrz = - (vrz + vrx * vry) +(define_insn "*fpuv2_fnmscs_1" + [(set (match_operand:SF 0 "register_operand" "=v") + (minus:SF (mult:SF (neg:SF (match_operand:SF 1 "register_operand" "%v")) + (match_operand:SF 2 "register_operand" "v")) + (match_operand:SF 3 "register_operand" "0")))] + "CSKY_ISA_FEATURE (fpv2_sf)" + "fnmscs\t%0, %1, %2") + +(define_insn "*fpuv2_fnmscs_2" + [(set (match_operand:SF 0 "register_operand" "=v") + (neg:SF (plus:SF (mult:SF (match_operand:SF 1 "register_operand" "v") + (match_operand:SF 2 "register_operand" "v")) + (match_operand:SF 3 "register_operand" "0"))))] + "CSKY_ISA_FEATURE (fpv2_sf)" + "fnmscs\t%0, %1, %2") + +(define_insn "*fpuv2_fnmscd_1" + [(set (match_operand:DF 0 "register_operand" "=v") + (minus:DF (mult:DF (neg:DF (match_operand:DF 1 "register_operand" "%v")) + (match_operand:DF 2 "register_operand" "v")) + (match_operand:DF 3 "register_operand" "0")))] + "CSKY_ISA_FEATURE (fpv2_df)" + "fnmscd\t%0, %1, %2") + +(define_insn "*fpuv2_fnmscd_2" + [(set (match_operand:DF 0 "register_operand" "=v") + (neg:DF (plus:DF (mult:DF (match_operand:DF 1 "register_operand" "v") + (match_operand:DF 2 "register_operand" "v")) + (match_operand:DF 3 "register_operand" "0"))))] + "CSKY_ISA_FEATURE (fpv2_df)" + "fnmscd\t%0, %1, %2") + + +;; ------------------------------------------------------------------------- +;; Float compare instructions +;; ------------------------------------------------------------------------- + +(define_insn "*fpuv2_unordered" + [(set (reg:CC 33) (unordered:CC (match_operand:SF 0 "register_operand" "v") + (match_operand:SF 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_sf)" + "fcmpuos\t%0, %1") + +(define_insn "*fpuv2_unordered_zero" + [(set (reg:CC 33) (unordered:CC (match_operand:SF 0 "register_operand" "v") + (match_operand:SF 1 "csky_const_float0_operand" "i")))] + "CSKY_ISA_FEATURE (fpv2_sf)" + "fcmpuos\t%0, %0") + +(define_insn "*fpuv2_ne" + [(set (reg:CC 33) (ne:CC (match_operand:SF 0 "register_operand" "v") + (match_operand:SF 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_sf)" + "fcmpnes\t%0, %1") + +(define_insn "*fpuv2_gt" + [(set (reg:CC 33) (gt:CC (match_operand:SF 0 "register_operand" "v") + (match_operand:SF 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_sf)" + "fcmplts\t%1, %0") + +(define_insn "*fpuv2_ge" + [(set (reg:CC 33) (ge:CC (match_operand:SF 0 "register_operand" "v") + (match_operand:SF 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_sf)" + "fcmphss\t%0, %1") + +(define_insn "*fpuv2_lt" + [(set (reg:CC 33) (lt:CC (match_operand:SF 0 "register_operand" "v") + (match_operand:SF 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_sf)" + "fcmplts\t%0, %1") + +(define_insn "*fpuv2_le" + [(set (reg:CC 33) (le:CC (match_operand:SF 0 "register_operand" "v") + (match_operand:SF 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_sf)" + "fcmphss\t%1, %0") + +(define_insn "*fpuv2_gez" + [(set (reg:CC 33) (ge:CC (match_operand:SF 0 "register_operand" "v") + (match_operand:SF 1 "csky_const_float0_operand" "i")))] + "CSKY_ISA_FEATURE (fpv2_sf)" + "fcmpzhss\t%0") + +(define_insn "*fpuv2_nez" + [(set (reg:CC 33) (ne:CC (match_operand:SF 0 "register_operand" "v") + (match_operand:SF 1 "csky_const_float0_operand" "i")))] + "CSKY_ISA_FEATURE (fpv2_sf)" + "fcmpznes\t%0") + +(define_insn "*fpuv2_dunordered" + [(set (reg:CC 33) (unordered:CC (match_operand:DF 0 "register_operand" "v") + (match_operand:DF 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_df)" + "fcmpuod\t%0, %1") + +(define_insn "*fpuv2_dunordered_zero" + [(set (reg:CC 33) (unordered:CC (match_operand:DF 0 "register_operand" "v") + (match_operand:DF 1 "csky_const_float0_operand" "i")))] + "CSKY_ISA_FEATURE (fpv2_df)" + "fcmpuod\t%0, %0") + +(define_insn "*fpuv2_dne" + [(set (reg:CC 33) (ne:CC (match_operand:DF 0 "register_operand" "v") + (match_operand:DF 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_df)" + "fcmpned\t%0, %1") + +(define_insn "*fpuv2_dgt" + [(set (reg:CC 33) (gt:CC (match_operand:DF 0 "register_operand" "v") + (match_operand:DF 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_df)" + "fcmpltd\t%1, %0") + +(define_insn "*fpuv2_dge" + [(set (reg:CC 33) (ge:CC (match_operand:DF 0 "register_operand" "v") + (match_operand:DF 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_df)" + "fcmphsd\t%0, %1") + +(define_insn "*fpuv2_dlt" + [(set (reg:CC 33) (lt:CC (match_operand:DF 0 "register_operand" "v") + (match_operand:DF 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_df)" + "fcmpltd\t%0, %1") + +(define_insn "*fpuv2_dle" + [(set (reg:CC 33) (le:CC (match_operand:DF 0 "register_operand" "v") + (match_operand:DF 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_df)" + "fcmphsd\t%1, %0") + +(define_insn "*fpuv2_dgez" + [(set (reg:CC 33) (ge:CC (match_operand:DF 0 "register_operand" "v") + (match_operand:DF 1 "csky_const_float0_operand" "i")))] + "CSKY_ISA_FEATURE (fpv2_df)" + "fcmpzhsd\t%0") + +(define_insn "*fpuv2_dnez" + [(set (reg:CC 33) (ne:CC (match_operand:DF 0 "register_operand" "v") + (match_operand:DF 1 "csky_const_float0_operand" "i")))] + "CSKY_ISA_FEATURE (fpv2_df)" + "fcmpzned\t%0") + + +;; ------------------------------------------------------------------------- +;; Float convert instructions +;; ------------------------------------------------------------------------- + +;; DF <- SF +(define_insn "*fpuv2_extendsfdf2" + [(set (match_operand:DF 0 "register_operand" "=v") + (float_extend:DF (match_operand:SF 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_df)" + "fstod\t%0, %1") + +;; SF <- DF +(define_insn "*fpuv2_truncdfsf2" + [(set (match_operand:SF 0 "register_operand" "=v") + (float_truncate:SF (match_operand:DF 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_df)" + "fdtos\t%0, %1") + +;; SF <- SI +(define_insn "*fpuv2_floatsisf2" + [(set (match_operand:SF 0 "register_operand" "=v") + (float:SF (match_operand:SI 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_sf)" + "fsitos\t%0, %1") + +;; DF <- SI +(define_insn "*fpuv2_floatsidf2" + [(set (match_operand:DF 0 "register_operand" "=v") + (float:DF (match_operand:SI 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_df)" + "fsitod\t%0, %1") + +;; SF <- unsigned SI +(define_insn "*fpuv2_floatunssisf2" + [(set (match_operand:SF 0 "register_operand" "=v") + (unsigned_float:SF (match_operand:SI 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_sf)" + "fuitos\t%0, %1") + +;; DF <- unsigned SI +(define_insn "*fpuv2_floatunssidf2" + [(set (match_operand:DF 0 "register_operand" "=v") + (unsigned_float:DF (match_operand:SI 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE (fpv2_df)" + "fuitod\t%0, %1") + +;; SI <- SF +(define_insn "*fpuv2_fix_truncsfsi2" + [(set (match_operand:SI 0 "register_operand" "=v") + (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "v"))))] + "CSKY_ISA_FEATURE (fpv2_sf)" + "fstosi.rz\t%0, %1") + +;; SI <- DF +(define_insn "*fpuv2_fix_truncdfsi2" + [(set (match_operand:SI 0 "register_operand" "=v") + (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "v"))))] + "CSKY_ISA_FEATURE (fpv2_df)" + "fdtosi.rz\t%0, %1") + +;; unsigned SI <- SF +(define_insn "*fpuv2_fixuns_truncsfsi2" + [(set (match_operand:SI 0 "register_operand" "=v") + (unsigned_fix:SI (fix:SF (match_operand:SF 1 "register_operand" "v"))))] + "CSKY_ISA_FEATURE (fpv2_sf)" + "fstoui.rz\t%0, %1") + +;; unsigned SI <- DF +(define_insn "*fpuv2_fixuns_truncdfsi2" + [(set (match_operand:SI 0 "register_operand" "=v") + (unsigned_fix:SI (fix:DF (match_operand:DF 1 "register_operand" "v"))))] + "CSKY_ISA_FEATURE (fpv2_df)" + "fdtoui.rz\t%0, %1") + + +;; ------------------------------------------------------------------------- +;; Float mov instructions +;; ------------------------------------------------------------------------- + +(define_insn "*fpuv2_movsf" + [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r, r,m,v,r,Q,v,v,v") + (match_operand:SF 1 "general_operand" " r,m,mF,r,r,v,v,Q,v,W"))] + "CSKY_ISA_FEATURE (fpv2_sf)" + "* return csky_output_move(insn, operands, SFmode);" +) + +(define_insn "*fpuv2_movdf" + [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r, r,m, v,?r,Q,v,v,v") + (match_operand:DF 1 "general_operand" " r,m,mF,r,?r, v,v,Q,v,m"))] + "CSKY_ISA_FEATURE (fpv2_df)" + "* return csky_output_movedouble(operands, DFmode);" + [(set (attr "length") + (symbol_ref "csky_get_movedouble_length (operands)"))] +) diff --git a/gcc/config/csky/csky_insn_fpuv3.md b/gcc/config/csky/csky_insn_fpuv3.md new file mode 100644 index 0000000..b5f4798 --- /dev/null +++ b/gcc/config/csky/csky_insn_fpuv3.md @@ -0,0 +1,516 @@ +;; C-SKY FPUV3 instruction descriptions. +;; Copyright (C) 2018-2021 Free Software Foundation, Inc. +;; Contributed by C-SKY Microsystems and Mentor Graphics. +;; +;; This file is part of GCC. +;; +;; GCC is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; GCC is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING3. If not see +;; <http://www.gnu.org/licenses/>. */ + +(define_c_enum "unspec" [ + UNSPEC_MAXNM_F3 + UNSPEC_MINNM_F3 +]) + +;; ------------------------------------------------------------------------- +;; Float mov instructions +;; ------------------------------------------------------------------------- + +(define_insn "*fpv3_movhf" + [(set (match_operand:HF 0 "nonimmediate_operand" "=r,r,v,r,m,r,Q,v,v,v, v") + (match_operand:HF 1 "general_operand" " r,F,r,v,r,m,v,Q,v,W,Dv"))] + "CSKY_ISA_FEATURE(fpv3_hf)" + "* + switch (which_alternative) + { + case 2: + return \"fmtvr.16\\t%0, %1\"; + case 3: + return \"fmfvr.16\\t%0, %1\"; + case 6: + case 7: + case 9: + return fpuv3_output_move(operands); + case 8: + return \"fmov.16\\t%0, %1\"; + case 10: + return \"fmovi.16\\t%0, %1\"; + case 1: + { + long bits; + rtx ops[4]; + + bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]), HFmode); + ops[0] = operands[0]; + ops[1] = GEN_INT (bits); + + output_asm_insn (\"lrw\\t%0, %1\", ops); + return \"\"; + } + default: + return csky_output_move(insn, operands, HFmode); + } + " +) + +(define_insn "*fpv3_movsf" + [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r, r,m,v,r,Q,v,v,v, v") + (match_operand:SF 1 "general_operand" " r,m,mF,r,r,v,v,Q,v,W,Dv"))] + "CSKY_ISA_FEATURE(fpv3_sf)" + "* + switch (which_alternative) + { + case 4: + return \"fmtvr.32.1\\t%0, %1\"; + case 5: + return \"fmfvr.32.1\\t%0, %1\"; + case 6: + case 7: + case 9: + return fpuv3_output_move(operands); + case 8: + return \"fmov.32\\t%0, %1\"; + case 10: + return \"fmovi.32\\t%0, %1\"; + default: + return csky_output_move(insn, operands, SFmode); + } + " +) + +(define_insn "*fpv3_movdf" + [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r, r,m,v,?r,Q,v,v,v, v") + (match_operand:DF 1 "general_operand" " r,m,mF,r,?r,v,v,Q,v,m,Dv"))] + "CSKY_ISA_FEATURE(fpv3_df)" + "* + switch (which_alternative) + { + case 4: + if (TARGET_BIG_ENDIAN) + return \"fmtvr.64\\t%0, %R1, %1\"; + return \"fmtvr.64\\t%0, %1, %R1\"; + case 5: + if (TARGET_BIG_ENDIAN) + return \"fmfvr.64\\t%R0, %0, %1\"; + return \"fmfvr.64\\t%0, %R0, %1\"; + case 6: + case 7: + case 9: + return fpuv3_output_move(operands); + case 8: + return \"fmov.64\\t%0, %1\"; + case 10: + return \"fmovi.64\\t%0, %1\"; + default: + return csky_output_movedouble(operands, DFmode); + } + " +) + +;; ------------------------------------------------------------------------- +;; Float Mul instructions +;; ------------------------------------------------------------------------- + +(define_insn "*fpv3_mul<mode>3" + [(set (match_operand:F3ANY 0 "register_operand" "=v") + (mult:F3ANY (match_operand:F3ANY 1 "register_operand" " v") + (match_operand:F3ANY 2 "register_operand" " v")))] + "CSKY_ISA_FEATURE(fpv3_<mode>)" + "fmul.<f3t>\t%0, %1, %2" +) + +;; ------------------------------------------------------------------------- +;; Float Muladd and mulsub instructions +;; ------------------------------------------------------------------------- + +(define_insn "*fpv3_mula<mode>3" + [(set (match_operand:F3ANY 0 "register_operand" "+v") + (plus:F3ANY (mult:F3ANY (match_operand:F3ANY 1 "register_operand" " v") + (match_operand:F3ANY 2 "register_operand" " v")) + (match_dup 0)))] + "CSKY_ISA_FEATURE(fpv3_<mode>)" + "fmula.<f3t>\t%0, %1, %2" +) + +(define_insn "*fpv3_muls<mode>3" + [(set (match_operand:F3ANY 0 "register_operand" "+v") + (minus:F3ANY (match_dup 0) + (mult:F3ANY (match_operand:F3ANY 1 "register_operand" " v") + (match_operand:F3ANY 2 "register_operand" " v"))))] + "CSKY_ISA_FEATURE(fpv3_<mode>)" + "fmuls.<f3t>\t%0, %1, %2" +) + +;; ------------------------------------------------------------------------- +;; Float fmula/fmuls/fnmula/fnmuls instructions +;; ------------------------------------------------------------------------- + +(define_insn "*fpv3_fmuls_<mode>4" + [(set (match_operand:F3ANY 0 "register_operand" "=v") + (fma:F3ANY (neg:F3ANY (match_operand:F3ANY 1 "register_operand" "v")) + (match_operand:F3ANY 2 "register_operand" "v") + (match_operand:F3ANY 3 "register_operand" "0")))] + "CSKY_ISA_FEATURE(fpv3_<mode>)" + "ffmuls.<f3t>\t%0, %1, %2" +) + +(define_insn "*fpv3_fmula_<mode>4" + [(set (match_operand:F3ANY 0 "register_operand" "=v") + (fma:F3ANY (match_operand:F3ANY 1 "register_operand" " v") + (match_operand:F3ANY 2 "register_operand" " v") + (match_operand:F3ANY 3 "register_operand" "0")))] + "CSKY_ISA_FEATURE(fpv3_<mode>)" + "ffmula.<f3t>\t%0, %1, %2" +) + +(define_insn "*fpv3_fnmula_<mode>4" + [(set (match_operand:F3ANY 0 "register_operand" "=v") + (neg: F3ANY (fma:F3ANY (match_operand:F3ANY 1 "register_operand" " v") + (match_operand:F3ANY 2 "register_operand" " v") + (match_operand:F3ANY 3 "register_operand" "0"))))] + "CSKY_ISA_FEATURE(fpv3_<mode>)" + "ffnmula.<f3t>\t%0, %1, %2" +) + +(define_insn "*fpv3_fnmuls_<mode>4" + [(set (match_operand:F3ANY 0 "register_operand" "=v") + (fma:F3ANY (match_operand:F3ANY 1 "register_operand" " v") + (match_operand:F3ANY 2 "register_operand" " v") + (neg:F3ANY (match_operand:F3ANY 3 "register_operand" "0"))))] + "CSKY_ISA_FEATURE(fpv3_sf)" + "ffnmuls.<f3t>\t%0, %1, %2" +) + +;; ------------------------------------------------------------------------- +;; Float div/recipe/sqrt instructions +;; ------------------------------------------------------------------------- + +(define_insn "*fpv3_div<mode>3" + [(set (match_operand:F3ANY 0 "register_operand" "=v") + (div:F3ANY (match_operand:F3ANY 1 "register_operand" " v") + (match_operand:F3ANY 2 "register_operand" " v")))] + "CSKY_ISA_FEATURE(fpv3_<mode>)" + "fdiv.<f3t>\t%0, %1, %2" +) + +(define_insn "*fpv3_recip<mode>3" + [(set (match_operand:F3ANY 0 "register_operand" "=v") + (div:F3ANY (match_operand:F3ANY 1 "csky_const_float1_operand" " i") + (match_operand:F3ANY 2 "register_operand" " v")))] + "CSKY_ISA_FEATURE(fpv3_<mode>)" + "frecip.<f3t>\t%0, %2" +) + +(define_insn "*fpv3_sqrt<mode>2" + [(set (match_operand:F3ANY 0 "register_operand" "=v") + (sqrt:F3ANY (match_operand:F3ANY 1 "register_operand" " v")))] + "CSKY_ISA_FEATURE(fpv3_<mode>)" + "fsqrt.<f3t>\t%0, %1" +) + +;; ------------------------------------------------------------------------- +;; Float fmax/fmin instructions +;; ------------------------------------------------------------------------- + +(define_insn "fmax<mode>3" + [(set (match_operand:F3ANY 0 "register_operand" "=v") + (unspec:F3ANY [(match_operand:F3ANY 1 "register_operand" " v") + (match_operand:F3ANY 2 "register_operand" " v")] + UNSPEC_MAXNM_F3))] + "CSKY_ISA_FEATURE(fpv3_<mode>)" + "fmaxnm.<f3t>\t%0, %1, %2" +) + +(define_insn "fmin<mode>3" + [(set (match_operand:F3ANY 0 "register_operand" "=v") + (unspec:F3ANY [(match_operand:F3ANY 1 "register_operand" " v") + (match_operand:F3ANY 2 "register_operand" " v")] + UNSPEC_MINNM_F3))] + "CSKY_ISA_FEATURE(fpv3_<mode>)" + "fminnm.<f3t>\t%0, %1, %2" +) + +;; ------------------------------------------------------------------------- +;; Float compare instructions +;; ------------------------------------------------------------------------- + +(define_insn "*fpv3_<zero_inst>_<mode>3" + [(set (reg:CC CSKY_CC_REGNUM) + (FCMPZ:CC (match_operand:F3ANY 0 "register_operand" "v") + (match_operand:F3ANY 1 "csky_const_float0_operand" "i")))] + "CSKY_ISA_FEATURE(fpv3_<mode>)" + "fcmp<zero_inst>.<f3t>\t%0" +) + +(define_insn "*fpv3_<reg_inst>_<mode>3" + [(set (reg:CC CSKY_CC_REGNUM) + (FCMP:CC (match_operand:F3ANY 0 "register_operand" "v") + (match_operand:F3ANY 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE(fpv3_<mode>)" + "fcmp<reg_inst>.<f3t>\t%0, %1" +) + +(define_insn "*fpv3_gt<mode>3" + [(set (reg:CC CSKY_CC_REGNUM) + (gt:CC (match_operand:F3ANY 0 "register_operand" "v") + (match_operand:F3ANY 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE(fpv3_<mode>)" + "fcmplt.<f3t>\t%1, %0" +) + +(define_insn "*fpv3_le<mode>3" + [(set (reg:CC CSKY_CC_REGNUM) + (le:CC (match_operand:F3ANY 0 "register_operand" "v") + (match_operand:F3ANY 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE(fpv3_<mode>)" + "fcmphs.<f3t>\t%1, %0" +) + +(define_insn "*fpv3_unordered" + [(set (reg:CC CSKY_CC_REGNUM) + (unordered:CC (match_operand:F3ANY 0 "register_operand" "v") + (match_operand:F3ANY 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE(fpv3_<mode>)" + "fcmpuo.<f3t>\t%0, %1") + +(define_insn "*fpv3_unordered_zero" + [(set (reg:CC CSKY_CC_REGNUM) + (unordered:CC (match_operand:F3ANY 0 "register_operand" "v") + (match_operand:F3ANY 1 "csky_const_float0_operand" "i")))] + "CSKY_ISA_FEATURE(fpv3_<mode>)" + "fcmpuoz.<f3t>\t%0") + +;; ------------------------------------------------------------------------- +;; Float ADD instructions +;; ------------------------------------------------------------------------- + +(define_insn "*fpv3_add<mode>3" + [(set (match_operand:F3ANY 0 "register_operand" "=v") + (plus:F3ANY (match_operand:F3ANY 1 "register_operand" " v") + (match_operand:F3ANY 2 "register_operand" " v")))] + "CSKY_ISA_FEATURE(fpv3_<mode>)" + "fadd.<f3t>\t%0, %1, %2" +) + +;; ------------------------------------------------------------------------- +;; Float SUB instructions +;; ------------------------------------------------------------------------- + +(define_insn "*fpv3_sub<mode>3" + [(set (match_operand:F3ANY 0 "register_operand" "=v") + (minus:F3ANY (match_operand:F3ANY 1 "register_operand" " v") + (match_operand:F3ANY 2 "register_operand" " v")))] + "CSKY_ISA_FEATURE(fpv3_<mode>)" + "fsub.<f3t>\t%0, %1, %2" +) + +;; ------------------------------------------------------------------------- +;; Float NEG instructions +;; ------------------------------------------------------------------------- + +(define_insn "*fpv3_neg<mode>2" + [(set (match_operand:F3ANY 0 "register_operand" "=v") + (neg:F3ANY (match_operand:F3ANY 1 "register_operand" " v")))] + "CSKY_ISA_FEATURE(fpv3_<mode>)" + "fneg.<f3t>\t%0, %1" +) + +;; ------------------------------------------------------------------------- +;; Float ABS instructions +;; ------------------------------------------------------------------------- + +(define_insn "*fpv3_abs<mode>2" + [(set (match_operand:F3ANY 0 "register_operand" "=v") + (abs:F3ANY (match_operand:F3ANY 1 "register_operand" " v")))] + "CSKY_ISA_FEATURE(fpv3_<mode>)" + "fabs.<f3t>\t%0, %1" +) + +;; ------------------------------------------------------------------------- +;; Float common convert instructions +;; ------------------------------------------------------------------------- + +;; SF <- HF +(define_insn "*fpv3_extendhfsf2" + [(set (match_operand:SF 0 "register_operand" "=v") + (float_extend:SF (match_operand:HF 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE(fpv3_hf)" + "fhtos\t%0, %1") + +;; HF <- SF +(define_insn "*fpv3_truncsfhf2" + [(set (match_operand:HF 0 "register_operand" "=v") + (float_truncate:HF (match_operand:SF 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE(fpv3_hf)" + "fstoh\t%0, %1") + +;; DF <- SF +(define_insn "*fpv3_extendsfdf2" + [(set (match_operand:DF 0 "register_operand" "=v") + (float_extend:DF (match_operand:SF 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE(fpv3_df)" + "fstod\t%0, %1") + +;; SF <- DF +(define_insn "*fpv3_truncdfsf2" + [(set (match_operand:SF 0 "register_operand" "=v") + (float_truncate:SF (match_operand:DF 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE(fpv3_df)" + "fdtos\t%0, %1") + +;; DF,SF,HF <- unsigned SI,SI +(define_insn "*fpv3_float<floatsuop>si<mode>2" + [(set (match_operand:F3ANY 0 "register_operand" "=v") + (FLOAT_SU:F3ANY (match_operand:SI 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE(fpv3_<mode>)" + "fitof.<floatsu>32.f<f3t>\t%0, %1") + +;; HF <- unsigned HI,HI +(define_insn "*fpv3_float<floatsuop>hihf2" + [(set (match_operand:HF 0 "register_operand" "=v") + (FLOAT_SU:HF (match_operand:HI 1 "register_operand" "v")))] + "CSKY_ISA_FEATURE(fpv3_hi) && CSKY_ISA_FEATURE(fpv3_hf)" + "fitof.<floatsu>16.f16\t%0, %1") + +;; unsigned SI,SI <- DF,SF,HF +(define_insn "*fpv3_fix<fixsuop>_trunc<mode>si2" + [(set (match_operand:SI 0 "register_operand" "=v") + (FIX_SU:SI (fix:F3ANY (match_operand:F3ANY 1 "register_operand" "v"))))] + "CSKY_ISA_FEATURE(fpv3_<mode>)" + "fftoi.f<f3t>.<fixsu>32.rz\t%0, %1") + +;; ------------------------------------------------------------------------- +;; Float complex convert instructions +;; ------------------------------------------------------------------------- + +;; Fixed point to floating point conversions. + +;(define_insn "*combine_fcvt_fixed16_<mode>" +; [(set (match_operand:F3ANY 0 "register_operand" "=v") +; (mult:F3ANY (float:F3ANY (match_operand:HI 1 "register_operand" "0")) +; (match_operand 2 +; "const_double_fcvt_power_of_two_reciprocal_hq" "Dt")))] +; "CSKY_ISA_FEATURE(fpv3_<mode>) && !flag_rounding_math +; && CSKY_ISA_FEATURE(fpv3_hi)" +; "fxtof.s16.f<f3t>\t%0, %1, %v2") +; +;(define_insn "*combine_fcvt_fixed32_<mode>" +; [(set (match_operand:F3ANY 0 "register_operand" "=v") +; (mult:F3ANY (float:F3ANY (match_operand:SI 1 "register_operand" "0")) +; (match_operand 2 +; "const_double_fcvt_power_of_two_reciprocal_sq" "Dt")))] +; "CSKY_ISA_FEATURE(fpv3_<mode>) && !flag_rounding_math" +; "fxtof.s32.f<f3t>\t%0, %1, %v2") +; +;(define_insn "*combine_fcvt_unfixed16_<mode>" +; [(set (match_operand:F3ANY 0 "register_operand" "=v") +; (mult:F3ANY (unsigned_float:F3ANY (match_operand:HI 1 "register_operand" "0")) +; (match_operand 2 +; "const_double_fcvt_power_of_two_reciprocal_hq" "Dt")))] +; "CSKY_ISA_FEATURE(fpv3_<mode>) && !flag_rounding_math +; && CSKY_ISA_FEATURE(fpv3_hi)" +; "fxtof.u16.f<f3t>\t%0, %1, %v2") +; +;(define_insn "*combine_fcvt_unfixed32_<mode>" +; [(set (match_operand:F3ANY 0 "register_operand" "=v") +; (mult:F3ANY (unsigned_float:F3ANY (match_operand:SI 1 "register_operand" "0")) +; (match_operand 2 +; "const_double_fcvt_power_of_two_reciprocal_sq" "Dt")))] +; "CSKY_ISA_FEATURE(fpv3_<mode>) && !flag_rounding_math" +; "fxtof.u32.f<f3t>\t%0, %1, %v2") + +;; Floating point to fixed point conversions. + +;(define_insn "*combine_fcvt<mode>_fixed16" +; [(set (match_operand:HI 0 "register_operand" "=v") +; (fix:HI (fix:F3ANY (mult:F3ANY (match_operand:F3ANY 1 "register_operand" "0") +; (match_operand 2 +; "const_double_fcvt_power_of_two_hq" "Du")))))] +; "CSKY_ISA_FEATURE(fpv3_<mode>) && !flag_rounding_math +; && CSKY_ISA_FEATURE(fpv3_hi)" +; "fftox.f<f3t>.s16\t%0, %1, %v2" +; ) +; +;(define_insn "*combine_fcvt<mode>_fixed32" +; [(set (match_operand:SI 0 "register_operand" "=v") +; (fix:SI (fix:F3ANY (mult:F3ANY (match_operand:F3ANY 1 "register_operand" "0") +; (match_operand 2 +; "const_double_fcvt_power_of_two_sq" "Du")))))] +; "CSKY_ISA_FEATURE(fpv3_<mode>) && !flag_rounding_math" +; "fftox.f<f3t>.s32\t%0, %1, %v2" +; ) +; +;(define_insn "*combine_fcvt<mode>_unfixed16" +; [(set (match_operand:HI 0 "register_operand" "=v") +; (unsigned_fix:HI (fix:F3ANY (mult:F3ANY (match_operand:F3ANY 1 "register_operand" "0") +; (match_operand 2 +; "const_double_fcvt_power_of_two_hq" "Du")))))] +; "CSKY_ISA_FEATURE(fpv3_<mode>) && !flag_rounding_math +; && CSKY_ISA_FEATURE(fpv3_hi)" +; "fftox.f<f3t>.u16\t%0, %1, %v2" +; ) +; +;(define_insn "*combine_fcvt<mode>_unfixed32" +; [(set (match_operand:SI 0 "register_operand" "=v") +; (unsigned_fix:SI (fix:F3ANY (mult:F3ANY (match_operand:F3ANY 1 "register_operand" "0") +; (match_operand 2 +; "const_double_fcvt_power_of_two_sq" "Du")))))] +; "CSKY_ISA_FEATURE(fpv3_<mode>) && !flag_rounding_math" +; "fftox.f<f3t>.u32\t%0, %1, %v2" +; ) + +;; conversions need to be rounding to nearest. + +(define_insn "l<frm_pattern><fixsuop><mode>si2" + [(set (match_operand:SI 0 "register_operand" "=v") + (FIX_SU:SI (unspec:F3ANY [(match_operand:F3ANY 1 "register_operand" "0")] + FRM)))] + "CSKY_ISA_FEATURE(fpv3_<mode>)" + "fftoi.f<f3t>.<fixsu>32<rm>\t%0, %1" +) + +(define_insn "<frm_pattern><mode>2" + [(set (match_operand:F3ANY 0 "register_operand" "=v") + (unspec:F3ANY [(match_operand:F3ANY 1 "register_operand" "0")] FRMF))] + "CSKY_ISA_FEATURE(fpv3_<mode>)" + "fftofi.f<f3t><rm>\t%0, %1" +) + +;; Write Floating-point Control Register. +(define_insn "csky_setfcrsi" + [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] VUNSPEC_SET_FCR)] + "CSKY_ISA_FEATURE(fcr)" + "mtcr\t%0, fcr" +) + +;; Read Floating-point Control Register. +(define_insn "csky_getfcrsi" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec_volatile:SI [(const_int 0)] VUNSPEC_GET_FCR))] + "CSKY_ISA_FEATURE(fcr)" + "mfcr\t%0, fcr" +) + +;; Insert Floating-point Control Register. +(define_insn "csky_insfcrsi" + [(unspec_volatile [(match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "const_int_operand" "i") + (match_operand:SI 2 "const_int_operand" "i")]VUNSPEC_INS_FCR) + (clobber (reg: SI 13))] + "CSKY_ISA_FEATURE(fcr)" + { + operands[1] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[1]) - 1); + return "mfcr\tt1, fcr\n\tins\tt1, %0, %1, %2\n\tmtcr\tt1, fcr"; + } +) diff --git a/gcc/config/csky/csky_isa.def b/gcc/config/csky/csky_isa.def index 5edce16..58498196 100644 --- a/gcc/config/csky/csky_isa.def +++ b/gcc/config/csky/csky_isa.def @@ -32,6 +32,7 @@ CSKY_ISA (7E10, "Extended insns for arch ck810 from ck807") /* Special insns */ CSKY_ISA (div, "divide insns") +CSKY_ISA (fcr, "Control the fcr register") /* Extended insns */ CSKY_ISA (dsp, "Extended insns for DSP") @@ -41,6 +42,11 @@ CSKY_ISA (fpv2_sf, "Single precision operations supported") CSKY_ISA (fpv2_df, "Double precision operations supported") CSKY_ISA (fpv2_divd, "Double precision div operations supported") +CSKY_ISA (fpv3_hi, "half word for fpu convert supported") +CSKY_ISA (fpv3_hf, "half precision operations supported") +CSKY_ISA (fpv3_sf, "Single precision operations supported") +CSKY_ISA (fpv3_df, "Double precision operations supported") + /* Specific insns mode */ #ifdef CSKY_ISA_MACRO #define CSKY_ISA_CK801 CSKY_ISA_FEATURE_GET (E1) @@ -50,10 +56,19 @@ CSKY_ISA (fpv2_divd, "Double precision div operations supported") #define CSKY_ISA_CK803R1 CSKY_ISA_CK803, CSKY_ISA_FEATURE_GET (3E3r1) #define CSKY_ISA_CK807 CSKY_ISA_CK803, CSKY_ISA_FEATURE_GET (3E7) #define CSKY_ISA_CK810 CSKY_ISA_CK807, CSKY_ISA_FEATURE_GET (7E10) +#define CSKY_ISA_CK860 CSKY_ISA_CK810, CSKY_ISA_FEATURE_GET(3E3r1) #define CSKY_ISA_DSP CSKY_ISA_FEATURE_GET (dsp) #define CSKY_ISA_FPv2_SF CSKY_ISA_FEATURE_GET (fpv2_sf) #define CSKY_ISA_FPv2 CSKY_ISA_FPv2_SF, CSKY_ISA_FEATURE_GET (fpv2_df) #define CSKY_ISA_FPv2_DIVD CSKY_ISA_FPv2, CSKY_ISA_FEATURE_GET (fpv2_divd) + +#define CSKY_ISA_FPv3_HF CSKY_ISA_FEATURE_GET (fpv3_hf), \ + CSKY_ISA_FEATURE_GET (fpv3_hi) +#define CSKY_ISA_FPv3_HSF CSKY_ISA_FPv3_HF, \ + CSKY_ISA_FEATURE_GET (fpv3_sf) +#define CSKY_ISA_FPv3_SDF CSKY_ISA_FEATURE_GET (fpv3_sf), \ + CSKY_ISA_FEATURE_GET (fpv3_df) +#define CSKY_ISA_FPv3 CSKY_ISA_FPv3_HF, CSKY_ISA_FPv3_SDF #endif diff --git a/gcc/config/csky/csky_tables.opt b/gcc/config/csky/csky_tables.opt index 3501f90..ca113dd 100644 --- a/gcc/config/csky/csky_tables.opt +++ b/gcc/config/csky/csky_tables.opt @@ -194,6 +194,12 @@ Enum(csky_processor_type) String(ck810ft) Value( TARGET_CPU_ck810ff) EnumValue Enum(csky_processor_type) String(ck810ftv) Value( TARGET_CPU_ck810ftv) +EnumValue +Enum(csky_processor_type) String(ck860) Value( TARGET_CPU_ck860) + +EnumValue +Enum(csky_processor_type) String(ck860f) Value( TARGET_CPU_ck860f) + Enum Name(csky_arch) Type(int) Known CSKY architectures (for use with the -march= option): @@ -213,6 +219,9 @@ Enum(csky_arch) String(ck807) Value(3) EnumValue Enum(csky_arch) String(ck810) Value(4) +EnumValue +Enum(csky_arch) String(ck860) Value(5) + Enum Name(csky_fpu) Type(enum csky_fpu_type) Known CSKY FPUs (for use with the -mfpu= option): @@ -227,4 +236,16 @@ EnumValue Enum(csky_fpu) String(fpv2_divd) Value(TARGET_FPU_fpv2_divd) EnumValue +Enum(csky_fpu) String(fpv3_hf) Value(TARGET_FPU_fpv3_hf) + +EnumValue +Enum(csky_fpu) String(fpv3_hsf) Value(TARGET_FPU_fpv3_hsf) + +EnumValue +Enum(csky_fpu) String(fpv3_sdf) Value(TARGET_FPU_fpv3_sdf) + +EnumValue +Enum(csky_fpu) String(fpv3) Value(TARGET_FPU_fpv3) + +EnumValue Enum(csky_fpu) String(auto) Value(TARGET_FPU_auto) diff --git a/gcc/config/csky/predicates.md b/gcc/config/csky/predicates.md index 4ffecb0..878446d 100644 --- a/gcc/config/csky/predicates.md +++ b/gcc/config/csky/predicates.md @@ -294,5 +294,4 @@ }) (define_special_predicate "csky_float_comparison_operator" - (match_code "eq,ne,le,lt,ge,gt,geu,gtu,leu,ltu, - unordered,ordered")) + (match_code "eq,ne,le,lt,ge,gt,unordered,ordered")) diff --git a/gcc/config/csky/t-csky-elf b/gcc/config/csky/t-csky-elf index bbdf286..4e7fcbe 100644 --- a/gcc/config/csky/t-csky-elf +++ b/gcc/config/csky/t-csky-elf @@ -27,8 +27,8 @@ MULTILIB_MATCHES = mbig-endian=EB MULTILIB_EXCEPTIONS = # Arch variants. -MULTILIB_OPTIONS += mcpu=ck802/mcpu=ck801/mcpu=ck803f/mcpu=ck807f/mcpu=ck810f -MULTILIB_DIRNAMES += ck802 ck801 ck803 ck807 ck810 +MULTILIB_OPTIONS += mcpu=ck802/mcpu=ck801/mcpu=ck803f/mcpu=ck807f/mcpu=ck810f/mcpu=ck860f +MULTILIB_DIRNAMES += ck802 ck801 ck803 ck807 ck810 ck860 # For arch ck802. MULTILIB_MATCHES += mcpu?ck802=march?ck802 @@ -100,6 +100,11 @@ MULTILIB_MATCHES += mcpu?ck807f=march?ck807ef MULTILIB_MATCHES += mcpu?ck807f=march?ck807 MULTILIB_MATCHES += mcpu?ck807f=mcpu?ck807 +# For arch ck860 +MULTILIB_MATCHES += mcpu?ck860f=march?ck860 +MULTILIB_MATCHES += mcpu?ck860f=mcpu?ck860 +MULTILIB_MATCHES += mcpu?ck860f=mcpu?c860 + # For option -mfloat-abi= MULTILIB_OPTIONS += mfloat-abi=soft/mfloat-abi=softfp/mfloat-abi=hard MULTILIB_DIRNAMES += soft soft-fp hard-fp diff --git a/gcc/config/csky/t-csky-linux b/gcc/config/csky/t-csky-linux index 9435b7a..0730c3a 100644 --- a/gcc/config/csky/t-csky-linux +++ b/gcc/config/csky/t-csky-linux @@ -21,11 +21,11 @@ MULTILIB_EXCEPTIONS = -CSKY_MULTILIB_OSDIRNAMES = mfloat-abi.softfp=/soft-fp mfloat-abi.hard=/hard-fp mfloat-abi.soft=/. mcpu.ck810f=/. mcpu.ck807f=/ck807 +CSKY_MULTILIB_OSDIRNAMES = mfloat-abi.softfp=/soft-fp mfloat-abi.hard=/hard-fp mfloat-abi.soft=/. mcpu.ck810f=/. mcpu.ck807f=/ck807 mcpu.ck860f=/ck860 # Arch variants. -MULTILIB_OPTIONS += mcpu=ck810f/mcpu=ck807f -MULTILIB_DIRNAMES += ck810 ck807 +MULTILIB_OPTIONS += mcpu=ck810f/mcpu=ck807f/mcpu=ck860f +MULTILIB_DIRNAMES += ck810 ck807 ck860 # For ck807. MULTILIB_MATCHES += mcpu?ck807f=march?ck807 @@ -41,6 +41,11 @@ MULTILIB_MATCHES += mcpu?ck810f=mcpu?ck810vf MULTILIB_MATCHES += mcpu?ck810f=mcpu?ck810ft MULTILIB_MATCHES += mcpu?ck810f=mcpu?ck810vft +# For ck860 +MULTILIB_MATCHES += mcpu?ck860f=march?ck860 +MULTILIB_MATCHES += mcpu?ck860f=mcpu?ck860 +MULTILIB_MATCHES += mcpu?ck860f=mcpu?c860 + # For option -mfloat-abi= MULTILIB_OPTIONS += mfloat-abi=soft/mfloat-abi=softfp/mfloat-abi=hard MULTILIB_DIRNAMES += soft soft-fp hard-fp diff --git a/gcc/config/rs6000/fusion.md b/gcc/config/rs6000/fusion.md index 4d810e6..5191210 100644 --- a/gcc/config/rs6000/fusion.md +++ b/gcc/config/rs6000/fusion.md @@ -355,11 +355,11 @@ (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar and -> and (define_insn "*fuse_and_and" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (and:GPR (and:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (and:GPR (and:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") (match_operand:GPR 1 "gpc_reg_operand" "%r,r,r,r")) (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -373,11 +373,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar andc -> and (define_insn "*fuse_andc_and" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (and:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (and:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -391,11 +391,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar eqv -> and (define_insn "*fuse_eqv_and" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (and:GPR (not:GPR (xor:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (and:GPR (not:GPR (xor:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -409,11 +409,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar nand -> and (define_insn "*fuse_nand_and" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (and:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (and:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -427,11 +427,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar nor -> and (define_insn "*fuse_nor_and" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (and:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (and:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -445,11 +445,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar or -> and (define_insn "*fuse_or_and" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (and:GPR (ior:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (and:GPR (ior:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -463,11 +463,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar orc -> and (define_insn "*fuse_orc_and" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (and:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (and:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -481,11 +481,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar xor -> and (define_insn "*fuse_xor_and" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (and:GPR (xor:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (and:GPR (xor:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -499,11 +499,47 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; add-logical fusion pattern generated by gen_logical_addsubf +;; scalar add -> and +(define_insn "*fuse_add_and" + [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") + (and:GPR (plus:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) + (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) + (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] + "(TARGET_P10_FUSION && TARGET_P10_FUSION_ADDLOG)" + "@ + add %3,%1,%0\;and %3,%3,%2 + add %3,%1,%0\;and %3,%3,%2 + add %3,%1,%0\;and %3,%3,%2 + add %4,%1,%0\;and %3,%4,%2" + [(set_attr "type" "fused_arith_logical") + (set_attr "cost" "6") + (set_attr "length" "8")]) + +;; add-logical fusion pattern generated by gen_logical_addsubf +;; scalar subf -> and +(define_insn "*fuse_subf_and" + [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") + (and:GPR (minus:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) + (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) + (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] + "(TARGET_P10_FUSION && TARGET_P10_FUSION_ADDLOG)" + "@ + subf %3,%1,%0\;and %3,%3,%2 + subf %3,%1,%0\;and %3,%3,%2 + subf %3,%1,%0\;and %3,%3,%2 + subf %4,%1,%0\;and %3,%4,%2" + [(set_attr "type" "fused_arith_logical") + (set_attr "cost" "6") + (set_attr "length" "8")]) + +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar and -> andc (define_insn "*fuse_and_andc" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (and:GPR (and:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (and:GPR (and:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -517,11 +553,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar andc -> andc (define_insn "*fuse_andc_andc" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (and:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (and:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -535,11 +571,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar eqv -> andc (define_insn "*fuse_eqv_andc" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (and:GPR (not:GPR (xor:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (and:GPR (not:GPR (xor:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -553,11 +589,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar nand -> andc (define_insn "*fuse_nand_andc" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (and:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (and:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -571,11 +607,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar nor -> andc (define_insn "*fuse_nor_andc" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (and:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (and:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -589,11 +625,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar or -> andc (define_insn "*fuse_or_andc" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (and:GPR (ior:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (and:GPR (ior:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -607,11 +643,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar orc -> andc (define_insn "*fuse_orc_andc" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (and:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (and:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -625,11 +661,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar xor -> andc (define_insn "*fuse_xor_andc" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (and:GPR (xor:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (and:GPR (xor:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -643,11 +679,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar and -> eqv (define_insn "*fuse_and_eqv" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (not:GPR (xor:GPR (and:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (not:GPR (xor:GPR (and:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -661,11 +697,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar andc -> eqv (define_insn "*fuse_andc_eqv" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (not:GPR (xor:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (not:GPR (xor:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -679,11 +715,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar eqv -> eqv (define_insn "*fuse_eqv_eqv" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (not:GPR (xor:GPR (not:GPR (xor:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (not:GPR (xor:GPR (not:GPR (xor:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") (match_operand:GPR 1 "gpc_reg_operand" "%r,r,r,r"))) (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -697,11 +733,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar nand -> eqv (define_insn "*fuse_nand_eqv" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (not:GPR (xor:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (not:GPR (xor:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -715,11 +751,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar nor -> eqv (define_insn "*fuse_nor_eqv" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (not:GPR (xor:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (not:GPR (xor:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -733,11 +769,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar or -> eqv (define_insn "*fuse_or_eqv" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (not:GPR (xor:GPR (ior:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (not:GPR (xor:GPR (ior:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -751,11 +787,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar orc -> eqv (define_insn "*fuse_orc_eqv" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (not:GPR (xor:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (not:GPR (xor:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -769,11 +805,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar xor -> eqv (define_insn "*fuse_xor_eqv" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (not:GPR (xor:GPR (xor:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (not:GPR (xor:GPR (xor:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -787,11 +823,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar and -> nand (define_insn "*fuse_and_nand" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (ior:GPR (not:GPR (and:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (ior:GPR (not:GPR (and:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -805,11 +841,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar andc -> nand (define_insn "*fuse_andc_nand" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (ior:GPR (not:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (ior:GPR (not:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -823,11 +859,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar eqv -> nand (define_insn "*fuse_eqv_nand" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (ior:GPR (not:GPR (not:GPR (xor:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (ior:GPR (not:GPR (not:GPR (xor:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")))) (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -841,11 +877,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar nand -> nand (define_insn "*fuse_nand_nand" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (ior:GPR (not:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (ior:GPR (not:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")))) (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -859,11 +895,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar nor -> nand (define_insn "*fuse_nor_nand" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (ior:GPR (not:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (ior:GPR (not:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")))) (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -877,11 +913,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar or -> nand (define_insn "*fuse_or_nand" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (ior:GPR (not:GPR (ior:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (ior:GPR (not:GPR (ior:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -895,11 +931,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar orc -> nand (define_insn "*fuse_orc_nand" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (ior:GPR (not:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (ior:GPR (not:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -913,11 +949,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar xor -> nand (define_insn "*fuse_xor_nand" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (ior:GPR (not:GPR (xor:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (ior:GPR (not:GPR (xor:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -931,11 +967,47 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; add-logical fusion pattern generated by gen_logical_addsubf +;; scalar add -> nand +(define_insn "*fuse_add_nand" + [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") + (ior:GPR (not:GPR (plus:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) + (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) + (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] + "(TARGET_P10_FUSION && TARGET_P10_FUSION_ADDLOG)" + "@ + add %3,%1,%0\;nand %3,%3,%2 + add %3,%1,%0\;nand %3,%3,%2 + add %3,%1,%0\;nand %3,%3,%2 + add %4,%1,%0\;nand %3,%4,%2" + [(set_attr "type" "fused_arith_logical") + (set_attr "cost" "6") + (set_attr "length" "8")]) + +;; add-logical fusion pattern generated by gen_logical_addsubf +;; scalar subf -> nand +(define_insn "*fuse_subf_nand" + [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") + (ior:GPR (not:GPR (minus:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) + (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) + (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] + "(TARGET_P10_FUSION && TARGET_P10_FUSION_ADDLOG)" + "@ + subf %3,%1,%0\;nand %3,%3,%2 + subf %3,%1,%0\;nand %3,%3,%2 + subf %3,%1,%0\;nand %3,%3,%2 + subf %4,%1,%0\;nand %3,%4,%2" + [(set_attr "type" "fused_arith_logical") + (set_attr "cost" "6") + (set_attr "length" "8")]) + +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar and -> nor (define_insn "*fuse_and_nor" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (and:GPR (not:GPR (and:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (and:GPR (not:GPR (and:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -949,11 +1021,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar andc -> nor (define_insn "*fuse_andc_nor" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (and:GPR (not:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (and:GPR (not:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -967,11 +1039,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar eqv -> nor (define_insn "*fuse_eqv_nor" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (and:GPR (not:GPR (not:GPR (xor:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (and:GPR (not:GPR (not:GPR (xor:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")))) (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -985,11 +1057,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar nand -> nor (define_insn "*fuse_nand_nor" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (and:GPR (not:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (and:GPR (not:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")))) (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -1003,11 +1075,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar nor -> nor (define_insn "*fuse_nor_nor" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (and:GPR (not:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (and:GPR (not:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")))) (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -1021,11 +1093,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar or -> nor (define_insn "*fuse_or_nor" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (and:GPR (not:GPR (ior:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (and:GPR (not:GPR (ior:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -1039,11 +1111,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar orc -> nor (define_insn "*fuse_orc_nor" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (and:GPR (not:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (and:GPR (not:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -1057,11 +1129,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar xor -> nor (define_insn "*fuse_xor_nor" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (and:GPR (not:GPR (xor:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (and:GPR (not:GPR (xor:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -1075,11 +1147,47 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; add-logical fusion pattern generated by gen_logical_addsubf +;; scalar add -> nor +(define_insn "*fuse_add_nor" + [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") + (and:GPR (not:GPR (plus:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) + (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) + (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] + "(TARGET_P10_FUSION && TARGET_P10_FUSION_ADDLOG)" + "@ + add %3,%1,%0\;nor %3,%3,%2 + add %3,%1,%0\;nor %3,%3,%2 + add %3,%1,%0\;nor %3,%3,%2 + add %4,%1,%0\;nor %3,%4,%2" + [(set_attr "type" "fused_arith_logical") + (set_attr "cost" "6") + (set_attr "length" "8")]) + +;; add-logical fusion pattern generated by gen_logical_addsubf +;; scalar subf -> nor +(define_insn "*fuse_subf_nor" + [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") + (and:GPR (not:GPR (minus:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) + (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) + (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] + "(TARGET_P10_FUSION && TARGET_P10_FUSION_ADDLOG)" + "@ + subf %3,%1,%0\;nor %3,%3,%2 + subf %3,%1,%0\;nor %3,%3,%2 + subf %3,%1,%0\;nor %3,%3,%2 + subf %4,%1,%0\;nor %3,%4,%2" + [(set_attr "type" "fused_arith_logical") + (set_attr "cost" "6") + (set_attr "length" "8")]) + +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar and -> or (define_insn "*fuse_and_or" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (ior:GPR (and:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (ior:GPR (and:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -1093,11 +1201,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar andc -> or (define_insn "*fuse_andc_or" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (ior:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (ior:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -1111,11 +1219,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar eqv -> or (define_insn "*fuse_eqv_or" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (ior:GPR (not:GPR (xor:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (ior:GPR (not:GPR (xor:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -1129,11 +1237,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar nand -> or (define_insn "*fuse_nand_or" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (ior:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (ior:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -1147,11 +1255,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar nor -> or (define_insn "*fuse_nor_or" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (ior:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (ior:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -1165,11 +1273,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar or -> or (define_insn "*fuse_or_or" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (ior:GPR (ior:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (ior:GPR (ior:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") (match_operand:GPR 1 "gpc_reg_operand" "%r,r,r,r")) (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -1183,11 +1291,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar orc -> or (define_insn "*fuse_orc_or" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (ior:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (ior:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -1201,11 +1309,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar xor -> or (define_insn "*fuse_xor_or" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (ior:GPR (xor:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (ior:GPR (xor:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -1219,11 +1327,47 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; add-logical fusion pattern generated by gen_logical_addsubf +;; scalar add -> or +(define_insn "*fuse_add_or" + [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") + (ior:GPR (plus:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) + (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) + (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] + "(TARGET_P10_FUSION && TARGET_P10_FUSION_ADDLOG)" + "@ + add %3,%1,%0\;or %3,%3,%2 + add %3,%1,%0\;or %3,%3,%2 + add %3,%1,%0\;or %3,%3,%2 + add %4,%1,%0\;or %3,%4,%2" + [(set_attr "type" "fused_arith_logical") + (set_attr "cost" "6") + (set_attr "length" "8")]) + +;; add-logical fusion pattern generated by gen_logical_addsubf +;; scalar subf -> or +(define_insn "*fuse_subf_or" + [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") + (ior:GPR (minus:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) + (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) + (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] + "(TARGET_P10_FUSION && TARGET_P10_FUSION_ADDLOG)" + "@ + subf %3,%1,%0\;or %3,%3,%2 + subf %3,%1,%0\;or %3,%3,%2 + subf %3,%1,%0\;or %3,%3,%2 + subf %4,%1,%0\;or %3,%4,%2" + [(set_attr "type" "fused_arith_logical") + (set_attr "cost" "6") + (set_attr "length" "8")]) + +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar and -> orc (define_insn "*fuse_and_orc" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (ior:GPR (and:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (ior:GPR (and:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -1237,11 +1381,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar andc -> orc (define_insn "*fuse_andc_orc" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (ior:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (ior:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -1255,11 +1399,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar eqv -> orc (define_insn "*fuse_eqv_orc" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (ior:GPR (not:GPR (xor:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (ior:GPR (not:GPR (xor:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -1273,11 +1417,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar nand -> orc (define_insn "*fuse_nand_orc" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (ior:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (ior:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -1291,11 +1435,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar nor -> orc (define_insn "*fuse_nor_orc" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (ior:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (ior:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -1309,11 +1453,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar or -> orc (define_insn "*fuse_or_orc" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (ior:GPR (ior:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (ior:GPR (ior:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -1327,11 +1471,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar orc -> orc (define_insn "*fuse_orc_orc" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (ior:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (ior:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -1345,11 +1489,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar xor -> orc (define_insn "*fuse_xor_orc" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (ior:GPR (xor:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (ior:GPR (xor:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r")))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -1363,11 +1507,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar and -> xor (define_insn "*fuse_and_xor" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (xor:GPR (and:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (xor:GPR (and:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -1381,11 +1525,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar andc -> xor (define_insn "*fuse_andc_xor" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (xor:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (xor:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -1399,11 +1543,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar eqv -> xor (define_insn "*fuse_eqv_xor" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (xor:GPR (not:GPR (xor:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (xor:GPR (not:GPR (xor:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -1417,11 +1561,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar nand -> xor (define_insn "*fuse_nand_xor" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (xor:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (xor:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -1435,11 +1579,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar nor -> xor (define_insn "*fuse_nor_xor" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (xor:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (xor:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -1453,11 +1597,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar or -> xor (define_insn "*fuse_or_xor" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (xor:GPR (ior:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (xor:GPR (ior:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -1471,11 +1615,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar orc -> xor (define_insn "*fuse_orc_xor" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (xor:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (xor:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -1489,11 +1633,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; scalar xor -> xor (define_insn "*fuse_xor_xor" [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") - (xor:GPR (xor:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (xor:GPR (xor:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") (match_operand:GPR 1 "gpc_reg_operand" "%r,r,r,r")) (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] @@ -1507,11 +1651,227 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-add fusion pattern generated by gen_logical_addsubf +;; scalar and -> add +(define_insn "*fuse_and_add" + [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") + (plus:GPR (and:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) + (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) + (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] + "(TARGET_P10_FUSION && TARGET_P10_FUSION_LOGADD)" + "@ + and %3,%1,%0\;add %3,%3,%2 + and %3,%1,%0\;add %3,%3,%2 + and %3,%1,%0\;add %3,%3,%2 + and %4,%1,%0\;add %3,%4,%2" + [(set_attr "type" "fused_arith_logical") + (set_attr "cost" "6") + (set_attr "length" "8")]) + +;; logical-add fusion pattern generated by gen_logical_addsubf +;; scalar nand -> add +(define_insn "*fuse_nand_add" + [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") + (plus:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) + (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) + (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] + "(TARGET_P10_FUSION && TARGET_P10_FUSION_LOGADD)" + "@ + nand %3,%1,%0\;add %3,%3,%2 + nand %3,%1,%0\;add %3,%3,%2 + nand %3,%1,%0\;add %3,%3,%2 + nand %4,%1,%0\;add %3,%4,%2" + [(set_attr "type" "fused_arith_logical") + (set_attr "cost" "6") + (set_attr "length" "8")]) + +;; logical-add fusion pattern generated by gen_logical_addsubf +;; scalar nor -> add +(define_insn "*fuse_nor_add" + [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") + (plus:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) + (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) + (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] + "(TARGET_P10_FUSION && TARGET_P10_FUSION_LOGADD)" + "@ + nor %3,%1,%0\;add %3,%3,%2 + nor %3,%1,%0\;add %3,%3,%2 + nor %3,%1,%0\;add %3,%3,%2 + nor %4,%1,%0\;add %3,%4,%2" + [(set_attr "type" "fused_arith_logical") + (set_attr "cost" "6") + (set_attr "length" "8")]) + +;; logical-add fusion pattern generated by gen_logical_addsubf +;; scalar or -> add +(define_insn "*fuse_or_add" + [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") + (plus:GPR (ior:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) + (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) + (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] + "(TARGET_P10_FUSION && TARGET_P10_FUSION_LOGADD)" + "@ + or %3,%1,%0\;add %3,%3,%2 + or %3,%1,%0\;add %3,%3,%2 + or %3,%1,%0\;add %3,%3,%2 + or %4,%1,%0\;add %3,%4,%2" + [(set_attr "type" "fused_arith_logical") + (set_attr "cost" "6") + (set_attr "length" "8")]) + +;; logical-add fusion pattern generated by gen_logical_addsubf +;; scalar and -> subf +(define_insn "*fuse_and_subf" + [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") + (minus:GPR (and:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) + (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) + (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] + "(TARGET_P10_FUSION && TARGET_P10_FUSION_LOGADD)" + "@ + and %3,%1,%0\;subf %3,%3,%2 + and %3,%1,%0\;subf %3,%3,%2 + and %3,%1,%0\;subf %3,%3,%2 + and %4,%1,%0\;subf %3,%4,%2" + [(set_attr "type" "fused_arith_logical") + (set_attr "cost" "6") + (set_attr "length" "8")]) + +;; logical-add fusion pattern generated by gen_logical_addsubf +;; scalar nand -> subf +(define_insn "*fuse_nand_subf" + [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") + (minus:GPR (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) + (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) + (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] + "(TARGET_P10_FUSION && TARGET_P10_FUSION_LOGADD)" + "@ + nand %3,%1,%0\;subf %3,%3,%2 + nand %3,%1,%0\;subf %3,%3,%2 + nand %3,%1,%0\;subf %3,%3,%2 + nand %4,%1,%0\;subf %3,%4,%2" + [(set_attr "type" "fused_arith_logical") + (set_attr "cost" "6") + (set_attr "length" "8")]) + +;; logical-add fusion pattern generated by gen_logical_addsubf +;; scalar nor -> subf +(define_insn "*fuse_nor_subf" + [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") + (minus:GPR (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))) + (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) + (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] + "(TARGET_P10_FUSION && TARGET_P10_FUSION_LOGADD)" + "@ + nor %3,%1,%0\;subf %3,%3,%2 + nor %3,%1,%0\;subf %3,%3,%2 + nor %3,%1,%0\;subf %3,%3,%2 + nor %4,%1,%0\;subf %3,%4,%2" + [(set_attr "type" "fused_arith_logical") + (set_attr "cost" "6") + (set_attr "length" "8")]) + +;; logical-add fusion pattern generated by gen_logical_addsubf +;; scalar or -> subf +(define_insn "*fuse_or_subf" + [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") + (minus:GPR (ior:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")) + (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r"))) + (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] + "(TARGET_P10_FUSION && TARGET_P10_FUSION_LOGADD)" + "@ + or %3,%1,%0\;subf %3,%3,%2 + or %3,%1,%0\;subf %3,%3,%2 + or %3,%1,%0\;subf %3,%3,%2 + or %4,%1,%0\;subf %3,%4,%2" + [(set_attr "type" "fused_arith_logical") + (set_attr "cost" "6") + (set_attr "length" "8")]) + +;; logical-add fusion pattern generated by gen_logical_addsubf +;; scalar and -> rsubf +(define_insn "*fuse_and_rsubf" + [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") + (minus:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r") + (and:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")))) + (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] + "(TARGET_P10_FUSION && TARGET_P10_FUSION_LOGADD)" + "@ + and %3,%1,%0\;subf %3,%2,%3 + and %3,%1,%0\;subf %3,%2,%3 + and %3,%1,%0\;subf %3,%2,%3 + and %4,%1,%0\;subf %3,%2,%4" + [(set_attr "type" "fused_arith_logical") + (set_attr "cost" "6") + (set_attr "length" "8")]) + +;; logical-add fusion pattern generated by gen_logical_addsubf +;; scalar nand -> rsubf +(define_insn "*fuse_nand_rsubf" + [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") + (minus:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r") + (ior:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))))) + (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] + "(TARGET_P10_FUSION && TARGET_P10_FUSION_LOGADD)" + "@ + nand %3,%1,%0\;subf %3,%2,%3 + nand %3,%1,%0\;subf %3,%2,%3 + nand %3,%1,%0\;subf %3,%2,%3 + nand %4,%1,%0\;subf %3,%2,%4" + [(set_attr "type" "fused_arith_logical") + (set_attr "cost" "6") + (set_attr "length" "8")]) + +;; logical-add fusion pattern generated by gen_logical_addsubf +;; scalar nor -> rsubf +(define_insn "*fuse_nor_rsubf" + [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") + (minus:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r") + (and:GPR (not:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r")) + (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r"))))) + (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] + "(TARGET_P10_FUSION && TARGET_P10_FUSION_LOGADD)" + "@ + nor %3,%1,%0\;subf %3,%2,%3 + nor %3,%1,%0\;subf %3,%2,%3 + nor %3,%1,%0\;subf %3,%2,%3 + nor %4,%1,%0\;subf %3,%2,%4" + [(set_attr "type" "fused_arith_logical") + (set_attr "cost" "6") + (set_attr "length" "8")]) + +;; logical-add fusion pattern generated by gen_logical_addsubf +;; scalar or -> rsubf +(define_insn "*fuse_or_rsubf" + [(set (match_operand:GPR 3 "gpc_reg_operand" "=0,1,&r,r") + (minus:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r,r,r") + (ior:GPR (match_operand:GPR 0 "gpc_reg_operand" "r,r,r,r") + (match_operand:GPR 1 "gpc_reg_operand" "r,r,r,r")))) + (clobber (match_scratch:GPR 4 "=X,X,X,&r"))] + "(TARGET_P10_FUSION && TARGET_P10_FUSION_LOGADD)" + "@ + or %3,%1,%0\;subf %3,%2,%3 + or %3,%1,%0\;subf %3,%2,%3 + or %3,%1,%0\;subf %3,%2,%3 + or %4,%1,%0\;subf %3,%2,%4" + [(set_attr "type" "fused_arith_logical") + (set_attr "cost" "6") + (set_attr "length" "8")]) + +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vand -> vand (define_insn "*fuse_vand_vand" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (and:VM (and:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") + (and:VM (and:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") (match_operand:VM 1 "altivec_register_operand" "%v,v,v,v")) (match_operand:VM 2 "altivec_register_operand" "v,v,v,v"))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -1525,11 +1885,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vandc -> vand (define_insn "*fuse_vandc_vand" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (and:VM (and:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) + (and:VM (and:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 2 "altivec_register_operand" "v,v,v,v"))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -1543,11 +1903,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector veqv -> vand (define_insn "*fuse_veqv_vand" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (and:VM (not:VM (xor:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") + (and:VM (not:VM (xor:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") (match_operand:VM 1 "altivec_register_operand" "v,v,v,v"))) (match_operand:VM 2 "altivec_register_operand" "v,v,v,v"))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -1561,11 +1921,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vnand -> vand (define_insn "*fuse_vnand_vand" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (and:VM (ior:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) + (and:VM (ior:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) (not:VM (match_operand:VM 1 "altivec_register_operand" "v,v,v,v"))) (match_operand:VM 2 "altivec_register_operand" "v,v,v,v"))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -1579,11 +1939,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vnor -> vand (define_insn "*fuse_vnor_vand" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (and:VM (and:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) + (and:VM (and:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) (not:VM (match_operand:VM 1 "altivec_register_operand" "v,v,v,v"))) (match_operand:VM 2 "altivec_register_operand" "v,v,v,v"))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -1597,11 +1957,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vor -> vand (define_insn "*fuse_vor_vand" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (and:VM (ior:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") + (and:VM (ior:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 2 "altivec_register_operand" "v,v,v,v"))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -1615,11 +1975,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vorc -> vand (define_insn "*fuse_vorc_vand" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (and:VM (ior:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) + (and:VM (ior:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 2 "altivec_register_operand" "v,v,v,v"))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -1633,11 +1993,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vxor -> vand (define_insn "*fuse_vxor_vand" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (and:VM (xor:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") + (and:VM (xor:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 2 "altivec_register_operand" "v,v,v,v"))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -1651,11 +2011,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vand -> vandc (define_insn "*fuse_vand_vandc" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (and:VM (and:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") + (and:VM (and:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")) (not:VM (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -1669,11 +2029,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vandc -> vandc (define_insn "*fuse_vandc_vandc" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (and:VM (and:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) + (and:VM (and:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")) (not:VM (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -1687,11 +2047,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector veqv -> vandc (define_insn "*fuse_veqv_vandc" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (and:VM (not:VM (xor:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") + (and:VM (not:VM (xor:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") (match_operand:VM 1 "altivec_register_operand" "v,v,v,v"))) (not:VM (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -1705,11 +2065,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vnand -> vandc (define_insn "*fuse_vnand_vandc" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (and:VM (ior:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) + (and:VM (ior:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) (not:VM (match_operand:VM 1 "altivec_register_operand" "v,v,v,v"))) (not:VM (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -1723,11 +2083,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vnor -> vandc (define_insn "*fuse_vnor_vandc" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (and:VM (and:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) + (and:VM (and:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) (not:VM (match_operand:VM 1 "altivec_register_operand" "v,v,v,v"))) (not:VM (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -1741,11 +2101,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vor -> vandc (define_insn "*fuse_vor_vandc" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (and:VM (ior:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") + (and:VM (ior:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")) (not:VM (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -1759,11 +2119,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vorc -> vandc (define_insn "*fuse_vorc_vandc" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (and:VM (ior:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) + (and:VM (ior:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")) (not:VM (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -1777,11 +2137,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vxor -> vandc (define_insn "*fuse_vxor_vandc" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (and:VM (xor:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") + (and:VM (xor:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")) (not:VM (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -1795,11 +2155,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vand -> veqv (define_insn "*fuse_vand_veqv" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (not:VM (xor:VM (and:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") + (not:VM (xor:VM (and:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -1813,11 +2173,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vandc -> veqv (define_insn "*fuse_vandc_veqv" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (not:VM (xor:VM (and:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) + (not:VM (xor:VM (and:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -1831,11 +2191,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector veqv -> veqv (define_insn "*fuse_veqv_veqv" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (not:VM (xor:VM (not:VM (xor:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") + (not:VM (xor:VM (not:VM (xor:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") (match_operand:VM 1 "altivec_register_operand" "%v,v,v,v"))) (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -1849,11 +2209,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vnand -> veqv (define_insn "*fuse_vnand_veqv" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (not:VM (xor:VM (ior:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) + (not:VM (xor:VM (ior:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) (not:VM (match_operand:VM 1 "altivec_register_operand" "v,v,v,v"))) (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -1867,11 +2227,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vnor -> veqv (define_insn "*fuse_vnor_veqv" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (not:VM (xor:VM (and:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) + (not:VM (xor:VM (and:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) (not:VM (match_operand:VM 1 "altivec_register_operand" "v,v,v,v"))) (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -1885,11 +2245,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vor -> veqv (define_insn "*fuse_vor_veqv" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (not:VM (xor:VM (ior:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") + (not:VM (xor:VM (ior:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -1903,11 +2263,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vorc -> veqv (define_insn "*fuse_vorc_veqv" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (not:VM (xor:VM (ior:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) + (not:VM (xor:VM (ior:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -1921,11 +2281,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vxor -> veqv (define_insn "*fuse_vxor_veqv" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (not:VM (xor:VM (xor:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") + (not:VM (xor:VM (xor:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -1939,11 +2299,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vand -> vnand (define_insn "*fuse_vand_vnand" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (ior:VM (not:VM (and:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") + (ior:VM (not:VM (and:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") (match_operand:VM 1 "altivec_register_operand" "v,v,v,v"))) (not:VM (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -1957,11 +2317,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vandc -> vnand (define_insn "*fuse_vandc_vnand" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (ior:VM (not:VM (and:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) + (ior:VM (not:VM (and:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 1 "altivec_register_operand" "v,v,v,v"))) (not:VM (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -1975,11 +2335,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector veqv -> vnand (define_insn "*fuse_veqv_vnand" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (ior:VM (not:VM (not:VM (xor:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") + (ior:VM (not:VM (not:VM (xor:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")))) (not:VM (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -1993,11 +2353,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vnand -> vnand (define_insn "*fuse_vnand_vnand" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (ior:VM (not:VM (ior:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) + (ior:VM (not:VM (ior:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) (not:VM (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")))) (not:VM (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2011,11 +2371,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vnor -> vnand (define_insn "*fuse_vnor_vnand" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (ior:VM (not:VM (and:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) + (ior:VM (not:VM (and:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) (not:VM (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")))) (not:VM (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2029,11 +2389,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vor -> vnand (define_insn "*fuse_vor_vnand" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (ior:VM (not:VM (ior:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") + (ior:VM (not:VM (ior:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") (match_operand:VM 1 "altivec_register_operand" "v,v,v,v"))) (not:VM (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2047,11 +2407,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vorc -> vnand (define_insn "*fuse_vorc_vnand" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (ior:VM (not:VM (ior:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) + (ior:VM (not:VM (ior:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 1 "altivec_register_operand" "v,v,v,v"))) (not:VM (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2065,11 +2425,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vxor -> vnand (define_insn "*fuse_vxor_vnand" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (ior:VM (not:VM (xor:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") + (ior:VM (not:VM (xor:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") (match_operand:VM 1 "altivec_register_operand" "v,v,v,v"))) (not:VM (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2083,11 +2443,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vand -> vnor (define_insn "*fuse_vand_vnor" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (and:VM (not:VM (and:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") + (and:VM (not:VM (and:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") (match_operand:VM 1 "altivec_register_operand" "v,v,v,v"))) (not:VM (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2101,11 +2461,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vandc -> vnor (define_insn "*fuse_vandc_vnor" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (and:VM (not:VM (and:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) + (and:VM (not:VM (and:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 1 "altivec_register_operand" "v,v,v,v"))) (not:VM (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2119,11 +2479,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector veqv -> vnor (define_insn "*fuse_veqv_vnor" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (and:VM (not:VM (not:VM (xor:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") + (and:VM (not:VM (not:VM (xor:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")))) (not:VM (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2137,11 +2497,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vnand -> vnor (define_insn "*fuse_vnand_vnor" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (and:VM (not:VM (ior:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) + (and:VM (not:VM (ior:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) (not:VM (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")))) (not:VM (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2155,11 +2515,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vnor -> vnor (define_insn "*fuse_vnor_vnor" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (and:VM (not:VM (and:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) + (and:VM (not:VM (and:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) (not:VM (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")))) (not:VM (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2173,11 +2533,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vor -> vnor (define_insn "*fuse_vor_vnor" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (and:VM (not:VM (ior:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") + (and:VM (not:VM (ior:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") (match_operand:VM 1 "altivec_register_operand" "v,v,v,v"))) (not:VM (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2191,11 +2551,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vorc -> vnor (define_insn "*fuse_vorc_vnor" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (and:VM (not:VM (ior:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) + (and:VM (not:VM (ior:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 1 "altivec_register_operand" "v,v,v,v"))) (not:VM (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2209,11 +2569,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vxor -> vnor (define_insn "*fuse_vxor_vnor" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (and:VM (not:VM (xor:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") + (and:VM (not:VM (xor:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") (match_operand:VM 1 "altivec_register_operand" "v,v,v,v"))) (not:VM (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2227,11 +2587,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vand -> vor (define_insn "*fuse_vand_vor" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (ior:VM (and:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") + (ior:VM (and:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 2 "altivec_register_operand" "v,v,v,v"))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2245,11 +2605,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vandc -> vor (define_insn "*fuse_vandc_vor" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (ior:VM (and:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) + (ior:VM (and:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 2 "altivec_register_operand" "v,v,v,v"))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2263,11 +2623,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector veqv -> vor (define_insn "*fuse_veqv_vor" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (ior:VM (not:VM (xor:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") + (ior:VM (not:VM (xor:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") (match_operand:VM 1 "altivec_register_operand" "v,v,v,v"))) (match_operand:VM 2 "altivec_register_operand" "v,v,v,v"))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2281,11 +2641,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vnand -> vor (define_insn "*fuse_vnand_vor" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (ior:VM (ior:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) + (ior:VM (ior:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) (not:VM (match_operand:VM 1 "altivec_register_operand" "v,v,v,v"))) (match_operand:VM 2 "altivec_register_operand" "v,v,v,v"))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2299,11 +2659,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vnor -> vor (define_insn "*fuse_vnor_vor" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (ior:VM (and:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) + (ior:VM (and:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) (not:VM (match_operand:VM 1 "altivec_register_operand" "v,v,v,v"))) (match_operand:VM 2 "altivec_register_operand" "v,v,v,v"))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2317,11 +2677,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vor -> vor (define_insn "*fuse_vor_vor" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (ior:VM (ior:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") + (ior:VM (ior:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") (match_operand:VM 1 "altivec_register_operand" "%v,v,v,v")) (match_operand:VM 2 "altivec_register_operand" "v,v,v,v"))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2335,11 +2695,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vorc -> vor (define_insn "*fuse_vorc_vor" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (ior:VM (ior:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) + (ior:VM (ior:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 2 "altivec_register_operand" "v,v,v,v"))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2353,11 +2713,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vxor -> vor (define_insn "*fuse_vxor_vor" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (ior:VM (xor:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") + (ior:VM (xor:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 2 "altivec_register_operand" "v,v,v,v"))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2371,11 +2731,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vand -> vorc (define_insn "*fuse_vand_vorc" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (ior:VM (and:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") + (ior:VM (and:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")) (not:VM (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2389,11 +2749,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vandc -> vorc (define_insn "*fuse_vandc_vorc" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (ior:VM (and:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) + (ior:VM (and:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")) (not:VM (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2407,11 +2767,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector veqv -> vorc (define_insn "*fuse_veqv_vorc" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (ior:VM (not:VM (xor:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") + (ior:VM (not:VM (xor:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") (match_operand:VM 1 "altivec_register_operand" "v,v,v,v"))) (not:VM (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2425,11 +2785,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vnand -> vorc (define_insn "*fuse_vnand_vorc" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (ior:VM (ior:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) + (ior:VM (ior:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) (not:VM (match_operand:VM 1 "altivec_register_operand" "v,v,v,v"))) (not:VM (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2443,11 +2803,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vnor -> vorc (define_insn "*fuse_vnor_vorc" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (ior:VM (and:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) + (ior:VM (and:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) (not:VM (match_operand:VM 1 "altivec_register_operand" "v,v,v,v"))) (not:VM (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2461,11 +2821,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vor -> vorc (define_insn "*fuse_vor_vorc" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (ior:VM (ior:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") + (ior:VM (ior:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")) (not:VM (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2479,11 +2839,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vorc -> vorc (define_insn "*fuse_vorc_vorc" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (ior:VM (ior:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) + (ior:VM (ior:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")) (not:VM (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2497,11 +2857,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vxor -> vorc (define_insn "*fuse_vxor_vorc" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (ior:VM (xor:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") + (ior:VM (xor:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")) (not:VM (match_operand:VM 2 "altivec_register_operand" "v,v,v,v")))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2515,11 +2875,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vand -> vxor (define_insn "*fuse_vand_vxor" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (xor:VM (and:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") + (xor:VM (and:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 2 "altivec_register_operand" "v,v,v,v"))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2533,11 +2893,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vandc -> vxor (define_insn "*fuse_vandc_vxor" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (xor:VM (and:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) + (xor:VM (and:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 2 "altivec_register_operand" "v,v,v,v"))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2551,11 +2911,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector veqv -> vxor (define_insn "*fuse_veqv_vxor" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (xor:VM (not:VM (xor:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") + (xor:VM (not:VM (xor:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") (match_operand:VM 1 "altivec_register_operand" "v,v,v,v"))) (match_operand:VM 2 "altivec_register_operand" "v,v,v,v"))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2569,11 +2929,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vnand -> vxor (define_insn "*fuse_vnand_vxor" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (xor:VM (ior:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) + (xor:VM (ior:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) (not:VM (match_operand:VM 1 "altivec_register_operand" "v,v,v,v"))) (match_operand:VM 2 "altivec_register_operand" "v,v,v,v"))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2587,11 +2947,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vnor -> vxor (define_insn "*fuse_vnor_vxor" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (xor:VM (and:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) + (xor:VM (and:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) (not:VM (match_operand:VM 1 "altivec_register_operand" "v,v,v,v"))) (match_operand:VM 2 "altivec_register_operand" "v,v,v,v"))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2605,11 +2965,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vor -> vxor (define_insn "*fuse_vor_vxor" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (xor:VM (ior:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") + (xor:VM (ior:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 2 "altivec_register_operand" "v,v,v,v"))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2623,11 +2983,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vorc -> vxor (define_insn "*fuse_vorc_vxor" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (xor:VM (ior:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) + (xor:VM (ior:VM (not:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 1 "altivec_register_operand" "v,v,v,v")) (match_operand:VM 2 "altivec_register_operand" "v,v,v,v"))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] @@ -2641,11 +3001,11 @@ (set_attr "cost" "6") (set_attr "length" "8")]) -;; logical-logical fusion pattern generated by gen_2logical +;; logical-logical fusion pattern generated by gen_logical_addsubf ;; vector vxor -> vxor (define_insn "*fuse_vxor_vxor" [(set (match_operand:VM 3 "altivec_register_operand" "=0,1,&v,v") - (xor:VM (xor:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") + (xor:VM (xor:VM (match_operand:VM 0 "altivec_register_operand" "v,v,v,v") (match_operand:VM 1 "altivec_register_operand" "%v,v,v,v")) (match_operand:VM 2 "altivec_register_operand" "v,v,v,v"))) (clobber (match_scratch:VM 4 "=X,X,X,&r"))] diff --git a/gcc/config/rs6000/genfusion.pl b/gcc/config/rs6000/genfusion.pl index 1fd46cc..1285dd4 100755 --- a/gcc/config/rs6000/genfusion.pl +++ b/gcc/config/rs6000/genfusion.pl @@ -144,23 +144,32 @@ sub gen_ld_cmpi_p10 } } -sub gen_2logical +sub gen_logical_addsubf { my @logicals = ( "and", "andc", "eqv", "nand", "nor", "or", "orc", "xor" ); + my %logicals_addsub = ( "and"=>1, "nand"=>1, "nor"=>1, "or"=>1 ); + my @addsub = ( "add", "subf" ); + my %isaddsub = ( "add"=>1, "subf"=>1 ); my %complement = ( "and"=> 0, "andc"=> 1, "eqv"=> 0, "nand"=> 3, - "nor"=> 3, "or"=> 0, "orc"=> 1, "xor"=> 0 ); + "nor"=> 3, "or"=> 0, "orc"=> 1, "xor"=> 0, + "add"=> 0, "subf"=> 0 ); my %invert = ( "and"=> 0, "andc"=> 0, "eqv"=> 1, "nand"=> 0, - "nor"=> 0, "or"=> 0, "orc"=> 0, "xor"=> 0 ); + "nor"=> 0, "or"=> 0, "orc"=> 0, "xor"=> 0, + "add"=> 0, "subf"=> 0 ); my %commute2 = ( "and"=> 1, "andc"=> 0, "eqv"=> 1, "nand"=> 0, "nor"=> 0, "or"=> 1, "orc"=> 0, "xor"=> 1 ); my %rtlop = ( "and"=>"and", "andc"=>"and", "eqv"=>"xor", "nand"=>"ior", - "nor"=>"and", "or"=>"ior", "orc"=>"ior", "xor"=>"xor" ); + "nor"=>"and", "or"=>"ior", "orc"=>"ior", "xor"=>"xor", + "add"=>"plus", "subf"=>"minus" ); - my ($kind, $vchr, $mode, $pred, $constraint, $cr, $outer, $outer_op, - $outer_comp, $outer_inv, $outer_rtl, $inner, $inner_comp, $inner_inv, - $inner_rtl, $inner_op, $both_commute, $c4, $bc, $inner_arg0, - $inner_arg1, $inner_exp, $outer_arg2, $outer_exp, $insn, $fuse_type); + my ($kind, $vchr, $mode, $pred, $constraint, $cr, $outer, @outer_ops, + $outer_op, $outer_comp, $outer_inv, $outer_rtl, $inner, @inner_ops, + $inner_comp, $inner_inv, $inner_rtl, $inner_op, $both_commute, $c4, + $bc, $inner_arg0, $inner_arg1, $inner_exp, $outer_arg2, $outer_exp, + $target_flag, $ftype, $insn, $is_rsubf, $outer_32, $outer_42, + $outer_name, $fuse_type); KIND: foreach $kind ('scalar','vector') { + @outer_ops = @logicals; if ( $kind eq 'vector' ) { $vchr = "v"; $mode = "VM"; @@ -173,14 +182,37 @@ sub gen_2logical $pred = "gpc_reg_operand"; $constraint = "r"; $fuse_type = "fused_arith_logical"; + push (@outer_ops, @addsub); + push (@outer_ops, ( "rsubf" )); } $c4 = "${constraint},${constraint},${constraint},${constraint}"; - OUTER: foreach $outer ( @logicals ) { + OUTER: foreach $outer ( @outer_ops ) { + $outer_name = "${vchr}${outer}"; + if ( $outer eq "rsubf" ) { + $is_rsubf = 1; + $outer = "subf"; + } else { + $is_rsubf = 0; + } $outer_op = "${vchr}${outer}"; $outer_comp = $complement{$outer}; $outer_inv = $invert{$outer}; $outer_rtl = $rtlop{$outer}; - INNER: foreach $inner ( @logicals ) { + @inner_ops = @logicals; + $ftype = "logical-logical"; + $target_flag = "TARGET_P10_FUSION_2LOGICAL"; + if ( exists $isaddsub{$outer} ) { + @inner_ops = sort keys %logicals_addsub; + $ftype = "logical-add"; + $target_flag = "TARGET_P10_FUSION_LOGADD"; + } elsif ( $kind ne 'vector' && exists $logicals_addsub{$outer} ) { + push (@inner_ops, @addsub); + } + INNER: foreach $inner ( @inner_ops ) { + if ( exists $isaddsub{$inner} ) { + $ftype = "add-logical"; + $target_flag = "TARGET_P10_FUSION_ADDLOG"; + } $inner_comp = $complement{$inner}; $inner_inv = $invert{$inner}; $inner_rtl = $rtlop{$inner}; @@ -197,7 +229,7 @@ sub gen_2logical if ( ($inner_comp & 2) == 2 ) { $inner_arg1 = "(not:${mode} $inner_arg1)"; } - $inner_exp = "(${inner_rtl}:${mode} ${inner_arg0} + $inner_exp = "(${inner_rtl}:${mode} ${inner_arg0} ${inner_arg1})"; if ( $inner_inv == 1 ) { $inner_exp = "(not:${mode} $inner_exp)"; @@ -209,26 +241,35 @@ sub gen_2logical if ( ($outer_comp & 2) == 2 ) { $inner_exp = "(not:${mode} $inner_exp)"; } - $outer_exp = "(${outer_rtl}:${mode} ${inner_exp} + if ( $is_rsubf == 1 ) { + $outer_exp = "(${outer_rtl}:${mode} ${outer_arg2} + ${inner_exp})"; + $outer_32 = "%2,%3"; + $outer_42 = "%2,%4"; + } else { + $outer_exp = "(${outer_rtl}:${mode} ${inner_exp} ${outer_arg2})"; + $outer_32 = "%3,%2"; + $outer_42 = "%4,%2"; + } if ( $outer_inv == 1 ) { $outer_exp = "(not:${mode} $outer_exp)"; } $insn = <<"EOF"; -;; logical-logical fusion pattern generated by gen_2logical -;; $kind $inner_op -> $outer_op -(define_insn "*fuse_${inner_op}_${outer_op}" +;; $ftype fusion pattern generated by gen_logical_addsubf +;; $kind $inner_op -> $outer_name +(define_insn "*fuse_${inner_op}_${outer_name}" [(set (match_operand:${mode} 3 "${pred}" "=0,1,&${constraint},${constraint}") ${outer_exp}) (clobber (match_scratch:${mode} 4 "=X,X,X,&r"))] - "(TARGET_P10_FUSION && TARGET_P10_FUSION_2LOGICAL)" + "(TARGET_P10_FUSION && $target_flag)" "@ - ${inner_op} %3,%1,%0\\;${outer_op} %3,%3,%2 - ${inner_op} %3,%1,%0\\;${outer_op} %3,%3,%2 - ${inner_op} %3,%1,%0\\;${outer_op} %3,%3,%2 - ${inner_op} %4,%1,%0\\;${outer_op} %3,%4,%2" + ${inner_op} %3,%1,%0\\;${outer_op} %3,${outer_32} + ${inner_op} %3,%1,%0\\;${outer_op} %3,${outer_32} + ${inner_op} %3,%1,%0\\;${outer_op} %3,${outer_32} + ${inner_op} %4,%1,%0\\;${outer_op} %3,${outer_42}" [(set_attr "type" "$fuse_type") (set_attr "cost" "6") (set_attr "length" "8")]) @@ -284,7 +325,7 @@ EOF } gen_ld_cmpi_p10(); -gen_2logical(); +gen_logical_addsubf(); gen_addadd; exit(0); diff --git a/gcc/config/rs6000/rs6000-cpus.def b/gcc/config/rs6000/rs6000-cpus.def index d46a91d..52ce848 100644 --- a/gcc/config/rs6000/rs6000-cpus.def +++ b/gcc/config/rs6000/rs6000-cpus.def @@ -86,6 +86,8 @@ | OPTION_MASK_P10_FUSION \ | OPTION_MASK_P10_FUSION_LD_CMPI \ | OPTION_MASK_P10_FUSION_2LOGICAL \ + | OPTION_MASK_P10_FUSION_LOGADD \ + | OPTION_MASK_P10_FUSION_ADDLOG \ | OPTION_MASK_P10_FUSION_2ADD) /* Flags that need to be turned off if -mno-power9-vector. */ @@ -136,6 +138,8 @@ | OPTION_MASK_P10_FUSION \ | OPTION_MASK_P10_FUSION_LD_CMPI \ | OPTION_MASK_P10_FUSION_2LOGICAL \ + | OPTION_MASK_P10_FUSION_LOGADD \ + | OPTION_MASK_P10_FUSION_ADDLOG \ | OPTION_MASK_P10_FUSION_2ADD \ | OPTION_MASK_HTM \ | OPTION_MASK_ISEL \ diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 9f03256..835af77 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -4478,6 +4478,14 @@ rs6000_option_override_internal (bool global_init_p) rs6000_isa_flags |= OPTION_MASK_P10_FUSION_2LOGICAL; if (TARGET_POWER10 + && (rs6000_isa_flags_explicit & OPTION_MASK_P10_FUSION_LOGADD) == 0) + rs6000_isa_flags |= OPTION_MASK_P10_FUSION_LOGADD; + + if (TARGET_POWER10 + && (rs6000_isa_flags_explicit & OPTION_MASK_P10_FUSION_ADDLOG) == 0) + rs6000_isa_flags |= OPTION_MASK_P10_FUSION_ADDLOG; + + if (TARGET_POWER10 && (rs6000_isa_flags_explicit & OPTION_MASK_P10_FUSION_2ADD) == 0) rs6000_isa_flags |= OPTION_MASK_P10_FUSION_2ADD; diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt index e30dc04..0538db3 100644 --- a/gcc/config/rs6000/rs6000.opt +++ b/gcc/config/rs6000/rs6000.opt @@ -500,11 +500,19 @@ Fuse certain integer operations together for better performance on power10. mpower10-fusion-2logical Target Undocumented Mask(P10_FUSION_2LOGICAL) Var(rs6000_isa_flags) -Fuse certain integer operations together for better performance on power10. +Fuse pairs of scalar or vector logical operations together for better performance on power10. + +mpower10-fusion-logical-add +Target Undocumented Mask(P10_FUSION_LOGADD) Var(rs6000_isa_flags) +Fuse scalar logical op with add/subf for better performance on power10. + +mpower10-fusion-add-logical +Target Undocumented Mask(P10_FUSION_ADDLOG) Var(rs6000_isa_flags) +Fuse scalar add/subf with logical op for better performance on power10. mpower10-fusion-2add Target Undocumented Mask(P10_FUSION_2ADD) Var(rs6000_isa_flags) -Fuse certain add operations together for better performance on power10. +Fuse dependent pairs of add or vaddudm instructions for better performance on power10. mcrypto Target Mask(CRYPTO) Var(rs6000_isa_flags) diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 826804e..3ddeb0d 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -3415,6 +3415,12 @@ The @code{no_sanitize_undefined} attribute on functions is used to inform the compiler that it should not check for undefined behavior in the function when compiling with the @option{-fsanitize=undefined} option. +@item no_sanitize_coverage +@cindex @code{no_sanitize_coverage} function attribute +The @code{no_sanitize_coverage} attribute on functions is used +to inform the compiler that it should not do coverage-guided +fuzzing code instrumentation (@option{-fsanitize-coverage}). + @item no_split_stack @cindex @code{no_split_stack} function attribute @opindex fsplit-stack diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 0e65b3a..00caf38 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -2258,6 +2258,14 @@ Vector registers. @item z Stack pointer register (SP). + +@item Q +A memory address which uses a base register with a short offset +or with a index register with its scale. + +@item W +A memory address which uses a base register with a index register +with its scale. @end table @ifset INTERNALS diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 3be9c15..d088187 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -6016,7 +6016,7 @@ fold_range_test (location_t loc, enum tree_code code, tree type, logical_op_non_short_circuit = param_logical_op_non_short_circuit; if (logical_op_non_short_circuit - && !flag_sanitize_coverage + && !sanitize_coverage_p () && lhs != 0 && rhs != 0 && (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR) && operand_equal_p (lhs, rhs, 0)) @@ -9652,7 +9652,7 @@ fold_truth_andor (location_t loc, enum tree_code code, tree type, logical_op_non_short_circuit = param_logical_op_non_short_circuit; if (logical_op_non_short_circuit - && !flag_sanitize_coverage + && !sanitize_coverage_p () && (code == TRUTH_AND_EXPR || code == TRUTH_ANDIF_EXPR || code == TRUTH_OR_EXPR diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 5e526916..e614039 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,12 @@ +2021-05-24 Tobias Burnus <tobias@codesourcery.com> + + PR fortran/86470 + * trans-expr.c (gfc_copy_class_to_class): Add unshare_expr. + * trans-openmp.c (gfc_is_polymorphic_nonptr, + gfc_is_unlimited_polymorphic_nonptr): New. + (gfc_omp_clause_copy_ctor, gfc_omp_clause_dtor): Handle + polymorphic scalars. + 2021-05-23 Harald Anlauf <anlauf@gmx.de> PR fortran/100551 diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi index ad16413..c9049b53 100644 --- a/gcc/fortran/intrinsic.texi +++ b/gcc/fortran/intrinsic.texi @@ -6835,7 +6835,7 @@ Subroutine @item @emph{Arguments}: @multitable @columnfractions .15 .70 -@item @var{RESULT} @tab Shall of type @code{CHARACTER} and of default +@item @var{RESULT} @tab Shall be of type @code{CHARACTER} and of default kind. @end multitable @item @emph{Example}: @@ -6885,7 +6885,6 @@ Subroutine the default integer kind; @math{@var{POS} \geq 0} @item @var{VALUE} @tab Shall be of type @code{CHARACTER} and of default kind. -@item @var{VALUE} @tab Shall be of type @code{CHARACTER}. @end multitable @item @emph{Return value}: @@ -7259,7 +7258,7 @@ Subroutine @end multitable @item @emph{Return value}: -Stores the current user name in @var{LOGIN}. (On systems where POSIX +Stores the current user name in @var{C}. (On systems where POSIX functions @code{geteuid} and @code{getpwuid} are not available, and the @code{getlogin} function is not implemented either, this will return a blank string.) @@ -11202,7 +11201,7 @@ end program test_nint @table @asis @item @emph{Description}: -Calculates the Euclidean vector norm (@math{L_2} norm) of +Calculates the Euclidean vector norm (@math{L_2} norm) of @var{ARRAY} along dimension @var{DIM}. @item @emph{Standard}: @@ -11555,7 +11554,7 @@ Transformational function @item @emph{Arguments}: @multitable @columnfractions .15 .70 -@item @var{LOGICAL} @tab Shall be an array of type @code{LOGICAL} +@item @var{MASK} @tab Shall be an array of type @code{LOGICAL} @item @var{DIM} @tab (Optional) shall be a scalar of type @code{INTEGER} with a value in the range from 1 to n, where n equals the rank of @var{MASK}. @@ -12005,7 +12004,7 @@ is set to a processor-dependent value. @code{LOGICAL} type, and it is @code{INTENT(IN)}. If it is @code{.true.}, the seed is set to a processor-dependent value that is distinct from th seed set by a call to @code{RANDOM_INIT} in another image. If it is -@code{.false.}, the seed is set value that does depend which image called +@code{.false.}, the seed is set to a value that does depend which image called @code{RANDOM_INIT}. @end multitable @@ -12057,7 +12056,7 @@ Fortran 90 and later Subroutine @item @emph{Syntax}: -@code{RANDOM_NUMBER(HARVEST)} +@code{CALL RANDOM_NUMBER(HARVEST)} @item @emph{Arguments}: @multitable @columnfractions .15 .70 diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c index 3432cd4..00690fe 100644 --- a/gcc/fortran/trans-expr.c +++ b/gcc/fortran/trans-expr.c @@ -1561,7 +1561,7 @@ gfc_copy_class_to_class (tree from, tree to, tree nelems, bool unlimited) { vec_safe_push (args, from_len); vec_safe_push (args, to_len); - extcopy = build_call_vec (fcn_type, fcn, args); + extcopy = build_call_vec (fcn_type, unshare_expr (fcn), args); tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node, from_len, build_zero_cst (TREE_TYPE (from_len))); diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c index 5666cd6..44542d9 100644 --- a/gcc/fortran/trans-openmp.c +++ b/gcc/fortran/trans-openmp.c @@ -360,6 +360,39 @@ gfc_has_alloc_comps (tree type, tree decl) return false; } +/* Return true if TYPE is polymorphic but not with pointer attribute. */ + +static bool +gfc_is_polymorphic_nonptr (tree type) +{ + if (POINTER_TYPE_P (type)) + type = TREE_TYPE (type); + return GFC_CLASS_TYPE_P (type); +} + +/* Return true if TYPE is unlimited polymorphic but not with pointer attribute; + unlimited means also intrinsic types are handled and _len is used. */ + +static bool +gfc_is_unlimited_polymorphic_nonptr (tree type) +{ + if (POINTER_TYPE_P (type)) + type = TREE_TYPE (type); + if (!GFC_CLASS_TYPE_P (type)) + return false; + + tree field = TYPE_FIELDS (type); /* _data */ + gcc_assert (field); + field = DECL_CHAIN (field); /* _vptr */ + gcc_assert (field); + field = DECL_CHAIN (field); + if (!field) + return false; + gcc_assert (strcmp ("_len", IDENTIFIER_POINTER (DECL_NAME (field))) == 0); + return true; +} + + /* Return true if DECL in private clause needs OMP_CLAUSE_PRIVATE_OUTER_REF on the private clause. */ bool @@ -743,12 +776,88 @@ tree gfc_omp_clause_copy_ctor (tree clause, tree dest, tree src) { tree type = TREE_TYPE (dest), ptr, size, call; + tree decl_type = TREE_TYPE (OMP_CLAUSE_DECL (clause)); tree cond, then_b, else_b; stmtblock_t block, cond_block; gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_FIRSTPRIVATE || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR); + if (DECL_ARTIFICIAL (OMP_CLAUSE_DECL (clause)) + && DECL_LANG_SPECIFIC (OMP_CLAUSE_DECL (clause)) + && GFC_DECL_SAVED_DESCRIPTOR (OMP_CLAUSE_DECL (clause))) + decl_type + = TREE_TYPE (GFC_DECL_SAVED_DESCRIPTOR (OMP_CLAUSE_DECL (clause))); + + if (gfc_is_polymorphic_nonptr (decl_type)) + { + if (POINTER_TYPE_P (decl_type)) + decl_type = TREE_TYPE (decl_type); + decl_type = TREE_TYPE (TYPE_FIELDS (decl_type)); + if (GFC_DESCRIPTOR_TYPE_P (decl_type) || GFC_ARRAY_TYPE_P (decl_type)) + fatal_error (input_location, + "Sorry, polymorphic arrays not yet supported for " + "firstprivate"); + tree src_len; + tree nelems = build_int_cst (size_type_node, 1); /* Scalar. */ + tree src_data = gfc_class_data_get (unshare_expr (src)); + tree dest_data = gfc_class_data_get (unshare_expr (dest)); + bool unlimited = gfc_is_unlimited_polymorphic_nonptr (type); + + gfc_start_block (&block); + gfc_add_modify (&block, gfc_class_vptr_get (dest), + gfc_class_vptr_get (src)); + gfc_init_block (&cond_block); + + if (unlimited) + { + src_len = gfc_class_len_get (src); + gfc_add_modify (&cond_block, gfc_class_len_get (unshare_expr (dest)), src_len); + } + + /* Use: size = class._vtab._size * (class._len > 0 ? class._len : 1). */ + size = fold_convert (size_type_node, gfc_class_vtab_size_get (src)); + if (unlimited) + { + cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node, + unshare_expr (src_len), + build_zero_cst (TREE_TYPE (src_len))); + cond = build3_loc (input_location, COND_EXPR, size_type_node, cond, + fold_convert (size_type_node, + unshare_expr (src_len)), + build_int_cst (size_type_node, 1)); + size = fold_build2_loc (input_location, MULT_EXPR, size_type_node, + size, cond); + } + + /* Malloc memory + call class->_vpt->_copy. */ + call = builtin_decl_explicit (BUILT_IN_MALLOC); + call = build_call_expr_loc (input_location, call, 1, size); + gfc_add_modify (&cond_block, dest_data, + fold_convert (TREE_TYPE (dest_data), call)); + gfc_add_expr_to_block (&cond_block, + gfc_copy_class_to_class (src, dest, nelems, + unlimited)); + + gcc_assert (TREE_CODE (dest_data) == COMPONENT_REF); + if (!GFC_DECL_GET_SCALAR_ALLOCATABLE (TREE_OPERAND (dest_data, 1))) + { + gfc_add_block_to_block (&block, &cond_block); + } + else + { + /* Create: if (class._data != 0) <cond_block> else class._data = NULL; */ + cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, + src_data, null_pointer_node); + gfc_add_expr_to_block (&block, build3_loc (input_location, COND_EXPR, + void_type_node, cond, + gfc_finish_block (&cond_block), + fold_build2_loc (input_location, MODIFY_EXPR, void_type_node, + unshare_expr (dest_data), null_pointer_node))); + } + return gfc_finish_block (&block); + } + if ((! GFC_DESCRIPTOR_TYPE_P (type) || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE) && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause)) @@ -773,7 +882,7 @@ gfc_omp_clause_copy_ctor (tree clause, tree dest, tree src) gfc_init_block (&cond_block); - gfc_add_modify (&cond_block, dest, src); + gfc_add_modify (&cond_block, dest, fold_convert (TREE_TYPE (dest), src)); if (GFC_DESCRIPTOR_TYPE_P (type)) { tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1]; @@ -1185,6 +1294,57 @@ tree gfc_omp_clause_dtor (tree clause, tree decl) { tree type = TREE_TYPE (decl), tem; + tree decl_type = TREE_TYPE (OMP_CLAUSE_DECL (clause)); + + if (DECL_ARTIFICIAL (OMP_CLAUSE_DECL (clause)) + && DECL_LANG_SPECIFIC (OMP_CLAUSE_DECL (clause)) + && GFC_DECL_SAVED_DESCRIPTOR (OMP_CLAUSE_DECL (clause))) + decl_type + = TREE_TYPE (GFC_DECL_SAVED_DESCRIPTOR (OMP_CLAUSE_DECL (clause))); + if (gfc_is_polymorphic_nonptr (decl_type)) + { + if (POINTER_TYPE_P (decl_type)) + decl_type = TREE_TYPE (decl_type); + decl_type = TREE_TYPE (TYPE_FIELDS (decl_type)); + if (GFC_DESCRIPTOR_TYPE_P (decl_type) || GFC_ARRAY_TYPE_P (decl_type)) + fatal_error (input_location, + "Sorry, polymorphic arrays not yet supported for " + "firstprivate"); + stmtblock_t block, cond_block; + gfc_start_block (&block); + gfc_init_block (&cond_block); + tree final = gfc_class_vtab_final_get (decl); + tree size = fold_convert (size_type_node, gfc_class_vtab_size_get (decl)); + gfc_se se; + gfc_init_se (&se, NULL); + symbol_attribute attr = {}; + tree data = gfc_class_data_get (decl); + tree desc = gfc_conv_scalar_to_descriptor (&se, data, attr); + + /* Call class->_vpt->_finalize + free. */ + tree call = build_fold_indirect_ref (final); + call = build_call_expr_loc (input_location, call, 3, + gfc_build_addr_expr (NULL, desc), + size, boolean_false_node); + gfc_add_block_to_block (&cond_block, &se.pre); + gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call)); + gfc_add_block_to_block (&cond_block, &se.post); + /* Create: if (_vtab && _final) <cond_block> */ + tree cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, + gfc_class_vptr_get (decl), + null_pointer_node); + tree cond2 = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, + final, null_pointer_node); + cond = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR, + boolean_type_node, cond, cond2); + gfc_add_expr_to_block (&block, build3_loc (input_location, COND_EXPR, + void_type_node, cond, + gfc_finish_block (&cond_block), NULL_TREE)); + call = builtin_decl_explicit (BUILT_IN_FREE); + call = build_call_expr_loc (input_location, call, 1, data); + gfc_add_expr_to_block (&block, fold_convert (void_type_node, call)); + return gfc_finish_block (&block); + } if ((! GFC_DESCRIPTOR_TYPE_P (type) || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE) diff --git a/gcc/gimple-expr.c b/gcc/gimple-expr.c index b8c732b..c321179 100644 --- a/gcc/gimple-expr.c +++ b/gcc/gimple-expr.c @@ -900,6 +900,8 @@ flush_mark_addressable_queue () void mark_addressable (tree x) { + if (TREE_CODE (x) == WITH_SIZE_EXPR) + x = TREE_OPERAND (x, 0); while (handled_component_p (x)) x = TREE_OPERAND (x, 0); if (TREE_CODE (x) == MEM_REF diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog index 85bd343..7cc756b 100644 --- a/gcc/go/ChangeLog +++ b/gcc/go/ChangeLog @@ -1,3 +1,9 @@ +2021-05-24 Ian Lance Taylor <iant@golang.org> + + PR go/100537 + * go-gcc.cc (class Gcc_backend): Update methods that create + variables to take a flags parameter. + 2021-01-28 Ian Lance Taylor <iant@golang.org> * gospec.c (lang_specific_driver): Add -g if no debugging options diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc index 5d9dbb5..41f309e 100644 --- a/gcc/go/go-gcc.cc +++ b/gcc/go/go-gcc.cc @@ -415,47 +415,46 @@ class Gcc_backend : public Backend global_variable(const std::string& var_name, const std::string& asm_name, Btype* btype, - bool is_external, - bool is_hidden, - bool in_unique_section, + unsigned int flags, Location location); void global_variable_set_init(Bvariable*, Bexpression*); Bvariable* - local_variable(Bfunction*, const std::string&, Btype*, Bvariable*, bool, - Location); + local_variable(Bfunction*, const std::string&, Btype*, Bvariable*, + unsigned int, Location); Bvariable* - parameter_variable(Bfunction*, const std::string&, Btype*, bool, + parameter_variable(Bfunction*, const std::string&, Btype*, unsigned int, Location); Bvariable* - static_chain_variable(Bfunction*, const std::string&, Btype*, Location); + static_chain_variable(Bfunction*, const std::string&, Btype*, unsigned int, + Location); Bvariable* - temporary_variable(Bfunction*, Bblock*, Btype*, Bexpression*, bool, + temporary_variable(Bfunction*, Bblock*, Btype*, Bexpression*, unsigned int, Location, Bstatement**); Bvariable* implicit_variable(const std::string&, const std::string&, Btype*, - bool, bool, bool, int64_t); + unsigned int, int64_t); void implicit_variable_set_init(Bvariable*, const std::string&, Btype*, - bool, bool, bool, Bexpression*); + unsigned int, Bexpression*); Bvariable* implicit_variable_reference(const std::string&, const std::string&, Btype*); Bvariable* immutable_struct(const std::string&, const std::string&, - bool, bool, Btype*, Location); + unsigned int, Btype*, Location); void - immutable_struct_set_init(Bvariable*, const std::string&, bool, bool, Btype*, - Location, Bexpression*); + immutable_struct_set_init(Bvariable*, const std::string&, unsigned int, + Btype*, Location, Bexpression*); Bvariable* immutable_struct_reference(const std::string&, const std::string&, @@ -2696,9 +2695,7 @@ Bvariable* Gcc_backend::global_variable(const std::string& var_name, const std::string& asm_name, Btype* btype, - bool is_external, - bool is_hidden, - bool in_unique_section, + unsigned int flags, Location location) { tree type_tree = btype->get_tree(); @@ -2707,30 +2704,49 @@ Gcc_backend::global_variable(const std::string& var_name, // The GNU linker does not like dynamic variables with zero size. tree orig_type_tree = type_tree; + bool is_external = (flags & variable_is_external) != 0; + bool is_hidden = (flags & variable_is_hidden) != 0; if ((is_external || !is_hidden) && int_size_in_bytes(type_tree) == 0) type_tree = this->non_zero_size_type(type_tree); tree decl = build_decl(location.gcc_location(), VAR_DECL, get_identifier_from_string(var_name), type_tree); - if (is_external) - DECL_EXTERNAL(decl) = 1; - else - TREE_STATIC(decl) = 1; - if (!is_hidden) + if ((flags & variable_is_external) != 0) { - TREE_PUBLIC(decl) = 1; - SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name)); + DECL_EXTERNAL(decl) = 1; + flags &=~ variable_is_external; } else + TREE_STATIC(decl) = 1; + + if ((flags & variable_is_hidden) == 0) + TREE_PUBLIC(decl) = 1; + else + flags &=~ variable_is_hidden; + + if ((flags & variable_address_is_taken) != 0) { - SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name)); + TREE_ADDRESSABLE(decl) = 1; + flags &=~ variable_address_is_taken; } + // We take the address in Bvariable::get_tree if orig_type_tree is + // different from type_tree. + if (orig_type_tree != type_tree) + TREE_ADDRESSABLE(decl) = 1; + + SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name)); + TREE_USED(decl) = 1; - if (in_unique_section) - resolve_unique_section (decl, 0, 1); + if ((flags & variable_in_unique_section) != 0) + { + resolve_unique_section (decl, 0, 1); + flags &=~ variable_in_unique_section; + } + + gcc_assert(flags == 0); go_preserve_from_gc(decl); @@ -2768,7 +2784,7 @@ Gcc_backend::global_variable_set_init(Bvariable* var, Bexpression* expr) Bvariable* Gcc_backend::local_variable(Bfunction* function, const std::string& name, Btype* btype, Bvariable* decl_var, - bool is_address_taken, Location location) + unsigned int flags, Location location) { tree type_tree = btype->get_tree(); if (type_tree == error_mark_node) @@ -2778,13 +2794,17 @@ Gcc_backend::local_variable(Bfunction* function, const std::string& name, type_tree); DECL_CONTEXT(decl) = function->get_tree(); TREE_USED(decl) = 1; - if (is_address_taken) - TREE_ADDRESSABLE(decl) = 1; + if ((flags & variable_address_is_taken) != 0) + { + TREE_ADDRESSABLE(decl) = 1; + flags &=~ variable_address_is_taken; + } if (decl_var != NULL) { DECL_HAS_VALUE_EXPR_P(decl) = 1; SET_DECL_VALUE_EXPR(decl, decl_var->get_decl()); } + go_assert(flags == 0); go_preserve_from_gc(decl); return new Bvariable(decl); } @@ -2793,7 +2813,7 @@ Gcc_backend::local_variable(Bfunction* function, const std::string& name, Bvariable* Gcc_backend::parameter_variable(Bfunction* function, const std::string& name, - Btype* btype, bool is_address_taken, + Btype* btype, unsigned int flags, Location location) { tree type_tree = btype->get_tree(); @@ -2805,8 +2825,12 @@ Gcc_backend::parameter_variable(Bfunction* function, const std::string& name, DECL_CONTEXT(decl) = function->get_tree(); DECL_ARG_TYPE(decl) = type_tree; TREE_USED(decl) = 1; - if (is_address_taken) - TREE_ADDRESSABLE(decl) = 1; + if ((flags & variable_address_is_taken) != 0) + { + TREE_ADDRESSABLE(decl) = 1; + flags &=~ variable_address_is_taken; + } + go_assert(flags == 0); go_preserve_from_gc(decl); return new Bvariable(decl); } @@ -2815,7 +2839,8 @@ Gcc_backend::parameter_variable(Bfunction* function, const std::string& name, Bvariable* Gcc_backend::static_chain_variable(Bfunction* function, const std::string& name, - Btype* btype, Location location) + Btype* btype, unsigned int flags, + Location location) { tree type_tree = btype->get_tree(); if (type_tree == error_mark_node) @@ -2840,6 +2865,7 @@ Gcc_backend::static_chain_variable(Bfunction* function, const std::string& name, gcc_assert(f->static_chain_decl == NULL); f->static_chain_decl = decl; DECL_STATIC_CHAIN(fndecl) = 1; + go_assert(flags == 0); go_preserve_from_gc(decl); return new Bvariable(decl); @@ -2850,7 +2876,7 @@ Gcc_backend::static_chain_variable(Bfunction* function, const std::string& name, Bvariable* Gcc_backend::temporary_variable(Bfunction* function, Bblock* bblock, Btype* btype, Bexpression* binit, - bool is_address_taken, + unsigned int flags, Location location, Bstatement** pstatement) { @@ -2904,8 +2930,13 @@ Gcc_backend::temporary_variable(Bfunction* function, Bblock* bblock, && TREE_TYPE(init_tree) != void_type_node) DECL_INITIAL(var) = this->convert_tree(type_tree, init_tree, location); - if (is_address_taken) - TREE_ADDRESSABLE(var) = 1; + if ((flags & variable_address_is_taken) != 0) + { + TREE_ADDRESSABLE(var) = 1; + flags &=~ variable_address_is_taken; + } + + gcc_assert(flags == 0); *pstatement = this->make_statement(build1_loc(location.gcc_location(), DECL_EXPR, @@ -2929,8 +2960,8 @@ Gcc_backend::temporary_variable(Bfunction* function, Bblock* bblock, Bvariable* Gcc_backend::implicit_variable(const std::string& name, const std::string& asm_name, - Btype* type, bool is_hidden, bool is_constant, - bool is_common, int64_t alignment) + Btype* type, unsigned int flags, + int64_t alignment) { tree type_tree = type->get_tree(); if (type_tree == error_mark_node) @@ -2939,11 +2970,14 @@ Gcc_backend::implicit_variable(const std::string& name, tree decl = build_decl(BUILTINS_LOCATION, VAR_DECL, get_identifier_from_string(name), type_tree); DECL_EXTERNAL(decl) = 0; - TREE_PUBLIC(decl) = !is_hidden; + if ((flags & variable_is_hidden) != 0) + flags &=~ variable_is_hidden; + else + TREE_PUBLIC(decl) = 1; TREE_STATIC(decl) = 1; TREE_USED(decl) = 1; DECL_ARTIFICIAL(decl) = 1; - if (is_common) + if ((flags & variable_is_common) != 0) { DECL_COMMON(decl) = 1; @@ -2960,11 +2994,19 @@ Gcc_backend::implicit_variable(const std::string& name, // mark this symbol as weak here. We undo that below in // immutable_struct_set_init before calling mark_decl_one_only. DECL_WEAK(decl) = 1; + + flags &=~ variable_is_common; } - if (is_constant) + if ((flags & variable_is_constant) != 0) { TREE_READONLY(decl) = 1; TREE_CONSTANT(decl) = 1; + flags &=~ variable_is_constant; + } + if ((flags & variable_address_is_taken) != 0) + { + TREE_ADDRESSABLE(decl) = 1; + flags &=~ variable_address_is_taken; } if (alignment != 0) { @@ -2973,6 +3015,7 @@ Gcc_backend::implicit_variable(const std::string& name, } if (! asm_name.empty()) SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name)); + gcc_assert(flags == 0); go_preserve_from_gc(decl); return new Bvariable(decl); @@ -2983,7 +3026,7 @@ Gcc_backend::implicit_variable(const std::string& name, void Gcc_backend::implicit_variable_set_init(Bvariable* var, const std::string&, - Btype*, bool, bool, bool is_common, + Btype*, unsigned int flags, Bexpression* init) { tree decl = var->get_decl(); @@ -2999,7 +3042,7 @@ Gcc_backend::implicit_variable_set_init(Bvariable* var, const std::string&, // Now that DECL_INITIAL is set, we can't call make_decl_one_only. // See the comment where DECL_WEAK is set in implicit_variable. - if (is_common) + if ((flags & variable_is_common) != 0) { DECL_WEAK(decl) = 0; make_decl_one_only(decl, DECL_ASSEMBLER_NAME(decl)); @@ -3038,8 +3081,8 @@ Gcc_backend::implicit_variable_reference(const std::string& name, Bvariable* Gcc_backend::immutable_struct(const std::string& name, const std::string& asm_name, - bool is_hidden, - bool is_common, Btype* btype, Location location) + unsigned int flags, Btype* btype, + Location location) { tree type_tree = btype->get_tree(); if (type_tree == error_mark_node) @@ -3053,10 +3096,17 @@ Gcc_backend::immutable_struct(const std::string& name, TREE_READONLY(decl) = 1; TREE_CONSTANT(decl) = 1; DECL_ARTIFICIAL(decl) = 1; - if (!is_hidden) + if ((flags & variable_is_hidden) != 0) + flags &=~ variable_is_hidden; + else TREE_PUBLIC(decl) = 1; if (! asm_name.empty()) SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name)); + if ((flags & variable_address_is_taken) != 0) + { + TREE_ADDRESSABLE(decl) = 1; + flags &=~ variable_address_is_taken; + } // When the initializer for one immutable_struct refers to another, // it needs to know the visibility of the referenced struct so that @@ -3070,8 +3120,13 @@ Gcc_backend::immutable_struct(const std::string& name, // the right value if some other initializer refers to this one, we // mark this symbol as weak here. We undo that below in // immutable_struct_set_init before calling mark_decl_one_only. - if (is_common) - DECL_WEAK(decl) = 1; + if ((flags & variable_is_common) != 0) + { + DECL_WEAK(decl) = 1; + flags &=~ variable_is_common; + } + + gcc_assert(flags == 0); // We don't call rest_of_decl_compilation until we have the // initializer. @@ -3085,7 +3140,7 @@ Gcc_backend::immutable_struct(const std::string& name, void Gcc_backend::immutable_struct_set_init(Bvariable* var, const std::string&, - bool, bool is_common, Btype*, Location, + unsigned int flags, Btype*, Location, Bexpression* initializer) { tree decl = var->get_decl(); @@ -3097,7 +3152,7 @@ Gcc_backend::immutable_struct_set_init(Bvariable* var, const std::string&, // Now that DECL_INITIAL is set, we can't call make_decl_one_only. // See the comment where DECL_WEAK is set in immutable_struct. - if (is_common) + if ((flags & variable_is_common) != 0) { DECL_WEAK(decl) = 0; make_decl_one_only(decl, DECL_ASSEMBLER_NAME(decl)); diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 373b58c..1f38c911 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -38228e7a91d37588463307ec60420c8f17f1aee4 +5a801b15699cced5203af5c7339b375cd55ecbac The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/go/gofrontend/backend.h b/gcc/go/gofrontend/backend.h index c5b5d8f..5b6ffea 100644 --- a/gcc/go/gofrontend/backend.h +++ b/gcc/go/gofrontend/backend.h @@ -481,24 +481,51 @@ class Backend virtual Bvariable* error_variable() = 0; + // Bit flags to pass to the various methods that return Bvariable*. + // Not all flags are meaningful for all methods. + + // Set if the variable's address is taken. For a local variable + // this implies that the address does not escape the function, as + // otherwise the variable would be on the heap. + static const unsigned int variable_address_is_taken = 1 << 0; + + // Set if the variable is defined in some other package. Only + // meaningful for the global_variable method. At most one of + // is_external, is_hidden, and is_common may be set. + static const unsigned int variable_is_external = 1 << 1; + + // Set if the variable is not exported, and as such is only defined + // in the current package. Only meaningful for global_variable, + // implicit_variable, and immutable_struct. At most one of + // is_external, is_hidden, and is_common may be set. + static const unsigned variable_is_hidden = 1 << 2; + + // Set if the variable should be treated as a common variable: + // multiple definitions with different sizes permitted in different + // object files, all merged into the largest definition at link + // time. Only meaningful for implicit_variable and immutable_struct. + // At most one of is_external, is_hidden, and is_common may be set. + static const unsigned int variable_is_common = 1 << 3; + + // Set if the variable should be put into a unique section if + // possible; this is intended to permit the linker to garbage + // collect the value if it is not referenced. Only meaningful for + // global_variable. + static const unsigned int variable_in_unique_section = 1 << 4; + + // Set if the variable should be treated as immutable. Only + // meaningful for implicit_variable. For example, this is set for + // slice initializers if the values must be copied to the heap. + static const unsigned int variable_is_constant = 1 << 5; + // Create a global variable. NAME is the package-qualified name of // the variable. ASM_NAME is the encoded identifier for the // variable, incorporating the package, and made safe for the - // assembler. BTYPE is the type of the variable. IS_EXTERNAL is - // true if the variable is defined in some other package. IS_HIDDEN - // is true if the variable is not exported (name begins with a lower - // case letter). IN_UNIQUE_SECTION is true if the variable should - // be put into a unique section if possible; this is intended to - // permit the linker to garbage collect the variable if it is not - // referenced. LOCATION is where the variable was defined. + // assembler. BTYPE is the type of the variable. FLAGS is the bit + // flags defined above. LOCATION is where the variable was defined. virtual Bvariable* - global_variable(const std::string& name, - const std::string& asm_name, - Btype* btype, - bool is_external, - bool is_hidden, - bool in_unique_section, - Location location) = 0; + global_variable(const std::string& name, const std::string& asm_name, + Btype* btype, unsigned int flags, Location location) = 0; // A global variable will 1) be initialized to zero, or 2) be // initialized to a constant value, or 3) be initialized in the init @@ -516,42 +543,40 @@ class Backend // null, gives the location at which the value of this variable may // be found, typically used to create an inner-scope reference to an // outer-scope variable, to extend the lifetime of the variable beyond - // the inner scope. IS_ADDRESS_TAKEN is true if the address of this - // variable is taken (this implies that the address does not escape - // the function, as otherwise the variable would be on the heap). + // the inner scope. FLAGS is the bit flags defined above. // LOCATION is where the variable is defined. For each local variable // the frontend will call init_statement to set the initial value. virtual Bvariable* local_variable(Bfunction* function, const std::string& name, Btype* type, - Bvariable* decl_var, bool is_address_taken, Location location) = 0; + Bvariable* decl_var, unsigned int flags, + Location location) = 0; // Create a function parameter. This is an incoming parameter, not // a result parameter (result parameters are treated as local // variables). The arguments are as for local_variable. virtual Bvariable* parameter_variable(Bfunction* function, const std::string& name, - Btype* type, bool is_address_taken, - Location location) = 0; + Btype* type, unsigned int flags, Location location) = 0; // Create a static chain parameter. This is the closure parameter. virtual Bvariable* static_chain_variable(Bfunction* function, const std::string& name, - Btype* type, Location location) = 0; + Btype* type, unsigned int flags, + Location location) = 0; // Create a temporary variable. A temporary variable has no name, // just a type. We pass in FUNCTION and BLOCK in case they are // needed. If INIT is not NULL, the variable should be initialized // to that value. Otherwise the initial value is irrelevant--the // backend does not have to explicitly initialize it to zero. - // ADDRESS_IS_TAKEN is true if the programs needs to take the - // address of this temporary variable. LOCATION is the location of + // FLAGS is the bit flags defined above. LOCATION is the location of // the statement or expression which requires creating the temporary // variable, and may not be very useful. This function should // return a variable which can be referenced later and should set // *PSTATEMENT to a statement which initializes the variable. virtual Bvariable* temporary_variable(Bfunction*, Bblock*, Btype*, Bexpression* init, - bool address_is_taken, Location location, + unsigned int flags, Location location, Bstatement** pstatement) = 0; // Create an implicit variable that is compiler-defined. This is @@ -566,46 +591,33 @@ class Backend // // TYPE is the type of the implicit variable. // - // IS_HIDDEN will be true if the descriptor should only be visible - // within the current object. - // - // IS_CONSTANT is true if the implicit variable should be treated like it is - // immutable. For slice initializers, if the values must be copied to the - // heap, the variable IS_CONSTANT. - // - // IS_COMMON is true if the implicit variable should - // be treated as a common variable (multiple definitions with - // different sizes permitted in different object files, all merged - // into the largest definition at link time); this will be true for - // the zero value. IS_HIDDEN and IS_COMMON will never both be true. + // FLAGS is the bit flags defined above. // // If ALIGNMENT is not zero, it is the desired alignment of the variable. virtual Bvariable* implicit_variable(const std::string& name, const std::string& asm_name, - Btype* type, bool is_hidden, bool is_constant, - bool is_common, int64_t alignment) = 0; + Btype* type, unsigned int flags, int64_t alignment) = 0; // Set the initial value of a variable created by implicit_variable. // This must be called even if there is no initializer, i.e., INIT is NULL. - // The NAME, TYPE, IS_HIDDEN, IS_CONSTANT, and IS_COMMON parameters are - // the same ones passed to implicit_variable. INIT will be a composite - // literal of type TYPE. It will not contain any function calls or anything - // else that can not be put into a read-only data section. - // It may contain the address of variables created by implicit_variable. + // The NAME, TYPE, and FLAGS parameters are the same ones passed to + // implicit_variable. INIT will be a composite literal of type + // TYPE. It will not contain any function calls or anything else + // that can not be put into a read-only data section. It may + // contain the address of variables created by implicit_variable. // - // If IS_COMMON is true, INIT will be NULL, and the + // If variable_is_common is set in FLAGS, INIT will be NULL, and the // variable should be initialized to all zeros. virtual void implicit_variable_set_init(Bvariable*, const std::string& name, Btype* type, - bool is_hidden, bool is_constant, bool is_common, - Bexpression* init) = 0; + unsigned int flags, Bexpression* init) = 0; // Create a reference to a named implicit variable defined in some // other package. This will be a variable created by a call to // implicit_variable with the same NAME, ASM_NAME and TYPE and with - // IS_COMMON passed as false. This corresponds to an extern global - // variable in C. + // variable_is_common not set in FLAGS. This corresponds to an + // extern global variable in C. virtual Bvariable* implicit_variable_reference(const std::string& name, const std::string& asm_name, @@ -622,15 +634,12 @@ class Backend // ASM_NAME is the encoded, assembler-friendly version of NAME, or // the empty string if no encoding is needed. // - // IS_HIDDEN will be true if the descriptor should only be visible - // within the current object. - // - // IS_COMMON is true if NAME may be defined by several packages, and - // the linker should merge all such definitions. If IS_COMMON is - // false, NAME should be defined in only one file. In general - // IS_COMMON will be true for the type descriptor of an unnamed type - // or a builtin type. IS_HIDDEN and IS_COMMON will never both be - // true. + // FLAGS is the bit flags defined above. The variable_is_common + // flag will be set if NAME may be defined by several packages, and + // the linker should merge all such definitions. If the + // variable_is_common flag is not set, NAME should be defined in + // only one file. In general variable_is_common will be set for the + // type descriptor of an unnamed type or a builtin type. // // TYPE will be a struct type; the type of the returned expression // must be a pointer to this struct type. @@ -640,28 +649,26 @@ class Backend // address. After calling this the frontend will call // immutable_struct_set_init. virtual Bvariable* - immutable_struct(const std::string& name, - const std::string& asm_name, - bool is_hidden, bool is_common, - Btype* type, Location) = 0; + immutable_struct(const std::string& name, const std::string& asm_name, + unsigned int flags, Btype* type, Location) = 0; // Set the initial value of a variable created by immutable_struct. - // The NAME, IS_HIDDEN, IS_COMMON, TYPE, and location parameters are - // the same ones passed to immutable_struct. INITIALIZER will be a - // composite literal of type TYPE. It will not contain any function - // calls or anything else that can not be put into a read-only data - // section. It may contain the address of variables created by + // The NAME, FLAGS, TYPE, and location parameters are the same ones + // passed to immutable_struct. INITIALIZER will be a composite + // literal of type TYPE. It will not contain any function calls or + // anything else that can not be put into a read-only data section. + // It may contain the address of variables created by // immutable_struct. virtual void immutable_struct_set_init(Bvariable*, const std::string& name, - bool is_hidden, bool is_common, Btype* type, + unsigned int flags, Btype* type, Location, Bexpression* initializer) = 0; // Create a reference to a named immutable initialized data // structure defined in some other package. This will be a // structure created by a call to immutable_struct with the same - // NAME, ASM_NAME and TYPE and with IS_COMMON passed as false. This - // corresponds to an extern const global variable in C. + // NAME, ASM_NAME and TYPE and with variable_is_common not set in + // flags. This corresponds to an extern const global variable in C. virtual Bvariable* immutable_struct_reference(const std::string& name, const std::string& asm_name, diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 5409d26..5d45e4b 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -1427,7 +1427,7 @@ Sink_expression::do_get_backend(Translate_context* context) Bstatement* decl; this->bvar_ = gogo->backend()->temporary_variable(fn_ctx, context->bblock(), bt, NULL, - false, loc, &decl); + 0, loc, &decl); Bexpression* var_ref = gogo->backend()->var_expression(this->bvar_, loc); var_ref = gogo->backend()->compound_expression(decl, var_ref, loc); @@ -1724,10 +1724,12 @@ Func_descriptor_expression::do_get_backend(Translate_context* context) if (no->is_function() && no->func_value()->is_referenced_by_inline()) is_hidden = false; + unsigned int flags = 0; + if (is_hidden) + flags |= Backend::variable_is_hidden; bvar = context->backend()->immutable_struct(bname.name(), bname.optional_asm_name(), - is_hidden, false, - btype, bloc); + flags, btype, bloc); Expression_list* vals = new Expression_list(); vals->push_back(Expression::make_func_code_reference(this->fn_, bloc)); Expression* init = @@ -1736,8 +1738,7 @@ Func_descriptor_expression::do_get_backend(Translate_context* context) bcontext.set_is_const(); Bexpression* binit = init->get_backend(&bcontext); context->backend()->immutable_struct_set_init(bvar, bname.name(), - is_hidden, false, btype, - bloc, binit); + flags, btype, bloc, binit); } this->dvar_ = bvar; @@ -5280,12 +5281,14 @@ Unary_expression::do_get_backend(Translate_context* context) copy_to_heap = (context->function() != NULL || context->is_const()); } + unsigned int flags = (Backend::variable_is_hidden + | Backend::variable_address_is_taken); + if (copy_to_heap) + flags |= Backend::variable_is_constant; Bvariable* implicit = - gogo->backend()->implicit_variable(var_name, "", btype, true, - copy_to_heap, false, 0); + gogo->backend()->implicit_variable(var_name, "", btype, flags, 0); gogo->backend()->implicit_variable_set_init(implicit, var_name, btype, - true, copy_to_heap, false, - bexpr); + flags, bexpr); bexpr = gogo->backend()->var_expression(implicit, loc); // If we are not copying a slice initializer to the heap, @@ -5307,22 +5310,24 @@ Unary_expression::do_get_backend(Translate_context* context) && this->expr_->is_static_initializer()) { std::string var_name(gogo->initializer_name()); + unsigned int flags = (Backend::variable_is_hidden + | Backend::variable_address_is_taken); Bvariable* decl = - gogo->backend()->immutable_struct(var_name, "", true, false, - btype, loc); - gogo->backend()->immutable_struct_set_init(decl, var_name, true, - false, btype, loc, bexpr); + gogo->backend()->immutable_struct(var_name, "", flags, btype, loc); + gogo->backend()->immutable_struct_set_init(decl, var_name, flags, + btype, loc, bexpr); bexpr = gogo->backend()->var_expression(decl, loc); } else if (this->expr_->is_constant()) { std::string var_name(gogo->initializer_name()); + unsigned int flags = (Backend::variable_is_hidden + | Backend::variable_is_constant + | Backend::variable_address_is_taken); Bvariable* decl = - gogo->backend()->implicit_variable(var_name, "", btype, - true, true, false, 0); + gogo->backend()->implicit_variable(var_name, "", btype, flags, 0); gogo->backend()->implicit_variable_set_init(decl, var_name, btype, - true, true, false, - bexpr); + flags, bexpr); bexpr = gogo->backend()->var_expression(decl, loc); } @@ -14888,7 +14893,9 @@ Allocation_expression::do_get_backend(Translate_context* context) : gogo->backend()->zero_expression(btype)); Bvariable* temp = gogo->backend()->temporary_variable(fndecl, context->bblock(), btype, - init, true, loc, &decl); + init, + Backend::variable_address_is_taken, + loc, &decl); Bexpression* ret = gogo->backend()->var_expression(temp, loc); ret = gogo->backend()->address_expression(ret, loc); ret = gogo->backend()->compound_expression(decl, ret, loc); @@ -17238,7 +17245,9 @@ Heap_expression::do_get_backend(Translate_context* context) Bfunction* fndecl = fn->func_value()->get_or_make_decl(gogo, fn); Bvariable* space_temp = gogo->backend()->temporary_variable(fndecl, context->bblock(), btype, - space, true, loc, &decl); + space, + Backend::variable_address_is_taken, + loc, &decl); Btype* expr_btype = etype->get_backend(gogo); Bexpression* bexpr = this->expr_->get_backend(context); @@ -17259,8 +17268,9 @@ Heap_expression::do_get_backend(Translate_context* context) Bstatement* edecl; Bvariable* btemp = gogo->backend()->temporary_variable(fndecl, context->bblock(), - expr_btype, bexpr, true, loc, - &edecl); + expr_btype, bexpr, + Backend::variable_address_is_taken, + loc, &edecl); Bexpression* btempref = gogo->backend()->var_expression(btemp, loc); space = gogo->backend()->var_expression(space_temp, loc); @@ -18478,10 +18488,13 @@ Interface_mtable_expression::do_get_backend(Translate_context* context) Bexpression* ctor = gogo->backend()->constructor_expression(btype, ctor_bexprs, loc); - this->bvar_ = gogo->backend()->immutable_struct(mangled_name, "", false, - !is_public, btype, loc); - gogo->backend()->immutable_struct_set_init(this->bvar_, mangled_name, false, - !is_public, btype, loc, ctor); + unsigned int flags = 0; + if (!is_public) + flags |= Backend::variable_is_hidden; + this->bvar_ = gogo->backend()->immutable_struct(mangled_name, "", flags, + btype, loc); + gogo->backend()->immutable_struct_set_init(this->bvar_, mangled_name, flags, + btype, loc, ctor); return gogo->backend()->var_expression(this->bvar_, loc); } diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index 93b54fd..2872d2e 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -918,9 +918,8 @@ Gogo::build_type_descriptor_list() // Create the variable std::string name = this->type_descriptor_list_symbol(this->pkgpath_symbol()); - Bvariable* bv = this->backend()->implicit_variable(name, name, bt, - false, true, false, - 0); + unsigned int flags = Backend::variable_is_constant; + Bvariable* bv = this->backend()->implicit_variable(name, name, bt, flags, 0); // Build the initializer std::vector<unsigned long> indexes; @@ -946,8 +945,7 @@ Gogo::build_type_descriptor_list() Bexpression* binit = this->backend()->constructor_expression(bt, fields, builtin_loc); - this->backend()->implicit_variable_set_init(bv, name, bt, false, - true, false, binit); + this->backend()->implicit_variable_set_init(bv, name, bt, flags, binit); } // Register the type descriptors with the runtime. This is to help @@ -1002,11 +1000,11 @@ Gogo::register_type_descriptors(std::vector<Bstatement*>& init_stmts, // Create a variable holding the list. std::string name = this->typelists_symbol(); - Bvariable* bv = this->backend()->implicit_variable(name, name, bat, - true, true, false, + unsigned int flags = (Backend::variable_is_hidden + | Backend::variable_is_constant); + Bvariable* bv = this->backend()->implicit_variable(name, name, bat, flags, 0); - this->backend()->implicit_variable_set_init(bv, name, bat, true, true, - false, barray); + this->backend()->implicit_variable_set_init(bv, name, bat, flags, barray); // Build the call in main package's init function. Translate_context context(this, NULL, NULL, NULL); @@ -8062,16 +8060,24 @@ Variable::get_backend_variable(Gogo* gogo, Named_object* function, if (package != NULL) is_hidden = false; + unsigned int flags = 0; + if (this->is_address_taken_ + || this->is_non_escaping_address_taken_) + flags |= Backend::variable_address_is_taken; + if (package != NULL) + flags |= Backend::variable_is_external; + if (is_hidden) + flags |= Backend::variable_is_hidden; + if (this->in_unique_section_) + flags |= Backend::variable_in_unique_section; + // For some reason asm_name can't be the empty string // for global_variable, so we call asm_name rather than // optional_asm_name here. FIXME. bvar = backend->global_variable(bname.name(), bname.asm_name(), - btype, - package != NULL, - is_hidden, - this->in_unique_section_, + btype, flags, this->location_); } else if (function == NULL) @@ -8083,15 +8089,16 @@ Variable::get_backend_variable(Gogo* gogo, Named_object* function, { const std::string n = Gogo::unpack_hidden_name(name); Bfunction* bfunction = function->func_value()->get_decl(); - bool is_address_taken = (this->is_non_escaping_address_taken_ - && !this->is_in_heap()); + unsigned int flags = 0; + if (this->is_non_escaping_address_taken_ + && !this->is_in_heap()) + flags |= Backend::variable_address_is_taken; if (this->is_closure()) bvar = backend->static_chain_variable(bfunction, n, btype, - this->location_); + flags, this->location_); else if (is_parameter) bvar = backend->parameter_variable(bfunction, n, btype, - is_address_taken, - this->location_); + flags, this->location_); else { Bvariable* bvar_decl = NULL; @@ -8102,8 +8109,7 @@ Variable::get_backend_variable(Gogo* gogo, Named_object* function, ->get_backend_variable(&context); } bvar = backend->local_variable(bfunction, n, btype, - bvar_decl, - is_address_taken, + bvar_decl, flags, this->location_); } } @@ -8134,10 +8140,12 @@ Result_variable::get_backend_variable(Gogo* gogo, Named_object* function, Btype* btype = type->get_backend(gogo); Bfunction* bfunction = function->func_value()->get_decl(); std::string n = Gogo::unpack_hidden_name(name); - bool is_address_taken = (this->is_non_escaping_address_taken_ - && !this->is_in_heap()); + unsigned int flags = 0; + if (this->is_non_escaping_address_taken_ + && !this->is_in_heap()) + flags |= Backend::variable_address_is_taken; this->backend_ = backend->local_variable(bfunction, n, btype, - NULL, is_address_taken, + NULL, flags, this->location_); } } diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc index b066011..9643d1b 100644 --- a/gcc/go/gofrontend/statements.cc +++ b/gcc/go/gofrontend/statements.cc @@ -643,11 +643,13 @@ Temporary_statement::do_get_backend(Translate_context* context) binit = context->backend()->convert_expression(btype, binit, this->location()); + unsigned int flags = 0; + if (this->is_address_taken_) + flags |= Backend::variable_address_is_taken; Bstatement* statement; this->bvariable_ = context->backend()->temporary_variable(bfunction, context->bblock(), - btype, binit, - this->is_address_taken_, + btype, binit, flags, this->location(), &statement); return statement; } diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index 7d4c47f..d08cbc9 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -1410,10 +1410,12 @@ Type::make_type_descriptor_var(Gogo* gogo) // ensure that type_descriptor_pointer will work if called while // converting INITIALIZER. + unsigned int flags = 0; + if (is_common) + flags |= Backend::variable_is_common; this->type_descriptor_var_ = gogo->backend()->immutable_struct(bname.name(), bname.optional_asm_name(), - false, is_common, initializer_btype, - loc); + flags, initializer_btype, loc); if (phash != NULL) *phash = this->type_descriptor_var_; @@ -1422,7 +1424,7 @@ Type::make_type_descriptor_var(Gogo* gogo) Bexpression* binitializer = initializer->get_backend(&context); gogo->backend()->immutable_struct_set_init(this->type_descriptor_var_, - bname.name(), false, is_common, + bname.name(), flags, initializer_btype, loc, binitializer); @@ -2714,9 +2716,13 @@ Type::make_gc_symbol_var(Gogo* gogo) // Since we are building the GC symbol in this package, we must create the // variable before converting the initializer to its backend representation // because the initializer may refer to the GC symbol for this type. + unsigned int flags = Backend::variable_is_constant; + if (is_common) + flags |= Backend::variable_is_common; + else + flags |= Backend::variable_is_hidden; this->gc_symbol_var_ = - gogo->backend()->implicit_variable(sym_name, "", sym_btype, false, true, - is_common, 0); + gogo->backend()->implicit_variable(sym_name, "", sym_btype, flags, 0); if (phash != NULL) *phash = this->gc_symbol_var_; @@ -2724,8 +2730,7 @@ Type::make_gc_symbol_var(Gogo* gogo) context.set_is_const(); Bexpression* sym_binit = sym_init->get_backend(&context); gogo->backend()->implicit_variable_set_init(this->gc_symbol_var_, sym_name, - sym_btype, false, true, is_common, - sym_binit); + sym_btype, flags, sym_binit); } // Return whether this type needs a GC program, and set *PTRDATA to @@ -3013,11 +3018,12 @@ Type::gc_ptrmask_var(Gogo* gogo, int64_t ptrsize, int64_t ptrdata) Bexpression* bval = val->get_backend(&context); Btype *btype = val->type()->get_backend(gogo); + unsigned int flags = (Backend::variable_is_constant + | Backend::variable_is_common); Bvariable* ret = gogo->backend()->implicit_variable(sym_name, "", - btype, false, true, - true, 0); - gogo->backend()->implicit_variable_set_init(ret, sym_name, btype, false, - true, true, bval); + btype, flags, 0); + gogo->backend()->implicit_variable_set_init(ret, sym_name, btype, flags, + bval); ins.first->second = ret; return ret; } @@ -8145,11 +8151,12 @@ Map_type::backend_zero_value(Gogo* gogo) Btype* barray_type = gogo->backend()->array_type(buint8_type, blength); std::string zname = Map_type::zero_value->name(); + unsigned int flags = Backend::variable_is_common; Bvariable* zvar = - gogo->backend()->implicit_variable(zname, "", barray_type, false, false, - true, Map_type::zero_value_align); + gogo->backend()->implicit_variable(zname, "", barray_type, flags, + Map_type::zero_value_align); gogo->backend()->implicit_variable_set_init(zvar, zname, barray_type, - false, false, true, NULL); + flags, NULL); return zvar; } diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c index f15c482..9d896be 100644 --- a/gcc/ipa-inline.c +++ b/gcc/ipa-inline.c @@ -283,6 +283,9 @@ sanitize_attrs_match_for_inline_p (const_tree caller, const_tree callee) != sanitize_flags_p (codes[i], callee)) return false; + if (sanitize_coverage_p (caller) != sanitize_coverage_p (callee)) + return false; + return true; } diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index 3cfbb1e..426f1c0 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,7 @@ +2021-05-24 Wang Liushuai <wangliushuai@bytedance.com> + + * lto-dump.c (get_size): Fix the NPD error about the thunk symbol. + 2021-04-15 Jan Hubicka <hubicka@ucw.cz> PR lto/98599 diff --git a/gcc/optc-save-gen.awk b/gcc/optc-save-gen.awk index 19afa89..e2a9a49 100644 --- a/gcc/optc-save-gen.awk +++ b/gcc/optc-save-gen.awk @@ -1438,19 +1438,10 @@ print "{" checked_options["flag_merge_constants"]++ checked_options["param_max_fields_for_field_sensitive"]++ checked_options["flag_omit_frame_pointer"]++ -checked_options["unroll_only_small_loops"]++ # arc exceptions checked_options["TARGET_ALIGN_CALL"]++ checked_options["TARGET_CASE_VECTOR_PC_RELATIVE"]++ checked_options["arc_size_opt_level"]++ -# arm exceptions -checked_options["arm_fp16_format"]++ -checked_options["flag_ipa_ra"]++ -# s390 exceptions -checked_options["param_max_completely_peel_times"]++ -checked_options["param_max_completely_peeled_insns"]++ -checked_options["param_max_unroll_times"]++ -checked_options["param_max_unrolled_insns"]++ for (i = 0; i < n_opts; i++) { diff --git a/gcc/sancov.c b/gcc/sancov.c index d656c37..9cfbd42 100644 --- a/gcc/sancov.c +++ b/gcc/sancov.c @@ -313,9 +313,9 @@ public: return new pass_sancov<O0> (m_ctxt); } virtual bool - gate (function *) + gate (function *fun) { - return flag_sanitize_coverage && (!O0 || !optimize); + return sanitize_coverage_p (fun->decl) && (!O0 || !optimize); } virtual unsigned int execute (function *fun) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0b3dc03..00550f6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,36 @@ +2021-05-24 Aaron Sawdey <acsawdey@linux.ibm.com> + + * gcc.target/powerpc/fusion-p10-logadd.c: New file. + +2021-05-24 Tobias Burnus <tobias@codesourcery.com> + + PR fortran/86470 + * gfortran.dg/gomp/class-firstprivate-1.f90: New test. + * gfortran.dg/gomp/class-firstprivate-2.f90: New test. + * gfortran.dg/gomp/class-firstprivate-3.f90: New test. + * gfortran.dg/gomp/class-firstprivate-4.f90: New test. + +2021-05-24 Christophe Lyon <christophe.lyon@linaro.org> + + * gcc.target/arm/simd/mve-vld4.c: New test, derived from + slp-perm-3.c + +2021-05-24 Christophe Lyon <christophe.lyon@linaro.org> + + * gcc.target/arm/simd/mve-vld2.c: New test, derived from + slp-perm-2.c + +2021-05-24 liuhongt <hongtao.liu@intel.com> + + PR target/100660 + * gcc.target/i386/pr100660.c: New test. + +2021-05-24 Andrew Pinski <apinski@marvell.com> + + * gcc.dg/tree-ssa/phi-opt-10.c: Use "\[0-9\]*" instead of '.' + when matching ssa name version. + * gcc.dg/tree-ssa/phi-opt-7.c: Likewise. + 2021-05-23 Uroš Bizjak <ubizjak@gmail.com> PR target/100722 diff --git a/gcc/testsuite/c-c++-common/gomp/pr99928-10.c b/gcc/testsuite/c-c++-common/gomp/pr99928-10.c index 4acff45..d2987a1 100644 --- a/gcc/testsuite/c-c++-common/gomp/pr99928-10.c +++ b/gcc/testsuite/c-c++-common/gomp/pr99928-10.c @@ -165,7 +165,7 @@ bar (void) /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:\\\*_\[0-9]* \\\[len: 92\\\]" "gimple" { xfail *-*-* } } } */ /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(firstprivate:r21 \\\[pointer assign, bias: 4\\\]\\)" "gimple" { xfail *-*-* } } } */ /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r21\\)" "gimple" } } */ - /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r21 \\+ 4" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r21 \\+ 4" "gimple" } } */ /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r21 \\+ 4" "gimple" } } */ /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r21 \\+ 4" "gimple" } } */ #pragma omp target teams distribute simd reduction(+:r21[1:23]) @@ -214,7 +214,7 @@ bar (void) #pragma omp teams distribute parallel for simd reduction(+:r27[1:29]) for (int i = 0; i < 64; i++) r27[1]++; - /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r28 \\+ 4" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r28 \\+ 4" "gimple" } } */ /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r28 \\+ 4" "gimple" } } */ /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r28 \\+ 4" "gimple" } } */ #pragma omp teams distribute simd reduction(+:r28[1:30]) diff --git a/gcc/testsuite/c-c++-common/gomp/pr99928-8.c b/gcc/testsuite/c-c++-common/gomp/pr99928-8.c index 755da3b..fc57573 100644 --- a/gcc/testsuite/c-c++-common/gomp/pr99928-8.c +++ b/gcc/testsuite/c-c++-common/gomp/pr99928-8.c @@ -155,7 +155,7 @@ bar (void) r20++; /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:r21" "gimple" { xfail *-*-* } } } */ /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r21\\)" "gimple" { xfail *-*-* } } } */ - /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:r21\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:r21\\)" "gimple" } } */ /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:r21\\)" "gimple" } } */ /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:r21\\)" "gimple" } } */ #pragma omp target teams distribute simd reduction(+:r21) @@ -202,7 +202,7 @@ bar (void) #pragma omp teams distribute parallel for simd reduction(+:r27) for (int i = 0; i < 64; i++) r27++; - /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:r28\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:r28\\)" "gimple" } } */ /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:r28\\)" "gimple" } } */ /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:r28\\)" "gimple" } } */ #pragma omp teams distribute simd reduction(+:r28) diff --git a/gcc/testsuite/c-c++-common/gomp/pr99928-9.c b/gcc/testsuite/c-c++-common/gomp/pr99928-9.c index a766b72..c049bb0 100644 --- a/gcc/testsuite/c-c++-common/gomp/pr99928-9.c +++ b/gcc/testsuite/c-c++-common/gomp/pr99928-9.c @@ -155,7 +155,7 @@ bar (void) r20[1]++; /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:r21\\\[1\\\] \\\[len: 8\\\]" "gimple" { xfail *-*-* } } } */ /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r21\\)" "gimple" } } */ - /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r21 \\+ 4" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r21 \\+ 4" "gimple" } } */ /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r21 \\+ 4" "gimple" } } */ /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r21 \\+ 4" "gimple" } } */ #pragma omp target teams distribute simd reduction(+:r21[1:2]) @@ -202,7 +202,7 @@ bar (void) #pragma omp teams distribute parallel for simd reduction(+:r27[1:2]) for (int i = 0; i < 64; i++) r27[1]++; - /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r28 \\+ 4" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r28 \\+ 4" "gimple" } } */ /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r28 \\+ 4" "gimple" } } */ /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r28 \\+ 4" "gimple" } } */ #pragma omp teams distribute simd reduction(+:r28[1:2]) diff --git a/gcc/testsuite/gcc.dg/sancov/attribute.c b/gcc/testsuite/gcc.dg/sancov/attribute.c new file mode 100644 index 0000000..7cfa913 --- /dev/null +++ b/gcc/testsuite/gcc.dg/sancov/attribute.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-fsanitize-coverage=trace-pc -fdump-tree-optimized" } */ + +void foo(void) +{ +} + +void +__attribute__((no_sanitize_coverage)) +bar(void) +{ +} + +static void inline +__attribute__((always_inline)) +inline_fn(void) +{ +} + +void +__attribute__((no_sanitize_coverage)) +baz(void) +{ + inline_fn(); +} + +/* { dg-final { scan-tree-dump-times "__builtin___sanitizer_cov_trace_pc \\(\\)" 1 "optimized" } } */ diff --git a/gcc/testsuite/gcc.target/arm/simd/mve-vld2.c b/gcc/testsuite/gcc.target/arm/simd/mve-vld2.c new file mode 100644 index 0000000..9c7c3f5 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/simd/mve-vld2.c @@ -0,0 +1,96 @@ +/* { dg-do assemble } */ +/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */ +/* { dg-add-options arm_v8_1m_mve_fp } */ +/* { dg-additional-options "-O3" } */ + +#include <stdint.h> + +#define M00 100 +#define M10 216 +#define M01 1322 +#define M11 13 + +#define N 128 + + +/* Integer tests. */ +#define FUNC(SIGN, TYPE, BITS) \ + void foo_##SIGN##BITS##x (TYPE##BITS##_t *__restrict__ pInput, \ + TYPE##BITS##_t *__restrict__ pOutput) \ + { \ + unsigned int i; \ + TYPE##BITS##_t a, b; \ + \ + for (i = 0; i < N / BITS; i++) \ + { \ + a = *pInput++; \ + b = *pInput++; \ + \ + *pOutput++ = M00 * a + M01 * b; \ + *pOutput++ = M10 * a + M11 * b; \ + } \ + } + +FUNC(s, int, 8) +FUNC(u, uint, 8) +FUNC(s, int, 16) +FUNC(u, uint, 16) +FUNC(s, int, 32) +FUNC(u, uint, 32) + +/* float test, keep the macro because it's similar to the above, but does not + need the ##BITS##_t. */ +#define FUNC_FLOAT(SIGN, TYPE, BITS) \ + void foo_##SIGN##BITS##x (TYPE *__restrict__ pInput, \ + TYPE *__restrict__ pOutput) \ + { \ + unsigned int i; \ + TYPE a, b; \ + \ + for (i = 0; i < N / BITS; i++) \ + { \ + a = *pInput++; \ + b = *pInput++; \ + \ + *pOutput++ = M00 * a + M01 * b; \ + *pOutput++ = M10 * a + M11 * b; \ + } \ + } + +FUNC_FLOAT(f, float, 32) + +/* __fp16 test, needs explicit casts to avoid conversions to floating-point and + failure to vectorize. */ +__fp16 M00_fp16 = 100.0f16; +__fp16 M10_fp16 = 216.0f16; +__fp16 M01_fp16 = 1322.0f16; +__fp16 M11_fp16 = 13.0f16; + +#define FUNC_FLOAT_FP16(SIGN, TYPE, BITS) \ + void foo_##SIGN##BITS##x (TYPE *__restrict__ pInput, \ + TYPE *__restrict__ pOutput) \ + { \ + unsigned int i; \ + TYPE a, b; \ + \ + for (i = 0; i < N / BITS; i++) \ + { \ + a = *pInput++; \ + b = *pInput++; \ + \ + *pOutput++ = (__fp16)(M00_fp16 * a) + (__fp16)(M01_fp16 * b); \ + *pOutput++ = (__fp16)(M10_fp16 * a) + (__fp16)(M11_fp16 * b); \ + } \ + } + +FUNC_FLOAT_FP16(f, __fp16, 16) + +/* vld2X.8 is used for signed and unsigned chars: 2 pairs. */ +/* vld2X.16 is used for signed and unsigned shorts and __fp16: 3 pairs. */ +/* vld2X.32 is used for signed and unsigned ints and float: 3 pairs. */ +/* { dg-final { scan-assembler-times {vld2[01].8\t.q[0-9]+, q[0-9]+., } 4 } } */ +/* { dg-final { scan-assembler-times {vld2[01].16\t.q[0-9]+, q[0-9]+., } 6 } } */ +/* { dg-final { scan-assembler-times {vld2[01].32\t.q[0-9]+, q[0-9]+., } 6 } } */ +/* { dg-final { scan-assembler-times {vst2[01].8\t.q[0-9]+, q[0-9]+., } 4 } } */ +/* { dg-final { scan-assembler-times {vst2[01].16\t.q[0-9]+, q[0-9]+., } 6 } } */ +/* { dg-final { scan-assembler-times {vst2[01].32\t.q[0-9]+, q[0-9]+., } 6 } } */ diff --git a/gcc/testsuite/gcc.target/arm/simd/mve-vld4.c b/gcc/testsuite/gcc.target/arm/simd/mve-vld4.c new file mode 100644 index 0000000..ce3e755 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/simd/mve-vld4.c @@ -0,0 +1,140 @@ +/* { dg-do assemble } */ +/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */ +/* { dg-add-options arm_v8_1m_mve_fp } */ +/* { dg-additional-options "-O3" } */ + +#include <stdint.h> + +#define M00 100 +#define M10 216 +#define M20 23 +#define M30 237 +#define M01 1322 +#define M11 13 +#define M21 27271 +#define M31 2280 +#define M02 74 +#define M12 191 +#define M22 500 +#define M32 111 +#define M03 134 +#define M13 117 +#define M23 11 +#define M33 771 + +#define N 128 + +/* Integer tests. */ +#define FUNC(SIGN, TYPE, BITS) \ + void foo_##SIGN##BITS##x (TYPE##BITS##_t *__restrict__ pInput, \ + TYPE##BITS##_t *__restrict__ pOutput) \ + { \ + unsigned int i; \ + TYPE##BITS##_t a, b, c, d; \ + \ + for (i = 0; i < N / BITS; i++) \ + { \ + a = *pInput++; \ + b = *pInput++; \ + c = *pInput++; \ + d = *pInput++; \ + \ + *pOutput++ = M00 * a + M01 * b + M02 * c + M03 * d; \ + *pOutput++ = M10 * a + M11 * b + M12 * c + M13 * d; \ + *pOutput++ = M20 * a + M21 * b + M22 * c + M23 * d; \ + *pOutput++ = M30 * a + M31 * b + M32 * c + M33 * d; \ + } \ + } + +FUNC(s, int, 8) +FUNC(u, uint, 8) +FUNC(s, int, 16) +FUNC(u, uint, 16) +FUNC(s, int, 32) +FUNC(u, uint, 32) + +/* float test, keep the macro because it's similar to the above, but does not + need the ##BITS##_t. */ +#define FUNC_FLOAT(SIGN, TYPE, BITS) \ + void foo_##SIGN##BITS##x (TYPE *__restrict__ pInput, \ + TYPE *__restrict__ pOutput) \ + { \ + unsigned int i; \ + TYPE a, b, c, d; \ + \ + for (i = 0; i < N / BITS; i++) \ + { \ + a = *pInput++; \ + b = *pInput++; \ + c = *pInput++; \ + d = *pInput++; \ + \ + *pOutput++ = M00 * a + M01 * b + M02 * c + M03 * d; \ + *pOutput++ = M10 * a + M11 * b + M12 * c + M13 * d; \ + *pOutput++ = M20 * a + M21 * b + M22 * c + M23 * d; \ + *pOutput++ = M30 * a + M31 * b + M32 * c + M33 * d; \ + } \ + } + +FUNC_FLOAT(f, float, 32) + +/* __fp16 test, needs explicit casts to avoid conversions to floating-point and + failure to vectorize. */ +__fp16 M00_fp16 = 100.0f16; +__fp16 M10_fp16 = 216.0f16; +__fp16 M20_fp16 = 23.0f16; +__fp16 M30_fp16 = 237.0f16; +__fp16 M01_fp16 = 1322.0f16; +__fp16 M11_fp16 = 13.0f16; +__fp16 M21_fp16 = 27271.0f16; +__fp16 M31_fp16 = 2280.0f16; +__fp16 M02_fp16 = 74.0f16; +__fp16 M12_fp16 = 191.0f16; +__fp16 M22_fp16 = 500.0f16; +__fp16 M32_fp16 = 111.0f16; +__fp16 M03_fp16 = 134.0f16; +__fp16 M13_fp16 = 117.0f16; +__fp16 M23_fp16 = 11.0f16; +__fp16 M33_fp16 = 771.0f16; + +#define FUNC_FLOAT_FP16(SIGN, TYPE, BITS) \ + void foo_##SIGN##BITS##x (TYPE *__restrict__ pInput, \ + TYPE *__restrict__ pOutput) \ + { \ + unsigned int i; \ + TYPE a, b, c, d; \ + \ + for (i = 0; i < N / BITS; i++) \ + { \ + a = *pInput++; \ + b = *pInput++; \ + c = *pInput++; \ + d = *pInput++; \ + \ + TYPE ab, cd; \ + ab = (__fp16)(M00_fp16 * a) + (__fp16)(M01_fp16 * b); \ + cd = (__fp16)(M02_fp16 * c) + (__fp16)(M03_fp16 * d); \ + *pOutput++ = ab + cd; \ + ab = (__fp16)(M10_fp16 * a) + (__fp16)(M11_fp16 * b); \ + cd = (__fp16)(M12_fp16 * c) + (__fp16)(M13_fp16 * d); \ + *pOutput++ = ab + cd; \ + ab = (__fp16)(M20_fp16 * a) + (__fp16)(M21_fp16 * b); \ + cd = (__fp16)(M22_fp16 * c) + (__fp16)(M23_fp16 * d); \ + *pOutput++ = ab + cd; \ + ab = (__fp16)(M30_fp16 * a) + (__fp16)(M31_fp16 * b); \ + cd = (__fp16)(M32_fp16 * c) + (__fp16)(M33_fp16 * d); \ + *pOutput++ = ab + cd; \ + } \ + } + +FUNC_FLOAT_FP16(f, __fp16, 16) + +/* vld4X.8 is used for signed and unsigned chars: 2 * 4. */ +/* vld4X.16 is used for signed and unsigned shorts and __fp16: 3 * 4. */ +/* vld4X.32 is used for signed and unsigned ints and float: 3 * 4. */ +/* { dg-final { scan-assembler-times {vld4[0123].8\t.q[0-9]+, q[0-9]+, q[0-9]+, q[0-9]+., } 8 } } */ +/* { dg-final { scan-assembler-times {vld4[0123].16\t.q[0-9]+, q[0-9]+, q[0-9]+, q[0-9]+., } 12 } } */ +/* { dg-final { scan-assembler-times {vld4[0123].32\t.q[0-9]+, q[0-9]+, q[0-9]+, q[0-9]+., } 12 } } */ +/* { dg-final { scan-assembler-times {vst4[0123].8\t.q[0-9]+, q[0-9]+, q[0-9]+, q[0-9]+., } 8 } } */ +/* { dg-final { scan-assembler-times {vst4[0123].16\t.q[0-9]+, q[0-9]+, q[0-9]+, q[0-9]+., } 12 } } */ +/* { dg-final { scan-assembler-times {vst4[0123].32\t.q[0-9]+, q[0-9]+, q[0-9]+, q[0-9]+., } 12 } } */ diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpuv3.exp b/gcc/testsuite/gcc.target/csky/fpuv3/fpuv3.exp new file mode 100644 index 0000000..68c166c --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpuv3.exp @@ -0,0 +1,51 @@ +# GCC testsuite for C-SKY targets FPUV3 instructions. +# Copyright (C) 2012-2021 Free Software Foundation, Inc. +# Contributed by C-SKY Microsystems and Mentor Graphics. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. + + +# Exit immediately if this isn't a csky target. +if { ![istarget csky*-*-*]} then { + return +} + +set cflags [board_info target cflags] +if { [string first "ck6" "${cflags}"] >= 0 } { + verbose "the test is not support " + return +} +if { [string first "ck5" "${cflags}"] >= 0 } { + verbose "the test is not support " + return +} + +# Load support procs. +load_lib gcc-dg.exp + +global DEFAULT_CFLAGS +if ![info exists DEFAULT_CFLAGS] then { + set DEFAULT_CFLAGS "" +} + +# Initialize `dg'. +dg-init + +# Main loop. +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cCS\]]] \ + "" $DEFAULT_CFLAGS + +# All done. +dg-finish diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_div.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_div.c new file mode 100644 index 0000000..32a1551 --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_div.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "" } */ + +float div32(float a, float b){ + return a/b; +} + + +float div64(double a, double b){ + return a/b; +} + +/* { dg-final { scan-assembler "fdiv\.32" } }*/ +/* { dg-final { scan-assembler "fdiv\.64" } }*/ diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fadd.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fadd.c new file mode 100644 index 0000000..d54b529 --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fadd.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "-mfpu=fpv3" } */ + +__fp16 funch(__fp16 a, __fp16 b) +{ + return a + b; +} + +float funcs(float a, float b) +{ + return a + b; +} + +double funcd(double a, double b) +{ + return a + b; +} + +/* { dg-final { scan-assembler "fadd\.16" } }*/ +/* { dg-final { scan-assembler "fadd\.32" } }*/ +/* { dg-final { scan-assembler "fadd\.64" } }*/ + diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fdtos.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fdtos.c new file mode 100644 index 0000000..034b15e --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fdtos.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "" } */ + +float func(double a) +{ + return (float)a; +} + +/* { dg-final { scan-assembler "fdtos" } }*/ + diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fftoi_rm.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fftoi_rm.c new file mode 100644 index 0000000..11c4f9d --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fftoi_rm.c @@ -0,0 +1,55 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "-ffast-math" } */ + +int lfloor_float32 (float x) +{ + return __builtin_lfloorf (x); +} + +int lfloor_float64 (double x) +{ + return __builtin_lfloor (x); +} + + +float floor_float32 (float x) +{ + return __builtin_floorf (x); +} + +double floor_float64 (double x) +{ + return __builtin_floor (x); +} + +/* { dg-final { scan-assembler "fftoi\.f32\.s32\.rni" } }*/ +/* { dg-final { scan-assembler "fftoi\.f64\.s32\.rni" } }*/ +/* { dg-final { scan-assembler "fftofi\.f32\.rni" } }*/ +/* { dg-final { scan-assembler "fftofi\.f64\.rni" } }*/ + +int lceil_float32 (float x) +{ + return __builtin_lceilf (x); +} + +int lceil_float64 (double x) +{ + return __builtin_lceil (x); +} + + +float ceil_float32 (float x) +{ + return __builtin_ceilf (x); +} + +double ceil_float64 (double x) +{ + return __builtin_ceil (x); +} + +/* { dg-final { scan-assembler "fftoi\.f32\.s32\.rpi" } }*/ +/* { dg-final { scan-assembler "fftoi\.f64\.s32\.rpi" } }*/ +/* { dg-final { scan-assembler "fftofi\.f32\.rpi" } }*/ +/* { dg-final { scan-assembler "fftofi\.f64\.rpi" } }*/ diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fftoi_rz.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fftoi_rz.c new file mode 100644 index 0000000..4b2990b --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fftoi_rz.c @@ -0,0 +1,41 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options " -mfpu=fpv3" } */ + +int funce(__fp16 a) +{ + return (int)a; +} + +unsigned int funcf(__fp16 a) +{ + return (unsigned int)a; +} + +int funca(float a) +{ + return (int)a; +} + +unsigned int funcb(float a) +{ + return (unsigned int)a; +} + +int funcc(double a) +{ + return (int)a; +} + +unsigned int funcd(double a) +{ + return (unsigned int)a; +} + +/* { dg-final { scan-assembler "fftoi\.f16\.s32\.rz" } }*/ +/* { dg-final { scan-assembler "fftoi\.f16\.u32\.rz" } }*/ +/* { dg-final { scan-assembler "fftoi\.f32\.s32\.rz" } }*/ +/* { dg-final { scan-assembler "fftoi\.f32\.u32\.rz" } }*/ +/* { dg-final { scan-assembler "fftoi\.f64\.s32\.rz" } }*/ +/* { dg-final { scan-assembler "fftoi\.f64\.u32\.rz" } }*/ + diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fhtos.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fhtos.c new file mode 100644 index 0000000..25fc542 --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fhtos.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "-mfpu=fpv3" } */ + +float func(__fp16 a) +{ + return (float)a; +} + +/* { dg-final { scan-assembler "fhtos" } }*/ + diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fitof.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fitof.c new file mode 100644 index 0000000..6a513dc --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fitof.c @@ -0,0 +1,72 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "-mfpu=fpv3" } */ + +__fp16 funce(int a) +{ + return (__fp16)a; +} + +__fp16 funcf(unsigned int a) +{ + return (__fp16)a; +} + +float funca(int a) +{ + return (float)a; +} + +float funcb(unsigned int a) +{ + return (float)a; +} + +double funcc(int a) +{ + return (double)a; +} + +double funcd(unsigned int a) +{ + return (double)a; +} + +//double funch(short a) +//{ +// return (double)a; +//} +// +//double funci(unsigned short a) +//{ +// return (double)a; +//} +// +//float funcj(short a) +//{ +// return (float)a; +//} +// +//float funck(unsigned short a) +//{ +// return (float)a; +//} + +__fp16 funcm(short a) +{ + return (__fp16)a; +} + +__fp16 funcn(unsigned short a) +{ + return (__fp16)a; +} + +/* { dg-final { scan-assembler "fitof\.s32\.f16" } }*/ +/* { dg-final { scan-assembler "fitof\.u32\.f16" } }*/ +/* { dg-final { scan-assembler "fitof\.s32\.f32" } }*/ +/* { dg-final { scan-assembler "fitof\.u32\.f32" } }*/ +/* { dg-final { scan-assembler "fitof\.s32\.f64" } }*/ +/* { dg-final { scan-assembler "fitof\.u32\.f64" } }*/ +/* { dg-final { scan-assembler "fitof\.s16\.f16" } }*/ +/* { dg-final { scan-assembler "fitof\.u16\.f16" } }*/ diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fmov.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fmov.c new file mode 100644 index 0000000..1aa87b1 --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fmov.c @@ -0,0 +1,96 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "-O2 -mfpu=fpv3" } */ + +#define FUNC(i) func_ ## i + +#define FTYPE __fp16 +FTYPE FUNC(ld16) (FTYPE *a, FTYPE *b) +{ + return *a = *b; +} + +/* { dg-final { scan-assembler "fld\.16" } }*/ +/* { dg-final { scan-assembler "fst\.16" } }*/ + +#undef FTYPE +#define FTYPE float +FTYPE FUNC(ld32) (FTYPE *a, FTYPE *b) +{ + return *a = *b; +} + +/* { dg-final { scan-assembler "fld\.32" } }*/ +/* { dg-final { scan-assembler "fld\.32" } }*/ + +#undef FTYPE +#define FTYPE double +FTYPE FUNC(ld64) (FTYPE *a, FTYPE *b) +{ + return *a = *b; +} + +/* { dg-final { scan-assembler "fld\.64" } }*/ +/* { dg-final { scan-assembler "fst\.64" } }*/ + + +#undef FTYPE +#define FTYPE __fp16 +FTYPE FUNC(ldr16) (FTYPE *a, int i, FTYPE *b) +{ + return a[i] = b[i]; +} + +/* { dg-final { scan-assembler "fldr\.16" } }*/ +/* { dg-final { scan-assembler "fstr\.16" } }*/ + +#undef FTYPE +#define FTYPE float +FTYPE FUNC(ldr32) (FTYPE *a, int i, FTYPE *b) +{ + return a[i] = b[i]; +} + +/* { dg-final { scan-assembler "fldr\.32" } }*/ +/* { dg-final { scan-assembler "fstr\.32" } }*/ + +#undef FTYPE +#define FTYPE double +FTYPE FUNC(ldr64) (FTYPE *a, int i, FTYPE *b) +{ + return a[i] = b[i]; +} + +/* { dg-final { scan-assembler "fldr\.64" } }*/ +/* { dg-final { scan-assembler "fstr\.64" } }*/ + + +#undef FTYPE +#define FTYPE __fp16 +FTYPE FUNC(mov16) (FTYPE a, FTYPE b) +{ + a = b; + return a; +} + +/* { dg-final { scan-assembler "fmov\.16" } }*/ + +#undef FTYPE +#define FTYPE float +FTYPE FUNC(mov32) (FTYPE a, FTYPE b) +{ + a = b; + return a; +} + +/* { dg-final { scan-assembler "fmov\.32" } }*/ + +#undef FTYPE +#define FTYPE double +FTYPE FUNC(mov64) (FTYPE a, FTYPE b) +{ + a = b; + return a; +} + +/* { dg-final { scan-assembler "fmov\.64" } }*/ diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fmovi.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fmovi.c new file mode 100644 index 0000000..5fbc011 --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fmovi.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "-O2 -mfpu=fpv3" } */ + +#define FUNC(i) func_ ## i + +#define FTYPE __fp16 +FTYPE FUNC(movi16) (void) +{ + return 1.0; +} + +/* { dg-final { scan-assembler "fmovi\.16" } }*/ + +#undef FTYPE +#define FTYPE float +FTYPE FUNC(movi32) (void) +{ + return 1.0; +} + +/* { dg-final { scan-assembler "fmovi\.32" } }*/ + +#undef FTYPE +#define FTYPE double +FTYPE FUNC(movi64) (void) +{ + return 1.0; +} + +/* { dg-final { scan-assembler "fmovi\.64" } }*/ diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fmula.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fmula.c new file mode 100644 index 0000000..078ebc7 --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fmula.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "-O2 -mfpu=fpv3" } */ + +__fp16 func16(__fp16 a, __fp16 b, __fp16 c){ + a += b * c; + return a; +} + +float func32(float a, float b, float c){ + a += b * c; + return a; +} + + +double func64(double a, double b, double c){ + a += b * c; + return a; +} + +/* { dg-final { scan-assembler "ffmula\.16" } }*/ +/* { dg-final { scan-assembler "ffmula\.32" } }*/ +/* { dg-final { scan-assembler "ffmula\.64" } }*/ diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fmuls.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fmuls.c new file mode 100644 index 0000000..efc80bc --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fmuls.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "-O2 -mfpu=fpv3" } */ + +__fp16 func16(__fp16 a, __fp16 b, __fp16 c){ + a -= b * c; + return a; +} + +float func32(float a, float b, float c){ + a -= b * c; + return a; +} + + +double func64(double a, double b, double c){ + a -= b * c; + return a; +} + +/* { dg-final { scan-assembler "ffmuls\.16" } }*/ +/* { dg-final { scan-assembler "ffmuls\.32" } }*/ +/* { dg-final { scan-assembler "ffmuls\.64" } }*/ diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fneg.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fneg.c new file mode 100644 index 0000000..9941cf8 --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fneg.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "-mfpu=fpv3" } */ + +__fp16 func16(__fp16 a) +{ + return -a; +} + +float func32(float a) +{ + return -a; +} + +double func64(double a) +{ + return -a; +} + +/* { dg-final { scan-assembler "fneg\.32" } }*/ +/* { dg-final { scan-assembler "fneg\.64" } }*/ + diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fnmula.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fnmula.c new file mode 100644 index 0000000..6770d29 --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fnmula.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "-O2" } */ + +float fnmula32(float a, float b, float c){ + return -(a + b * c); +} + +double fnmula64(double a, double b, double c){ + return -(a + b * c); +} + +/* { dg-final { scan-assembler "ffnmula\.32" } }*/ +/* { dg-final { scan-assembler "ffnmula\.64" } }*/ diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fnmuls.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fnmuls.c new file mode 100644 index 0000000..86ba96b --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fnmuls.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "-O2" } */ + +float fnmula32(float a, float b, float c){ + return -a + b * c; +} + +double fnmula64(double a, double b, double c){ + return -a + b * c; +} + +/* { dg-final { scan-assembler "ffnmuls\.32" } }*/ +/* { dg-final { scan-assembler "ffnmuls\.64" } }*/ diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fstod.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fstod.c new file mode 100644 index 0000000..d4a615c --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fstod.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "" } */ + +double func(float a) +{ + return (double)a; +} + +/* { dg-final { scan-assembler "fstod" } }*/ + diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fstoh.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fstoh.c new file mode 100644 index 0000000..1333c41 --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fstoh.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "-mfpu=fpv3" } */ + +__fp16 func(float a) +{ + return (__fp16)a; +} + +/* { dg-final { scan-assembler "fstoh" } }*/ + diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fsub.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fsub.c new file mode 100644 index 0000000..914b2e6 --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fsub.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "-mfpu=fpv3" } */ + +__fp16 funch(__fp16 a, __fp16 b) +{ + return a - b; +} + +float funcs(float a, float b) +{ + return a - b; +} + +double funcd(double a, double b) +{ + return a - b; +} + +/* { dg-final { scan-assembler "fsub\.16" } }*/ +/* { dg-final { scan-assembler "fsub\.32" } }*/ +/* { dg-final { scan-assembler "fsub\.64" } }*/ + diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fxtof.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fxtof.c new file mode 100644 index 0000000..d5182a7 --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_fxtof.c @@ -0,0 +1,76 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "-O1" } */ + +//__fp16 +//fixed32_to_float16 (int i) +//{ +// return ((__fp16) i / (1 << 15)); +//} +// +//__fp16 +//fixedu32_to_float16 (unsigned int i) +//{ +// return ((__fp16) i / (1 << 15)); +//} +// +//float +//fixed32_to_float32 (int i) +//{ +// return ((float) i / (1 << 30)); +//} +// +// +//float +//fixedu32_to_float32 (unsigned int i) +//{ +// return ((float) i / (1 << 30)); +//} +// +//double +//fixed32_to_float64 (int i) +//{ +// return ((double) i / (1 << 30)); +//} +// +//double +//fixedu32_to_float64 (unsigned int i) +//{ +// return ((double) i / (1 << 30)); +//} +// +//__fp16 +//fixed16_to_float16 (short i) +//{ +// return ((__fp16) i / (1 << 15)); +//} +// +//__fp16 +//fixedu16_to_float16 (unsigned short i) +//{ +// return ((__fp16) i / (1 << 15)); +//} +// +//float +//fixed16_to_float32 (short i) +//{ +// return ((float) i / (1 << 16)); +//} +// +//float +//fixedu16_to_float32 (unsigned short i) +//{ +// return ((float) i / (1 << 16)); +//} +// +//double +//fixed16_to_float64 (short i) +//{ +// return ((double) i / (1 << 16)); +//} +// +//double +//fixedu16_to_float64 (unsigned short i) +//{ +// return ((double) i / (1 << 16)); +//} diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_h.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_h.c new file mode 100644 index 0000000..c2e76d0 --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_h.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "" } */ + +float fh32(float a, float b, float c, float d){ + if(a > b) + return c; + + return d; +} + +double fh64(double a, double b, double c, double d){ + if( a > b) + return c; + return d; +} + +/* { dg-final { scan-assembler "fcmplt\.32" } }*/ +/* { dg-final { scan-assembler "fcmplt\.64" } }*/ + diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_hs.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_hs.c new file mode 100644 index 0000000..ecfaa63 --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_hs.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "" } */ + +float fhs32(float a, float b, float c, float d){ + if(a >= b) + return c; + return d; +} + +double fhs64(double a, double b, double c, double d){ + if( a >= b) + return c; + return d; +} + +/* { dg-final { scan-assembler "fcmphs\.32" } }*/ +/* { dg-final { scan-assembler "fcmphs\.64" } }*/ + diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_hsz.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_hsz.c new file mode 100644 index 0000000..530a4be --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_hsz.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "" } */ + +float fhsz32(float a, float b, float c){ + if(a >= 0.0f) + return b; + else + return c; +} + +double fhsz64(double a, double b, double c){ + if( a >= 0.0) + return b; + else + return c; +} + +/* { dg-final { scan-assembler "fcmphsz\.32" } }*/ +/* { dg-final { scan-assembler "fcmphsz\.64" } }*/ + diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_hz.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_hz.c new file mode 100644 index 0000000..a2a8d8f --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_hz.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "-O2" } */ + +float fhz32(float a, float b, float c){ + if(a > 0.0f) + return b; + else + return c; +} + +double fhz64(double a, double b, double c){ + if( a > 0.0) + return b; + else + return c; +} + +/* { dg-final { scan-assembler "fcmphz\.32" } }*/ +/* { dg-final { scan-assembler "fcmphz\.64" } }*/ diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_ls.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_ls.c new file mode 100644 index 0000000..3bb6ac6 --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_ls.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "-O2" } */ + +float fls32(float a, float b, float c, float d){ + if(a <= b) + return c; + + return d; +} + +double fhz64(double a, double b, double c, double d){ + if( a <= b) + return c; + return d; +} + +/* { dg-final { scan-assembler "fcmphs\.32" } }*/ +/* { dg-final { scan-assembler "fcmphs\.64" } }*/ diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_lsz.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_lsz.c new file mode 100644 index 0000000..6e19efa --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_lsz.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "-O2" } */ + +float flsz32(float a, float b, float c){ + if(a <= 0.0f) + return b; + else + return c; +} + +double fhz64(double a, double b, double c){ + if( a <= 0.0) + return b; + else + return c; +} + +/* { dg-final { scan-assembler "fcmplsz\.32" } }*/ +/* { dg-final { scan-assembler "fcmplsz\.64" } }*/ diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_lt.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_lt.c new file mode 100644 index 0000000..e4a716f --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_lt.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "" } */ + +float flt32(float a, float b, float c, float d){ + if(a < b) + return c; + return d; +} + +double flt64(double a, double b, double c, double d){ + if( a < b) + return c; + return d; +} + +/* { dg-final { scan-assembler "fcmplt\.32" } }*/ +/* { dg-final { scan-assembler "fcmplt\.64" } }*/ + diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_ltz.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_ltz.c new file mode 100644 index 0000000..984079c --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_ltz.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "-O2" } */ + +float fltz32(float a, float b, float c){ + if(a < 0.0f) + return b; + else + return c; +} + +double fltz64(double a, double b, double c){ + if( a < 0.0) + return b; + else + return c; +} + +/* { dg-final { scan-assembler "fcmpltz\.32" } }*/ +/* { dg-final { scan-assembler "fcmpltz\.64" } }*/ diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_max.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_max.c new file mode 100644 index 0000000..32fb74e --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_max.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "-O2" } */ + +extern float fmaxf( float x, float y ); +float fmax32(float a, float b){ + return fmaxf(a, b); +} + +extern double fmax( double x, double y ); +double fmax64(double a, double b){ + return fmax(a, b); +} + +/* { dg-final { scan-assembler "fmaxnm\.32" } }*/ +/* { dg-final { scan-assembler "fmaxnm\.64" } }*/ diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_min.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_min.c new file mode 100644 index 0000000..95c0878 --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_min.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "-O2" } */ + +extern float fminf( float x, float y ); +float fmin32(float a, float b){ + return fminf(a, b); +} + +extern double fmin( double x, double y ); +double fmin64(double a, double b){ + return fmin(a, b); +} + +/* { dg-final { scan-assembler "fminnm\.32" } }*/ +/* { dg-final { scan-assembler "fminnm\.64" } }*/ diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_mul.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_mul.c new file mode 100644 index 0000000..a168dc7 --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_mul.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "" } */ + +float mul32(float a, float b){ + return a*b; +} + +double mul64(double a, double b){ + return a*b; +} + +/* { dg-final { scan-assembler "fmul\.32" } }*/ +/* { dg-final { scan-assembler "fmul\.64" } }*/ + diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_mula.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_mula.c new file mode 100644 index 0000000..f78534e --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_mula.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "-O2" } */ + +float func32(float a, float b, float c){ + a += b * c; + return a; +} + +double func64(double a, double b, double c){ + a += b * c; + return a; +} + +/* { dg-final { scan-assembler "fmula\.32" } }*/ +/* { dg-final { scan-assembler "fmula\.64" } }*/ diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_muls.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_muls.c new file mode 100644 index 0000000..f144e45 --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_muls.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "-O2" } */ + +float muls32(float a, float b, float c){ + a -= b * c; + return a; +} + +double muls64(double a, double b, double c){ + a -= b * c; + return a; +} + +/* { dg-final { scan-assembler "fmuls\.32" } }*/ +/* { dg-final { scan-assembler "fmuls\.64" } }*/ diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_ne.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_ne.c new file mode 100644 index 0000000..c24f0ce --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_ne.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "" } */ + +float fne32(float a, float b, float c, float d){ + if(a != b) + return c; + return d; +} + +double fne64(double a, double b, double c, double d){ + if( a != b) + return c; + return d; +} + +/* { dg-final { scan-assembler "fcmpne\.32" } }*/ +/* { dg-final { scan-assembler "fcmpne\.64" } }*/ + diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_nez.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_nez.c new file mode 100644 index 0000000..348211d --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_nez.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "" } */ + +float fnez32(float a, float b, float c){ + if(a != 0.0f) + return b; + else + return c; +} + +double fnez64(double a, double b, double c){ + if( a != 0.0) + return b; + else + return c; +} + +/* { dg-final { scan-assembler "fcmpnez\.32" } }*/ +/* { dg-final { scan-assembler "fcmpnez\.64" } }*/ + diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_recip.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_recip.c new file mode 100644 index 0000000..cadd367 --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_recip.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "" } */ + +float recip32(float a){ + return 1.0f/a; +} + +double recip64(double a){ + return 1.0/a; +} + +/* { dg-final { scan-assembler "frecip\.32" } }*/ +/* { dg-final { scan-assembler "frecip\.64" } }*/ diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_sqrt.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_sqrt.c new file mode 100644 index 0000000..4d79900 --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_sqrt.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "-O2" } */ + +float sqrtf(float); +float sqrt32(float a){ + return sqrtf(a); +} + +double sqrt(double); +double sqrt64(double a){ + return sqrt(a); +} + +/* { dg-final { scan-assembler "fsqrt\.32" } }*/ +/* { dg-final { scan-assembler "fsqrt\.64" } }*/ diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_unordered.c b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_unordered.c new file mode 100644 index 0000000..3539eb4 --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fpv3_unordered.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "-O2" } */ + +int func32(float a, float b) +{ + return __builtin_isunordered(a, b); +} + +int func64(double a, double b) +{ + return __builtin_isunordered(a, b); +} + +/* { dg-final { scan-assembler "fcmpuo\.32" } }*/ +/* { dg-final { scan-assembler "fcmpuo\.64" } }*/ + +int func32z(float a) +{ + return __builtin_isunordered(a, 0); +} + +int func64z(double a) +{ + return __builtin_isunordered(a, 0); +} + +/* { dg-final { scan-assembler "fcmpuoz\.32" } }*/ +/* { dg-final { scan-assembler "fcmpuoz\.64" } }*/ diff --git a/gcc/testsuite/gcc.target/powerpc/fusion-p10-logadd.c b/gcc/testsuite/gcc.target/powerpc/fusion-p10-logadd.c new file mode 100644 index 0000000..b7022b2 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/fusion-p10-logadd.c @@ -0,0 +1,97 @@ +/* { dg-do compile } */ +/* { dg-options "-mdejagnu-cpu=power10 -O3 -dp" } */ + +#include <altivec.h> +#include <stdint.h> + +#define ADD(a,b) ((a)+(b)) +#define SUB1(a,b) ((a)-(b)) +#define SUB2(a,b) ((b)-(a)) + +/* and/andc/eqv/nand/nor/or/orc/xor */ +#define AND(a,b) ((a)&(b)) +#define NAND(a,b) (~((a)&(b))) +#define NOR(a,b) (~((a)|(b))) +#define OR(a,b) ((a)|(b)) +#define TEST1(type, func) \ + type func ## _add_T_ ## type (type a, type b, type c) { return ADD(func(a,b),c); } \ + type func ## _sub1_T_ ## type (type a, type b, type c) { return SUB1(func(a,b),c); } \ + type func ## _sub2_T_ ## type (type a, type b, type c) { return SUB2(func(a,b),c); } \ + type func ## _rev_add_T_ ## type (type a, type b, type c) { return ADD(c,func(a,b)); } \ + type func ## _rev_sub1_T_ ## type (type a, type b, type c) { return SUB1(c,func(a,b)); } \ + type func ## _rev_sub2_T_ ## type (type a, type b, type c) { return SUB2(c,func(a,b)); } +#define TEST2(type, func) \ + type func ## _and_T_ ## type (type a, type b, type c) { return AND(func(a,b),c); } \ + type func ## _nand_T_ ## type (type a, type b, type c) { return NAND(func(a,b),c); } \ + type func ## _or_T_ ## type (type a, type b, type c) { return OR(func(a,b),c); } \ + type func ## _nor_T_ ## type (type a, type b, type c) { return NOR(func(a,b),c); } \ + type func ## _rev_and_T_ ## type (type a, type b, type c) { return AND(c,func(a,b)); } \ + type func ## _rev_nand_T_ ## type (type a, type b, type c) { return NAND(c,func(a,b)); } \ + type func ## _rev_or_T_ ## type (type a, type b, type c) { return OR(c,func(a,b)); } \ + type func ## _rev_nor_T_ ## type (type a, type b, type c) { return NOR(c,func(a,b)); } +#define TEST(type) \ + TEST1(type,AND) \ + TEST1(type,NAND) \ + TEST1(type,NOR) \ + TEST1(type,OR) \ + TEST2(type,ADD) \ + TEST2(type,SUB1) \ + TEST2(type,SUB2) + +typedef vector bool char vboolchar_t; +typedef vector unsigned int vuint_t; + +TEST(uint8_t); +TEST(int8_t); +TEST(uint16_t); +TEST(int16_t); +TEST(uint32_t); +TEST(int32_t); +TEST(uint64_t); +TEST(int64_t); + +/* { dg-final { scan-assembler-times "fuse_nand_rsubf/0" 2 } } */ +/* { dg-final { scan-assembler-times "fuse_nand_rsubf/2" 2 } } */ +/* { dg-final { scan-assembler-times "fuse_nor_rsubf/0" 2 } } */ +/* { dg-final { scan-assembler-times "fuse_nor_rsubf/2" 2 } } */ +/* { dg-final { scan-assembler-times "fuse_add_nand/0" 4 } } */ +/* { dg-final { scan-assembler-times "fuse_add_nor/0" 4 } } */ +/* { dg-final { scan-assembler-times "fuse_add_or/0" 4 } } */ +/* { dg-final { scan-assembler-times "fuse_and_rsubf/0" 4 } } */ +/* { dg-final { scan-assembler-times "fuse_and_subf/0" 4 } } */ +/* { dg-final { scan-assembler-times "fuse_nand_add/0" 4 } } */ +/* { dg-final { scan-assembler-times "fuse_nand_subf/0" 4 } } */ +/* { dg-final { scan-assembler-times "fuse_nor_add/0" 4 } } */ +/* { dg-final { scan-assembler-times "fuse_nor_subf/0" 4 } } */ +/* { dg-final { scan-assembler-times "fuse_or_rsubf/0" 4 } } */ +/* { dg-final { scan-assembler-times "fuse_or_subf/0" 4 } } */ +/* { dg-final { scan-assembler-times "fuse_subf_nand/0" 4 } } */ +/* { dg-final { scan-assembler-times "fuse_subf_nand/1" 4 } } */ +/* { dg-final { scan-assembler-times "fuse_subf_nor/0" 4 } } */ +/* { dg-final { scan-assembler-times "fuse_subf_nor/1" 4 } } */ +/* { dg-final { scan-assembler-times "fuse_subf_or/0" 4 } } */ +/* { dg-final { scan-assembler-times "fuse_subf_or/1" 4 } } */ +/* { dg-final { scan-assembler-times "fuse_and_add/0" 6 } } */ +/* { dg-final { scan-assembler-times "fuse_or_add/0" 6 } } */ +/* { dg-final { scan-assembler-times "fuse_add_and/0" 8 } } */ +/* { dg-final { scan-assembler-times "fuse_add_and/2" 8 } } */ +/* { dg-final { scan-assembler-times "fuse_subf_and/0" 8 } } */ +/* { dg-final { scan-assembler-times "fuse_subf_and/1" 8 } } */ +/* { dg-final { scan-assembler-times "fuse_add_nand/2" 12 } } */ +/* { dg-final { scan-assembler-times "fuse_add_nor/2" 12 } } */ +/* { dg-final { scan-assembler-times "fuse_add_or/2" 12 } } */ +/* { dg-final { scan-assembler-times "fuse_and_rsubf/2" 12 } } */ +/* { dg-final { scan-assembler-times "fuse_and_subf/2" 12 } } */ +/* { dg-final { scan-assembler-times "fuse_nand_add/2" 12 } } */ +/* { dg-final { scan-assembler-times "fuse_nand_subf/2" 12 } } */ +/* { dg-final { scan-assembler-times "fuse_nor_add/2" 12 } } */ +/* { dg-final { scan-assembler-times "fuse_nor_subf/2" 12 } } */ +/* { dg-final { scan-assembler-times "fuse_or_rsubf/2" 12 } } */ +/* { dg-final { scan-assembler-times "fuse_or_subf/2" 12 } } */ +/* { dg-final { scan-assembler-times "fuse_subf_and/2" 16 } } */ +/* { dg-final { scan-assembler-times "fuse_and_add/2" 22 } } */ +/* { dg-final { scan-assembler-times "fuse_or_add/2" 22 } } */ +/* { dg-final { scan-assembler-times "fuse_subf_nand/2" 24 } } */ +/* { dg-final { scan-assembler-times "fuse_subf_nor/2" 24 } } */ +/* { dg-final { scan-assembler-times "fuse_subf_or/2" 24 } } */ + diff --git a/gcc/testsuite/gfortran.dg/gomp/class-firstprivate-1.f90 b/gcc/testsuite/gfortran.dg/gomp/class-firstprivate-1.f90 new file mode 100644 index 0000000..0ff851d --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/class-firstprivate-1.f90 @@ -0,0 +1,62 @@ +! { dg-do compile } +! { dg-prune-output "compilation terminated." } +! +! FIRSTPRIVATE + class array +! +! For now: Expected to give "Sorry" for polymorphic arrays. +! +! Polymorphic arrays are tricky - at least if not allocatable, they become: +! var.0 = var._data.data +! which needs to be handled properly. +! +! +program select_type_openmp + use iso_c_binding + !use omp_lib + implicit none + integer :: i + integer :: A(4) + type(c_ptr) :: B(4) + + B = [(c_null_ptr, i=1,4)] + A = [1,2,3,4] + call sub(A, B) +contains + subroutine sub(val1, val2) + class(*) :: val1(4) + type(c_ptr) :: val2(2:5) + + !$OMP PARALLEL firstprivate(val2) + do i = 2, 5 + if (c_associated (val2(i))) stop 123 + end do + !$OMP END PARALLEL + + !$OMP PARALLEL firstprivate(val1) ! { dg-error "Sorry, polymorphic arrays not yet supported for firstprivate" } + select type (val1) + type is (integer) + if (size(val1) /= 4) stop 33 + if (any (val1 /= [1, 2, 3, 4])) stop 4549 + val1 = [32,6,48,28] + class default + stop 99 + end select + select type (val1) + type is (integer) + if (size(val1) /= 4) stop 33 + if (any (val1 /= [32,6,48,28])) stop 4512 + class default + stop 99 + end select + !$OMP END PARALLEL + + select type (val1) + type is (integer) + if (size(val1) /= 4) stop 33 + if (any (val1 /= [1, 2, 3, 4])) stop 454 + class default + stop 99 + end select + print *, "PASS!" + end subroutine +end program select_type_openmp diff --git a/gcc/testsuite/gfortran.dg/gomp/class-firstprivate-2.f90 b/gcc/testsuite/gfortran.dg/gomp/class-firstprivate-2.f90 new file mode 100644 index 0000000..3542237 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/class-firstprivate-2.f90 @@ -0,0 +1,54 @@ +! { dg-do compile } +! { dg-prune-output "compilation terminated." } +! +! FIRSTPRIVATE + class array +! +! For now: Expected to give "Sorry" for polymorphic arrays. +! +! Polymorphic arrays are tricky - at least if not allocatable, they become: +! var.0 = var._data.data +! which needs to be handled properly. +! +! +program select_type_openmp + !use omp_lib + implicit none + class(*), allocatable :: B(:) + + allocate(B, source=["abcdef","cdefi2"]) + allocate(B, source=[1,2,3]) + call sub(B) +contains + subroutine sub(val2) + class(*), allocatable :: val2(:) + + !$OMP PARALLEL firstprivate(val2) ! { dg-error "Sorry, polymorphic arrays not yet supported for firstprivate" } + if (.not.allocated(val2)) stop 3 + select type (val2) + type is (character(len=*)) + if (len(val2) /= 6) stop 44 + if (val2(1) /= "abcdef" .or. val2(2) /= "cdefi2") stop 4545 + val2 = ["123456", "789ABC"] + class default + stop 991 + end select + select type (val2) + type is (character(len=*)) + if (len(val2) /= 6) stop 44 + if (val2(1) /= "123456" .or. val2(2) /= "789ABC") stop 453 + class default + stop 991 + end select + !$OMP END PARALLEL + + if (.not.allocated(val2)) stop 3 + select type (val2) + type is (character(len=*)) + if (len(val2) /= 6) stop 44 + if (val2(1) /= "abcdef" .or. val2(2) /= "cdefi2") stop 456 + class default + stop 991 + end select + print *, "PASS!" + end subroutine +end program select_type_openmp diff --git a/gcc/testsuite/gfortran.dg/gomp/class-firstprivate-3.f90 b/gcc/testsuite/gfortran.dg/gomp/class-firstprivate-3.f90 new file mode 100644 index 0000000..c83bf29 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/class-firstprivate-3.f90 @@ -0,0 +1,61 @@ +! { dg-do compile } +! { dg-prune-output "compilation terminated." } +! +! FIRSTPRIVATE + class array +! +! For now: Expected to give "Sorry" for polymorphic arrays. +! +! Polymorphic arrays are tricky - at least if not allocatable, they become: +! var.0 = var._data.data +! which needs to be handled properly. +! +! +program select_type_openmp + use iso_c_binding + !use omp_lib + implicit none + call sub +contains + subroutine sub + integer :: i + class(*), allocatable :: val1(:) + type(c_ptr), allocatable :: val2(:) + + allocate(val1, source=[1, 2, 3, 4]) + allocate(val2(2:5)) + val2 = c_null_ptr + + !$OMP PARALLEL firstprivate(val2) + do i = 2, 5 + if (c_associated (val2(i))) stop 123 + end do + !$OMP END PARALLEL + + !$OMP PARALLEL firstprivate(val1) ! { dg-error "Sorry, polymorphic arrays not yet supported for firstprivate" } + select type (val1) + type is (integer) + if (size(val1) /= 4) stop 33 + if (any (val1 /= [1, 2, 3, 4])) stop 4549 + val1 = [32,6,48,28] + class default + stop 99 + end select + select type (val1) + type is (integer) + if (size(val1) /= 4) stop 33 + if (any (val1 /= [32,6,48,28])) stop 4512 + class default + stop 99 + end select + !$OMP END PARALLEL + + select type (val1) + type is (integer) + if (size(val1) /= 4) stop 33 + if (any (val1 /= [1, 2, 3, 4])) stop 454 + class default + stop 99 + end select + print *, "PASS!" + end subroutine +end program select_type_openmp diff --git a/gcc/testsuite/gfortran.dg/gomp/class-firstprivate-4.f90 b/gcc/testsuite/gfortran.dg/gomp/class-firstprivate-4.f90 new file mode 100644 index 0000000..237c6c5 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/class-firstprivate-4.f90 @@ -0,0 +1,44 @@ +! { dg-do compile } +! { dg-prune-output "compilation terminated." } +! +! FIRSTPRIVATE + class array +! +! For now: Expected to give "Sorry" for polymorphic arrays. +! +! Polymorphic arrays are tricky - at least if not allocatable, they become: +! var.0 = var._data.data +! which needs to be handled properly. +! +! +program select_type_openmp + use iso_c_binding + !use omp_lib + implicit none + integer x(4) + x = [1, 2, 3, 4] + call sub(x) + if (any (x /= [1,2,3,4])) stop 3 +contains + subroutine sub(val1) + integer :: i + class(*) :: val1(4) + + !$OMP PARALLEL firstprivate(val1) ! { dg-error "Sorry, polymorphic arrays not yet supported for firstprivate" } + select type (val1) + type is (integer) + if (size(val1) /= 4) stop 33 + if (any (val1 /= [1, 2, 3, 4])) stop 4549 + val1 = [32,6,48,28] + class default + stop 99 + end select + select type (val1) + type is (integer) + if (size(val1) /= 4) stop 34 + if (any (val1 /= [32,6,48,28])) stop 4512 + class default + stop 98 + end select + !$OMP END PARALLEL + end +end diff --git a/gcc/tree-ssa-ifcombine.c b/gcc/tree-ssa-ifcombine.c index 836a12d..f93e04a 100644 --- a/gcc/tree-ssa-ifcombine.c +++ b/gcc/tree-ssa-ifcombine.c @@ -40,6 +40,8 @@ along with GCC; see the file COPYING3. If not see #include "gimplify-me.h" #include "tree-cfg.h" #include "tree-ssa.h" +#include "attribs.h" +#include "asan.h" #ifndef LOGICAL_OP_NON_SHORT_CIRCUIT #define LOGICAL_OP_NON_SHORT_CIRCUIT \ @@ -567,7 +569,7 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv, if (param_logical_op_non_short_circuit != -1) logical_op_non_short_circuit = param_logical_op_non_short_circuit; - if (!logical_op_non_short_circuit || flag_sanitize_coverage) + if (!logical_op_non_short_circuit || sanitize_coverage_p ()) return false; /* Only do this optimization if the inner bb contains only the conditional. */ if (!gsi_one_before_end_p (gsi_start_nondebug_after_labels_bb (inner_cond_bb))) diff --git a/gcc/value-range.cc b/gcc/value-range.cc index 865344f..8d7b46c 100644 --- a/gcc/value-range.cc +++ b/gcc/value-range.cc @@ -28,6 +28,7 @@ along with GCC; see the file COPYING3. If not see #include "ssa.h" #include "tree-pretty-print.h" #include "fold-const.h" +#include "gimple-range.h" // Here we copy between any two irange's. The ranges can be legacy or // multi-ranges, and copying between any combination works correctly. @@ -454,8 +455,10 @@ irange::legacy_equal_p (const irange &other) const if (m_kind != other.m_kind) return false; - if (m_kind == VR_UNDEFINED || m_kind == VR_VARYING) + if (m_kind == VR_UNDEFINED) return true; + if (m_kind == VR_VARYING) + return range_compatible_p (type (), other.type ()); return (vrp_operand_equal_p (tree_lower_bound (0), other.tree_lower_bound (0)) && vrp_operand_equal_p (tree_upper_bound (0), @@ -2245,6 +2248,14 @@ range_tests_legacy () copy = legacy_range; ASSERT_TRUE (copy.varying_p ()); } + + // VARYING of different sizes should not be equal. + int_range_max r0 (integer_type_node); + int_range_max r1 (short_integer_type_node); + ASSERT_TRUE (r0 != r1); + value_range vr0 (integer_type_node); + int_range_max vr1 (short_integer_type_node); + ASSERT_TRUE (vr0 != vr1); } // Simulate -fstrict-enums where the domain of a type is less than the diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog index 8dec62e..8a5289a 100644 --- a/libgomp/ChangeLog +++ b/libgomp/ChangeLog @@ -1,3 +1,10 @@ +2021-05-24 Tobias Burnus <tobias@codesourcery.com> + + PR fortran/86470 + * testsuite/libgomp.fortran/class-firstprivate-1.f90: New test. + * testsuite/libgomp.fortran/class-firstprivate-2.f90: New test. + * testsuite/libgomp.fortran/class-firstprivate-3.f90: New test. + 2021-05-22 Thomas Schwinge <thomas@codesourcery.com> PR testsuite/90115 diff --git a/libgomp/testsuite/libgomp.c-c++-common/reduction-17.c b/libgomp/testsuite/libgomp.c-c++-common/reduction-17.c new file mode 100644 index 0000000..5e680d6 --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/reduction-17.c @@ -0,0 +1,16 @@ +/* PR middle-end/99928 */ +/* { dg-do run } */ + +#define N 64 + +int +main () +{ + int r = 0, i; + #pragma omp teams distribute simd reduction(+:r) + for (i = 0; i < N; i++) + r += i; + if (r != N * (N - 1) / 2) + __builtin_abort (); + return 0; +} diff --git a/libgomp/testsuite/libgomp.fortran/class-firstprivate-1.f90 b/libgomp/testsuite/libgomp.fortran/class-firstprivate-1.f90 new file mode 100644 index 0000000..b77117e --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/class-firstprivate-1.f90 @@ -0,0 +1,323 @@ +! FIRSTPRIVATE: CLASS(*) + intrinsic types +program select_type_openmp + implicit none + class(*), allocatable :: val1, val1a, val2, val3 + + call sub() ! local var + + call sub2(val1, val1a, val2, val3) ! allocatable args + + allocate(val1, source=7) + allocate(val1a, source=7) + allocate(val2, source="abcdef") + allocate(val3, source=4_"zyx4") + call sub3(val1, val1a, val2, val3) ! nonallocatable vars + deallocate(val1, val1a, val2, val3) +contains +subroutine sub() + class(*), allocatable :: val1, val1a, val2, val3 + allocate(val1a, source=7) + allocate(val2, source="abcdef") + allocate(val3, source=4_"zyx4") + + if (allocated(val1)) stop 1 + + !$OMP PARALLEL firstprivate(val1, val1a, val2, val3) + if (allocated(val1)) stop 2 + if (.not.allocated(val1a)) stop 3 + if (.not.allocated(val2)) stop 4 + if (.not.allocated(val3)) stop 5 + + allocate(val1, source=7) + + select type (val1) + type is (integer) + if (val1 /= 7) stop 6 + val1 = 8 + class default + stop 7 + end select + + select type (val1a) + type is (integer) + if (val1a /= 7) stop 8 + val1a = 8 + class default + stop 9 + end select + + select type (val2) + type is (character(len=*)) + if (len(val2) /= 6) stop 10 + if (val2 /= "abcdef") stop 11 + val2 = "123456" + class default + stop 12 + end select + + select type (val3) + type is (character(len=*, kind=4)) + if (len(val3) /= 4) stop 13 + if (val3 /= 4_"zyx4") stop 14 + val3 = 4_"AbCd" + class default + stop 15 + end select + + select type (val3) + type is (character(len=*, kind=4)) + if (len(val3) /= 4) stop 16 + if (val3 /= 4_"AbCd") stop 17 + val3 = 4_"1ab2" + class default + stop 18 + end select + + select type (val2) + type is (character(len=*)) + if (len(val2) /= 6) stop 19 + if (val2 /= "123456") stop 20 + val2 = "A2C4E6" + class default + stop 21 + end select + + select type (val1) + type is (integer) + if (val1 /= 8) stop 22 + val1 = 9 + class default + stop 23 + end select + + select type (val1a) + type is (integer) + if (val1a /= 8) stop 24 + val1a = 9 + class default + stop 25 + end select + !$OMP END PARALLEL + + if (allocated(val1)) stop 26 + if (.not. allocated(val1a)) stop 27 + if (.not. allocated(val2)) stop 28 + + select type (val2) + type is (character(len=*)) + if (len(val2) /= 6) stop 29 + if (val2 /= "abcdef") stop 30 + class default + stop 31 + end select + select type (val3) + type is (character(len=*,kind=4)) + if (len(val3) /= 4) stop 32 + if (val3 /= 4_"zyx4") stop 33 + class default + stop 34 + end select + deallocate(val1a, val2, val3) +end subroutine sub + +subroutine sub2(val1, val1a, val2, val3) + class(*), allocatable :: val1, val1a, val2, val3 + optional :: val1a + allocate(val1a, source=7) + allocate(val2, source="abcdef") + allocate(val3, source=4_"zyx4") + + if (allocated(val1)) stop 35 + + !$OMP PARALLEL firstprivate(val1, val1a, val2, val3) + if (allocated(val1)) stop 36 + if (.not.allocated(val1a)) stop 37 + if (.not.allocated(val2)) stop 38 + if (.not.allocated(val3)) stop 39 + + allocate(val1, source=7) + + select type (val1) + type is (integer) + if (val1 /= 7) stop 40 + val1 = 8 + class default + stop 41 + end select + + select type (val1a) + type is (integer) + if (val1a /= 7) stop 42 + val1a = 8 + class default + stop 43 + end select + + select type (val2) + type is (character(len=*)) + if (len(val2) /= 6) stop 44 + if (val2 /= "abcdef") stop 45 + val2 = "123456" + class default + stop 46 + end select + + select type (val3) + type is (character(len=*, kind=4)) + if (len(val3) /= 4) stop 47 + if (val3 /= 4_"zyx4") stop 48 + val3 = "AbCd" + class default + stop 49 + end select + + select type (val3) + type is (character(len=*, kind=4)) + if (len(val3) /= 4) stop 50 + if (val3 /= 4_"AbCd") stop 51 + val3 = 4_"1ab2" + class default + stop 52 + end select + + select type (val2) + type is (character(len=*)) + if (len(val2) /= 6) stop 53 + if (val2 /= "123456") stop 54 + val2 = "A2C4E6" + class default + stop 55 + end select + + select type (val1) + type is (integer) + if (val1 /= 8) stop 56 + val1 = 9 + class default + stop 57 + end select + + select type (val1a) + type is (integer) + if (val1a /= 8) stop 58 + val1a = 9 + class default + stop 59 + end select + !$OMP END PARALLEL + + if (allocated(val1)) stop 60 + if (.not. allocated(val1a)) stop 61 + if (.not. allocated(val2)) stop 62 + + select type (val2) + type is (character(len=*)) + if (len(val2) /= 6) stop 63 + if (val2 /= "abcdef") stop 64 + class default + stop 65 + end select + + select type (val3) + type is (character(len=*, kind=4)) + if (len(val3) /= 4) stop 66 + if (val3 /= 4_"zyx4") stop 67 + val3 = 4_"AbCd" + class default + stop 68 + end select + deallocate(val1a, val2, val3) +end subroutine sub2 + +subroutine sub3(val1, val1a, val2, val3) + class(*) :: val1, val1a, val2, val3 + optional :: val1a + + !$OMP PARALLEL firstprivate(val1, val1a, val2, val3) + select type (val1) + type is (integer) + if (val1 /= 7) stop 69 + val1 = 8 + class default + stop 70 + end select + + select type (val1a) + type is (integer) + if (val1a /= 7) stop 71 + val1a = 8 + class default + stop 72 + end select + + select type (val2) + type is (character(len=*)) + if (len(val2) /= 6) stop 73 + if (val2 /= "abcdef") stop 74 + val2 = "123456" + class default + stop 75 + end select + + select type (val3) + type is (character(len=*, kind=4)) + if (len(val3) /= 4) stop 76 + if (val3 /= 4_"zyx4") stop 77 + val3 = 4_"AbCd" + class default + stop 78 + end select + + select type (val3) + type is (character(len=*, kind=4)) + if (len(val3) /= 4) stop 79 + if (val3 /= 4_"AbCd") stop 80 + val3 = 4_"1ab2" + class default + stop 81 + end select + + select type (val2) + type is (character(len=*)) + if (len(val2) /= 6) stop 82 + if (val2 /= "123456") stop 83 + val2 = "A2C4E6" + class default + stop 84 + end select + + select type (val1) + type is (integer) + if (val1 /= 8) stop 85 + val1 = 9 + class default + stop 86 + end select + + select type (val1a) + type is (integer) + if (val1a /= 8) stop 87 + val1a = 9 + class default + stop 88 + end select + !$OMP END PARALLEL + + select type (val2) + type is (character(len=*)) + if (len(val2) /= 6) stop 89 + if (val2 /= "abcdef") stop 90 + class default + stop 91 + end select + + select type (val3) + type is (character(len=*, kind=4)) + if (len(val3) /= 4) stop 92 + if (val3 /= 4_"zyx4") stop 93 + val3 = 4_"AbCd" + class default + stop 94 + end select +end subroutine sub3 +end program select_type_openmp diff --git a/libgomp/testsuite/libgomp.fortran/class-firstprivate-2.f90 b/libgomp/testsuite/libgomp.fortran/class-firstprivate-2.f90 new file mode 100644 index 0000000..7528d32 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/class-firstprivate-2.f90 @@ -0,0 +1,334 @@ +! FIRSTPRIVATE: CLASS(t) + derived types +program select_type_openmp + implicit none + type t + end type t + type, extends(t) :: t_int + integer :: i + end type + type, extends(t) :: t_char1 + character(len=:, kind=1), allocatable :: str + end type + type, extends(t) :: t_char4 + character(len=:, kind=4), allocatable :: str + end type + class(t), allocatable :: val1, val1a, val2, val3 + + call sub() ! local var + + call sub2(val1, val1a, val2, val3) ! allocatable args + + allocate(val1, source=t_int(7)) + allocate(val1a, source=t_int(7)) + allocate(val2, source=t_char1("abcdef")) + allocate(val3, source=t_char4(4_"zyx4")) + call sub3(val1, val1a, val2, val3) ! nonallocatable vars + deallocate(val1, val1a, val2, val3) +contains +subroutine sub() + class(t), allocatable :: val1, val1a, val2, val3 + allocate(val1a, source=t_int(7)) + allocate(val2, source=t_char1("abcdef")) + allocate(val3, source=t_char4(4_"zyx4")) + + if (allocated(val1)) stop 1 + + !$OMP PARALLEL firstprivate(val1, val1a, val2, val3) + if (allocated(val1)) stop 2 + if (.not.allocated(val1a)) stop 3 + if (.not.allocated(val2)) stop 4 + if (.not.allocated(val3)) stop 5 + + allocate(val1, source=t_int(7)) + + select type (val1) + type is (t_int) + if (val1%i /= 7) stop 6 + val1%i = 8 + class default + stop 7 + end select + + select type (val1a) + type is (t_int) + if (val1a%i /= 7) stop 8 + val1a%i = 8 + class default + stop 9 + end select + + select type (val2) + type is (t_char1) + if (len(val2%str) /= 6) stop 10 + if (val2%str /= "abcdef") stop 11 + val2%str = "123456" + class default + stop 12 + end select + + select type (val3) + type is (t_char4) + if (len(val3%str) /= 4) stop 13 + if (val3%str /= 4_"zyx4") stop 14 + val3%str = 4_"AbCd" + class default + stop 15 + end select + + select type (val3) + type is (t_char4) + if (len(val3%str) /= 4) stop 16 + if (val3%str /= 4_"AbCd") stop 17 + val3%str = 4_"1ab2" + class default + stop 18 + end select + + select type (val2) + type is (t_char1) + if (len(val2%str) /= 6) stop 19 + if (val2%str /= "123456") stop 20 + val2%str = "A2C4E6" + class default + stop 21 + end select + + select type (val1) + type is (t_int) + if (val1%i /= 8) stop 22 + val1%i = 9 + class default + stop 23 + end select + + select type (val1a) + type is (t_int) + if (val1a%i /= 8) stop 24 + val1a%i = 9 + class default + stop 25 + end select + !$OMP END PARALLEL + + if (allocated(val1)) stop 26 + if (.not. allocated(val1a)) stop 27 + if (.not. allocated(val2)) stop 28 + + select type (val2) + type is (t_char1) + if (len(val2%str) /= 6) stop 29 + if (val2%str /= "abcdef") stop 30 + class default + stop 31 + end select + select type (val3) + type is (t_char4) + if (len(val3%str) /= 4) stop 32 + if (val3%str /= 4_"zyx4") stop 33 + class default + stop 34 + end select + deallocate(val1a,val2, val3) +end subroutine sub + +subroutine sub2(val1, val1a, val2, val3) + class(t), allocatable :: val1, val1a, val2, val3 + optional :: val1a + allocate(val1a, source=t_int(7)) + allocate(val2, source=t_char1("abcdef")) + allocate(val3, source=t_char4(4_"zyx4")) + + if (allocated(val1)) stop 35 + + !$OMP PARALLEL firstprivate(val1, val1a, val2, val3) + if (allocated(val1)) stop 36 + if (.not.allocated(val1a)) stop 37 + if (.not.allocated(val2)) stop 38 + if (.not.allocated(val3)) stop 39 + + allocate(val1, source=t_int(7)) + + select type (val1) + type is (t_int) + if (val1%i /= 7) stop 40 + val1%i = 8 + class default + stop 41 + end select + + select type (val1a) + type is (t_int) + if (val1a%i /= 7) stop 42 + val1a%i = 8 + class default + stop 43 + end select + + select type (val2) + type is (t_char1) + if (len(val2%str) /= 6) stop 44 + if (val2%str /= "abcdef") stop 45 + val2%str = "123456" + class default + stop 46 + end select + + select type (val3) + type is (t_char4) + if (len(val3%str) /= 4) stop 47 + if (val3%str /= 4_"zyx4") stop 48 + val3%str = "AbCd" + class default + stop 49 + end select + + select type (val3) + type is (t_char4) + if (len(val3%str) /= 4) stop 50 + if (val3%str /= 4_"AbCd") stop 51 + val3%str = 4_"1ab2" + class default + stop 52 + end select + + select type (val2) + type is (t_char1) + if (len(val2%str) /= 6) stop 53 + if (val2%str /= "123456") stop 54 + val2%str = "A2C4E6" + class default + stop 55 + end select + + select type (val1) + type is (t_int) + if (val1%i /= 8) stop 56 + val1%i = 9 + class default + stop 57 + end select + + select type (val1a) + type is (t_int) + if (val1a%i /= 8) stop 58 + val1a%i = 9 + class default + stop 59 + end select + !$OMP END PARALLEL + + if (allocated(val1)) stop 60 + if (.not. allocated(val1a)) stop 61 + if (.not. allocated(val2)) stop 62 + + select type (val2) + type is (t_char1) + if (len(val2%str) /= 6) stop 63 + if (val2%str /= "abcdef") stop 64 + class default + stop 65 + end select + + select type (val3) + type is (t_char4) + if (len(val3%str) /= 4) stop 66 + if (val3%str /= 4_"zyx4") stop 67 + val3%str = 4_"AbCd" + class default + stop 68 + end select + deallocate(val1a, val2, val3) +end subroutine sub2 + +subroutine sub3(val1, val1a, val2, val3) + class(t) :: val1, val1a, val2, val3 + optional :: val1a + + !$OMP PARALLEL firstprivate(val1, val1a, val2, val3) + select type (val1) + type is (t_int) + if (val1%i /= 7) stop 69 + val1%i = 8 + class default + stop 70 + end select + + select type (val1a) + type is (t_int) + if (val1a%i /= 7) stop 71 + val1a%i = 8 + class default + stop 72 + end select + + select type (val2) + type is (t_char1) + if (len(val2%str) /= 6) stop 73 + if (val2%str /= "abcdef") stop 74 + val2%str = "123456" + class default + stop 75 + end select + + select type (val3) + type is (t_char4) + if (len(val3%str) /= 4) stop 76 + if (val3%str /= 4_"zyx4") stop 77 + val3%str = 4_"AbCd" + class default + stop 78 + end select + + select type (val3) + type is (t_char4) + if (len(val3%str) /= 4) stop 79 + if (val3%str /= 4_"AbCd") stop 80 + val3%str = 4_"1ab2" + class default + stop 81 + end select + + select type (val2) + type is (t_char1) + if (len(val2%str) /= 6) stop 82 + if (val2%str /= "123456") stop 83 + val2%str = "A2C4E6" + class default + stop 84 + end select + + select type (val1) + type is (t_int) + if (val1%i /= 8) stop 85 + val1%i = 9 + class default + stop 86 + end select + + select type (val1a) + type is (t_int) + if (val1a%i /= 8) stop 87 + val1a%i = 9 + class default + stop 88 + end select + !$OMP END PARALLEL + + select type (val2) + type is (t_char1) + if (len(val2%str) /= 6) stop 89 + if (val2%str /= "abcdef") stop 90 + class default + stop 91 + end select + + select type (val3) + type is (t_char4) + if (len(val3%str) /= 4) stop 92 + if (val3%str /= 4_"zyx4") stop 93 + val3%str = 4_"AbCd" + class default + stop 94 + end select +end subroutine sub3 +end program select_type_openmp diff --git a/libgomp/testsuite/libgomp.fortran/class-firstprivate-3.f90 b/libgomp/testsuite/libgomp.fortran/class-firstprivate-3.f90 new file mode 100644 index 0000000..a450fde --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/class-firstprivate-3.f90 @@ -0,0 +1,334 @@ +! FIRSTPRIVATE: CLASS(*) + derived types +program select_type_openmp + implicit none + type t + end type t + type, extends(t) :: t_int + integer :: i + end type + type, extends(t) :: t_char1 + character(len=:, kind=1), allocatable :: str + end type + type, extends(t) :: t_char4 + character(len=:, kind=4), allocatable :: str + end type + class(*), allocatable :: val1, val1a, val2, val3 + + call sub() ! local var + + call sub2(val1, val1a, val2, val3) ! allocatable args + + allocate(val1, source=t_int(7)) + allocate(val1a, source=t_int(7)) + allocate(val2, source=t_char1("abcdef")) + allocate(val3, source=t_char4(4_"zyx4")) + call sub3(val1, val1a, val2, val3) ! nonallocatable vars + deallocate(val1, val1a, val2, val3) +contains +subroutine sub() + class(*), allocatable :: val1, val1a, val2, val3 + allocate(val1a, source=t_int(7)) + allocate(val2, source=t_char1("abcdef")) + allocate(val3, source=t_char4(4_"zyx4")) + + if (allocated(val1)) stop 1 + + !$OMP PARALLEL firstprivate(val1, val1a, val2, val3) + if (allocated(val1)) stop 2 + if (.not.allocated(val1a)) stop 3 + if (.not.allocated(val2)) stop 4 + if (.not.allocated(val3)) stop 5 + + allocate(val1, source=t_int(7)) + + select type (val1) + type is (t_int) + if (val1%i /= 7) stop 6 + val1%i = 8 + class default + stop 7 + end select + + select type (val1a) + type is (t_int) + if (val1a%i /= 7) stop 8 + val1a%i = 8 + class default + stop 9 + end select + + select type (val2) + type is (t_char1) + if (len(val2%str) /= 6) stop 10 + if (val2%str /= "abcdef") stop 11 + val2%str = "123456" + class default + stop 12 + end select + + select type (val3) + type is (t_char4) + if (len(val3%str) /= 4) stop 13 + if (val3%str /= 4_"zyx4") stop 14 + val3%str = 4_"AbCd" + class default + stop 15 + end select + + select type (val3) + type is (t_char4) + if (len(val3%str) /= 4) stop 16 + if (val3%str /= 4_"AbCd") stop 17 + val3%str = 4_"1ab2" + class default + stop 18 + end select + + select type (val2) + type is (t_char1) + if (len(val2%str) /= 6) stop 19 + if (val2%str /= "123456") stop 20 + val2%str = "A2C4E6" + class default + stop 21 + end select + + select type (val1) + type is (t_int) + if (val1%i /= 8) stop 22 + val1%i = 9 + class default + stop 23 + end select + + select type (val1a) + type is (t_int) + if (val1a%i /= 8) stop 24 + val1a%i = 9 + class default + stop 25 + end select + !$OMP END PARALLEL + + if (allocated(val1)) stop 26 + if (.not. allocated(val1a)) stop 27 + if (.not. allocated(val2)) stop 28 + + select type (val2) + type is (t_char1) + if (len(val2%str) /= 6) stop 29 + if (val2%str /= "abcdef") stop 30 + class default + stop 31 + end select + select type (val3) + type is (t_char4) + if (len(val3%str) /= 4) stop 32 + if (val3%str /= 4_"zyx4") stop 33 + class default + stop 34 + end select + deallocate(val1a,val2, val3) +end subroutine sub + +subroutine sub2(val1, val1a, val2, val3) + class(*), allocatable :: val1, val1a, val2, val3 + optional :: val1a + allocate(val1a, source=t_int(7)) + allocate(val2, source=t_char1("abcdef")) + allocate(val3, source=t_char4(4_"zyx4")) + + if (allocated(val1)) stop 35 + + !$OMP PARALLEL firstprivate(val1, val1a, val2, val3) + if (allocated(val1)) stop 36 + if (.not.allocated(val1a)) stop 37 + if (.not.allocated(val2)) stop 38 + if (.not.allocated(val3)) stop 39 + + allocate(val1, source=t_int(7)) + + select type (val1) + type is (t_int) + if (val1%i /= 7) stop 40 + val1%i = 8 + class default + stop 41 + end select + + select type (val1a) + type is (t_int) + if (val1a%i /= 7) stop 42 + val1a%i = 8 + class default + stop 43 + end select + + select type (val2) + type is (t_char1) + if (len(val2%str) /= 6) stop 44 + if (val2%str /= "abcdef") stop 45 + val2%str = "123456" + class default + stop 46 + end select + + select type (val3) + type is (t_char4) + if (len(val3%str) /= 4) stop 47 + if (val3%str /= 4_"zyx4") stop 48 + val3%str = "AbCd" + class default + stop 49 + end select + + select type (val3) + type is (t_char4) + if (len(val3%str) /= 4) stop 50 + if (val3%str /= 4_"AbCd") stop 51 + val3%str = 4_"1ab2" + class default + stop 52 + end select + + select type (val2) + type is (t_char1) + if (len(val2%str) /= 6) stop 53 + if (val2%str /= "123456") stop 54 + val2%str = "A2C4E6" + class default + stop 55 + end select + + select type (val1) + type is (t_int) + if (val1%i /= 8) stop 56 + val1%i = 9 + class default + stop 57 + end select + + select type (val1a) + type is (t_int) + if (val1a%i /= 8) stop 58 + val1a%i = 9 + class default + stop 59 + end select + !$OMP END PARALLEL + + if (allocated(val1)) stop 60 + if (.not. allocated(val1a)) stop 61 + if (.not. allocated(val2)) stop 62 + + select type (val2) + type is (t_char1) + if (len(val2%str) /= 6) stop 63 + if (val2%str /= "abcdef") stop 64 + class default + stop 65 + end select + + select type (val3) + type is (t_char4) + if (len(val3%str) /= 4) stop 66 + if (val3%str /= 4_"zyx4") stop 67 + val3%str = 4_"AbCd" + class default + stop 68 + end select + deallocate(val1a, val2, val3) +end subroutine sub2 + +subroutine sub3(val1, val1a, val2, val3) + class(*) :: val1, val1a, val2, val3 + optional :: val1a + + !$OMP PARALLEL firstprivate(val1, val1a, val2, val3) + select type (val1) + type is (t_int) + if (val1%i /= 7) stop 69 + val1%i = 8 + class default + stop 70 + end select + + select type (val1a) + type is (t_int) + if (val1a%i /= 7) stop 71 + val1a%i = 8 + class default + stop 72 + end select + + select type (val2) + type is (t_char1) + if (len(val2%str) /= 6) stop 73 + if (val2%str /= "abcdef") stop 74 + val2%str = "123456" + class default + stop 75 + end select + + select type (val3) + type is (t_char4) + if (len(val3%str) /= 4) stop 76 + if (val3%str /= 4_"zyx4") stop 77 + val3%str = 4_"AbCd" + class default + stop 78 + end select + + select type (val3) + type is (t_char4) + if (len(val3%str) /= 4) stop 79 + if (val3%str /= 4_"AbCd") stop 80 + val3%str = 4_"1ab2" + class default + stop 81 + end select + + select type (val2) + type is (t_char1) + if (len(val2%str) /= 6) stop 82 + if (val2%str /= "123456") stop 83 + val2%str = "A2C4E6" + class default + stop 84 + end select + + select type (val1) + type is (t_int) + if (val1%i /= 8) stop 85 + val1%i = 9 + class default + stop 86 + end select + + select type (val1a) + type is (t_int) + if (val1a%i /= 8) stop 87 + val1a%i = 9 + class default + stop 88 + end select + !$OMP END PARALLEL + + select type (val2) + type is (t_char1) + if (len(val2%str) /= 6) stop 89 + if (val2%str /= "abcdef") stop 90 + class default + stop 91 + end select + + select type (val3) + type is (t_char4) + if (len(val3%str) /= 4) stop 92 + if (val3%str /= 4_"zyx4") stop 93 + val3%str = 4_"AbCd" + class default + stop 94 + end select +end subroutine sub3 +end program select_type_openmp diff --git a/liboffloadmic/configure b/liboffloadmic/configure index dfa8287..dfa8287 100644..100755 --- a/liboffloadmic/configure +++ b/liboffloadmic/configure diff --git a/liboffloadmic/plugin/configure b/liboffloadmic/plugin/configure index 0b21d7d..0b21d7d 100644..100755 --- a/liboffloadmic/plugin/configure +++ b/liboffloadmic/plugin/configure diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 947b35d..3297f63 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,53 @@ +2021-05-24 François Dumont <fdumont@gcc.gnu.org> + + PR libstdc++/96088 + * include/bits/hashtable_policy.h (_Select2nd): New. + (_NodeBuilder<>): New. + (_ReuseOrAllocNode<>::operator()): Use variadic template args. + (_AllocNode<>::operator()): Likewise. + * include/bits/hashtable.h + (_Hashtable<>::__node_builder_t): New. + (_Hashtable<>::_M_insert_unique<>(_Kt&&, _Arg&&, const _NodeGenerator&)): + New. + (_Hashtable<>::_S_forward_key): New. + (_Hashtable<>::_M_insert): Use latter. + (_Hashtable<>::_M_insert(const_iterator, _Arg&&, const _NodeGenerator&, false_type)): + Instantiate node first, compute hash code second. + * testsuite/23_containers/unordered_map/96088.cc: New test. + * testsuite/23_containers/unordered_multimap/96088.cc: New test. + * testsuite/23_containers/unordered_multiset/96088.cc: New test. + * testsuite/23_containers/unordered_set/96088.cc: New test. + * testsuite/util/replacement_memory_operators.h + (counter::_M_increment): New. + (counter::_M_decrement): New. + (counter::reset()): New. + +2021-05-24 Patrick Palka <ppalka@redhat.com> + + PR libstdc++/100479 + * include/std/ranges (__detail::__non_propagating_cache): Move + definition up to before that of _CachedPosition. Make base + class _Optional_base protected instead of private. Add const + overload for operator*. + (__detail::_CachedPosition): Rewrite the partial specialization + for forward ranges as a derived class of __non_propagating_cache. + Remove the size constraint on the partial specialization for + random access ranges. Add copy/move/copy-assignment/move-assignment + members to the offset partial specialization for random + access ranges that propagate the cached value but additionally + invalidate it in the source object on move. + * testsuite/std/ranges/adaptors/100479.cc: New test. + +2021-05-24 Jonathan Wakely <jwakely@redhat.com> + + * testsuite/25_algorithms/inplace_merge/constrained.cc: Qualify + call to ranges::next. + * testsuite/25_algorithms/is_sorted/constrained.cc: Likewise. + * testsuite/25_algorithms/is_sorted_until/constrained.cc: + Likewise. + * testsuite/25_algorithms/swap_ranges/1.cc: Qualify call to + swap_ranges. + 2021-05-21 Patrick Palka <ppalka@redhat.com> PR libstdc++/100606 diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h index 6711d08..4bdbe7d 100644 --- a/libstdc++-v3/include/bits/hashtable.h +++ b/libstdc++-v3/include/bits/hashtable.h @@ -274,6 +274,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __detail::_ReuseOrAllocNode<__node_alloc_type>; using __alloc_node_gen_t = __detail::_AllocNode<__node_alloc_type>; + using __node_builder_t = + __detail::_NodeBuilder<_ExtractKey>; // Simple RAII type for managing a node containing an element struct _Scoped_node @@ -850,9 +852,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION iterator _M_emplace(const_iterator, false_type __uks, _Args&&... __args); + template<typename _Kt, typename _Arg, typename _NodeGenerator> + std::pair<iterator, bool> + _M_insert_unique(_Kt&&, _Arg&&, const _NodeGenerator&); + + template<typename _Kt> + static typename conditional< + __and_<__is_nothrow_invocable<_Hash&, const key_type&>, + __not_<__is_nothrow_invocable<_Hash&, _Kt>>>::value, + key_type, _Kt&&>::type + _S_forward_key(_Kt&& __k) + { return std::forward<_Kt>(__k); } + + static const key_type& + _S_forward_key(const key_type& __k) + { return __k; } + + static key_type&& + _S_forward_key(key_type&& __k) + { return std::move(__k); } + template<typename _Arg, typename _NodeGenerator> std::pair<iterator, bool> - _M_insert(_Arg&&, const _NodeGenerator&, true_type __uks); + _M_insert(_Arg&& __arg, const _NodeGenerator& __node_gen, + true_type /* __uks */) + { + return _M_insert_unique( + _S_forward_key(_ExtractKey{}(std::forward<_Arg>(__arg))), + std::forward<_Arg>(__arg), __node_gen); + } template<typename _Arg, typename _NodeGenerator> iterator @@ -2067,22 +2095,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typename _ExtractKey, typename _Equal, typename _Hash, typename _RangeHash, typename _Unused, typename _RehashPolicy, typename _Traits> - template<typename _Arg, typename _NodeGenerator> + template<typename _Kt, typename _Arg, typename _NodeGenerator> auto _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>:: - _M_insert(_Arg&& __v, const _NodeGenerator& __node_gen, - true_type /* __uks */) + _M_insert_unique(_Kt&& __k, _Arg&& __v, + const _NodeGenerator& __node_gen) -> pair<iterator, bool> { - const key_type& __k = _ExtractKey{}(__v); - __hash_code __code = this->_M_hash_code(__k); + __hash_code __code = this->_M_hash_code_tr(__k); size_type __bkt = _M_bucket_index(__code); - if (__node_ptr __node = _M_find_node(__bkt, __k, __code)) + if (__node_ptr __node = _M_find_node_tr(__bkt, __k, __code)) return { iterator(__node), false }; - _Scoped_node __node{ __node_gen(std::forward<_Arg>(__v)), this }; + _Scoped_node __node { + __node_builder_t::_S_build(std::forward<_Kt>(__k), + std::forward<_Arg>(__v), + __node_gen), + this + }; auto __pos = _M_insert_unique_node(__bkt, __code, __node._M_node); __node._M_node = nullptr; @@ -2103,12 +2135,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION false_type /* __uks */) -> iterator { - // First compute the hash code so that we don't do anything if it - // throws. - __hash_code __code = this->_M_hash_code(_ExtractKey{}(__v)); - - // Second allocate new node so that we don't rehash if it throws. + // First allocate new node so that we don't do anything if it throws. _Scoped_node __node{ __node_gen(std::forward<_Arg>(__v)), this }; + + // Second compute the hash code so that we don't rehash if it throws. + __hash_code __code + = this->_M_hash_code(_ExtractKey{}(__node._M_node->_M_v())); + auto __pos = _M_insert_multi_node(__hint._M_cur, __code, __node._M_node); __node._M_node = nullptr; diff --git a/libstdc++-v3/include/bits/hashtable_policy.h b/libstdc++-v3/include/bits/hashtable_policy.h index ad8a4ec..1090a39 100644 --- a/libstdc++-v3/include/bits/hashtable_policy.h +++ b/libstdc++-v3/include/bits/hashtable_policy.h @@ -94,6 +94,45 @@ namespace __detail { return std::get<0>(std::forward<_Tp>(__x)); } }; + struct _Select2nd + { + template<typename _Tp> + auto + operator()(_Tp&& __x) const noexcept + -> decltype(std::get<1>(std::forward<_Tp>(__x))) + { return std::get<1>(std::forward<_Tp>(__x)); } + }; + + template<typename _ExKey> + struct _NodeBuilder; + + template<> + struct _NodeBuilder<_Select1st> + { + template<typename _Kt, typename _Arg, typename _NodeGenerator> + static auto + _S_build(_Kt&& __k, _Arg&& __arg, const _NodeGenerator& __node_gen) + -> decltype(__node_gen(std::piecewise_construct, + std::forward_as_tuple(std::forward<_Kt>(__k)), + std::forward_as_tuple(_Select2nd{}( + std::forward<_Arg>(__arg))))) + { + return __node_gen(std::piecewise_construct, + std::forward_as_tuple(std::forward<_Kt>(__k)), + std::forward_as_tuple(_Select2nd{}(std::forward<_Arg>(__arg)))); + } + }; + + template<> + struct _NodeBuilder<_Identity> + { + template<typename _Kt, typename _Arg, typename _NodeGenerator> + static auto + _S_build(_Kt&& __k, _Arg&&, const _NodeGenerator& __node_gen) + -> decltype(__node_gen(std::forward<_Kt>(__k))) + { return __node_gen(std::forward<_Kt>(__k)); } + }; + template<typename _NodeAlloc> struct _Hashtable_alloc; @@ -117,9 +156,9 @@ namespace __detail ~_ReuseOrAllocNode() { _M_h._M_deallocate_nodes(_M_nodes); } - template<typename _Arg> + template<typename... _Args> __node_type* - operator()(_Arg&& __arg) const + operator()(_Args&&... __args) const { if (_M_nodes) { @@ -131,7 +170,7 @@ namespace __detail __try { __node_alloc_traits::construct(__a, __node->_M_valptr(), - std::forward<_Arg>(__arg)); + std::forward<_Args>(__args)...); } __catch(...) { @@ -140,7 +179,7 @@ namespace __detail } return __node; } - return _M_h._M_allocate_node(std::forward<_Arg>(__arg)); + return _M_h._M_allocate_node(std::forward<_Args>(__args)...); } private: @@ -161,10 +200,10 @@ namespace __detail _AllocNode(__hashtable_alloc& __h) : _M_h(__h) { } - template<typename _Arg> + template<typename... _Args> __node_type* - operator()(_Arg&& __arg) const - { return _M_h._M_allocate_node(std::forward<_Arg>(__arg)); } + operator()(_Args&&... __args) const + { return _M_h._M_allocate_node(std::forward<_Args>(__args)...); } private: __hashtable_alloc& _M_h; diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index 76add25..e1df424 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -1043,6 +1043,67 @@ namespace views::__adaptor namespace __detail { + template<typename _Tp> + struct __non_propagating_cache + { + // When _Tp is not an object type (e.g. is a reference type), we make + // __non_propagating_cache<_Tp> empty rather than ill-formed so that + // users can easily conditionally declare data members with this type + // (such as join_view::_M_inner). + }; + + template<typename _Tp> + requires is_object_v<_Tp> + struct __non_propagating_cache<_Tp> : protected _Optional_base<_Tp> + { + __non_propagating_cache() = default; + + constexpr + __non_propagating_cache(const __non_propagating_cache&) noexcept + { } + + constexpr + __non_propagating_cache(__non_propagating_cache&& __other) noexcept + { __other._M_reset(); } + + constexpr __non_propagating_cache& + operator=(const __non_propagating_cache& __other) noexcept + { + if (std::__addressof(__other) != this) + this->_M_reset(); + return *this; + } + + constexpr __non_propagating_cache& + operator=(__non_propagating_cache&& __other) noexcept + { + this->_M_reset(); + __other._M_reset(); + return *this; + } + + constexpr _Tp& + operator*() noexcept + { return this->_M_get(); } + + constexpr const _Tp& + operator*() const noexcept + { return this->_M_get(); } + + template<typename _Iter> + _Tp& + _M_emplace_deref(const _Iter& __i) + { + this->_M_reset(); + // Using _Optional_base::_M_construct to initialize from '*__i' + // would incur an extra move due to the indirection, so we instead + // use placement new directly. + ::new ((void *) std::__addressof(this->_M_payload._M_payload)) _Tp(*__i); + this->_M_payload._M_engaged = true; + return this->_M_get(); + } + }; + template<range _Range> struct _CachedPosition { @@ -1064,27 +1125,26 @@ namespace views::__adaptor template<forward_range _Range> struct _CachedPosition<_Range> + : protected __non_propagating_cache<iterator_t<_Range>> { - private: - iterator_t<_Range> _M_iter{}; - - public: constexpr bool _M_has_value() const - { return _M_iter != iterator_t<_Range>{}; } + { return this->_M_is_engaged(); } constexpr iterator_t<_Range> _M_get(const _Range&) const { __glibcxx_assert(_M_has_value()); - return _M_iter; + return **this; } constexpr void _M_set(const _Range&, const iterator_t<_Range>& __it) { __glibcxx_assert(!_M_has_value()); - _M_iter = __it; + std::construct_at(std::__addressof(this->_M_payload._M_payload), + in_place, __it); + this->_M_payload._M_engaged = true; } }; @@ -1097,6 +1157,27 @@ namespace views::__adaptor range_difference_t<_Range> _M_offset = -1; public: + _CachedPosition() = default; + + constexpr + _CachedPosition(const _CachedPosition&) = default; + + constexpr + _CachedPosition(_CachedPosition&& __other) noexcept + { *this = std::move(__other); } + + constexpr _CachedPosition& + operator=(const _CachedPosition&) = default; + + constexpr _CachedPosition& + operator=(_CachedPosition&& __other) noexcept + { + // Propagate the cached offset, but invalidate the source. + _M_offset = __other._M_offset; + __other._M_offset = -1; + return *this; + } + constexpr bool _M_has_value() const { return _M_offset >= 0; } @@ -2238,66 +2319,6 @@ namespace views::__adaptor inline constexpr _DropWhile drop_while; } // namespace views - namespace __detail - { - template<typename _Tp> - struct __non_propagating_cache - { - // When _Tp is not an object type (e.g. is a reference type), we make - // __non_propagating_cache<_Tp> empty rather than ill-formed so that - // users can easily conditionally declare data members with this type - // (such as join_view::_M_inner). - }; - - template<typename _Tp> - requires is_object_v<_Tp> - struct __non_propagating_cache<_Tp> : private _Optional_base<_Tp> - { - __non_propagating_cache() = default; - - constexpr - __non_propagating_cache(const __non_propagating_cache&) noexcept - { } - - constexpr - __non_propagating_cache(__non_propagating_cache&& __other) noexcept - { __other._M_reset(); } - - constexpr __non_propagating_cache& - operator=(const __non_propagating_cache& __other) noexcept - { - if (std::__addressof(__other) != this) - this->_M_reset(); - return *this; - } - - constexpr __non_propagating_cache& - operator=(__non_propagating_cache&& __other) noexcept - { - this->_M_reset(); - __other._M_reset(); - return *this; - } - - constexpr _Tp& - operator*() noexcept - { return this->_M_get(); } - - template<typename _Iter> - _Tp& - _M_emplace_deref(const _Iter& __i) - { - this->_M_reset(); - // Using _Optional_base::_M_construct to initialize from '*__i' - // would incur an extra move due to the indirection, so we instead - // use placement new directly. - ::new ((void *) std::__addressof(this->_M_payload._M_payload)) _Tp(*__i); - this->_M_payload._M_engaged = true; - return this->_M_get(); - } - }; - } - template<input_range _Vp> requires view<_Vp> && input_range<range_reference_t<_Vp>> class join_view : public view_interface<join_view<_Vp>> diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/96088.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/96088.cc new file mode 100644 index 0000000..062c831 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_map/96088.cc @@ -0,0 +1,269 @@ +// { dg-do run { target c++11 } } + +// Copyright (C) 2021 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// libstdc++/96088 + +#include <string_view> +#include <string> +#include <unordered_map> +#include <vector> + +#include <testsuite_hooks.h> +#include <replacement_memory_operators.h> + +static constexpr std::initializer_list<std::pair<const char*, int>> lst = { + {"long_str_for_dynamic_allocating", 1} +}; + +void +test01() +{ + __gnu_test::counter::reset(); + std::unordered_map<std::string, int> um; + um.insert(lst.begin(), lst.end()); + VERIFY( um.size() == 1 ); + + VERIFY( __gnu_test::counter::count() == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 3 ); + + um.insert(lst.begin(), lst.end()); + VERIFY( um.size() == 1 ); + + VERIFY( __gnu_test::counter::count() == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 4 ); +} + +void +test02() +{ + __gnu_test::counter::reset(); + std::unordered_map<std::string, int, + std::hash<std::string_view>, + std::equal_to<std::string_view>> um; + um.insert(lst.begin(), lst.end()); + VERIFY( um.size() == 1 ); + + VERIFY( __gnu_test::counter::count() == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 3 ); + + um.insert(lst.begin(), lst.end()); + VERIFY( um.size() == 1 ); + + VERIFY( __gnu_test::counter::count() == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 3 ); +} + +std::size_t +hash_string_f(const std::string& str) noexcept +{ + std::hash<std::string> h; + return h(str); +} + +void +test11() +{ + typedef std::size_t (*hash_string_t)(const std::string&) noexcept; + __gnu_test::counter::reset(); + hash_string_t hasher = &hash_string_f; + std::unordered_map<std::string, int, + hash_string_t, + std::equal_to<std::string>> um(0, hasher); + um.insert(lst.begin(), lst.end()); + VERIFY( um.size() == 1 ); + + VERIFY( __gnu_test::counter::count() == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 3 ); + + um.insert(lst.begin(), lst.end()); + VERIFY( um.size() == 1 ); + + VERIFY( __gnu_test::counter::count() == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 4 ); +} + +std::size_t +hash_string_view_f(const std::string_view& str) noexcept +{ + std::hash<std::string_view> h; + return h(str); +} + +void +test12() +{ + typedef std::size_t (*hash_stringview_t) (const std::string_view&) noexcept; + __gnu_test::counter::reset(); + hash_stringview_t hasher = &hash_string_view_f; + std::unordered_map<std::string, int, hash_stringview_t, + std::equal_to<std::string_view>> um(0, hasher); + um.insert(lst.begin(), lst.end()); + VERIFY( um.size() == 1 ); + + VERIFY( __gnu_test::counter::count() == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 3 ); + + um.insert(lst.begin(), lst.end()); + VERIFY( um.size() == 1 ); + + VERIFY( __gnu_test::counter::count() == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 3 ); +} + +struct hash_string_functor +{ + std::size_t + operator()(const std::string& str) const noexcept + { + std::hash<std::string> h; + return h(str); + } +}; + +void +test21() +{ + __gnu_test::counter::reset(); + std::unordered_map<std::string, int, + hash_string_functor, + std::equal_to<std::string>> um; + um.insert(lst.begin(), lst.end()); + VERIFY( um.size() == 1 ); + + VERIFY( __gnu_test::counter::count() == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 3 ); + + um.insert(lst.begin(), lst.end()); + VERIFY( um.size() == 1 ); + + VERIFY( __gnu_test::counter::count() == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 4 ); +} + +struct hash_string_view_noexcept_functor +{ + std::size_t + operator()(const std::string_view& str) const noexcept + { + std::hash<std::string_view> h; + return h(str); + } +}; + +void +test22() +{ + __gnu_test::counter::reset(); + std::unordered_map<std::string, int, + hash_string_view_noexcept_functor, + std::equal_to<std::string_view>> um; + um.insert(lst.begin(), lst.end()); + VERIFY( um.size() == 1 ); + + VERIFY( __gnu_test::counter::count() == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 3 ); + + um.insert(lst.begin(), lst.end()); + VERIFY( um.size() == 1 ); + + VERIFY( __gnu_test::counter::count() == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 3 ); +} + +struct hash_string_view_functor +{ + std::size_t + operator()(const std::string_view& str) const + { + std::hash<std::string_view> h; + return h(str); + } +}; + +void +test23() +{ + __gnu_test::counter::reset(); + std::unordered_map<std::string, int, + hash_string_view_functor, + std::equal_to<std::string_view>> um; + um.insert(lst.begin(), lst.end()); + VERIFY( um.size() == 1 ); + + VERIFY( __gnu_test::counter::count() == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 3 ); + + um.insert(lst.begin(), lst.end()); + VERIFY( um.size() == 1 ); + + VERIFY( __gnu_test::counter::count() == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 3 ); +} + +void +test03() +{ + std::vector<std::pair<std::string, int>> v; + v.insert(v.end(), lst.begin(), lst.end()); + + auto __offset = __gnu_test::counter::count(); + { + __gnu_test::counter::reset(); + std::unordered_map<std::string, int, + std::hash<std::string_view>, + std::equal_to<std::string_view>> um; + um.insert(v.begin(), v.end()); + VERIFY( um.size() == 1 ); + + VERIFY( __gnu_test::counter::count() - __offset == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 3 ); + + um.insert(v.begin(), v.end()); + VERIFY( um.size() == 1 ); + + VERIFY( __gnu_test::counter::count() - __offset == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 3 ); + } + + { + __gnu_test::counter::reset(); + std::unordered_map<std::string, int, + std::hash<std::string_view>, + std::equal_to<std::string_view>> um; + um.insert(std::make_move_iterator(v.begin()), + std::make_move_iterator(v.end())); + VERIFY( um.size() == 1 ); + + VERIFY( __gnu_test::counter::count() - __offset == 2 ); + VERIFY( __gnu_test::counter::get()._M_increments == 2 ); + } +} + +int +main() +{ + test01(); + test02(); + test11(); + test12(); + test21(); + test22(); + test03(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/96088.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/96088.cc new file mode 100644 index 0000000..de7f009 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/96088.cc @@ -0,0 +1,65 @@ +// { dg-do run { target c++17 } } + +// Copyright (C) 2021 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// libstdc++/96088 + +#include <string_view> +#include <string> +#include <unordered_map> + +#include <testsuite_hooks.h> +#include <replacement_memory_operators.h> + +static constexpr std::initializer_list<std::pair<const char*, int>> lst = { + {"long_str_for_dynamic_allocating", 1} +}; + +void +test01() +{ + __gnu_test::counter::reset(); + std::unordered_multimap<std::string, int, + std::hash<std::string_view>, + std::equal_to<std::string_view>> foo; + foo.insert(lst.begin(), lst.end()); + VERIFY( foo.size() == 1 ); + + VERIFY( __gnu_test::counter::count() == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 3 ); +} + +void +test02() +{ + __gnu_test::counter::reset(); + std::unordered_multimap<std::string, int> foo; + foo.insert(lst.begin(), lst.end()); + VERIFY( foo.size() == 1 ); + + VERIFY( __gnu_test::counter::count() == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 3 ); +} + +int +main() +{ + test01(); + test02(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/96088.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/96088.cc new file mode 100644 index 0000000..b9bbf63 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/96088.cc @@ -0,0 +1,65 @@ +// { dg-do run { target c++17 } } + +// Copyright (C) 2021 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// libstdc++/96088 + +#include <string_view> +#include <string> +#include <unordered_set> + +#include <testsuite_hooks.h> +#include <replacement_memory_operators.h> + +static constexpr std::initializer_list<const char*> lst = { + "long_str_for_dynamic_allocating" +}; + +void +test01() +{ + __gnu_test::counter::reset(); + std::unordered_multiset<std::string, + std::hash<std::string_view>, + std::equal_to<std::string_view>> foo; + foo.insert(lst.begin(), lst.end()); + VERIFY( foo.size() == 1 ); + + VERIFY( __gnu_test::counter::count() == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 3 ); +} + +void +test02() +{ + __gnu_test::counter::reset(); + std::unordered_multiset<std::string> foo; + foo.insert(lst.begin(), lst.end()); + VERIFY( foo.size() == 1 ); + + VERIFY( __gnu_test::counter::count() == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 3 ); +} + +int +main() +{ + test01(); + test02(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/96088.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/96088.cc new file mode 100644 index 0000000..53bb754 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_set/96088.cc @@ -0,0 +1,271 @@ +// { dg-do run { target c++11 } } + +// Copyright (C) 2021 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// libstdc++/96088 + +#include <string_view> +#include <string> +#include <unordered_set> +#include <vector> + +#include <testsuite_hooks.h> +#include <replacement_memory_operators.h> + +static constexpr std::initializer_list<const char*> lst = { + "long_str_for_dynamic_allocating" +}; + +void +test01() +{ + __gnu_test::counter::reset(); + std::unordered_set<std::string> us; + us.insert(lst.begin(), lst.end()); + VERIFY( us.size() == 1 ); + + VERIFY( __gnu_test::counter::count() == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 3 ); + + us.insert(lst.begin(), lst.end()); + VERIFY( us.size() == 1 ); + + VERIFY( __gnu_test::counter::count() == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 4 ); +} + +void +test02() +{ + __gnu_test::counter::reset(); + std::unordered_set<std::string, + std::hash<std::string_view>, + std::equal_to<std::string_view>> us; + us.insert(lst.begin(), lst.end()); + VERIFY( us.size() == 1 ); + + VERIFY( __gnu_test::counter::count() == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 3 ); + + us.insert(lst.begin(), lst.end()); + VERIFY( us.size() == 1 ); + + VERIFY( __gnu_test::counter::count() == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 3 ); +} + +std::size_t +hash_string_f(const std::string& str) noexcept +{ + std::hash<std::string> h; + return h(str); +} + +void +test11() +{ + typedef std::size_t (*hash_string_t)(const std::string&) noexcept; + __gnu_test::counter::reset(); + hash_string_t hasher = &hash_string_f; + std::unordered_set<std::string, + hash_string_t, + std::equal_to<std::string>> us(0, hasher); + us.insert(lst.begin(), lst.end()); + VERIFY( us.size() == 1 ); + + VERIFY( __gnu_test::counter::count() == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 3 ); + + us.insert(lst.begin(), lst.end()); + VERIFY( us.size() == 1 ); + + VERIFY( __gnu_test::counter::count() == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 4 ); +} + +std::size_t +hash_string_view_f(const std::string_view& str) noexcept +{ + std::hash<std::string_view> h; + return h(str); +} + +void +test12() +{ + typedef std::size_t (*hash_stringview_t)(const std::string_view&) noexcept; + __gnu_test::counter::reset(); + hash_stringview_t hasher = &hash_string_view_f; + std::unordered_set<std::string, + hash_stringview_t, + std::equal_to<std::string_view>> us(0, hasher); + us.insert(lst.begin(), lst.end()); + VERIFY( us.size() == 1 ); + + VERIFY( __gnu_test::counter::count() == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 3 ); + + us.insert(lst.begin(), lst.end()); + VERIFY( us.size() == 1 ); + + VERIFY( __gnu_test::counter::count() == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 3 ); +} + +struct hash_string_functor +{ + std::size_t + operator()(const std::string& str) const noexcept + { + std::hash<std::string> h; + return h(str); + } +}; + +void +test21() +{ + __gnu_test::counter::reset(); + std::unordered_set<std::string, + hash_string_functor, + std::equal_to<std::string>> us; + us.insert(lst.begin(), lst.end()); + VERIFY( us.size() == 1 ); + + VERIFY( __gnu_test::counter::count() == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 3 ); + + us.insert(lst.begin(), lst.end()); + VERIFY( us.size() == 1 ); + + VERIFY( __gnu_test::counter::count() == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 4 ); +} + +struct hash_string_view_noexcept_functor +{ + std::size_t + operator()(const std::string_view& str) const noexcept + { + std::hash<std::string_view> h; + return h(str); + } +}; + +void +test22() +{ + __gnu_test::counter::reset(); + std::unordered_set<std::string, + hash_string_view_noexcept_functor, + std::equal_to<std::string_view>> us; + us.insert(lst.begin(), lst.end()); + VERIFY( us.size() == 1 ); + + VERIFY( __gnu_test::counter::count() == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 3 ); + + us.insert(lst.begin(), lst.end()); + VERIFY( us.size() == 1 ); + + VERIFY( __gnu_test::counter::count() == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 3 ); +} + +struct hash_string_view_functor +{ + std::size_t + operator()(const std::string_view& str) const + { + std::hash<std::string_view> h; + return h(str); + } +}; + +void +test23() +{ + __gnu_test::counter::reset(); + std::unordered_set<std::string, + hash_string_view_functor, + std::equal_to<std::string_view>> us; + us.insert(lst.begin(), lst.end()); + VERIFY( us.size() == 1 ); + + VERIFY( __gnu_test::counter::count() == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 3 ); + + us.insert(lst.begin(), lst.end()); + VERIFY( us.size() == 1 ); + + VERIFY( __gnu_test::counter::count() == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 3 ); +} + +void +test03() +{ + std::vector<std::string> v; + v.insert(v.end(), lst.begin(), lst.end()); + + auto __offset = __gnu_test::counter::count(); + { + __gnu_test::counter::reset(); + std::unordered_set<std::string, + std::hash<std::string_view>, + std::equal_to<std::string_view>> us; + us.insert(v.begin(), v.end()); + VERIFY( us.size() == 1 ); + + VERIFY( __gnu_test::counter::count() - __offset == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 3 ); + + us.insert(v.begin(), v.end()); + VERIFY( us.size() == 1 ); + + VERIFY( __gnu_test::counter::count() - __offset == 3 ); + VERIFY( __gnu_test::counter::get()._M_increments == 3 ); + } + + { + __gnu_test::counter::reset(); + std::unordered_set<std::string, + std::hash<std::string_view>, + std::equal_to<std::string_view>> us; + us.insert(std::make_move_iterator(v.begin()), + std::make_move_iterator(v.end())); + VERIFY( us.size() == 1 ); + + VERIFY( __gnu_test::counter::count() - __offset == 2 ); + VERIFY( __gnu_test::counter::get()._M_increments == 2 ); + } +} + +int +main() +{ + test01(); + test02(); + test11(); + test12(); + test21(); + test22(); + test23(); + test03(); + return 0; +} diff --git a/libstdc++-v3/testsuite/25_algorithms/inplace_merge/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/inplace_merge/constrained.cc index e1f59bf..2f3d5d6 100644 --- a/libstdc++-v3/testsuite/25_algorithms/inplace_merge/constrained.cc +++ b/libstdc++-v3/testsuite/25_algorithms/inplace_merge/constrained.cc @@ -41,7 +41,7 @@ test01() ranges::sort(v); test_range<int, bidirectional_iterator_wrapper> rz(v.data(), v.data()+i+j); - auto result = ranges::inplace_merge(rz, next(ranges::begin(rz), i)); + auto result = ranges::inplace_merge(rz, ranges::next(ranges::begin(rz), i)); VERIFY( result == rz.end() ); VERIFY( ranges::is_sorted(rz) ); diff --git a/libstdc++-v3/testsuite/25_algorithms/is_sorted/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/is_sorted/constrained.cc index c376484..92440bb 100644 --- a/libstdc++-v3/testsuite/25_algorithms/is_sorted/constrained.cc +++ b/libstdc++-v3/testsuite/25_algorithms/is_sorted/constrained.cc @@ -46,7 +46,7 @@ test02() test_range<int, forward_iterator_wrapper> rx(x); VERIFY( ranges::is_sorted(rx) ); VERIFY( !ranges::is_sorted(ranges::begin(rx), - next(ranges::begin(rx), 2), + ranges::next(ranges::begin(rx), 2), ranges::greater{}) ); } diff --git a/libstdc++-v3/testsuite/25_algorithms/is_sorted_until/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/is_sorted_until/constrained.cc index 9d23ebc..bc32334 100644 --- a/libstdc++-v3/testsuite/25_algorithms/is_sorted_until/constrained.cc +++ b/libstdc++-v3/testsuite/25_algorithms/is_sorted_until/constrained.cc @@ -50,9 +50,9 @@ test02() test_range<int, forward_iterator_wrapper> rx(x); VERIFY( ranges::is_sorted_until(rx) == ranges::end(rx) ); VERIFY( ranges::is_sorted_until(ranges::begin(rx), - next(ranges::begin(rx), 2), + ranges::next(ranges::begin(rx), 2), ranges::greater{}) - == next(ranges::begin(rx), 1) ); + == ranges::next(ranges::begin(rx), 1) ); } constexpr bool diff --git a/libstdc++-v3/testsuite/25_algorithms/swap_ranges/1.cc b/libstdc++-v3/testsuite/25_algorithms/swap_ranges/1.cc index 31eee31..4660199 100644 --- a/libstdc++-v3/testsuite/25_algorithms/swap_ranges/1.cc +++ b/libstdc++-v3/testsuite/25_algorithms/swap_ranges/1.cc @@ -24,7 +24,7 @@ using __gnu_test::test_container; using __gnu_test::forward_iterator_wrapper; -typedef test_container<int, forward_iterator_wrapper> Container; +typedef test_container<int, forward_iterator_wrapper> Container; void @@ -46,10 +46,10 @@ test2() int array2[] = {1}; Container con1(array1, array1); Container con2(array2, array2); - VERIFY(swap_ranges(con1.begin(), con1.end(), con2.begin()).ptr == array2); + VERIFY(std::swap_ranges(con1.begin(), con1.end(), con2.begin()).ptr == array2); } -int +int main() { test1(); diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/100479.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/100479.cc new file mode 100644 index 0000000..ba10b7b --- /dev/null +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/100479.cc @@ -0,0 +1,113 @@ +// Copyright (C) 2021 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +// PR libstdc++/100479 + +#include <ranges> +#include <testsuite_hooks.h> +#include <testsuite_iterators.h> + +using __gnu_test::test_forward_range; +using __gnu_test::test_random_access_range; + +namespace ranges = std::ranges; +namespace views = std::views; + +void +test01() +{ + // Verify we don't propagate cached iterators when copying/moving an adapted + // forward range that memoizes its begin(). + static int pred_counter; + int x[] = {1,2,3,4,5}; + test_forward_range rx(x); + auto is_odd = [](auto n) { ++pred_counter; return n%2 != 0; }; + + auto v = rx | views::filter(is_odd); + v.begin(); v.begin(); + VERIFY( pred_counter == 1 ); // filter_view caches its begin() iterator + + auto w = v; + v.begin(); v.begin(); + VERIFY( pred_counter == 1 ); // cached iterator not invalidated on copy + w.begin(); w.begin(); + VERIFY( pred_counter == 2 ); // cached iterator not propagated on copy + + auto z = std::move(w); + w.begin(); w.begin(); + VERIFY( pred_counter == 3 ); // cached iterator invalidated on move + z.begin(); z.begin(); + VERIFY( pred_counter == 4 ); // cached iterator not propagated on move +} + +void +test02() +{ + // Verify we invalidate the cached offset when moving an adapted + // random access range that memoizes its begin(). + static int pred_counter; + int x[] = {1,2,3,4,5}; + test_random_access_range rx(x); + auto is_odd = [](auto n) { ++pred_counter; return n%2 != 0; }; + + auto v = rx | views::filter(is_odd); + v.begin(); v.begin(); + VERIFY( pred_counter == 1 ); // filter_view caches its begin() iterator + + auto w = v; + v.begin(); v.begin(); + VERIFY( pred_counter == 1 ); // cached offset not invalidated on copy + w.begin(); w.begin(); + VERIFY( pred_counter == 1 ); // cached offset propagated on copy + + auto z = std::move(w); + w.begin(); w.begin(); + VERIFY( pred_counter == 2 ); // cached offset invalidated on move + z.begin(); z.begin(); + VERIFY( pred_counter == 2 ); // cached offset propagated on move +} + +constexpr bool +test03() +{ + // Propagating cached iterators during copy/move would cause these asserts + // to fail here. + auto v = views::single(1) + | views::split(1) + | views::drop(0) + | views::drop_while([](auto) { return false; }) + | views::filter([](auto) { return true; }); + static_assert(ranges::forward_range<decltype(v)>); + VERIFY( ranges::next(v.begin()) == v.end() ); + auto w = v; + VERIFY( ranges::next(w.begin()) == w.end() ); + auto z = std::move(w); + VERIFY( ranges::next(z.begin()) == z.end() ); + return true; +} + +int +main() +{ + test01(); + test02(); + test03(); + static_assert(test03()); +} diff --git a/libstdc++-v3/testsuite/util/replacement_memory_operators.h b/libstdc++-v3/testsuite/util/replacement_memory_operators.h index 7e421db..e460c41 100644 --- a/libstdc++-v3/testsuite/util/replacement_memory_operators.h +++ b/libstdc++-v3/testsuite/util/replacement_memory_operators.h @@ -29,6 +29,7 @@ namespace __gnu_test struct counter { std::size_t _M_count; + std::size_t _M_increments, _M_decrements; bool _M_throw; counter() : _M_count(0), _M_throw(true) { } @@ -40,10 +41,20 @@ namespace __gnu_test } static void - increment() { get()._M_count++; } + increment() + { + counter& cntr = get(); + cntr._M_count++; + cntr._M_increments++; + } static void - decrement() { get()._M_count--; } + decrement() + { + counter& cntr = get(); + cntr._M_count--; + cntr._M_decrements++; + } static counter& get() @@ -57,6 +68,13 @@ namespace __gnu_test static void exceptions(bool __b) { get()._M_throw = __b; } + + static void + reset() + { + counter& cntr = get(); + cntr._M_increments = cntr._M_decrements = 0; + } }; template<typename Alloc, bool uses_global_new> |