aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2022-10-15 15:32:39 +0200
committerMartin Liska <mliska@suse.cz>2022-10-15 15:32:39 +0200
commit2c92cfe87d2bb8aa0eb78f3932fca16699cb35c9 (patch)
treeb118381a0a883a762ddd56c0e91608d937ee8bdf /gcc
parentbd21c04269deded2c7476ceca1100a26f28ea526 (diff)
parentbaeec7cc83b19b46d1c73523f06efa7ea2b30390 (diff)
downloadgcc-2c92cfe87d2bb8aa0eb78f3932fca16699cb35c9.zip
gcc-2c92cfe87d2bb8aa0eb78f3932fca16699cb35c9.tar.gz
gcc-2c92cfe87d2bb8aa0eb78f3932fca16699cb35c9.tar.bz2
Merge branch 'master' into devel/sphinx
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog238
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/analyzer/ChangeLog6
-rw-r--r--gcc/analyzer/svalue.cc3
-rw-r--r--gcc/builtin-types.def4
-rw-r--r--gcc/builtins.def1
-rw-r--r--gcc/c-family/ChangeLog24
-rw-r--r--gcc/c-family/c-common.def7
-rw-r--r--gcc/c-family/c-cppbuiltin.cc21
-rw-r--r--gcc/c-family/c-lex.cc21
-rw-r--r--gcc/c-family/c-opts.cc12
-rw-r--r--gcc/c/ChangeLog23
-rw-r--r--gcc/c/c-decl.cc33
-rw-r--r--gcc/c/c-parser.cc91
-rw-r--r--gcc/c/c-tree.h2
-rw-r--r--gcc/c/c-typeck.cc8
-rw-r--r--gcc/config/aarch64/aarch64-modes.def1
-rw-r--r--gcc/config/aarch64/aarch64.cc39
-rw-r--r--gcc/config/aarch64/aarch64.md76
-rw-r--r--gcc/config/i386/i386-builtin-types.def2
-rw-r--r--gcc/config/i386/i386-builtins.cc17
-rw-r--r--gcc/config/i386/i386-expand.cc2
-rw-r--r--gcc/config/i386/i386.cc63
-rw-r--r--gcc/config/i386/i386.md81
-rw-r--r--gcc/config/sparc/sparc.cc24
-rw-r--r--gcc/cp/ChangeLog96
-rw-r--r--gcc/cp/call.cc190
-rw-r--r--gcc/cp/constexpr.cc18
-rw-r--r--gcc/cp/cp-gimplify.cc5
-rw-r--r--gcc/cp/cp-tree.h6
-rw-r--r--gcc/cp/decl.cc2
-rw-r--r--gcc/cp/except.cc7
-rw-r--r--gcc/cp/parser.cc16
-rw-r--r--gcc/cp/parser.h2
-rw-r--r--gcc/cp/pt.cc34
-rw-r--r--gcc/cp/rtti.cc4
-rw-r--r--gcc/cp/typeck.cc203
-rw-r--r--gcc/cp/vtable-class-hierarchy.cc14
-rw-r--r--gcc/doc/invoke.texi10
-rw-r--r--gcc/expmed.cc4
-rw-r--r--gcc/expmed.h2
-rw-r--r--gcc/expr.cc194
-rw-r--r--gcc/fold-const-call.cc1
-rw-r--r--gcc/fortran/ChangeLog6
-rw-r--r--gcc/fortran/resolve.cc5
-rw-r--r--gcc/genmodes.cc33
-rw-r--r--gcc/gimple-range-cache.cc45
-rw-r--r--gcc/gimple-range-op.cc41
-rw-r--r--gcc/gimple-ssa-warn-access.cc8
-rw-r--r--gcc/machmode.h70
-rw-r--r--gcc/optabs.cc8
-rw-r--r--gcc/output.h4
-rw-r--r--gcc/range-op-float.cc12
-rw-r--r--gcc/range-op.cc69
-rw-r--r--gcc/range-op.h1
-rw-r--r--gcc/real.h2
-rw-r--r--gcc/testsuite/ChangeLog157
-rw-r--r--gcc/testsuite/c-c++-common/dfp/compare-eq-const.c1
-rw-r--r--gcc/testsuite/c-c++-common/dfp/convert-bfp-10.c1
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist-defarg3.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi-union1.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-tuple.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/pr68180.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/constexpr-96862.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/decomp12.C4
-rw-r--r--gcc/testsuite/g++.dg/gcov/gcov-1.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/pr106304_a.C12
-rw-r--r--gcc/testsuite/g++.dg/modules/pr106304_b.C8
-rw-r--r--gcc/testsuite/g++.dg/other/thunk1.C1
-rw-r--r--gcc/testsuite/g++.dg/vect/pr64410.cc1
-rw-r--r--gcc/testsuite/g++.dg/vect/pr89653.cc1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.brendan/copy9.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.brendan/overload7.C1
-rw-r--r--gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C4
-rw-r--r--gcc/testsuite/g++.target/i386/excess-precision-1.C6
-rw-r--r--gcc/testsuite/g++.target/i386/excess-precision-10.C6
-rw-r--r--gcc/testsuite/g++.target/i386/excess-precision-11.C105
-rw-r--r--gcc/testsuite/g++.target/i386/excess-precision-12.C20
-rw-r--r--gcc/testsuite/g++.target/i386/excess-precision-2.C5
-rw-r--r--gcc/testsuite/g++.target/i386/excess-precision-3.C6
-rw-r--r--gcc/testsuite/g++.target/i386/excess-precision-4.C7
-rw-r--r--gcc/testsuite/g++.target/i386/excess-precision-5.C32
-rw-r--r--gcc/testsuite/g++.target/i386/excess-precision-6.C19
-rw-r--r--gcc/testsuite/g++.target/i386/excess-precision-8.C7
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-89.c16
-rw-r--r--gcc/testsuite/gcc.dg/c11-complit-1.c7
-rw-r--r--gcc/testsuite/gcc.dg/c11-complit-2.c7
-rw-r--r--gcc/testsuite/gcc.dg/c11-complit-3.c7
-rw-r--r--gcc/testsuite/gcc.dg/c2x-complit-2.c48
-rw-r--r--gcc/testsuite/gcc.dg/c2x-complit-3.c24
-rw-r--r--gcc/testsuite/gcc.dg/c2x-complit-4.c60
-rw-r--r--gcc/testsuite/gcc.dg/c2x-complit-5.c52
-rw-r--r--gcc/testsuite/gcc.dg/c2x-complit-6.c7
-rw-r--r--gcc/testsuite/gcc.dg/c2x-complit-7.c7
-rw-r--r--gcc/testsuite/gcc.dg/c90-complit-2.c8
-rw-r--r--gcc/testsuite/gcc.dg/cpp/c2x-ucnid-1-utf8.c13
-rw-r--r--gcc/testsuite/gcc.dg/cpp/c2x-ucnid-1.c13
-rw-r--r--gcc/testsuite/gcc.dg/gnu2x-complit-1.c7
-rw-r--r--gcc/testsuite/gcc.dg/gnu2x-complit-2.c18
-rw-r--r--gcc/testsuite/gcc.dg/pr102540.c19
-rw-r--r--gcc/testsuite/gcc.dg/pr102872.c16
-rw-r--r--gcc/testsuite/gcc.dg/torture/bfloat16-basic.c11
-rw-r--r--gcc/testsuite/gcc.dg/torture/bfloat16-builtin-issignaling-1.c21
-rw-r--r--gcc/testsuite/gcc.dg/torture/bfloat16-builtin.c47
-rw-r--r--gcc/testsuite/gcc.dg/torture/bfloat16-complex.c61
-rw-r--r--gcc/testsuite/gcc.dg/torture/builtin-issignaling-1.c47
-rw-r--r--gcc/testsuite/gcc.dg/torture/floatn-basic.h18
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr107160.c41
-rw-r--r--gcc/testsuite/gcc.misc-tests/gcov-4.c30
-rw-r--r--gcc/testsuite/gcc.target/aarch64/ands_2.c30
-rw-r--r--gcc/testsuite/gcc.target/aarch64/bics_2.c24
-rw-r--r--gcc/testsuite/gcc.target/aarch64/tst_2.c30
-rw-r--r--gcc/testsuite/gcc.target/aarch64/tst_imm_split_1.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/excess-precision-1.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/excess-precision-10.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/excess-precision-2.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/excess-precision-3.c10
-rw-r--r--gcc/testsuite/gcc.target/i386/excess-precision-7.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/excess-precision-8.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/excess-precision-9.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c196
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_1.c100
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_2.c98
-rw-r--r--gcc/testsuite/gfortran.dg/analyzer/pr107210.f9016
-rw-r--r--gcc/testsuite/gfortran.dg/c-interop/deferred-character-2.f902
-rw-r--r--gcc/testsuite/gfortran.dg/der_io_5.f9017
-rw-r--r--gcc/testsuite/gfortran.dg/vect/pr107254.f9049
-rw-r--r--gcc/testsuite/lib/target-supports.exp16
-rw-r--r--gcc/tree-core.h3
-rw-r--r--gcc/tree-vect-loop.cc15
-rw-r--r--gcc/tree-vect-slp.cc33
-rw-r--r--gcc/tree.cc26
-rw-r--r--gcc/tree.h1
-rw-r--r--gcc/value-range.cc24
-rw-r--r--gcc/value-relation.cc243
-rw-r--r--gcc/value-relation.h117
-rw-r--r--gcc/varasm.cc17
137 files changed, 3433 insertions, 626 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7d9d899..c1fc2ec 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,241 @@
+2022-10-14 Aldy Hernandez <aldyh@redhat.com>
+
+ * value-range.cc (frange::set): Implement distinction between
+ HONOR_SIGNED_ZEROS and MODE_HAS_SIGNED_ZEROS.
+
+2022-10-14 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-op.cc (class cfn_copysign): New.
+ (gimple_range_op_handler::maybe_builtin_call): Add
+ CFN_BUILT_IN_COPYSIGN*.
+
+2022-10-14 Aldy Hernandez <aldyh@redhat.com>
+
+ * real.h (real_isdenormal): Check rvc_normal.
+ * value-range.cc (range_tests_floats): New test.
+
+2022-10-14 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-op.cc
+ (gimple_range_op_handler::maybe_builtin_call): Replace
+ CFN_BUILTIN_SIGNBIT* cases with CASE_FLT_FN.
+
+2022-10-14 Aldy Hernandez <aldyh@redhat.com>
+
+ * value-range.cc (frange::set): Normalize ranges for both bounds.
+
+2022-10-14 Aldy Hernandez <aldyh@redhat.com>
+
+ * value-range.cc (frange::set): Drop -0.0 for !HONOR_SIGNED_ZEROS.
+
+2022-10-14 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-range-op.cc
+ (gimple_range_op_handler::maybe_builtin_call): Add
+ CFN_BUILT_IN_SIGNBIT[FL]* entries.
+
+2022-10-14 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/107254
+ * tree-vect-slp.cc (vect_slp_analyze_node_operations_1):
+ For permutes also analyze live lanes.
+ (vect_schedule_slp_node): For permutes also code generate
+ live lane extracts.
+
+2022-10-14 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR target/107248
+ * config/sparc/sparc.cc (sparc_expand_prologue): Emit a frame
+ blockage for leaf functions.
+ (sparc_flat_expand_prologue): Emit frame instead of full blockage.
+ (sparc_expand_epilogue): Emit a frame blockage for leaf functions.
+ (sparc_flat_expand_epilogue): Emit frame instead of full blockage.
+
+2022-10-14 Jakub Jelinek <jakub@redhat.com>
+
+ * tree-core.h (enum tree_index): Add TI_BFLOAT16_TYPE.
+ * tree.h (bfloat16_type_node): Define.
+ * tree.cc (excess_precision_type): Promote bfloat16_type_mode
+ like float16_type_mode.
+ (build_common_tree_nodes): Initialize bfloat16_type_node if
+ BFmode is supported.
+ * expmed.h (maybe_expand_shift): Declare.
+ * expmed.cc (maybe_expand_shift): No longer static.
+ * expr.cc (convert_mode_scalar): Don't ICE on BF -> HF or HF -> BF
+ conversions. If there is no optab, handle BF -> {DF,XF,TF,HF}
+ conversions as separate BF -> SF -> {DF,XF,TF,HF} conversions, add
+ -ffast-math generic implementation for BF -> SF and SF -> BF
+ conversions.
+ * builtin-types.def (BT_BFLOAT16, BT_FN_BFLOAT16_CONST_STRING): New.
+ * builtins.def (BUILT_IN_NANSF16B): New builtin.
+ * fold-const-call.cc (fold_const_call): Handle CFN_BUILT_IN_NANSF16B.
+ * config/i386/i386.cc (classify_argument): Handle E_BCmode.
+ (ix86_libgcc_floating_mode_supported_p): Also return true for BFmode
+ for -msse2.
+ (ix86_mangle_type): Mangle BFmode as DF16b.
+ (ix86_invalid_conversion, ix86_invalid_unary_op,
+ ix86_invalid_binary_op): Remove.
+ (TARGET_INVALID_CONVERSION, TARGET_INVALID_UNARY_OP,
+ TARGET_INVALID_BINARY_OP): Don't redefine.
+ * config/i386/i386-builtins.cc (ix86_bf16_type_node): Remove.
+ (ix86_register_bf16_builtin_type): Use bfloat16_type_node rather than
+ ix86_bf16_type_node, only create it if still NULL.
+ * config/i386/i386-builtin-types.def (BFLOAT16): Likewise.
+ * config/i386/i386.md (cbranchbf4, cstorebf4): New expanders.
+
+2022-10-14 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/323
+ PR c++/107097
+ * doc/invoke.texi (-fexcess-precision=standard): Mention that the
+ option now also works in C++.
+
+2022-10-13 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gimple-ssa-warn-access.cc (pass_waccess::check_call): Return
+ early for calls made from thunks.
+
+2022-10-13 Eric Botcazou <ebotcazou@adacore.com>
+
+ * expr.cc (emit_group_stote): Fix handling of modes of different
+ sizes for big-endian targets in latest change and add commentary.
+
+2022-10-13 Martin Liska <mliska@suse.cz>
+
+ * output.h (assemble_vtv_preinit_initializer): Remove.
+ * varasm.cc (assemble_vtv_preinit_initializer): Remove.
+
+2022-10-13 Andrew MacLeod <amacleod@redhat.com>
+
+ PR tree-optimization/102540
+ PR tree-optimization/102872
+ * gimple-range-cache.cc (ranger_cache::fill_block_cache):
+ Handle partial equivs.
+ (ranger_cache::range_from_dom): Cleanup dump output.
+
+2022-10-13 Andrew MacLeod <amacleod@redhat.com>
+
+ * range-op.cc (operator_cast::lhs_op1_relation): New.
+ (operator_bitwise_and::lhs_op1_relation): New.
+
+2022-10-13 Andrew MacLeod <amacleod@redhat.com>
+
+ * gimple-range-cache.cc (ranger_cache::fill_block_cache): Use
+ iterator.
+ * value-relation.cc
+ (equiv_relation_iterator::equiv_relation_iterator): New.
+ (equiv_relation_iterator::next): New.
+ (equiv_relation_iterator::get_name): New.
+ * value-relation.h (class relation_oracle): Privatize some methods.
+ (class equiv_relation_iterator): New.
+ (FOR_EACH_EQUIVALENCE): New.
+ (FOR_EACH_PARTIAL_EQUIV): New.
+ (FOR_EACH_PARTIAL_AND_FULL_EQUIV): New.
+
+2022-10-13 Andrew MacLeod <amacleod@redhat.com>
+
+ * value-relation.cc (equiv_chain::dump): Don't print empty
+ equivalences.
+ (equiv_oracle::equiv_oracle): Allocate a partial equiv table.
+ (equiv_oracle::~equiv_oracle): Release the partial equiv table.
+ (equiv_oracle::add_partial_equiv): New.
+ (equiv_oracle::partial_equiv_set): New.
+ (equiv_oracle::partial_equiv): New.
+ (equiv_oracle::query_relation): Check for partial equivs too.
+ (equiv_oracle::dump): Also dump partial equivs.
+ (dom_oracle::register_relation): Handle partial equivs.
+ (dom_oracle::query_relation): Check for partial equivs.
+ * value-relation.h (enum relation_kind_t): Add partial equivs.
+ (relation_partial_equiv_p): New.
+ (relation_equiv_p): New.
+ (class pe_slice): New.
+ (class equiv_oracle): Add prototypes.
+ (pe_to_bits): New.
+ (bits_to_pe): New.
+ (pe_min): New.
+
+2022-10-13 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/107247
+ * tree-vect-loop.cc (vect_create_epilog_for_reduction):
+ Reduce multi vector SLP reduction accumulators. Check
+ the adjusted number of accumulator vectors against
+ one for the re-use in the epilogue.
+
+2022-10-13 Jakub Jelinek <jakub@redhat.com>
+
+ * genmodes.cc (emit_mode_wider): Emit previous content of
+ mode_wider array into mode_next array and for mode_wider
+ emit always VOIDmode for !CLASS_HAS_WIDER_MODES_P classes,
+ otherwise skip through modes with the same precision.
+ * machmode.h (mode_next): Declare.
+ (GET_MODE_NEXT_MODE): New inline function.
+ (mode_iterator::get_next, mode_iterator::get_known_next): New
+ function templates.
+ (FOR_EACH_MODE_IN_CLASS): Use get_next instead of get_wider.
+ (FOR_EACH_MODE): Use get_known_next instead of get_known_wider.
+ (FOR_EACH_MODE_FROM): Use get_next instead of get_wider.
+ (FOR_EACH_WIDER_MODE_FROM): Define.
+ (FOR_EACH_NEXT_MODE): Define.
+ * expmed.cc (emit_store_flag_1): Use FOR_EACH_WIDER_MODE_FROM
+ instead of FOR_EACH_MODE_FROM.
+ * optabs.cc (prepare_cmp_insn): Likewise. Remove redundant
+ !CLASS_HAS_WIDER_MODES_P check.
+ (prepare_float_lib_cmp): Use FOR_EACH_WIDER_MODE_FROM instead of
+ FOR_EACH_MODE_FROM.
+ * config/i386/i386-expand.cc (get_mode_wider_vector): Use
+ GET_MODE_NEXT_MODE instead of GET_MODE_WIDER_MODE.
+
+2022-10-13 Wilco Dijkstra <wdijkstr@arm.com>
+
+ PR target/105773
+ * config/aarch64/aarch64.cc (aarch64_select_cc_mode): Allow
+ GT/LE for merging compare with zero into AND.
+ (aarch64_get_condition_code_1): Add CC_NZVmode support.
+ * config/aarch64/aarch64-modes.def: Add CC_NZV.
+ * config/aarch64/aarch64.md: Use CC_NZV in cmp+and patterns.
+
+2022-10-13 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/107160
+ * tree-vect-loop.cc (vect_create_epilog_for_reduction):
+ Do not register accumulator if we failed to reduce it
+ to a single vector.
+
+2022-10-13 Aldy Hernandez <aldyh@redhat.com>
+
+ * range-op-float.cc (range_operator_float::op1_op2_relation): New.
+ (class foperator_equal): Add using.
+ (class foperator_not_equal): Same.
+ (class foperator_lt): Same.
+ (class foperator_le): Same.
+ (class foperator_gt): Same.
+ (class foperator_ge): Same.
+ * range-op.cc (range_op_handler::op1_op2_relation): New.
+ * range-op.h (range_operator_float::op1_op2_relation): New.
+
+2022-10-13 Richard Biener <rguenther@suse.de>
+
+ * genmatch.cc (parser::parse_c_expr): Diagnose 'return'.
+ * match.pd: Replace 'return' statements in with expressions
+ with appropriate variants.
+
+2022-10-13 Andre Vieira <andre.simoesdiasvieira@arm.com>
+
+ PR tree-optimization/107229
+ * tree-if-conv.cc (get_bitfield_rep): Fix bitposition calculation.
+
+2022-10-13 Andre Vieira <andre.simoesdiasvieira@arm.com>
+
+ PR tree-optimization/107226
+ * tree-vect-patterns.cc (vect_recog_bitfield_ref_pattern): Reject
+ BITFIELD_REF's with non integral typed first operands.
+
+2022-10-13 Joseph Myers <joseph@codesourcery.com>
+
+ * ginclude/float.h (FLT_IS_IEC_60559, DBL_IS_IEC_60559)
+ (LDBL_IS_IEC_60559): Update comment.
+
2022-10-12 Aldy Hernandez <aldyh@redhat.com>
* range-op-float.cc (class foperator_negate): New.
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 0c497e6..88e8f3f 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20221013
+20221015
diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog
index 33477da..f753d1a 100644
--- a/gcc/analyzer/ChangeLog
+++ b/gcc/analyzer/ChangeLog
@@ -1,3 +1,9 @@
+2022-10-13 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/107210
+ * svalue.cc (constant_svalue::maybe_fold_bits_within): Only
+ attempt to extract individual bits when tree_fits_uhwi_p.
+
2022-10-07 David Malcolm <dmalcolm@redhat.com>
PR analyzer/105783
diff --git a/gcc/analyzer/svalue.cc b/gcc/analyzer/svalue.cc
index a0838c0..4b00a81 100644
--- a/gcc/analyzer/svalue.cc
+++ b/gcc/analyzer/svalue.cc
@@ -884,7 +884,8 @@ constant_svalue::maybe_fold_bits_within (tree type,
if (bits.m_size_in_bits == 1
&& TREE_CODE (m_cst_expr) == INTEGER_CST
&& type
- && INTEGRAL_TYPE_P (type))
+ && INTEGRAL_TYPE_P (type)
+ && tree_fits_uhwi_p (m_cst_expr))
{
unsigned HOST_WIDE_INT bit = bits.m_start_bit_offset.to_uhwi ();
unsigned HOST_WIDE_INT mask = (1 << bit);
diff --git a/gcc/builtin-types.def b/gcc/builtin-types.def
index 3a7cecd..df3a88f2 100644
--- a/gcc/builtin-types.def
+++ b/gcc/builtin-types.def
@@ -82,6 +82,9 @@ DEF_PRIMITIVE_TYPE (BT_UNWINDWORD, (*lang_hooks.types.type_for_mode)
DEF_PRIMITIVE_TYPE (BT_FLOAT, float_type_node)
DEF_PRIMITIVE_TYPE (BT_DOUBLE, double_type_node)
DEF_PRIMITIVE_TYPE (BT_LONGDOUBLE, long_double_type_node)
+DEF_PRIMITIVE_TYPE (BT_BFLOAT16, (bfloat16_type_node
+ ? bfloat16_type_node
+ : error_mark_node))
DEF_PRIMITIVE_TYPE (BT_FLOAT16, (float16_type_node
? float16_type_node
: error_mark_node))
@@ -264,6 +267,7 @@ DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT_CONST_STRING, BT_FLOAT, BT_CONST_STRING)
DEF_FUNCTION_TYPE_1 (BT_FN_DOUBLE_CONST_STRING, BT_DOUBLE, BT_CONST_STRING)
DEF_FUNCTION_TYPE_1 (BT_FN_LONGDOUBLE_CONST_STRING,
BT_LONGDOUBLE, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_1 (BT_FN_BFLOAT16_CONST_STRING, BT_BFLOAT16, BT_CONST_STRING)
DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT16_CONST_STRING, BT_FLOAT16, BT_CONST_STRING)
DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT32_CONST_STRING, BT_FLOAT32, BT_CONST_STRING)
DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT64_CONST_STRING, BT_FLOAT64, BT_CONST_STRING)
diff --git a/gcc/builtins.def b/gcc/builtins.def
index 109b387..5f2e627 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -514,6 +514,7 @@ DEF_GCC_BUILTIN (BUILT_IN_NANSF, "nansf", BT_FN_FLOAT_CONST_STRING, ATTR_
DEF_GCC_BUILTIN (BUILT_IN_NANSL, "nansl", BT_FN_LONGDOUBLE_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
DEF_GCC_FLOATN_NX_BUILTINS (BUILT_IN_NANS, "nans", NAN_TYPE, ATTR_CONST_NOTHROW_NONNULL)
#undef NAN_TYPE
+DEF_GCC_BUILTIN (BUILT_IN_NANSF16B, "nansf16b", BT_FN_BFLOAT16_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
DEF_GCC_BUILTIN (BUILT_IN_NANSD32, "nansd32", BT_FN_DFLOAT32_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
DEF_GCC_BUILTIN (BUILT_IN_NANSD64, "nansd64", BT_FN_DFLOAT64_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
DEF_GCC_BUILTIN (BUILT_IN_NANSD128, "nansd128", BT_FN_DFLOAT128_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 1fade0a..2047e2e 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,27 @@
+2022-10-14 Jakub Jelinek <jakub@redhat.com>
+
+ * c-cppbuiltin.cc (c_cpp_builtins): If bfloat16_type_node,
+ predefine __BFLT16_*__ macros and for C++23 also
+ __STDCPP_BFLOAT16_T__. Predefine bfloat16_type_node related
+ macros for -fbuilding-libgcc.
+ * c-lex.cc (interpret_float): Handle CPP_N_BFLOAT16.
+
+2022-10-14 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/323
+ PR c++/107097
+ * c-common.def (EXCESS_PRECISION_EXPR): Remove comment part about
+ the tree being specific to C/ObjC.
+ * c-opts.cc (c_common_post_options): Handle flag_excess_precision
+ in C++ the same as in C.
+ * c-lex.cc (interpret_float): Set const_type to excess_precision ()
+ even for C++.
+
+2022-10-13 Joseph Myers <joseph@codesourcery.com>
+
+ * c-cppbuiltin.cc (builtin_define_float_constants): Do not use
+ value 2 for *_IS_IEC_60559.
+
2022-10-12 Lewis Hyatt <lhyatt@gmail.com>
PR preprocessor/60014
diff --git a/gcc/c-family/c-common.def b/gcc/c-family/c-common.def
index 0759ace..dd8be7f 100644
--- a/gcc/c-family/c-common.def
+++ b/gcc/c-family/c-common.def
@@ -38,10 +38,9 @@ along with GCC; see the file COPYING3. If not see
not. */
DEFTREECODE (C_MAYBE_CONST_EXPR, "c_maybe_const_expr", tcc_expression, 2)
-/* An EXCESS_PRECISION_EXPR, currently only used for C and Objective
- C, represents an expression evaluated in greater range or precision
- than its type. The type of the EXCESS_PRECISION_EXPR is the
- semantic type while the operand represents what is actually being
+/* An EXCESS_PRECISION_EXPR represents an expression evaluated in greater
+ range or precision than its type. The type of the EXCESS_PRECISION_EXPR
+ is the semantic type while the operand represents what is actually being
evaluated. */
DEFTREECODE (EXCESS_PRECISION_EXPR, "excess_precision_expr", tcc_expression, 1)
diff --git a/gcc/c-family/c-cppbuiltin.cc b/gcc/c-family/c-cppbuiltin.cc
index 2e39acb..cdb658f 100644
--- a/gcc/c-family/c-cppbuiltin.cc
+++ b/gcc/c-family/c-cppbuiltin.cc
@@ -1260,6 +1260,13 @@ c_cpp_builtins (cpp_reader *pfile)
builtin_define_float_constants (prefix, ggc_strdup (csuffix), "%s",
csuffix, FLOATN_NX_TYPE_NODE (i));
}
+ if (bfloat16_type_node)
+ {
+ if (c_dialect_cxx () && cxx_dialect > cxx20)
+ cpp_define (pfile, "__STDCPP_BFLOAT16_T__=1");
+ builtin_define_float_constants ("BFLT16", "BF16", "%s",
+ "BF16", bfloat16_type_node);
+ }
/* For float.h. */
if (targetm.decimal_float_supported_p ())
@@ -1370,6 +1377,12 @@ c_cpp_builtins (cpp_reader *pfile)
suffix[0] = 'l';
memcpy (float_h_prefix, "LDBL", 5);
}
+ else if (bfloat16_type_node
+ && mode == TYPE_MODE (bfloat16_type_node))
+ {
+ memcpy (suffix, "bf16", 5);
+ memcpy (float_h_prefix, "BFLT16", 7);
+ }
else
{
bool found_suffix = false;
@@ -1396,22 +1409,28 @@ c_cpp_builtins (cpp_reader *pfile)
machine_mode float16_type_mode = (float16_type_node
? TYPE_MODE (float16_type_node)
: VOIDmode);
+ machine_mode bfloat16_type_mode = (bfloat16_type_node
+ ? TYPE_MODE (bfloat16_type_node)
+ : VOIDmode);
switch (targetm.c.excess_precision
(EXCESS_PRECISION_TYPE_IMPLICIT))
{
case FLT_EVAL_METHOD_UNPREDICTABLE:
case FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE:
excess_precision = (mode == float16_type_mode
+ || mode == bfloat16_type_mode
|| mode == TYPE_MODE (float_type_node)
|| mode == TYPE_MODE (double_type_node));
break;
case FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE:
excess_precision = (mode == float16_type_mode
+ || mode == bfloat16_type_mode
|| mode == TYPE_MODE (float_type_node));
break;
case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT:
- excess_precision = mode == float16_type_mode;
+ excess_precision = (mode == float16_type_mode
+ || mode == bfloat16_type_mode);
break;
case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16:
excess_precision = false;
diff --git a/gcc/c-family/c-lex.cc b/gcc/c-family/c-lex.cc
index 050fa77..89c65ac 100644
--- a/gcc/c-family/c-lex.cc
+++ b/gcc/c-family/c-lex.cc
@@ -1000,6 +1000,22 @@ interpret_float (const cpp_token *token, unsigned int flags,
pedwarn (input_location, OPT_Wpedantic,
"non-standard suffix on floating constant");
}
+ else if ((flags & CPP_N_BFLOAT16) != 0)
+ {
+ type = bfloat16_type_node;
+ if (type == NULL_TREE)
+ {
+ error ("unsupported non-standard suffix on floating constant");
+ return error_mark_node;
+ }
+ if (!c_dialect_cxx ())
+ pedwarn (input_location, OPT_Wpedantic,
+ "non-standard suffix on floating constant");
+ else if (cxx_dialect < cxx23)
+ pedwarn (input_location, OPT_Wpedantic,
+ "%<bf16%> or %<BF16%> suffix on floating constant only "
+ "available with %<-std=c++2b%> or %<-std=gnu++2b%>");
+ }
else if ((flags & CPP_N_WIDTH) == CPP_N_LARGE)
type = long_double_type_node;
else if ((flags & CPP_N_WIDTH) == CPP_N_SMALL
@@ -1008,10 +1024,7 @@ interpret_float (const cpp_token *token, unsigned int flags,
else
type = double_type_node;
- if (c_dialect_cxx ())
- const_type = NULL_TREE;
- else
- const_type = excess_precision_type (type);
+ const_type = excess_precision_type (type);
if (!const_type)
const_type = type;
diff --git a/gcc/c-family/c-opts.cc b/gcc/c-family/c-opts.cc
index 55cebf6..32b929e 100644
--- a/gcc/c-family/c-opts.cc
+++ b/gcc/c-family/c-opts.cc
@@ -812,17 +812,9 @@ c_common_post_options (const char **pfilename)
C_COMMON_OVERRIDE_OPTIONS;
#endif
- /* Excess precision other than "fast" requires front-end
- support. */
- if (c_dialect_cxx ())
- {
- if (flag_excess_precision == EXCESS_PRECISION_STANDARD)
- sorry ("%<-fexcess-precision=standard%> for C++");
- flag_excess_precision = EXCESS_PRECISION_FAST;
- }
- else if (flag_excess_precision == EXCESS_PRECISION_DEFAULT)
+ if (flag_excess_precision == EXCESS_PRECISION_DEFAULT)
flag_excess_precision = (flag_iso ? EXCESS_PRECISION_STANDARD
- : EXCESS_PRECISION_FAST);
+ : EXCESS_PRECISION_FAST);
/* ISO C restricts floating-point expression contraction to within
source-language expressions (-ffp-contract=on, currently an alias
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index a25e1b4..d28585b 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,26 @@
+2022-10-14 Jakub Jelinek <jakub@redhat.com>
+
+ * c-typeck.cc (convert_arguments): Don't promote __bf16 to
+ double.
+
+2022-10-14 Joseph Myers <joseph@codesourcery.com>
+
+ * c-decl.cc (build_compound_literal): Add parameter scspecs.
+ Handle storage class specifiers.
+ * c-parser.cc (c_token_starts_compound_literal)
+ (c_parser_compound_literal_scspecs): New.
+ (c_parser_postfix_expression_after_paren_type): Add parameter
+ scspecs. Call pedwarn_c11 for use of storage class specifiers.
+ Update call to build_compound_literal.
+ (c_parser_cast_expression, c_parser_sizeof_expression)
+ (c_parser_alignof_expression): Handle storage class specifiers for
+ compound literals. Update calls to
+ c_parser_postfix_expression_after_paren_type.
+ (c_parser_postfix_expression): Update syntax comment.
+ * c-tree.h (build_compound_literal): Update prototype.
+ * c-typeck.cc (c_mark_addressable): Diagnose taking address of
+ register compound literal.
+
2022-10-07 Qing Zhao <qing.zhao@oracle.com>
* c-decl.cc (flexible_array_member_type_p): New function.
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 193e268..a7571cc 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -6048,11 +6048,13 @@ mark_forward_parm_decls (void)
literal. NON_CONST is true if the initializers contain something
that cannot occur in a constant expression. If ALIGNAS_ALIGN is nonzero,
it is the (valid) alignment for this compound literal, as specified
- with _Alignas. */
+ with _Alignas. SCSPECS are the storage class specifiers (C2x) from the
+ compound literal. */
tree
build_compound_literal (location_t loc, tree type, tree init, bool non_const,
- unsigned int alignas_align)
+ unsigned int alignas_align,
+ struct c_declspecs *scspecs)
{
/* We do not use start_decl here because we have a type, not a declarator;
and do not use finish_decl because the decl should be stored inside
@@ -6060,15 +6062,33 @@ build_compound_literal (location_t loc, tree type, tree init, bool non_const,
tree decl;
tree complit;
tree stmt;
+ bool threadp = scspecs ? scspecs->thread_p : false;
+ enum c_storage_class storage_class = (scspecs
+ ? scspecs->storage_class
+ : csc_none);
if (type == error_mark_node
|| init == error_mark_node)
return error_mark_node;
+ if (current_scope == file_scope && storage_class == csc_register)
+ {
+ error_at (loc, "file-scope compound literal specifies %<register%>");
+ storage_class = csc_none;
+ }
+
+ if (current_scope != file_scope && threadp && storage_class == csc_none)
+ {
+ error_at (loc, "compound literal implicitly auto and declared %qs",
+ scspecs->thread_gnu_p ? "__thread" : "_Thread_local");
+ threadp = false;
+ }
+
decl = build_decl (loc, VAR_DECL, NULL_TREE, type);
DECL_EXTERNAL (decl) = 0;
TREE_PUBLIC (decl) = 0;
- TREE_STATIC (decl) = (current_scope == file_scope);
+ TREE_STATIC (decl) = (current_scope == file_scope
+ || storage_class == csc_static);
DECL_CONTEXT (decl) = current_function_decl;
TREE_USED (decl) = 1;
DECL_READ_P (decl) = 1;
@@ -6076,6 +6096,13 @@ build_compound_literal (location_t loc, tree type, tree init, bool non_const,
DECL_IGNORED_P (decl) = 1;
C_DECL_COMPOUND_LITERAL_P (decl) = 1;
TREE_TYPE (decl) = type;
+ if (threadp)
+ set_decl_tls_model (decl, decl_default_tls_model (decl));
+ if (storage_class == csc_register)
+ {
+ C_DECL_REGISTER (decl) = 1;
+ DECL_REGISTER (decl) = 1;
+ }
c_apply_type_quals_to_decl (TYPE_QUALS (strip_array_types (type)), decl);
if (alignas_align)
{
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 89e0587..602e023 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -666,6 +666,30 @@ c_parser_next_tokens_start_typename (c_parser *parser, enum c_lookahead_kind la)
return false;
}
+/* Return true if TOKEN, after an open parenthesis, can start a
+ compound literal (either a storage class specifier allowed in that
+ context, or a type name), false otherwise. */
+static bool
+c_token_starts_compound_literal (c_token *token)
+{
+ switch (token->type)
+ {
+ case CPP_KEYWORD:
+ switch (token->keyword)
+ {
+ case RID_REGISTER:
+ case RID_STATIC:
+ case RID_THREAD:
+ return true;
+ default:
+ break;
+ }
+ /* Fall through. */
+ default:
+ return c_token_starts_typename (token);
+ }
+}
+
/* Return true if TOKEN is a type qualifier, false otherwise. */
static bool
c_token_is_qualifier (c_token *token)
@@ -1563,6 +1587,7 @@ static struct c_expr c_parser_sizeof_expression (c_parser *);
static struct c_expr c_parser_alignof_expression (c_parser *);
static struct c_expr c_parser_postfix_expression (c_parser *);
static struct c_expr c_parser_postfix_expression_after_paren_type (c_parser *,
+ struct c_declspecs *,
struct c_type_name *,
location_t);
static struct c_expr c_parser_postfix_expression_after_primary (c_parser *,
@@ -8237,6 +8262,34 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after,
#undef POP
}
+/* Parse any storage class specifiers after an open parenthesis in a
+ context where a compound literal is permitted. */
+
+static struct c_declspecs *
+c_parser_compound_literal_scspecs (c_parser *parser)
+{
+ bool seen_scspec = false;
+ struct c_declspecs *specs = build_null_declspecs ();
+ while (c_parser_next_token_is (parser, CPP_KEYWORD))
+ {
+ switch (c_parser_peek_token (parser)->keyword)
+ {
+ case RID_REGISTER:
+ case RID_STATIC:
+ case RID_THREAD:
+ seen_scspec = true;
+ declspecs_add_scspec (c_parser_peek_token (parser)->location,
+ specs, c_parser_peek_token (parser)->value);
+ c_parser_consume_token (parser);
+ break;
+ default:
+ goto out;
+ }
+ }
+ out:
+ return seen_scspec ? specs : NULL;
+}
+
/* Parse a cast expression (C90 6.3.4, C99 6.5.4, C11 6.5.4). If AFTER
is not NULL then it is an Objective-C message expression which is the
primary-expression starting the expression as an initializer.
@@ -8260,13 +8313,15 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
an unary expression. Full detection of unknown typenames here
would require a 3-token lookahead. */
if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
- && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
+ && c_token_starts_compound_literal (c_parser_peek_2nd_token (parser)))
{
+ struct c_declspecs *scspecs;
struct c_type_name *type_name;
struct c_expr ret;
struct c_expr expr;
matching_parens parens;
parens.consume_open (parser);
+ scspecs = c_parser_compound_literal_scspecs (parser);
type_name = c_parser_type_name (parser, true);
parens.skip_until_found_close (parser);
if (type_name == NULL)
@@ -8281,8 +8336,11 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
used_types_insert (type_name->specs->type);
if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
- return c_parser_postfix_expression_after_paren_type (parser, type_name,
+ return c_parser_postfix_expression_after_paren_type (parser, scspecs,
+ type_name,
cast_loc);
+ if (scspecs)
+ error_at (cast_loc, "storage class specifier in cast");
if (type_name->specs->alignas_p)
error_at (type_name->specs->locations[cdw_alignas],
"alignment specified for type name in cast");
@@ -8485,14 +8543,16 @@ c_parser_sizeof_expression (c_parser *parser)
c_inhibit_evaluation_warnings++;
in_sizeof++;
if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
- && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
+ && c_token_starts_compound_literal (c_parser_peek_2nd_token (parser)))
{
/* Either sizeof ( type-name ) or sizeof unary-expression
starting with a compound literal. */
+ struct c_declspecs *scspecs;
struct c_type_name *type_name;
matching_parens parens;
parens.consume_open (parser);
expr_loc = c_parser_peek_token (parser)->location;
+ scspecs = c_parser_compound_literal_scspecs (parser);
type_name = c_parser_type_name (parser, true);
parens.skip_until_found_close (parser);
finish = parser->tokens_buf[0].location;
@@ -8508,13 +8568,15 @@ c_parser_sizeof_expression (c_parser *parser)
}
if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
{
- expr = c_parser_postfix_expression_after_paren_type (parser,
+ expr = c_parser_postfix_expression_after_paren_type (parser, scspecs,
type_name,
expr_loc);
finish = expr.get_finish ();
goto sizeof_expr;
}
/* sizeof ( type-name ). */
+ if (scspecs)
+ error_at (expr_loc, "storage class specifier in %<sizeof%>");
if (type_name->specs->alignas_p)
error_at (type_name->specs->locations[cdw_alignas],
"alignment specified for type name in %<sizeof%>");
@@ -8572,16 +8634,18 @@ c_parser_alignof_expression (c_parser *parser)
c_inhibit_evaluation_warnings++;
in_alignof++;
if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
- && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
+ && c_token_starts_compound_literal (c_parser_peek_2nd_token (parser)))
{
/* Either __alignof__ ( type-name ) or __alignof__
unary-expression starting with a compound literal. */
location_t loc;
+ struct c_declspecs *scspecs;
struct c_type_name *type_name;
struct c_expr ret;
matching_parens parens;
parens.consume_open (parser);
loc = c_parser_peek_token (parser)->location;
+ scspecs = c_parser_compound_literal_scspecs (parser);
type_name = c_parser_type_name (parser, true);
end_loc = c_parser_peek_token (parser)->location;
parens.skip_until_found_close (parser);
@@ -8597,12 +8661,14 @@ c_parser_alignof_expression (c_parser *parser)
}
if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
{
- expr = c_parser_postfix_expression_after_paren_type (parser,
+ expr = c_parser_postfix_expression_after_paren_type (parser, scspecs,
type_name,
loc);
goto alignof_expr;
}
/* alignof ( type-name ). */
+ if (scspecs)
+ error_at (loc, "storage class specifier in %qE", alignof_spelling);
if (type_name->specs->alignas_p)
error_at (type_name->specs->locations[cdw_alignas],
"alignment specified for type name in %qE",
@@ -9140,8 +9206,8 @@ c_parser_predefined_identifier (c_parser *parser)
postfix-expression -> identifier
postfix-expression ++
postfix-expression --
- ( type-name ) { initializer-list }
- ( type-name ) { initializer-list , }
+ ( storage-class-specifiers[opt] type-name ) { initializer-list[opt] }
+ ( storage-class-specifiers[opt] type-name ) { initializer-list , }
argument-expression-list:
argument-expression
@@ -10483,6 +10549,7 @@ c_parser_postfix_expression (c_parser *parser)
static struct c_expr
c_parser_postfix_expression_after_paren_type (c_parser *parser,
+ struct c_declspecs *scspecs,
struct c_type_name *type_name,
location_t type_loc)
{
@@ -10515,7 +10582,11 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser,
type = error_mark_node;
}
- pedwarn_c90 (start_loc, OPT_Wpedantic, "ISO C90 forbids compound literals");
+ if (!pedwarn_c90 (start_loc, OPT_Wpedantic,
+ "ISO C90 forbids compound literals") && scspecs)
+ pedwarn_c11 (start_loc, OPT_Wpedantic,
+ "ISO C forbids storage class specifiers in compound literals "
+ "before C2X");
non_const = ((init.value && TREE_CODE (init.value) == CONSTRUCTOR)
? CONSTRUCTOR_NON_CONST (init.value)
: init.original_code == C_MAYBE_CONST_EXPR);
@@ -10534,7 +10605,7 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser,
}
}
expr.value = build_compound_literal (start_loc, type, init.value, non_const,
- alignas_align);
+ alignas_align, scspecs);
set_c_expr_source_range (&expr, init.src_range);
expr.m_decimal = 0;
expr.original_code = ERROR_MARK;
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index 46a3e8e..e7cdd2f 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -734,7 +734,7 @@ extern void set_init_label (location_t, tree, location_t, struct obstack *);
extern void process_init_element (location_t, struct c_expr, bool,
struct obstack *);
extern tree build_compound_literal (location_t, tree, tree, bool,
- unsigned int);
+ unsigned int, struct c_declspecs *);
extern void check_compound_literal_type (location_t, struct c_type_name *);
extern tree c_start_switch (location_t, location_t, tree, bool);
extern void c_finish_switch (tree, tree);
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index f919068..fdb96c2 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -3678,6 +3678,9 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
promote_float_arg = false;
break;
}
+ /* Don't promote __bf16 either. */
+ if (TYPE_MAIN_VARIANT (valtype) == bfloat16_type_node)
+ promote_float_arg = false;
}
if (type != NULL_TREE)
@@ -5114,6 +5117,11 @@ c_mark_addressable (tree exp, bool array_ref_p)
break;
case COMPOUND_LITERAL_EXPR:
+ if (C_DECL_REGISTER (COMPOUND_LITERAL_EXPR_DECL (x)))
+ {
+ error ("address of register compound literal requested");
+ return false;
+ }
TREE_ADDRESSABLE (x) = 1;
TREE_ADDRESSABLE (COMPOUND_LITERAL_EXPR_DECL (x)) = 1;
return true;
diff --git a/gcc/config/aarch64/aarch64-modes.def b/gcc/config/aarch64/aarch64-modes.def
index d3c9b74..0fd4c32 100644
--- a/gcc/config/aarch64/aarch64-modes.def
+++ b/gcc/config/aarch64/aarch64-modes.def
@@ -35,6 +35,7 @@ CC_MODE (CCFPE);
CC_MODE (CC_SWP);
CC_MODE (CC_NZC); /* Only N, Z and C bits of condition flags are valid.
(Used with SVE predicate tests.) */
+CC_MODE (CC_NZV); /* Only N, Z and V bits of condition flags are valid. */
CC_MODE (CC_NZ); /* Only N and Z bits of condition flags are valid. */
CC_MODE (CC_Z); /* Only Z bit of condition flags is valid. */
CC_MODE (CC_C); /* C represents unsigned overflow of a simple addition. */
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index a8845a5..1d0f994 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -11274,7 +11274,7 @@ aarch64_select_cc_mode (RTX_CODE code, rtx x, rtx y)
if (y == const0_rtx && (REG_P (x) || SUBREG_P (x))
&& (code == EQ || code == NE)
&& (mode_x == HImode || mode_x == QImode))
- return CC_NZmode;
+ return CC_Zmode;
/* Similarly, comparisons of zero_extends from shorter modes can
be performed using an ANDS with an immediate mask. */
@@ -11282,15 +11282,29 @@ aarch64_select_cc_mode (RTX_CODE code, rtx x, rtx y)
&& (mode_x == SImode || mode_x == DImode)
&& (GET_MODE (XEXP (x, 0)) == HImode || GET_MODE (XEXP (x, 0)) == QImode)
&& (code == EQ || code == NE))
- return CC_NZmode;
+ return CC_Zmode;
+
+ /* Zero extracts support equality comparisons. */
+ if ((mode_x == SImode || mode_x == DImode)
+ && y == const0_rtx
+ && (code_x == ZERO_EXTRACT && CONST_INT_P (XEXP (x, 1))
+ && CONST_INT_P (XEXP (x, 2)))
+ && (code == EQ || code == NE))
+ return CC_Zmode;
+
+ /* ANDS/BICS/TST support equality and all signed comparisons. */
+ if ((mode_x == SImode || mode_x == DImode)
+ && y == const0_rtx
+ && (code_x == AND)
+ && (code == EQ || code == NE || code == LT || code == GE
+ || code == GT || code == LE))
+ return CC_NZVmode;
+ /* ADDS/SUBS correctly set N and Z flags. */
if ((mode_x == SImode || mode_x == DImode)
&& y == const0_rtx
&& (code == EQ || code == NE || code == LT || code == GE)
- && (code_x == PLUS || code_x == MINUS || code_x == AND
- || code_x == NEG
- || (code_x == ZERO_EXTRACT && CONST_INT_P (XEXP (x, 1))
- && CONST_INT_P (XEXP (x, 2)))))
+ && (code_x == PLUS || code_x == MINUS || code_x == NEG))
return CC_NZmode;
/* A compare with a shifted operand. Because of canonicalization,
@@ -11427,6 +11441,19 @@ aarch64_get_condition_code_1 (machine_mode mode, enum rtx_code comp_code)
}
break;
+ case E_CC_NZVmode:
+ switch (comp_code)
+ {
+ case NE: return AARCH64_NE;
+ case EQ: return AARCH64_EQ;
+ case GE: return AARCH64_PL;
+ case LT: return AARCH64_MI;
+ case GT: return AARCH64_GT;
+ case LE: return AARCH64_LE;
+ default: return -1;
+ }
+ break;
+
case E_CC_NZmode:
switch (comp_code)
{
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 0a7633e..f2e3d90 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -4514,8 +4514,8 @@
)
(define_insn "*and<mode>3_compare0"
- [(set (reg:CC_NZ CC_REGNUM)
- (compare:CC_NZ
+ [(set (reg:CC_NZV CC_REGNUM)
+ (compare:CC_NZV
(and:GPI (match_operand:GPI 1 "register_operand" "%r,r")
(match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>"))
(const_int 0)))
@@ -4530,8 +4530,8 @@
;; zero_extend version of above
(define_insn "*andsi3_compare0_uxtw"
- [(set (reg:CC_NZ CC_REGNUM)
- (compare:CC_NZ
+ [(set (reg:CC_NZV CC_REGNUM)
+ (compare:CC_NZV
(and:SI (match_operand:SI 1 "register_operand" "%r,r")
(match_operand:SI 2 "aarch64_logical_operand" "r,K"))
(const_int 0)))
@@ -4545,8 +4545,8 @@
)
(define_insn "*and_<SHIFT:optab><mode>3_compare0"
- [(set (reg:CC_NZ CC_REGNUM)
- (compare:CC_NZ
+ [(set (reg:CC_NZV CC_REGNUM)
+ (compare:CC_NZV
(and:GPI (SHIFT:GPI
(match_operand:GPI 1 "register_operand" "r")
(match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
@@ -4565,8 +4565,8 @@
;; zero_extend version of above
(define_insn "*and_<SHIFT:optab>si3_compare0_uxtw"
- [(set (reg:CC_NZ CC_REGNUM)
- (compare:CC_NZ
+ [(set (reg:CC_NZV CC_REGNUM)
+ (compare:CC_NZV
(and:SI (SHIFT:SI
(match_operand:SI 1 "register_operand" "r")
(match_operand:QI 2 "aarch64_shift_imm_si" "n"))
@@ -4770,8 +4770,8 @@
)
(define_insn "*and_one_cmpl<mode>3_compare0"
- [(set (reg:CC_NZ CC_REGNUM)
- (compare:CC_NZ
+ [(set (reg:CC_NZV CC_REGNUM)
+ (compare:CC_NZV
(and:GPI (not:GPI
(match_operand:GPI 1 "register_operand" "r"))
(match_operand:GPI 2 "register_operand" "r"))
@@ -4785,8 +4785,8 @@
;; zero_extend version of above
(define_insn "*and_one_cmplsi3_compare0_uxtw"
- [(set (reg:CC_NZ CC_REGNUM)
- (compare:CC_NZ
+ [(set (reg:CC_NZV CC_REGNUM)
+ (compare:CC_NZV
(and:SI (not:SI
(match_operand:SI 1 "register_operand" "r"))
(match_operand:SI 2 "register_operand" "r"))
@@ -4799,8 +4799,8 @@
)
(define_insn "*and_one_cmpl<mode>3_compare0_no_reuse"
- [(set (reg:CC_NZ CC_REGNUM)
- (compare:CC_NZ
+ [(set (reg:CC_NZV CC_REGNUM)
+ (compare:CC_NZV
(and:GPI (not:GPI
(match_operand:GPI 0 "register_operand" "r"))
(match_operand:GPI 1 "register_operand" "r"))
@@ -4878,8 +4878,8 @@
)
(define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0"
- [(set (reg:CC_NZ CC_REGNUM)
- (compare:CC_NZ
+ [(set (reg:CC_NZV CC_REGNUM)
+ (compare:CC_NZV
(and:GPI (not:GPI
(SHIFT:GPI
(match_operand:GPI 1 "register_operand" "r")
@@ -4901,8 +4901,8 @@
;; zero_extend version of above
(define_insn "*and_one_cmpl_<SHIFT:optab>si3_compare0_uxtw"
- [(set (reg:CC_NZ CC_REGNUM)
- (compare:CC_NZ
+ [(set (reg:CC_NZV CC_REGNUM)
+ (compare:CC_NZV
(and:SI (not:SI
(SHIFT:SI
(match_operand:SI 1 "register_operand" "r")
@@ -4923,8 +4923,8 @@
)
(define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0_no_reuse"
- [(set (reg:CC_NZ CC_REGNUM)
- (compare:CC_NZ
+ [(set (reg:CC_NZV CC_REGNUM)
+ (compare:CC_NZV
(and:GPI (not:GPI
(SHIFT:GPI
(match_operand:GPI 0 "register_operand" "r")
@@ -5029,8 +5029,8 @@
")
(define_insn "*and<mode>_compare0"
- [(set (reg:CC_NZ CC_REGNUM)
- (compare:CC_NZ
+ [(set (reg:CC_Z CC_REGNUM)
+ (compare:CC_Z
(match_operand:SHORT 0 "register_operand" "r")
(const_int 0)))]
""
@@ -5039,8 +5039,8 @@
)
(define_insn "*ands<GPI:mode>_compare0"
- [(set (reg:CC_NZ CC_REGNUM)
- (compare:CC_NZ
+ [(set (reg:CC_Z CC_REGNUM)
+ (compare:CC_Z
(zero_extend:GPI (match_operand:SHORT 1 "register_operand" "r"))
(const_int 0)))
(set (match_operand:GPI 0 "register_operand" "=r")
@@ -5051,8 +5051,8 @@
)
(define_insn "*and<mode>3nr_compare0"
- [(set (reg:CC_NZ CC_REGNUM)
- (compare:CC_NZ
+ [(set (reg:CC_NZV CC_REGNUM)
+ (compare:CC_NZV
(and:GPI (match_operand:GPI 0 "register_operand" "%r,r")
(match_operand:GPI 1 "aarch64_logical_operand" "r,<lconst>"))
(const_int 0)))]
@@ -5064,24 +5064,24 @@
)
(define_split
- [(set (reg:CC_NZ CC_REGNUM)
- (compare:CC_NZ
+ [(set (reg:CC_NZV CC_REGNUM)
+ (compare:CC_NZV
(and:GPI (match_operand:GPI 0 "register_operand")
(match_operand:GPI 1 "aarch64_mov_imm_operand"))
(const_int 0)))
(clobber (match_operand:SI 2 "register_operand"))]
""
[(set (match_dup 2) (match_dup 1))
- (set (reg:CC_NZ CC_REGNUM)
- (compare:CC_NZ
+ (set (reg:CC_NZV CC_REGNUM)
+ (compare:CC_NZV
(and:GPI (match_dup 0)
(match_dup 2))
(const_int 0)))]
)
(define_insn "*and<mode>3nr_compare0_zextract"
- [(set (reg:CC_NZ CC_REGNUM)
- (compare:CC_NZ
+ [(set (reg:CC_Z CC_REGNUM)
+ (compare:CC_Z
(zero_extract:GPI (match_operand:GPI 0 "register_operand" "r")
(match_operand:GPI 1 "const_int_operand" "n")
(match_operand:GPI 2 "const_int_operand" "n"))
@@ -5102,8 +5102,8 @@
)
(define_insn "*and_<SHIFT:optab><mode>3nr_compare0"
- [(set (reg:CC_NZ CC_REGNUM)
- (compare:CC_NZ
+ [(set (reg:CC_NZV CC_REGNUM)
+ (compare:CC_NZV
(and:GPI (SHIFT:GPI
(match_operand:GPI 0 "register_operand" "r")
(match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
@@ -5119,8 +5119,8 @@
)
(define_split
- [(set (reg:CC_NZ CC_REGNUM)
- (compare:CC_NZ
+ [(set (reg:CC_NZV CC_REGNUM)
+ (compare:CC_NZV
(and:GPI (SHIFT:GPI
(match_operand:GPI 0 "register_operand")
(match_operand:QI 1 "aarch64_shift_imm_<mode>"))
@@ -5129,8 +5129,8 @@
(clobber (match_operand:SI 3 "register_operand"))]
""
[(set (match_dup 3) (match_dup 2))
- (set (reg:CC_NZ CC_REGNUM)
- (compare:CC_NZ
+ (set (reg:CC_NZV CC_REGNUM)
+ (compare:CC_NZV
(and:GPI (SHIFT:GPI
(match_dup 0)
(match_dup 1))
diff --git a/gcc/config/i386/i386-builtin-types.def b/gcc/config/i386/i386-builtin-types.def
index 63a360b..2c27a4e 100644
--- a/gcc/config/i386/i386-builtin-types.def
+++ b/gcc/config/i386/i386-builtin-types.def
@@ -69,7 +69,7 @@ DEF_PRIMITIVE_TYPE (UINT16, short_unsigned_type_node)
DEF_PRIMITIVE_TYPE (INT64, long_long_integer_type_node)
DEF_PRIMITIVE_TYPE (UINT64, long_long_unsigned_type_node)
DEF_PRIMITIVE_TYPE (FLOAT16, ix86_float16_type_node)
-DEF_PRIMITIVE_TYPE (BFLOAT16, ix86_bf16_type_node)
+DEF_PRIMITIVE_TYPE (BFLOAT16, bfloat16_type_node)
DEF_PRIMITIVE_TYPE (FLOAT, float_type_node)
DEF_PRIMITIVE_TYPE (DOUBLE, double_type_node)
DEF_PRIMITIVE_TYPE (FLOAT80, float80_type_node)
diff --git a/gcc/config/i386/i386-builtins.cc b/gcc/config/i386/i386-builtins.cc
index b91aba1..b5c651a 100644
--- a/gcc/config/i386/i386-builtins.cc
+++ b/gcc/config/i386/i386-builtins.cc
@@ -126,7 +126,6 @@ BDESC_VERIFYS (IX86_BUILTIN_MAX,
static GTY(()) tree ix86_builtin_type_tab[(int) IX86_BT_LAST_CPTR + 1];
tree ix86_float16_type_node = NULL_TREE;
-tree ix86_bf16_type_node = NULL_TREE;
tree ix86_bf16_ptr_type_node = NULL_TREE;
/* Retrieve an element from the above table, building some of
@@ -1372,16 +1371,18 @@ ix86_register_float16_builtin_type (void)
static void
ix86_register_bf16_builtin_type (void)
{
- ix86_bf16_type_node = make_node (REAL_TYPE);
- TYPE_PRECISION (ix86_bf16_type_node) = 16;
- SET_TYPE_MODE (ix86_bf16_type_node, BFmode);
- layout_type (ix86_bf16_type_node);
+ if (bfloat16_type_node == NULL_TREE)
+ {
+ bfloat16_type_node = make_node (REAL_TYPE);
+ TYPE_PRECISION (bfloat16_type_node) = 16;
+ SET_TYPE_MODE (bfloat16_type_node, BFmode);
+ layout_type (bfloat16_type_node);
+ }
if (!maybe_get_identifier ("__bf16") && TARGET_SSE2)
{
- lang_hooks.types.register_builtin_type (ix86_bf16_type_node,
- "__bf16");
- ix86_bf16_ptr_type_node = build_pointer_type (ix86_bf16_type_node);
+ lang_hooks.types.register_builtin_type (bfloat16_type_node, "__bf16");
+ ix86_bf16_ptr_type_node = build_pointer_type (bfloat16_type_node);
}
}
diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc
index 6baff6d..a0f8a98 100644
--- a/gcc/config/i386/i386-expand.cc
+++ b/gcc/config/i386/i386-expand.cc
@@ -14941,7 +14941,7 @@ static machine_mode
get_mode_wider_vector (machine_mode o)
{
/* ??? Rely on the ordering that genmodes.cc gives to vectors. */
- machine_mode n = GET_MODE_WIDER_MODE (o).require ();
+ machine_mode n = GET_MODE_NEXT_MODE (o).require ();
gcc_assert (GET_MODE_NUNITS (o) == GET_MODE_NUNITS (n) * 2);
gcc_assert (GET_MODE_SIZE (o) == GET_MODE_SIZE (n));
return n;
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index ff4de2d..480db35 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -2423,6 +2423,7 @@ classify_argument (machine_mode mode, const_tree type,
classes[1] = X86_64_SSEUP_CLASS;
return 2;
case E_HCmode:
+ case E_BCmode:
classes[0] = X86_64_SSE_CLASS;
if (!(bit_offset % 64))
return 1;
@@ -22428,7 +22429,7 @@ ix86_libgcc_floating_mode_supported_p (scalar_float_mode mode)
be defined by the C front-end for AVX512FP16 intrinsics. We will
issue an error in ix86_expand_move for HFmode if AVX512FP16 isn't
enabled. */
- return ((mode == HFmode && TARGET_SSE2)
+ return (((mode == HFmode || mode == BFmode) && TARGET_SSE2)
? true
: default_libgcc_floating_mode_supported_p (mode));
}
@@ -22731,7 +22732,7 @@ ix86_mangle_type (const_tree type)
switch (TYPE_MODE (type))
{
case E_BFmode:
- return "u6__bf16";
+ return "DF16b";
case E_HFmode:
/* _Float16 is "DF16_".
Align with clang's decision in https://reviews.llvm.org/D33719. */
@@ -22747,55 +22748,6 @@ ix86_mangle_type (const_tree type)
}
}
-/* Return the diagnostic message string if conversion from FROMTYPE to
- TOTYPE is not allowed, NULL otherwise. */
-
-static const char *
-ix86_invalid_conversion (const_tree fromtype, const_tree totype)
-{
- if (element_mode (fromtype) != element_mode (totype))
- {
- /* Do no allow conversions to/from BFmode scalar types. */
- if (TYPE_MODE (fromtype) == BFmode)
- return N_("invalid conversion from type %<__bf16%>");
- if (TYPE_MODE (totype) == BFmode)
- return N_("invalid conversion to type %<__bf16%>");
- }
-
- /* Conversion allowed. */
- return NULL;
-}
-
-/* Return the diagnostic message string if the unary operation OP is
- not permitted on TYPE, NULL otherwise. */
-
-static const char *
-ix86_invalid_unary_op (int op, const_tree type)
-{
- /* Reject all single-operand operations on BFmode except for &. */
- if (element_mode (type) == BFmode && op != ADDR_EXPR)
- return N_("operation not permitted on type %<__bf16%>");
-
- /* Operation allowed. */
- return NULL;
-}
-
-/* Return the diagnostic message string if the binary operation OP is
- not permitted on TYPE1 and TYPE2, NULL otherwise. */
-
-static const char *
-ix86_invalid_binary_op (int op ATTRIBUTE_UNUSED, const_tree type1,
- const_tree type2)
-{
- /* Reject all 2-operand operations on BFmode. */
- if (element_mode (type1) == BFmode
- || element_mode (type2) == BFmode)
- return N_("operation not permitted on type %<__bf16%>");
-
- /* Operation allowed. */
- return NULL;
-}
-
static GTY(()) tree ix86_tls_stack_chk_guard_decl;
static tree
@@ -24853,15 +24805,6 @@ ix86_libgcc_floating_mode_supported_p
#undef TARGET_MANGLE_TYPE
#define TARGET_MANGLE_TYPE ix86_mangle_type
-#undef TARGET_INVALID_CONVERSION
-#define TARGET_INVALID_CONVERSION ix86_invalid_conversion
-
-#undef TARGET_INVALID_UNARY_OP
-#define TARGET_INVALID_UNARY_OP ix86_invalid_unary_op
-
-#undef TARGET_INVALID_BINARY_OP
-#define TARGET_INVALID_BINARY_OP ix86_invalid_binary_op
-
#undef TARGET_STACK_PROTECT_GUARD
#define TARGET_STACK_PROTECT_GUARD ix86_stack_protect_guard
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 8e84752..6688d92 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -1644,6 +1644,48 @@
DONE;
})
+(define_expand "cbranchbf4"
+ [(set (reg:CC FLAGS_REG)
+ (compare:CC (match_operand:BF 1 "cmp_fp_expander_operand")
+ (match_operand:BF 2 "cmp_fp_expander_operand")))
+ (set (pc) (if_then_else
+ (match_operator 0 "comparison_operator"
+ [(reg:CC FLAGS_REG)
+ (const_int 0)])
+ (label_ref (match_operand 3))
+ (pc)))]
+ ""
+{
+ rtx op1 = gen_lowpart (HImode, operands[1]);
+ if (CONST_INT_P (op1))
+ op1 = simplify_const_unary_operation (FLOAT_EXTEND, SFmode,
+ operands[1], BFmode);
+ else
+ {
+ rtx t1 = gen_reg_rtx (SImode);
+ emit_insn (gen_zero_extendhisi2 (t1, op1));
+ emit_insn (gen_ashlsi3 (t1, t1, GEN_INT (16)));
+ op1 = gen_lowpart (SFmode, t1);
+ }
+ rtx op2 = gen_lowpart (HImode, operands[2]);
+ if (CONST_INT_P (op2))
+ op2 = simplify_const_unary_operation (FLOAT_EXTEND, SFmode,
+ operands[2], BFmode);
+ else
+ {
+ rtx t2 = gen_reg_rtx (SImode);
+ emit_insn (gen_zero_extendhisi2 (t2, op2));
+ emit_insn (gen_ashlsi3 (t2, t2, GEN_INT (16)));
+ op2 = gen_lowpart (SFmode, t2);
+ }
+ do_compare_rtx_and_jump (op1, op2, GET_CODE (operands[0]), 0,
+ SFmode, NULL_RTX, NULL,
+ as_a <rtx_code_label *> (operands[3]),
+ /* Unfortunately this isn't propagated. */
+ profile_probability::even ());
+ DONE;
+})
+
(define_expand "cstorehf4"
[(set (reg:CC FLAGS_REG)
(compare:CC (match_operand:HF 2 "cmp_fp_expander_operand")
@@ -1659,6 +1701,45 @@
DONE;
})
+(define_expand "cstorebf4"
+ [(set (reg:CC FLAGS_REG)
+ (compare:CC (match_operand:BF 2 "cmp_fp_expander_operand")
+ (match_operand:BF 3 "cmp_fp_expander_operand")))
+ (set (match_operand:QI 0 "register_operand")
+ (match_operator 1 "comparison_operator"
+ [(reg:CC FLAGS_REG)
+ (const_int 0)]))]
+ ""
+{
+ rtx op1 = gen_lowpart (HImode, operands[2]);
+ if (CONST_INT_P (op1))
+ op1 = simplify_const_unary_operation (FLOAT_EXTEND, SFmode,
+ operands[2], BFmode);
+ else
+ {
+ rtx t1 = gen_reg_rtx (SImode);
+ emit_insn (gen_zero_extendhisi2 (t1, op1));
+ emit_insn (gen_ashlsi3 (t1, t1, GEN_INT (16)));
+ op1 = gen_lowpart (SFmode, t1);
+ }
+ rtx op2 = gen_lowpart (HImode, operands[3]);
+ if (CONST_INT_P (op2))
+ op2 = simplify_const_unary_operation (FLOAT_EXTEND, SFmode,
+ operands[3], BFmode);
+ else
+ {
+ rtx t2 = gen_reg_rtx (SImode);
+ emit_insn (gen_zero_extendhisi2 (t2, op2));
+ emit_insn (gen_ashlsi3 (t2, t2, GEN_INT (16)));
+ op2 = gen_lowpart (SFmode, t2);
+ }
+ rtx res = emit_store_flag_force (operands[0], GET_CODE (operands[1]),
+ op1, op2, SFmode, 0, 1);
+ if (!rtx_equal_p (res, operands[0]))
+ emit_move_insn (operands[0], res);
+ DONE;
+})
+
(define_expand "cstore<mode>4"
[(set (reg:CC FLAGS_REG)
(compare:CC (match_operand:MODEF 2 "cmp_fp_expander_operand")
diff --git a/gcc/config/sparc/sparc.cc b/gcc/config/sparc/sparc.cc
index c72c38e..10c0f52 100644
--- a/gcc/config/sparc/sparc.cc
+++ b/gcc/config/sparc/sparc.cc
@@ -6051,6 +6051,9 @@ sparc_expand_prologue (void)
}
RTX_FRAME_RELATED_P (insn) = 1;
+
+ /* Ensure no memory access is done before the frame is established. */
+ emit_insn (gen_frame_blockage ());
}
else
{
@@ -6065,13 +6068,7 @@ sparc_expand_prologue (void)
/* %sp is not the CFA register anymore. */
emit_insn (gen_stack_pointer_inc (GEN_INT (4096 - size)));
- /* Make sure no %fp-based store is issued until after the frame is
- established. The offset between the frame pointer and the stack
- pointer is calculated relative to the value of the stack pointer
- at the end of the function prologue, and moving instructions that
- access the stack via the frame pointer between the instructions
- that decrement the stack pointer could result in accessing the
- register window save area, which is volatile. */
+ /* Likewise. */
emit_insn (gen_frame_blockage ());
}
else
@@ -6167,8 +6164,8 @@ sparc_flat_expand_prologue (void)
}
RTX_FRAME_RELATED_P (insn) = 1;
- /* Ensure nothing is scheduled until after the frame is established. */
- emit_insn (gen_blockage ());
+ /* Ensure no memory access is done before the frame is established. */
+ emit_insn (gen_frame_blockage ());
if (frame_pointer_needed)
{
@@ -6255,6 +6252,9 @@ sparc_expand_epilogue (bool for_eh)
; /* do nothing. */
else if (sparc_leaf_function_p)
{
+ /* Ensure no memory access is done after the frame is destroyed. */
+ emit_insn (gen_frame_blockage ());
+
if (size <= 4096)
emit_insn (gen_stack_pointer_inc (GEN_INT (size)));
else if (size <= 8192)
@@ -6305,15 +6305,15 @@ sparc_flat_expand_epilogue (bool for_eh)
; /* do nothing. */
else if (frame_pointer_needed)
{
- /* Make sure the frame is destroyed after everything else is done. */
- emit_insn (gen_blockage ());
+ /* Ensure no memory access is done after the frame is destroyed. */
+ emit_insn (gen_frame_blockage ());
emit_move_insn (stack_pointer_rtx, gen_rtx_REG (Pmode, 1));
}
else
{
/* Likewise. */
- emit_insn (gen_blockage ());
+ emit_insn (gen_frame_blockage ());
if (size <= 4096)
emit_insn (gen_stack_pointer_inc (GEN_INT (size)));
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 320b465..a9983c1 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,99 @@
+2022-10-14 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/106304
+ * constexpr.cc (cxx_dynamic_cast_fn_p): Check for abi_node
+ instead of global_namespace.
+ * rtti.cc (build_dynamic_cast_1): Set DECL_CONTEXT and
+ DECL_SOURCE_LOCATION when building dynamic_cast_node. Push
+ it into the namespace.
+
+2022-10-14 Jakub Jelinek <jakub@redhat.com>
+
+ * cp-tree.h (extended_float_type_p): Return true for
+ bfloat16_type_node.
+ * typeck.cc (cp_compare_floating_point_conversion_ranks): Set
+ extended{1,2} if mv{1,2} is bfloat16_type_node. Adjust comment.
+
+2022-10-14 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/82071
+ PR c/87390
+ PR c++/107097
+ * cp-tree.h (cp_ep_convert_and_check): Remove.
+ * cvt.cc (cp_ep_convert_and_check): Remove.
+ * call.cc (build_conditional_expr): Use excess precision for ?: with
+ one arm floating and another integral. Don't convert first to
+ semantic result type from integral types.
+ (convert_like_internal): Don't call cp_ep_convert_and_check, instead
+ just strip EXCESS_PRECISION_EXPR before calling cp_convert_and_check
+ or cp_convert.
+ * typeck.cc (cp_build_binary_op): Set may_need_excess_precision
+ for comparisons or SPACESHIP_EXPR with at least one operand integral.
+ Don't compute semantic_result_type if build_type is non-NULL. Call
+ cp_convert_and_check instead of cp_ep_convert_and_check.
+
+2022-10-14 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/323
+ PR c++/107097
+ * parser.cc (cp_parser_primary_expression): Handle
+ EXCESS_PRECISION_EXPR with REAL_CST operand the same as REAL_CST.
+ * cvt.cc (cp_ep_convert_and_check): New function.
+ * call.cc (build_conditional_expr): Add excess precision support.
+ When type_after_usual_arithmetic_conversions returns error_mark_node,
+ use gcc_checking_assert that it is because of uncomparable floating
+ point ranks instead of checking all those conditions and make it
+ work also with complex types.
+ (convert_like_internal): Likewise. Add NESTED_P argument, pass true
+ to recursive calls to convert_like.
+ (convert_like): Add NESTED_P argument, pass it through to
+ convert_like_internal. For other overload pass false to it.
+ (convert_like_with_context): Pass false to NESTED_P.
+ (convert_arg_to_ellipsis): Add excess precision support.
+ (magic_varargs_p): For __builtin_is{finite,inf,inf_sign,nan,normal}
+ and __builtin_fpclassify return 2 instead of 1, document what it
+ means.
+ (build_over_call): Don't handle former magic 2 which is no longer
+ used, instead for magic 1 remove EXCESS_PRECISION_EXPR.
+ (perform_direct_initialization_if_possible): Pass false to NESTED_P
+ convert_like argument.
+ * constexpr.cc (cxx_eval_constant_expression): Handle
+ EXCESS_PRECISION_EXPR.
+ (potential_constant_expression_1): Likewise.
+ * pt.cc (tsubst_copy, tsubst_copy_and_build): Likewise.
+ * cp-tree.h (cp_ep_convert_and_check): Declare.
+ * cp-gimplify.cc (cp_fold): Handle EXCESS_PRECISION_EXPR.
+ * typeck.cc (cp_common_type): For COMPLEX_TYPEs, return error_mark_node
+ if recursive call returned it.
+ (convert_arguments): For magic 1 remove EXCESS_PRECISION_EXPR.
+ (cp_build_binary_op): Add excess precision support. When
+ cp_common_type returns error_mark_node, use gcc_checking_assert that
+ it is because of uncomparable floating point ranks instead of checking
+ all those conditions and make it work also with complex types.
+ (cp_build_unary_op): Likewise.
+ (cp_build_compound_expr): Likewise.
+ (build_static_cast_1): Remove EXCESS_PRECISION_EXPR.
+
+2022-10-13 Jason Merrill <jason@redhat.com>
+
+ * cp-tree.h: Fix whitespace.
+ * parser.h: Fix whitespace.
+ * decl.cc: Fix whitespace.
+ * parser.cc: Fix whitespace.
+ * pt.cc: Fix whitespace.
+
+2022-10-13 Martin Liska <mliska@suse.cz>
+
+ * vtable-class-hierarchy.cc (vtv_generate_init_routine): Emit
+ an artificial variable that would be put into .preinit_array
+ section.
+
+2022-10-13 Marek Polacek <polacek@redhat.com>
+
+ PR c++/106925
+ * except.cc (maybe_splice_retval_cleanup): Check current_function_decl.
+ Make the bool const.
+
2022-10-12 Marek Polacek <polacek@redhat.com>
* call.cc (standard_conversion): Remove LOOKUP_PREFER_RVALUE code.
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index b9c08d6..6a34e9c 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -5359,6 +5359,7 @@ build_conditional_expr (const op_location_t &loc,
tree arg3_type;
tree result = NULL_TREE;
tree result_type = NULL_TREE;
+ tree semantic_result_type = NULL_TREE;
bool is_glvalue = true;
struct z_candidate *candidates = 0;
struct z_candidate *cand;
@@ -5392,6 +5393,9 @@ build_conditional_expr (const op_location_t &loc,
expression, since it needs to be materialized for the
conversion to bool, so treat it as an xvalue in arg2. */
arg2 = move (TARGET_EXPR_SLOT (arg1));
+ else if (TREE_CODE (arg1) == EXCESS_PRECISION_EXPR)
+ arg2 = arg1 = build1 (EXCESS_PRECISION_EXPR, TREE_TYPE (arg1),
+ cp_save_expr (TREE_OPERAND (arg1, 0)));
else
arg2 = arg1 = cp_save_expr (arg1);
}
@@ -5550,6 +5554,52 @@ build_conditional_expr (const op_location_t &loc,
if (error_operand_p (arg1))
return error_mark_node;
+ arg2_type = unlowered_expr_type (arg2);
+ arg3_type = unlowered_expr_type (arg3);
+
+ if ((TREE_CODE (arg2) == EXCESS_PRECISION_EXPR
+ || TREE_CODE (arg3) == EXCESS_PRECISION_EXPR)
+ && (TREE_CODE (arg2_type) == INTEGER_TYPE
+ || TREE_CODE (arg2_type) == REAL_TYPE
+ || TREE_CODE (arg2_type) == COMPLEX_TYPE)
+ && (TREE_CODE (arg3_type) == INTEGER_TYPE
+ || TREE_CODE (arg3_type) == REAL_TYPE
+ || TREE_CODE (arg3_type) == COMPLEX_TYPE))
+ {
+ semantic_result_type
+ = type_after_usual_arithmetic_conversions (arg2_type, arg3_type);
+ if (semantic_result_type == error_mark_node)
+ {
+ tree t1 = arg2_type;
+ tree t2 = arg3_type;
+ if (TREE_CODE (t1) == COMPLEX_TYPE)
+ t1 = TREE_TYPE (t1);
+ if (TREE_CODE (t2) == COMPLEX_TYPE)
+ t2 = TREE_TYPE (t2);
+ gcc_checking_assert (TREE_CODE (t1) == REAL_TYPE
+ && TREE_CODE (t2) == REAL_TYPE
+ && (extended_float_type_p (t1)
+ || extended_float_type_p (t2))
+ && cp_compare_floating_point_conversion_ranks
+ (t1, t2) == 3);
+ if (complain & tf_error)
+ error_at (loc, "operands to %<?:%> of types %qT and %qT "
+ "have unordered conversion rank",
+ arg2_type, arg3_type);
+ return error_mark_node;
+ }
+ if (TREE_CODE (arg2) == EXCESS_PRECISION_EXPR)
+ {
+ arg2 = TREE_OPERAND (arg2, 0);
+ arg2_type = TREE_TYPE (arg2);
+ }
+ if (TREE_CODE (arg3) == EXCESS_PRECISION_EXPR)
+ {
+ arg3 = TREE_OPERAND (arg3, 0);
+ arg3_type = TREE_TYPE (arg3);
+ }
+ }
+
/* [expr.cond]
If either the second or the third operand has type (possibly
@@ -5557,8 +5607,6 @@ build_conditional_expr (const op_location_t &loc,
array-to-pointer (_conv.array_), and function-to-pointer
(_conv.func_) standard conversions are performed on the second
and third operands. */
- arg2_type = unlowered_expr_type (arg2);
- arg3_type = unlowered_expr_type (arg3);
if (VOID_TYPE_P (arg2_type) || VOID_TYPE_P (arg3_type))
{
/* 'void' won't help in resolving an overloaded expression on the
@@ -5847,17 +5895,65 @@ build_conditional_expr (const op_location_t &loc,
&& (ARITHMETIC_TYPE_P (arg3_type)
|| UNSCOPED_ENUM_P (arg3_type)))
{
- /* In this case, there is always a common type. */
- result_type = type_after_usual_arithmetic_conversions (arg2_type,
- arg3_type);
- if (result_type == error_mark_node
- && TREE_CODE (arg2_type) == REAL_TYPE
- && TREE_CODE (arg3_type) == REAL_TYPE
- && (extended_float_type_p (arg2_type)
- || extended_float_type_p (arg3_type))
- && cp_compare_floating_point_conversion_ranks (arg2_type,
- arg3_type) == 3)
+ /* A conditional expression between a floating-point
+ type and an integer type should convert the integer type to
+ the evaluation format of the floating-point type, with
+ possible excess precision. */
+ tree eptype2 = arg2_type;
+ tree eptype3 = arg3_type;
+ tree eptype;
+ if (ANY_INTEGRAL_TYPE_P (arg2_type)
+ && (eptype = excess_precision_type (arg3_type)) != NULL_TREE)
+ {
+ eptype3 = eptype;
+ if (!semantic_result_type)
+ semantic_result_type
+ = type_after_usual_arithmetic_conversions (arg2_type, arg3_type);
+ }
+ else if (ANY_INTEGRAL_TYPE_P (arg3_type)
+ && (eptype = excess_precision_type (arg2_type)) != NULL_TREE)
+ {
+ eptype2 = eptype;
+ if (!semantic_result_type)
+ semantic_result_type
+ = type_after_usual_arithmetic_conversions (arg2_type, arg3_type);
+ }
+ result_type = type_after_usual_arithmetic_conversions (eptype2,
+ eptype3);
+ if (result_type == error_mark_node)
{
+ tree t1 = eptype2;
+ tree t2 = eptype3;
+ if (TREE_CODE (t1) == COMPLEX_TYPE)
+ t1 = TREE_TYPE (t1);
+ if (TREE_CODE (t2) == COMPLEX_TYPE)
+ t2 = TREE_TYPE (t2);
+ gcc_checking_assert (TREE_CODE (t1) == REAL_TYPE
+ && TREE_CODE (t2) == REAL_TYPE
+ && (extended_float_type_p (t1)
+ || extended_float_type_p (t2))
+ && cp_compare_floating_point_conversion_ranks
+ (t1, t2) == 3);
+ if (complain & tf_error)
+ error_at (loc, "operands to %<?:%> of types %qT and %qT "
+ "have unordered conversion rank",
+ eptype2, eptype3);
+ return error_mark_node;
+ }
+ if (semantic_result_type == error_mark_node)
+ {
+ tree t1 = arg2_type;
+ tree t2 = arg3_type;
+ if (TREE_CODE (t1) == COMPLEX_TYPE)
+ t1 = TREE_TYPE (t1);
+ if (TREE_CODE (t2) == COMPLEX_TYPE)
+ t2 = TREE_TYPE (t2);
+ gcc_checking_assert (TREE_CODE (t1) == REAL_TYPE
+ && TREE_CODE (t2) == REAL_TYPE
+ && (extended_float_type_p (t1)
+ || extended_float_type_p (t2))
+ && cp_compare_floating_point_conversion_ranks
+ (t1, t2) == 3);
if (complain & tf_error)
error_at (loc, "operands to %<?:%> of types %qT and %qT "
"have unordered conversion rank",
@@ -6009,9 +6105,15 @@ build_conditional_expr (const op_location_t &loc,
/* If this expression is an rvalue, but might be mistaken for an
lvalue, we must add a NON_LVALUE_EXPR. */
result = rvalue (result);
+ if (semantic_result_type)
+ result = build1 (EXCESS_PRECISION_EXPR, semantic_result_type,
+ result);
}
else
- result = force_paren_expr (result);
+ {
+ result = force_paren_expr (result);
+ gcc_assert (semantic_result_type == NULL_TREE);
+ }
return result;
}
@@ -7875,7 +7977,7 @@ maybe_warn_array_conv (location_t loc, conversion *c, tree expr)
}
/* We call this recursively in convert_like_internal. */
-static tree convert_like (conversion *, tree, tree, int, bool, bool,
+static tree convert_like (conversion *, tree, tree, int, bool, bool, bool,
tsubst_flags_t);
/* Perform the conversions in CONVS on the expression EXPR. FN and
@@ -7891,7 +7993,7 @@ static tree convert_like (conversion *, tree, tree, int, bool, bool,
static tree
convert_like_internal (conversion *convs, tree expr, tree fn, int argnum,
bool issue_conversion_warnings, bool c_cast_p,
- tsubst_flags_t complain)
+ bool nested_p, tsubst_flags_t complain)
{
tree totype = convs->type;
diagnostic_t diag_kind;
@@ -7968,7 +8070,8 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum,
print_z_candidate (loc, N_("candidate is:"), t->cand);
expr = convert_like (t, expr, fn, argnum,
/*issue_conversion_warnings=*/false,
- /*c_cast_p=*/false, complain);
+ /*c_cast_p=*/false, /*nested_p=*/true,
+ complain);
if (convs->kind == ck_ref_bind)
expr = convert_to_reference (totype, expr, CONV_IMPLICIT,
LOOKUP_NORMAL, NULL_TREE,
@@ -7983,13 +8086,15 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum,
{
expr = convert_like (t, expr, fn, argnum,
/*issue_conversion_warnings=*/false,
- /*c_cast_p=*/false, complain);
+ /*c_cast_p=*/false, /*nested_p=*/true,
+ complain);
break;
}
else if (t->kind == ck_ambig)
return convert_like (t, expr, fn, argnum,
/*issue_conversion_warnings=*/false,
- /*c_cast_p=*/false, complain);
+ /*c_cast_p=*/false, /*nested_p=*/true,
+ complain);
else if (t->kind == ck_identity)
break;
}
@@ -8109,6 +8214,8 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum,
if (type_unknown_p (expr))
expr = instantiate_type (totype, expr, complain);
+ if (!nested_p && TREE_CODE (expr) == EXCESS_PRECISION_EXPR)
+ expr = cp_convert (totype, TREE_OPERAND (expr, 0), complain);
if (expr == null_node
&& INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (totype))
/* If __null has been converted to an integer type, we do not want to
@@ -8148,7 +8255,8 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum,
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expr), ix, val)
{
tree sub = convert_like (convs->u.list[ix], val, fn,
- argnum, false, false, complain);
+ argnum, false, false,
+ /*nested_p=*/true, complain);
if (sub == error_mark_node)
return sub;
if (!BRACE_ENCLOSED_INITIALIZER_P (val)
@@ -8216,7 +8324,7 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum,
expr = convert_like (next_conversion (convs), expr, fn, argnum,
convs->kind == ck_ref_bind
? issue_conversion_warnings : false,
- c_cast_p, complain & ~tf_no_cleanup);
+ c_cast_p, /*nested_p=*/true, complain & ~tf_no_cleanup);
if (expr == error_mark_node)
return error_mark_node;
@@ -8475,6 +8583,8 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum,
return error_mark_node;
warning_sentinel w (warn_zero_as_null_pointer_constant);
+ if (TREE_CODE (expr) == EXCESS_PRECISION_EXPR)
+ expr = TREE_OPERAND (expr, 0);
if (issue_conversion_warnings)
expr = cp_convert_and_check (totype, expr, complain);
else
@@ -8509,7 +8619,7 @@ conv_unsafe_in_template_p (tree to, tree from)
static tree
convert_like (conversion *convs, tree expr, tree fn, int argnum,
- bool issue_conversion_warnings, bool c_cast_p,
+ bool issue_conversion_warnings, bool c_cast_p, bool nested_p,
tsubst_flags_t complain)
{
/* Creating &TARGET_EXPR<> in a template breaks when substituting,
@@ -8532,7 +8642,8 @@ convert_like (conversion *convs, tree expr, tree fn, int argnum,
error_mark_node. */
}
expr = convert_like_internal (convs, expr, fn, argnum,
- issue_conversion_warnings, c_cast_p, complain);
+ issue_conversion_warnings, c_cast_p,
+ nested_p, complain);
if (expr == error_mark_node)
return error_mark_node;
return conv_expr ? conv_expr : expr;
@@ -8545,7 +8656,7 @@ convert_like (conversion *convs, tree expr, tsubst_flags_t complain)
{
return convert_like (convs, expr, NULL_TREE, 0,
/*issue_conversion_warnings=*/true,
- /*c_cast_p=*/false, complain);
+ /*c_cast_p=*/false, /*nested_p=*/false, complain);
}
/* Convenience wrapper for convert_like. */
@@ -8556,7 +8667,7 @@ convert_like_with_context (conversion *convs, tree expr, tree fn, int argnum,
{
return convert_like (convs, expr, fn, argnum,
/*issue_conversion_warnings=*/true,
- /*c_cast_p=*/false, complain);
+ /*c_cast_p=*/false, /*nested_p=*/false, complain);
}
/* ARG is being passed to a varargs function. Perform any conversions
@@ -8587,6 +8698,8 @@ convert_arg_to_ellipsis (tree arg, tsubst_flags_t complain)
"implicit conversion from %qH to %qI when passing "
"argument to function",
arg_type, double_type_node);
+ if (TREE_CODE (arg) == EXCESS_PRECISION_EXPR)
+ arg = TREE_OPERAND (arg, 0);
arg = mark_rvalue_use (arg);
arg = convert_to_real_nofold (double_type_node, arg);
}
@@ -8893,9 +9006,9 @@ convert_for_arg_passing (tree type, tree val, tsubst_flags_t complain)
/* Returns non-zero iff FN is a function with magic varargs, i.e. ones for
which just decay_conversion or no conversions at all should be done.
This is true for some builtins which don't act like normal functions.
- Return 2 if no conversions at all should be done, 1 if just
- decay_conversion. Return 3 for special treatment of the 3rd argument
- for __builtin_*_overflow_p. */
+ Return 2 if just decay_conversion and removal of excess precision should
+ be done, 1 if just decay_conversion. Return 3 for special treatment of
+ the 3rd argument for __builtin_*_overflow_p. */
int
magic_varargs_p (tree fn)
@@ -8914,7 +9027,15 @@ magic_varargs_p (tree fn)
case BUILT_IN_MUL_OVERFLOW_P:
return 3;
- default:;
+ case BUILT_IN_ISFINITE:
+ case BUILT_IN_ISINF:
+ case BUILT_IN_ISINF_SIGN:
+ case BUILT_IN_ISNAN:
+ case BUILT_IN_ISNORMAL:
+ case BUILT_IN_FPCLASSIFY:
+ return 2;
+
+ default:
return lookup_attribute ("type generic",
TYPE_ATTRIBUTES (TREE_TYPE (fn))) != 0;
}
@@ -9717,7 +9838,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
for (; arg_index < vec_safe_length (args); ++arg_index)
{
tree a = (*args)[arg_index];
- if ((magic == 3 && arg_index == 2) || magic == 2)
+ if (magic == 3 && arg_index == 2)
{
/* Do no conversions for certain magic varargs. */
a = mark_type_use (a);
@@ -9725,8 +9846,13 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
return error_mark_node;
}
else if (magic != 0)
- /* For other magic varargs only do decay_conversion. */
- a = decay_conversion (a, complain);
+ {
+ /* Don't truncate excess precision to the semantic type. */
+ if (magic == 1 && TREE_CODE (a) == EXCESS_PRECISION_EXPR)
+ a = TREE_OPERAND (a, 0);
+ /* For other magic varargs only do decay_conversion. */
+ a = decay_conversion (a, complain);
+ }
else if (DECL_CONSTRUCTOR_P (fn)
&& same_type_ignoring_top_level_qualifiers_p (DECL_CONTEXT (fn),
TREE_TYPE (a)))
@@ -13004,7 +13130,7 @@ perform_direct_initialization_if_possible (tree type,
else
expr = convert_like (conv, expr, NULL_TREE, 0,
/*issue_conversion_warnings=*/false,
- c_cast_p, complain);
+ c_cast_p, /*nested_p=*/false, complain);
/* Free all the conversions we allocated. */
obstack_free (&conversion_obstack, p);
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 2038f43..0366396 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -2088,7 +2088,7 @@ cxx_dynamic_cast_fn_p (tree fndecl)
{
return (cxx_dialect >= cxx20
&& id_equal (DECL_NAME (fndecl), "__dynamic_cast")
- && CP_DECL_CONTEXT (fndecl) == global_namespace);
+ && CP_DECL_CONTEXT (fndecl) == abi_node);
}
/* Often, we have an expression in the form of address + offset, e.g.
@@ -7598,6 +7598,19 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
}
break;
+ case EXCESS_PRECISION_EXPR:
+ {
+ tree oldop = TREE_OPERAND (t, 0);
+
+ tree op = cxx_eval_constant_expression (ctx, oldop,
+ lval,
+ non_constant_p, overflow_p);
+ if (*non_constant_p)
+ return t;
+ r = fold_convert (TREE_TYPE (t), op);
+ break;
+ }
+
case EMPTY_CLASS_EXPR:
/* Handle EMPTY_CLASS_EXPR produced by build_call_a by lowering
it to an appropriate CONSTRUCTOR. */
@@ -8898,6 +8911,9 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
sub-object of such an object; */
return RECUR (TREE_OPERAND (t, 0), rval);
+ case EXCESS_PRECISION_EXPR:
+ return RECUR (TREE_OPERAND (t, 0), rval);
+
case VAR_DECL:
if (DECL_HAS_VALUE_EXPR_P (t))
{
diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
index a937060..2608475 100644
--- a/gcc/cp/cp-gimplify.cc
+++ b/gcc/cp/cp-gimplify.cc
@@ -2515,6 +2515,11 @@ cp_fold (tree x)
break;
+ case EXCESS_PRECISION_EXPR:
+ op0 = cp_fold_maybe_rvalue (TREE_OPERAND (x, 0), rval_ops);
+ x = fold_convert_loc (EXPR_LOCATION (x), TREE_TYPE (x), op0);
+ break;
+
case INDIRECT_REF:
/* We don't need the decltype(auto) obfuscation anymore. */
if (REF_PARENTHESIZED_P (x))
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 3b67be6..e2607f0 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7458,7 +7458,7 @@ extern tree get_template_argument_pack_elems (const_tree);
extern tree get_function_template_decl (const_tree);
extern tree resolve_nondeduced_context (tree, tsubst_flags_t);
extern tree resolve_nondeduced_context_or_error (tree, tsubst_flags_t);
-extern hashval_t iterative_hash_template_arg (tree arg, hashval_t val);
+extern hashval_t iterative_hash_template_arg (tree arg, hashval_t val);
extern tree coerce_template_parms (tree, tree, tree);
extern tree coerce_template_parms (tree, tree, tree, tsubst_flags_t);
extern tree canonicalize_type_argument (tree, tsubst_flags_t);
@@ -7519,7 +7519,7 @@ extern tree lookup_fnfields (tree, tree, int, tsubst_flags_t);
extern tree lookup_member (tree, tree, int, bool,
tsubst_flags_t,
access_failure_info *afi = NULL);
-extern tree lookup_member_fuzzy (tree, tree, bool);
+extern tree lookup_member_fuzzy (tree, tree, bool);
extern tree locate_field_accessor (tree, tree, bool);
extern int look_for_overrides (tree, tree);
extern void get_pure_virtuals (tree);
@@ -8741,6 +8741,8 @@ extended_float_type_p (tree type)
for (int i = 0; i < NUM_FLOATN_NX_TYPES; ++i)
if (type == FLOATN_TYPE_NODE (i))
return true;
+ if (type == bfloat16_type_node)
+ return true;
return false;
}
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 82eb0c2..85b892c 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -2319,7 +2319,6 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
= DECL_DECLARED_INLINE_P (new_result);
DECL_DISREGARD_INLINE_LIMITS (old_result)
|= DECL_DISREGARD_INLINE_LIMITS (new_result);
-
}
else
{
@@ -10220,7 +10219,6 @@ grokfndecl (tree ctype,
return NULL_TREE;
}
-
/* A friend declaration of the form friend void f<>(). Record
the information in the TEMPLATE_ID_EXPR. */
SET_DECL_IMPLICIT_INSTANTIATION (decl);
diff --git a/gcc/cp/except.cc b/gcc/cp/except.cc
index 703d1d5..2677a9b 100644
--- a/gcc/cp/except.cc
+++ b/gcc/cp/except.cc
@@ -1307,9 +1307,12 @@ maybe_splice_retval_cleanup (tree compound_stmt)
{
/* If we need a cleanup for the return value, add it in at the same level as
pushdecl_outermost_localscope. And also in try blocks. */
- bool function_body
+ const bool function_body
= (current_binding_level->level_chain
- && current_binding_level->level_chain->kind == sk_function_parms);
+ && current_binding_level->level_chain->kind == sk_function_parms
+ /* When we're processing a default argument, c_f_d may not have been
+ set. */
+ && current_function_decl);
if ((function_body || current_binding_level->kind == sk_try)
&& !DECL_CONSTRUCTOR_P (current_function_decl)
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 4e3ed66..9ddfb02 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -5583,7 +5583,9 @@ cp_parser_primary_expression (cp_parser *parser,
/* Floating-point literals are only allowed in an integral
constant expression if they are cast to an integral or
enumeration type. */
- if (TREE_CODE (token->u.value) == REAL_CST
+ if ((TREE_CODE (token->u.value) == REAL_CST
+ || (TREE_CODE (token->u.value) == EXCESS_PRECISION_EXPR
+ && TREE_CODE (TREE_OPERAND (token->u.value, 0)) == REAL_CST))
&& parser->integral_constant_expression_p
&& pedantic)
{
@@ -11677,10 +11679,10 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
declarator = make_call_declarator (declarator, param_list, quals,
VIRT_SPEC_UNSPECIFIED,
- REF_QUAL_NONE,
+ REF_QUAL_NONE,
tx_qual,
exception_spec,
- return_type,
+ return_type,
trailing_requires_clause,
UNKNOWN_LOCATION);
declarator->std_attributes = std_attrs;
@@ -25410,6 +25412,7 @@ cp_parser_skip_to_closing_square_bracket (cp_parser *parser)
if (!parser->lexer->in_pragma)
break;
/* FALLTHRU */
+
case CPP_EOF:
/* If we've run out of tokens, then there is no closing `]'. */
return false;
@@ -27490,6 +27493,7 @@ cp_parser_member_declaration (cp_parser* parser)
&decl_specifiers,
declarator,
attributes);
+
if (parser->fully_implicit_function_template_p)
decl = finish_fully_implicit_template (parser, decl);
/* If the member was not a friend, declare it here. */
@@ -27513,6 +27517,7 @@ cp_parser_member_declaration (cp_parser* parser)
else
if (declarator->kind == cdk_function)
declarator->id_loc = token->location;
+
/* Create the declaration. */
decl = grokfield (declarator, &decl_specifiers,
initializer, /*init_const_expr_p=*/true,
@@ -29107,6 +29112,7 @@ cp_parser_std_attribute (cp_parser *parser, tree attr_ns)
attr_id = canonicalize_attr_name (attr_id);
attribute = build_tree_list (build_tree_list (NULL_TREE, attr_id),
NULL_TREE);
+
/* We used to treat C++11 noreturn attribute as equivalent to GNU's,
but no longer: we have to be able to tell [[noreturn]] and
__attribute__((noreturn)) apart. */
@@ -29437,8 +29443,7 @@ cp_parser_std_attribute_spec (cp_parser *parser)
/* Parse a standard C++-11 attribute-specifier-seq.
attribute-specifier-seq:
- attribute-specifier-seq [opt] attribute-specifier
- */
+ attribute-specifier-seq [opt] attribute-specifier */
static tree
cp_parser_std_attribute_spec_seq (cp_parser *parser)
@@ -31393,6 +31398,7 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,
/* Generate code for it, if necessary. */
expand_or_defer_fn (fn);
+
/* Restore the saved values. */
parser->in_unbraced_linkage_specification_p
= saved_in_unbraced_linkage_specification_p;
diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h
index d688fd1..3e95bfc 100644
--- a/gcc/cp/parser.h
+++ b/gcc/cp/parser.h
@@ -391,7 +391,7 @@ struct GTY(()) cp_parser {
/* When parsing #pragma acc routine, this is a pointer to a helper data
structure. */
cp_oacc_routine_data * GTY((skip)) oacc_routine;
-
+
/* Nonzero if parsing a parameter list where 'auto' should trigger an implicit
template parameter. */
bool auto_is_implicit_function_template_parm_p;
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index ec337e2..e4dca9d 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -1581,6 +1581,7 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
there were no definition, and vice versa. */
DECL_INITIAL (fn) = NULL_TREE;
duplicate_decls (spec, fn, /*hiding=*/is_friend);
+
/* The call to duplicate_decls will have applied
[temp.expl.spec]:
@@ -12185,6 +12186,7 @@ instantiate_class_template (tree type)
r = tsubst (t, args, tf_error, NULL_TREE);
if (TREE_CODE (t) == TEMPLATE_DECL)
--processing_template_decl;
+
set_current_access_from_decl (r);
finish_member_declaration (r);
/* Instantiate members marked with attribute used. */
@@ -17020,7 +17022,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
/* This can happen for a parameter name used later in a function
declaration (such as in a late-specified return type). Just
make a dummy decl, since it's only used for its type. */
- gcc_assert (cp_unevaluated_operand != 0);
+ gcc_assert (cp_unevaluated_operand);
r = tsubst_decl (t, args, complain);
/* Give it the template pattern as its context; its true context
hasn't been instantiated yet and this is good enough for
@@ -17412,6 +17414,18 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
return r;
}
+ case EXCESS_PRECISION_EXPR:
+ {
+ tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+ if (TREE_CODE (op0) == EXCESS_PRECISION_EXPR)
+ {
+ gcc_checking_assert (same_type_p (type, TREE_TYPE (op0)));
+ return op0;
+ }
+ return build1_loc (EXPR_LOCATION (t), code, type, op0);
+ }
+
case COMPONENT_REF:
{
tree object;
@@ -20440,6 +20454,16 @@ tsubst_copy_and_build (tree t,
templated_operator_saved_lookups (t),
complain|decltype_flag));
+ case EXCESS_PRECISION_EXPR:
+ {
+ tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ tree op0 = RECUR (TREE_OPERAND (t, 0));
+ if (TREE_CODE (op0) == EXCESS_PRECISION_EXPR)
+ RETURN (op0);
+ RETURN (build1_loc (EXPR_LOCATION (t), EXCESS_PRECISION_EXPR,
+ type, op0));
+ }
+
case FIX_TRUNC_EXPR:
/* convert_like should have created an IMPLICIT_CONV_EXPR. */
gcc_unreachable ();
@@ -21918,6 +21942,7 @@ instantiate_template (tree tmpl, tree orig_args, tsubst_flags_t complain)
}
return error_mark_node;
}
+
return fndecl;
}
@@ -26183,12 +26208,9 @@ regenerate_decl_from_template (tree decl, tree tmpl, tree args)
{
/* The arguments used to instantiate DECL, from the most general
template. */
- tree code_pattern;
-
- code_pattern = DECL_TEMPLATE_RESULT (tmpl);
+ tree code_pattern = DECL_TEMPLATE_RESULT (tmpl);
- /* Make sure that we can see identifiers, and compute access
- correctly. */
+ /* Make sure that we can see identifiers, and compute access correctly. */
push_access_scope (decl);
if (TREE_CODE (decl) == FUNCTION_DECL)
diff --git a/gcc/cp/rtti.cc b/gcc/cp/rtti.cc
index f5b43ec..a85c7b5 100644
--- a/gcc/cp/rtti.cc
+++ b/gcc/cp/rtti.cc
@@ -787,6 +787,10 @@ build_dynamic_cast_1 (location_t loc, tree type, tree expr,
NULL_TREE));
dcast_fn = (build_library_fn_ptr
(fn_name, fn_type, ECF_LEAF | ECF_PURE | ECF_NOTHROW));
+ /* As with __cxa_atexit in get_atexit_node. */
+ DECL_CONTEXT (dcast_fn) = FROB_CONTEXT (current_namespace);
+ DECL_SOURCE_LOCATION (dcast_fn) = BUILTINS_LOCATION;
+ dcast_fn = pushdecl (dcast_fn, /*hiding=*/true);
pop_abi_namespace (flags);
dynamic_cast_node = dcast_fn;
}
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 69c378d..da0e142 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -293,6 +293,10 @@ cp_compare_floating_point_conversion_ranks (tree t1, tree t2)
if (mv2 == FLOATN_NX_TYPE_NODE (i))
extended2 = i + 1;
}
+ if (mv1 == bfloat16_type_node)
+ extended1 = true;
+ if (mv2 == bfloat16_type_node)
+ extended2 = true;
if (extended2 && !extended1)
{
int ret = cp_compare_floating_point_conversion_ranks (t2, t1);
@@ -390,7 +394,9 @@ cp_compare_floating_point_conversion_ranks (tree t1, tree t2)
if (cnt > 1 && mv2 == long_double_type_node)
return -2;
/* Otherwise, they have equal rank, but extended types
- (other than std::bfloat16_t) have higher subrank. */
+ (other than std::bfloat16_t) have higher subrank.
+ std::bfloat16_t shouldn't have equal rank to any standard
+ floating point type. */
return 1;
}
@@ -439,6 +445,8 @@ cp_common_type (tree t1, tree t2)
tree subtype
= type_after_usual_arithmetic_conversions (subtype1, subtype2);
+ if (subtype == error_mark_node)
+ return subtype;
if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype)
return build_type_attribute_variant (t1, attributes);
else if (code2 == COMPLEX_TYPE && TREE_TYPE (t2) == subtype)
@@ -4603,11 +4611,17 @@ convert_arguments (tree typelist, vec<tree, va_gc> **values, tree fndecl,
}
else
{
- if (fndecl && magic_varargs_p (fndecl))
- /* Don't do ellipsis conversion for __built_in_constant_p
- as this will result in spurious errors for non-trivial
- types. */
- val = require_complete_type (val, complain);
+ int magic = fndecl ? magic_varargs_p (fndecl) : 0;
+ if (magic)
+ {
+ /* Don't truncate excess precision to the semantic type. */
+ if (magic == 1 && TREE_CODE (val) == EXCESS_PRECISION_EXPR)
+ val = TREE_OPERAND (val, 0);
+ /* Don't do ellipsis conversion for __built_in_constant_p
+ as this will result in spurious errors for non-trivial
+ types. */
+ val = require_complete_type (val, complain);
+ }
else
val = convert_arg_to_ellipsis (val, complain);
@@ -5057,7 +5071,7 @@ cp_build_binary_op (const op_location_t &location,
{
tree op0, op1;
enum tree_code code0, code1;
- tree type0, type1;
+ tree type0, type1, orig_type0, orig_type1;
const char *invalid_op_diag;
/* Expression code to give to the expression when it is built.
@@ -5069,6 +5083,10 @@ cp_build_binary_op (const op_location_t &location,
In the simplest cases this is the common type of the arguments. */
tree result_type = NULL_TREE;
+ /* When the computation is in excess precision, the type of the
+ final EXCESS_PRECISION_EXPR. */
+ tree semantic_result_type = NULL;
+
/* Nonzero means operands have already been type-converted
in whatever way is necessary.
Zero means they need to be converted to RESULT_TYPE. */
@@ -5116,6 +5134,10 @@ cp_build_binary_op (const op_location_t &location,
/* Tree holding instrumentation expression. */
tree instrument_expr = NULL_TREE;
+ /* True means this is an arithmetic operation that may need excess
+ precision. */
+ bool may_need_excess_precision;
+
/* Apply default conversions. */
op0 = resolve_nondeduced_context (orig_op0, complain);
op1 = resolve_nondeduced_context (orig_op1, complain);
@@ -5167,8 +5189,8 @@ cp_build_binary_op (const op_location_t &location,
}
}
- type0 = TREE_TYPE (op0);
- type1 = TREE_TYPE (op1);
+ orig_type0 = type0 = TREE_TYPE (op0);
+ orig_type1 = type1 = TREE_TYPE (op1);
/* The expression codes of the data types of the arguments tell us
whether the arguments are integers, floating, pointers, etc. */
@@ -5201,6 +5223,59 @@ cp_build_binary_op (const op_location_t &location,
return error_mark_node;
}
+ switch (code)
+ {
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ case MULT_EXPR:
+ case TRUNC_DIV_EXPR:
+ case CEIL_DIV_EXPR:
+ case FLOOR_DIV_EXPR:
+ case ROUND_DIV_EXPR:
+ case EXACT_DIV_EXPR:
+ may_need_excess_precision = true;
+ break;
+ case EQ_EXPR:
+ case NE_EXPR:
+ case LE_EXPR:
+ case GE_EXPR:
+ case LT_EXPR:
+ case GT_EXPR:
+ case SPACESHIP_EXPR:
+ /* Excess precision for implicit conversions of integers to
+ floating point. */
+ may_need_excess_precision = (ANY_INTEGRAL_TYPE_P (type0)
+ || ANY_INTEGRAL_TYPE_P (type1));
+ break;
+ default:
+ may_need_excess_precision = false;
+ break;
+ }
+ if (TREE_CODE (op0) == EXCESS_PRECISION_EXPR)
+ {
+ op0 = TREE_OPERAND (op0, 0);
+ type0 = TREE_TYPE (op0);
+ }
+ else if (may_need_excess_precision
+ && (code0 == REAL_TYPE || code0 == COMPLEX_TYPE))
+ if (tree eptype = excess_precision_type (type0))
+ {
+ type0 = eptype;
+ op0 = convert (eptype, op0);
+ }
+ if (TREE_CODE (op1) == EXCESS_PRECISION_EXPR)
+ {
+ op1 = TREE_OPERAND (op1, 0);
+ type1 = TREE_TYPE (op1);
+ }
+ else if (may_need_excess_precision
+ && (code1 == REAL_TYPE || code1 == COMPLEX_TYPE))
+ if (tree eptype = excess_precision_type (type1))
+ {
+ type1 = eptype;
+ op1 = convert (eptype, op1);
+ }
+
/* Issue warnings about peculiar, but valid, uses of NULL. */
if ((null_node_p (orig_op0) || null_node_p (orig_op1))
/* It's reasonable to use pointer values as operands of &&
@@ -5240,7 +5315,7 @@ cp_build_binary_op (const op_location_t &location,
op0 = convert (TREE_TYPE (type1), op0);
op0 = save_expr (op0);
op0 = build_vector_from_val (type1, op0);
- type0 = TREE_TYPE (op0);
+ orig_type0 = type0 = TREE_TYPE (op0);
code0 = TREE_CODE (type0);
converted = 1;
break;
@@ -5250,7 +5325,7 @@ cp_build_binary_op (const op_location_t &location,
op1 = convert (TREE_TYPE (type0), op1);
op1 = save_expr (op1);
op1 = build_vector_from_val (type0, op1);
- type1 = TREE_TYPE (op1);
+ orig_type1 = type1 = TREE_TYPE (op1);
code1 = TREE_CODE (type1);
converted = 1;
break;
@@ -6067,12 +6142,20 @@ cp_build_binary_op (const op_location_t &location,
&& (shorten || common || short_compare))
{
result_type = cp_common_type (type0, type1);
- if (result_type == error_mark_node
- && code0 == REAL_TYPE
- && code1 == REAL_TYPE
- && (extended_float_type_p (type0) || extended_float_type_p (type1))
- && cp_compare_floating_point_conversion_ranks (type0, type1) == 3)
+ if (result_type == error_mark_node)
{
+ tree t1 = type0;
+ tree t2 = type1;
+ if (TREE_CODE (t1) == COMPLEX_TYPE)
+ t1 = TREE_TYPE (t1);
+ if (TREE_CODE (t2) == COMPLEX_TYPE)
+ t2 = TREE_TYPE (t2);
+ gcc_checking_assert (TREE_CODE (t1) == REAL_TYPE
+ && TREE_CODE (t2) == REAL_TYPE
+ && (extended_float_type_p (t1)
+ || extended_float_type_p (t2))
+ && cp_compare_floating_point_conversion_ranks
+ (t1, t2) == 3);
if (complain & tf_error)
{
rich_location richloc (line_table, location);
@@ -6091,6 +6174,34 @@ cp_build_binary_op (const op_location_t &location,
TREE_TYPE (orig_op1));
}
}
+ if (may_need_excess_precision
+ && (orig_type0 != type0 || orig_type1 != type1)
+ && build_type == NULL_TREE)
+ {
+ gcc_assert (common);
+ semantic_result_type = cp_common_type (orig_type0, orig_type1);
+ if (semantic_result_type == error_mark_node)
+ {
+ tree t1 = orig_type0;
+ tree t2 = orig_type1;
+ if (TREE_CODE (t1) == COMPLEX_TYPE)
+ t1 = TREE_TYPE (t1);
+ if (TREE_CODE (t2) == COMPLEX_TYPE)
+ t2 = TREE_TYPE (t2);
+ gcc_checking_assert (TREE_CODE (t1) == REAL_TYPE
+ && TREE_CODE (t2) == REAL_TYPE
+ && (extended_float_type_p (t1)
+ || extended_float_type_p (t2))
+ && cp_compare_floating_point_conversion_ranks
+ (t1, t2) == 3);
+ if (complain & tf_error)
+ {
+ rich_location richloc (line_table, location);
+ binary_op_error (&richloc, code, type0, type1);
+ }
+ return error_mark_node;
+ }
+ }
if (code == SPACESHIP_EXPR)
{
@@ -6181,6 +6292,8 @@ cp_build_binary_op (const op_location_t &location,
build_type ? build_type : result_type,
NULL_TREE, op1);
TREE_OPERAND (tmp, 0) = op0;
+ if (semantic_result_type)
+ tmp = build1 (EXCESS_PRECISION_EXPR, semantic_result_type, tmp);
return tmp;
}
@@ -6268,6 +6381,9 @@ cp_build_binary_op (const op_location_t &location,
}
}
result = build2 (COMPLEX_EXPR, result_type, real, imag);
+ if (semantic_result_type)
+ result = build1 (EXCESS_PRECISION_EXPR, semantic_result_type,
+ result);
return result;
}
@@ -6435,6 +6551,9 @@ cp_build_binary_op (const op_location_t &location,
if (resultcode == SPACESHIP_EXPR && !processing_template_decl)
result = get_target_expr (result, complain);
+ if (semantic_result_type)
+ result = build1 (EXCESS_PRECISION_EXPR, semantic_result_type, result);
+
if (!c_inhibit_evaluation_warnings)
{
if (!processing_template_decl)
@@ -7161,6 +7280,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, bool noconvert,
tree arg = xarg;
location_t location = cp_expr_loc_or_input_loc (arg);
tree argtype = 0;
+ tree eptype = NULL_TREE;
const char *errstring = NULL;
tree val;
const char *invalid_op_diag;
@@ -7181,6 +7301,12 @@ cp_build_unary_op (enum tree_code code, tree xarg, bool noconvert,
return error_mark_node;
}
+ if (TREE_CODE (arg) == EXCESS_PRECISION_EXPR)
+ {
+ eptype = TREE_TYPE (arg);
+ arg = TREE_OPERAND (arg, 0);
+ }
+
switch (code)
{
case UNARY_PLUS_EXPR:
@@ -7276,8 +7402,11 @@ cp_build_unary_op (enum tree_code code, tree xarg, bool noconvert,
case REALPART_EXPR:
case IMAGPART_EXPR:
- arg = build_real_imag_expr (input_location, code, arg);
- return arg;
+ val = build_real_imag_expr (input_location, code, arg);
+ if (eptype && TREE_CODE (eptype) == COMPLEX_EXPR)
+ val = build1_loc (input_location, EXCESS_PRECISION_EXPR,
+ TREE_TYPE (eptype), val);
+ return val;
case PREINCREMENT_EXPR:
case POSTINCREMENT_EXPR:
@@ -7288,7 +7417,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, bool noconvert,
val = unary_complex_lvalue (code, arg);
if (val != 0)
- return val;
+ goto return_build_unary_op;
arg = mark_lvalue_use (arg);
@@ -7304,8 +7433,8 @@ cp_build_unary_op (enum tree_code code, tree xarg, bool noconvert,
real = cp_build_unary_op (code, real, true, complain);
if (real == error_mark_node || imag == error_mark_node)
return error_mark_node;
- return build2 (COMPLEX_EXPR, TREE_TYPE (arg),
- real, imag);
+ val = build2 (COMPLEX_EXPR, TREE_TYPE (arg), real, imag);
+ goto return_build_unary_op;
}
/* Report invalid types. */
@@ -7468,7 +7597,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, bool noconvert,
val = build2 (code, TREE_TYPE (arg), arg, inc);
TREE_SIDE_EFFECTS (val) = 1;
- return val;
+ goto return_build_unary_op;
}
case ADDR_EXPR:
@@ -7484,7 +7613,11 @@ cp_build_unary_op (enum tree_code code, tree xarg, bool noconvert,
{
if (argtype == 0)
argtype = TREE_TYPE (arg);
- return build1 (code, argtype, arg);
+ val = build1 (code, argtype, arg);
+ return_build_unary_op:
+ if (eptype)
+ val = build1 (EXCESS_PRECISION_EXPR, eptype, val);
+ return val;
}
if (complain & tf_error)
@@ -7875,6 +8008,15 @@ cp_build_compound_expr (tree lhs, tree rhs, tsubst_flags_t complain)
if (lhs == error_mark_node || rhs == error_mark_node)
return error_mark_node;
+ if (TREE_CODE (lhs) == EXCESS_PRECISION_EXPR)
+ lhs = TREE_OPERAND (lhs, 0);
+ tree eptype = NULL_TREE;
+ if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR)
+ {
+ eptype = TREE_TYPE (rhs);
+ rhs = TREE_OPERAND (rhs, 0);
+ }
+
if (TREE_CODE (rhs) == TARGET_EXPR)
{
/* If the rhs is a TARGET_EXPR, then build the compound
@@ -7885,6 +8027,8 @@ cp_build_compound_expr (tree lhs, tree rhs, tsubst_flags_t complain)
init = build2 (COMPOUND_EXPR, TREE_TYPE (init), lhs, init);
TREE_OPERAND (rhs, 1) = init;
+ if (eptype)
+ rhs = build1 (EXCESS_PRECISION_EXPR, eptype, rhs);
return rhs;
}
@@ -7896,7 +8040,10 @@ cp_build_compound_expr (tree lhs, tree rhs, tsubst_flags_t complain)
return error_mark_node;
}
- return build2 (COMPOUND_EXPR, TREE_TYPE (rhs), lhs, rhs);
+ tree ret = build2 (COMPOUND_EXPR, TREE_TYPE (rhs), lhs, rhs);
+ if (eptype)
+ ret = build1 (EXCESS_PRECISION_EXPR, eptype, ret);
+ return ret;
}
/* Issue a diagnostic message if casting from SRC_TYPE to DEST_TYPE
@@ -8180,7 +8327,11 @@ build_static_cast_1 (location_t loc, tree type, tree expr, bool c_cast_p,
Any expression can be explicitly converted to type cv void. */
if (VOID_TYPE_P (type))
- return convert_to_void (expr, ICV_CAST, complain);
+ {
+ if (TREE_CODE (expr) == EXCESS_PRECISION_EXPR)
+ expr = TREE_OPERAND (expr, 0);
+ return convert_to_void (expr, ICV_CAST, complain);
+ }
/* [class.abstract]
An abstract class shall not be used ... as the type of an explicit
@@ -8259,6 +8410,8 @@ build_static_cast_1 (location_t loc, tree type, tree expr, bool c_cast_p,
{
if (processing_template_decl)
return expr;
+ if (TREE_CODE (expr) == EXCESS_PRECISION_EXPR)
+ expr = TREE_OPERAND (expr, 0);
return ocp_convert (type, expr, CONV_C_CAST, LOOKUP_NORMAL, complain);
}
diff --git a/gcc/cp/vtable-class-hierarchy.cc b/gcc/cp/vtable-class-hierarchy.cc
index 79cb5f8..cc1df1e 100644
--- a/gcc/cp/vtable-class-hierarchy.cc
+++ b/gcc/cp/vtable-class-hierarchy.cc
@@ -1192,8 +1192,18 @@ vtv_generate_init_routine (void)
cgraph_node::add_new_function (vtv_fndecl, false);
if (flag_vtable_verify == VTV_PREINIT_PRIORITY && !TARGET_PECOFF)
- assemble_vtv_preinit_initializer (vtv_fndecl);
-
+ {
+ tree vtv_var
+ = build_decl (BUILTINS_LOCATION, VAR_DECL,
+ get_identifier ("__vtv_preinit"),
+ build_pointer_type (TREE_TYPE (vtv_fndecl)));
+ TREE_STATIC (vtv_var) = 1;
+ DECL_ARTIFICIAL (vtv_var) = 1;
+ DECL_INITIAL (vtv_var) = build_fold_addr_expr (vtv_fndecl);
+ set_decl_section_name (vtv_var, ".preinit_array");
+
+ varpool_node::add (vtv_var);
+ }
}
pop_lang_context ();
}
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index c6de620..1c0fe7d 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -13747,18 +13747,18 @@ default, @option{-fexcess-precision=fast} is in effect; this means that
operations may be carried out in a wider precision than the types specified
in the source if that would result in faster code, and it is unpredictable
when rounding to the types specified in the source code takes place.
-When compiling C, if @option{-fexcess-precision=standard} is specified then
-excess precision follows the rules specified in ISO C99; in particular,
+When compiling C or C++, if @option{-fexcess-precision=standard} is specified
+then excess precision follows the rules specified in ISO C99 or C++; in particular,
both casts and assignments cause values to be rounded to their
semantic types (whereas @option{-ffloat-store} only affects
-assignments). This option is enabled by default for C if a strict
-conformance option such as @option{-std=c99} is used.
+assignments). This option is enabled by default for C or C++ if a strict
+conformance option such as @option{-std=c99} or @option{-std=c++17} is used.
@option{-ffast-math} enables @option{-fexcess-precision=fast} by default
regardless of whether a strict conformance option is used.
@opindex mfpmath
@option{-fexcess-precision=standard} is not implemented for languages
-other than C. On the x86, it has no effect if @option{-mfpmath=sse}
+other than C or C++. On the x86, it has no effect if @option{-mfpmath=sse}
or @option{-mfpmath=sse+387} is specified; in the former case, IEEE
semantics apply without excess precision, and in the latter, rounding
is unpredictable.
diff --git a/gcc/expmed.cc b/gcc/expmed.cc
index 6c02c3b..323565f 100644
--- a/gcc/expmed.cc
+++ b/gcc/expmed.cc
@@ -2705,7 +2705,7 @@ expand_shift (enum tree_code code, machine_mode mode, rtx shifted,
/* Likewise, but return 0 if that cannot be done. */
-static rtx
+rtx
maybe_expand_shift (enum tree_code code, machine_mode mode, rtx shifted,
int amount, rtx target, int unsignedp)
{
@@ -5712,7 +5712,7 @@ emit_store_flag_1 (rtx target, enum rtx_code code, rtx op0, rtx op1,
/* Next try expanding this via the backend's cstore<mode>4. */
mclass = GET_MODE_CLASS (mode);
- FOR_EACH_MODE_FROM (compare_mode, mode)
+ FOR_EACH_WIDER_MODE_FROM (compare_mode, mode)
{
machine_mode optab_mode = mclass == MODE_CC ? CCmode : compare_mode;
icode = optab_handler (cstore_optab, optab_mode);
diff --git a/gcc/expmed.h b/gcc/expmed.h
index 0b2538c..f50f323 100644
--- a/gcc/expmed.h
+++ b/gcc/expmed.h
@@ -707,6 +707,8 @@ extern rtx expand_variable_shift (enum tree_code, machine_mode,
rtx, tree, rtx, int);
extern rtx expand_shift (enum tree_code, machine_mode, rtx, poly_int64, rtx,
int);
+extern rtx maybe_expand_shift (enum tree_code, machine_mode, rtx, int, rtx,
+ int);
#ifdef GCC_OPTABS_H
extern rtx expand_divmod (int, enum tree_code, machine_mode, rtx, rtx,
rtx, int, enum optab_methods = OPTAB_LIB_WIDEN);
diff --git a/gcc/expr.cc b/gcc/expr.cc
index ba627f1..4c892d6 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -344,7 +344,11 @@ convert_mode_scalar (rtx to, rtx from, int unsignedp)
gcc_assert ((GET_MODE_PRECISION (from_mode)
!= GET_MODE_PRECISION (to_mode))
|| (DECIMAL_FLOAT_MODE_P (from_mode)
- != DECIMAL_FLOAT_MODE_P (to_mode)));
+ != DECIMAL_FLOAT_MODE_P (to_mode))
+ || (REAL_MODE_FORMAT (from_mode) == &arm_bfloat_half_format
+ && REAL_MODE_FORMAT (to_mode) == &ieee_half_format)
+ || (REAL_MODE_FORMAT (to_mode) == &arm_bfloat_half_format
+ && REAL_MODE_FORMAT (from_mode) == &ieee_half_format));
if (GET_MODE_PRECISION (from_mode) == GET_MODE_PRECISION (to_mode))
/* Conversion between decimal float and binary float, same size. */
@@ -364,6 +368,150 @@ convert_mode_scalar (rtx to, rtx from, int unsignedp)
return;
}
+#ifdef HAVE_SFmode
+ if (REAL_MODE_FORMAT (from_mode) == &arm_bfloat_half_format
+ && REAL_MODE_FORMAT (SFmode) == &ieee_single_format)
+ {
+ if (GET_MODE_PRECISION (to_mode) > GET_MODE_PRECISION (SFmode))
+ {
+ /* To cut down on libgcc size, implement
+ BFmode -> {DF,XF,TF}mode conversions by
+ BFmode -> SFmode -> {DF,XF,TF}mode conversions. */
+ rtx temp = gen_reg_rtx (SFmode);
+ convert_mode_scalar (temp, from, unsignedp);
+ convert_mode_scalar (to, temp, unsignedp);
+ return;
+ }
+ if (REAL_MODE_FORMAT (to_mode) == &ieee_half_format)
+ {
+ /* Similarly, implement BFmode -> HFmode as
+ BFmode -> SFmode -> HFmode conversion where SFmode
+ has superset of BFmode values. We don't need
+ to handle sNaNs by raising exception and turning
+ into into qNaN though, as that can be done in the
+ SFmode -> HFmode conversion too. */
+ rtx temp = gen_reg_rtx (SFmode);
+ int save_flag_finite_math_only = flag_finite_math_only;
+ flag_finite_math_only = true;
+ convert_mode_scalar (temp, from, unsignedp);
+ flag_finite_math_only = save_flag_finite_math_only;
+ convert_mode_scalar (to, temp, unsignedp);
+ return;
+ }
+ if (to_mode == SFmode
+ && !HONOR_NANS (from_mode)
+ && !HONOR_NANS (to_mode)
+ && optimize_insn_for_speed_p ())
+ {
+ /* If we don't expect sNaNs, for BFmode -> SFmode we can just
+ shift the bits up. */
+ machine_mode fromi_mode, toi_mode;
+ if (int_mode_for_size (GET_MODE_BITSIZE (from_mode),
+ 0).exists (&fromi_mode)
+ && int_mode_for_size (GET_MODE_BITSIZE (to_mode),
+ 0).exists (&toi_mode))
+ {
+ start_sequence ();
+ rtx fromi = lowpart_subreg (fromi_mode, from, from_mode);
+ rtx tof = NULL_RTX;
+ if (fromi)
+ {
+ rtx toi = gen_reg_rtx (toi_mode);
+ convert_mode_scalar (toi, fromi, 1);
+ toi
+ = maybe_expand_shift (LSHIFT_EXPR, toi_mode, toi,
+ GET_MODE_PRECISION (to_mode)
+ - GET_MODE_PRECISION (from_mode),
+ NULL_RTX, 1);
+ if (toi)
+ {
+ tof = lowpart_subreg (to_mode, toi, toi_mode);
+ if (tof)
+ emit_move_insn (to, tof);
+ }
+ }
+ insns = get_insns ();
+ end_sequence ();
+ if (tof)
+ {
+ emit_insn (insns);
+ return;
+ }
+ }
+ }
+ }
+ if (REAL_MODE_FORMAT (from_mode) == &ieee_single_format
+ && REAL_MODE_FORMAT (to_mode) == &arm_bfloat_half_format
+ && !HONOR_NANS (from_mode)
+ && !HONOR_NANS (to_mode)
+ && !flag_rounding_math
+ && optimize_insn_for_speed_p ())
+ {
+ /* If we don't expect qNaNs nor sNaNs and can assume rounding
+ to nearest, we can expand the conversion inline as
+ (fromi + 0x7fff + ((fromi >> 16) & 1)) >> 16. */
+ machine_mode fromi_mode, toi_mode;
+ if (int_mode_for_size (GET_MODE_BITSIZE (from_mode),
+ 0).exists (&fromi_mode)
+ && int_mode_for_size (GET_MODE_BITSIZE (to_mode),
+ 0).exists (&toi_mode))
+ {
+ start_sequence ();
+ rtx fromi = lowpart_subreg (fromi_mode, from, from_mode);
+ rtx tof = NULL_RTX;
+ do
+ {
+ if (!fromi)
+ break;
+ int shift = (GET_MODE_PRECISION (from_mode)
+ - GET_MODE_PRECISION (to_mode));
+ rtx temp1
+ = maybe_expand_shift (RSHIFT_EXPR, fromi_mode, fromi,
+ shift, NULL_RTX, 1);
+ if (!temp1)
+ break;
+ rtx temp2
+ = expand_binop (fromi_mode, and_optab, temp1, const1_rtx,
+ NULL_RTX, 1, OPTAB_DIRECT);
+ if (!temp2)
+ break;
+ rtx temp3
+ = expand_binop (fromi_mode, add_optab, fromi,
+ gen_int_mode ((HOST_WIDE_INT_1U
+ << (shift - 1)) - 1,
+ fromi_mode), NULL_RTX,
+ 1, OPTAB_DIRECT);
+ if (!temp3)
+ break;
+ rtx temp4
+ = expand_binop (fromi_mode, add_optab, temp3, temp2,
+ NULL_RTX, 1, OPTAB_DIRECT);
+ if (!temp4)
+ break;
+ rtx temp5 = maybe_expand_shift (RSHIFT_EXPR, fromi_mode,
+ temp4, shift, NULL_RTX, 1);
+ if (!temp5)
+ break;
+ rtx temp6 = lowpart_subreg (toi_mode, temp5, fromi_mode);
+ if (!temp6)
+ break;
+ tof = lowpart_subreg (to_mode, force_reg (toi_mode, temp6),
+ toi_mode);
+ if (tof)
+ emit_move_insn (to, tof);
+ }
+ while (0);
+ insns = get_insns ();
+ end_sequence ();
+ if (tof)
+ {
+ emit_insn (insns);
+ return;
+ }
+ }
+ }
+#endif
+
/* Otherwise use a libcall. */
libcall = convert_optab_libfunc (tab, to_mode, from_mode);
@@ -2813,50 +2961,69 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED,
else
adj_bytelen = bytelen;
+ /* Deal with destination CONCATs by either storing into one of the parts
+ or doing a copy after storing into a register or stack temporary. */
if (GET_CODE (dst) == CONCAT)
{
if (known_le (bytepos + adj_bytelen,
GET_MODE_SIZE (GET_MODE (XEXP (dst, 0)))))
dest = XEXP (dst, 0);
+
else if (known_ge (bytepos, GET_MODE_SIZE (GET_MODE (XEXP (dst, 0)))))
{
bytepos -= GET_MODE_SIZE (GET_MODE (XEXP (dst, 0)));
dest = XEXP (dst, 1);
}
+
else
{
machine_mode dest_mode = GET_MODE (dest);
machine_mode tmp_mode = GET_MODE (tmps[i]);
- scalar_int_mode imode;
+ scalar_int_mode dest_imode;
gcc_assert (known_eq (bytepos, 0) && XVECLEN (src, 0));
- if (finish == 1
+ /* If the source is a single scalar integer register, and the
+ destination has a complex mode for which a same-sized integer
+ mode exists, then we can take the left-justified part of the
+ source in the complex mode. */
+ if (finish == start + 1
&& REG_P (tmps[i])
- && COMPLEX_MODE_P (dest_mode)
&& SCALAR_INT_MODE_P (tmp_mode)
- && int_mode_for_mode (dest_mode).exists (&imode))
+ && COMPLEX_MODE_P (dest_mode)
+ && int_mode_for_mode (dest_mode).exists (&dest_imode))
{
- if (tmp_mode != imode)
+ const scalar_int_mode tmp_imode
+ = as_a <scalar_int_mode> (tmp_mode);
+
+ if (GET_MODE_BITSIZE (dest_imode)
+ < GET_MODE_BITSIZE (tmp_imode))
{
- rtx tmp = gen_reg_rtx (imode);
- emit_move_insn (tmp, gen_lowpart (imode, tmps[i]));
- dst = gen_lowpart (dest_mode, tmp);
+ dest = gen_reg_rtx (dest_imode);
+ if (BYTES_BIG_ENDIAN)
+ tmps[i] = expand_shift (RSHIFT_EXPR, tmp_mode, tmps[i],
+ GET_MODE_BITSIZE (tmp_imode)
+ - GET_MODE_BITSIZE (dest_imode),
+ NULL_RTX, 1);
+ emit_move_insn (dest, gen_lowpart (dest_imode, tmps[i]));
+ dst = gen_lowpart (dest_mode, dest);
}
else
dst = gen_lowpart (dest_mode, tmps[i]);
}
+
+ /* Otherwise spill the source onto the stack using the more
+ aligned of the two modes. */
else if (GET_MODE_ALIGNMENT (dest_mode)
- >= GET_MODE_ALIGNMENT (tmp_mode))
+ >= GET_MODE_ALIGNMENT (tmp_mode))
{
dest = assign_stack_temp (dest_mode,
GET_MODE_SIZE (dest_mode));
- emit_move_insn (adjust_address (dest,
- tmp_mode,
- bytepos),
+ emit_move_insn (adjust_address (dest, tmp_mode, bytepos),
tmps[i]);
dst = dest;
}
+
else
{
dest = assign_stack_temp (tmp_mode,
@@ -2864,6 +3031,7 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED,
emit_move_insn (dest, tmps[i]);
dst = adjust_address (dest, dest_mode, bytepos);
}
+
break;
}
}
diff --git a/gcc/fold-const-call.cc b/gcc/fold-const-call.cc
index 7295387..7e0d671 100644
--- a/gcc/fold-const-call.cc
+++ b/gcc/fold-const-call.cc
@@ -1301,6 +1301,7 @@ fold_const_call (combined_fn fn, tree type, tree arg)
CASE_CFN_NANS:
CASE_FLT_FN_FLOATN_NX (CFN_BUILT_IN_NANS):
+ case CFN_BUILT_IN_NANSF16B:
case CFN_BUILT_IN_NANSD32:
case CFN_BUILT_IN_NANSD64:
case CFN_BUILT_IN_NANSD128:
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index fa03b33..8b80242 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,9 @@
+2022-10-14 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/100971
+ * resolve.cc (resolve_transfer): Extend check for permissibility
+ of polymorphic elements in a data transfer to arrays.
+
2022-10-12 Harald Anlauf <anlauf@gmx.de>
PR fortran/107217
diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc
index d133bc2..9202e2f 100644
--- a/gcc/fortran/resolve.cc
+++ b/gcc/fortran/resolve.cc
@@ -10017,6 +10017,7 @@ resolve_transfer (gfc_code *code)
if (exp == NULL || (exp->expr_type != EXPR_VARIABLE
&& exp->expr_type != EXPR_FUNCTION
+ && exp->expr_type != EXPR_ARRAY
&& exp->expr_type != EXPR_STRUCTURE))
return;
@@ -10030,6 +10031,7 @@ resolve_transfer (gfc_code *code)
const gfc_typespec *ts = exp->expr_type == EXPR_STRUCTURE
|| exp->expr_type == EXPR_FUNCTION
+ || exp->expr_type == EXPR_ARRAY
? &exp->ts : &exp->symtree->n.sym->ts;
/* Go to actual component transferred. */
@@ -10128,6 +10130,9 @@ resolve_transfer (gfc_code *code)
if (exp->expr_type == EXPR_STRUCTURE)
return;
+ if (exp->expr_type == EXPR_ARRAY)
+ return;
+
sym = exp->symtree->n.sym;
if (sym->as != NULL && sym->as->type == AS_ASSUMED_SIZE && exp->ref
diff --git a/gcc/genmodes.cc b/gcc/genmodes.cc
index 59850bb..9f0cc9c 100644
--- a/gcc/genmodes.cc
+++ b/gcc/genmodes.cc
@@ -1527,7 +1527,7 @@ emit_mode_wider (void)
int c;
struct mode_data *m;
- print_decl ("unsigned char", "mode_wider", "NUM_MACHINE_MODES");
+ print_decl ("unsigned char", "mode_next", "NUM_MACHINE_MODES");
for_all_modes (c, m)
tagged_printf ("E_%smode",
@@ -1535,6 +1535,37 @@ emit_mode_wider (void)
m->name);
print_closer ();
+ print_decl ("unsigned char", "mode_wider", "NUM_MACHINE_MODES");
+
+ for_all_modes (c, m)
+ {
+ struct mode_data *m2 = 0;
+
+ if (m->cl == MODE_INT
+ || m->cl == MODE_PARTIAL_INT
+ || m->cl == MODE_FLOAT
+ || m->cl == MODE_DECIMAL_FLOAT
+ || m->cl == MODE_COMPLEX_FLOAT
+ || m->cl == MODE_FRACT
+ || m->cl == MODE_UFRACT
+ || m->cl == MODE_ACCUM
+ || m->cl == MODE_UACCUM)
+ for (m2 = m->wider; m2 && m2 != void_mode; m2 = m2->wider)
+ {
+ if (m2->bytesize == m->bytesize
+ && m2->precision == m->precision)
+ continue;
+ break;
+ }
+
+ if (m2 == void_mode)
+ m2 = 0;
+ tagged_printf ("E_%smode",
+ m2 ? m2->name : void_mode->name,
+ m->name);
+ }
+
+ print_closer ();
print_decl ("unsigned char", "mode_2xwider", "NUM_MACHINE_MODES");
for_all_modes (c, m)
diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc
index 4782d47..0b9aa36 100644
--- a/gcc/gimple-range-cache.cc
+++ b/gcc/gimple-range-cache.cc
@@ -1189,8 +1189,9 @@ ranger_cache::fill_block_cache (tree name, basic_block bb, basic_block def_bb)
{
edge_iterator ei;
edge e;
- Value_Range block_result (TREE_TYPE (name));
- Value_Range undefined (TREE_TYPE (name));
+ tree type = TREE_TYPE (name);
+ Value_Range block_result (type);
+ Value_Range undefined (type);
// At this point we shouldn't be looking at the def, entry or exit block.
gcc_checking_assert (bb != def_bb && bb != ENTRY_BLOCK_PTR_FOR_FN (cfun) &&
@@ -1220,17 +1221,17 @@ ranger_cache::fill_block_cache (tree name, basic_block bb, basic_block def_bb)
// See if any equivalences can refine it.
if (m_oracle)
{
- unsigned i;
- bitmap_iterator bi;
- // Query equivalences in read-only mode.
- const_bitmap equiv = m_oracle->equiv_set (name, bb);
- EXECUTE_IF_SET_IN_BITMAP (equiv, 0, i, bi)
+ tree equiv_name;
+ relation_kind rel;
+ int prec = TYPE_PRECISION (type);
+ FOR_EACH_PARTIAL_AND_FULL_EQUIV (m_oracle, bb, name, equiv_name, rel)
{
- if (i == SSA_NAME_VERSION (name))
- continue;
- tree equiv_name = ssa_name (i);
basic_block equiv_bb = gimple_bb (SSA_NAME_DEF_STMT (equiv_name));
+ // Ignore partial equivs that are smaller than this object.
+ if (rel != VREL_EQ && prec > pe_to_bits (rel))
+ continue;
+
// Check if the equiv has any ranges calculated.
if (!m_gori.has_edge_range_p (equiv_name))
continue;
@@ -1240,16 +1241,32 @@ ranger_cache::fill_block_cache (tree name, basic_block bb, basic_block def_bb)
(equiv_bb && !dominated_by_p (CDI_DOMINATORS, bb, equiv_bb)))
continue;
+ if (DEBUG_RANGE_CACHE)
+ {
+ if (rel == VREL_EQ)
+ fprintf (dump_file, "Checking Equivalence (");
+ else
+ fprintf (dump_file, "Checking Partial equiv (");
+ print_relation (dump_file, rel);
+ fprintf (dump_file, ") ");
+ print_generic_expr (dump_file, equiv_name, TDF_SLIM);
+ fprintf (dump_file, "\n");
+ }
Value_Range equiv_range (TREE_TYPE (equiv_name));
if (range_from_dom (equiv_range, equiv_name, bb, RFD_READ_ONLY))
{
+ if (rel != VREL_EQ)
+ range_cast (equiv_range, type);
if (block_result.intersect (equiv_range))
{
if (DEBUG_RANGE_CACHE)
{
- fprintf (dump_file, "Equivalence update! : ");
+ if (rel == VREL_EQ)
+ fprintf (dump_file, "Equivalence update! : ");
+ else
+ fprintf (dump_file, "Partial equiv update! : ");
print_generic_expr (dump_file, equiv_name, TDF_SLIM);
- fprintf (dump_file, "had range : ");
+ fprintf (dump_file, " has range : ");
equiv_range.dump (dump_file);
fprintf (dump_file, " refining range to :");
block_result.dump (dump_file);
@@ -1464,7 +1481,9 @@ ranger_cache::range_from_dom (vrange &r, tree name, basic_block start_bb,
if (DEBUG_RANGE_CACHE)
{
- fprintf (dump_file, "CACHE: BB %d DOM query, found ", start_bb->index);
+ fprintf (dump_file, "CACHE: BB %d DOM query for ", start_bb->index);
+ print_generic_expr (dump_file, name, TDF_SLIM);
+ fprintf (dump_file, ", found ");
r.dump (dump_file);
if (bb)
fprintf (dump_file, " at BB%d\n", bb->index);
diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc
index bc4389e..2662319 100644
--- a/gcc/gimple-range-op.cc
+++ b/gcc/gimple-range-op.cc
@@ -342,6 +342,38 @@ public:
}
} op_cfn_signbit;
+// Implement range operator for CFN_BUILT_IN_COPYSIGN
+class cfn_copysign : public range_operator_float
+{
+public:
+ using range_operator_float::fold_range;
+ virtual bool fold_range (frange &r, tree type, const frange &lh,
+ const frange &rh, relation_kind) const override
+ {
+ frange neg;
+ range_op_handler abs_op (ABS_EXPR, type);
+ range_op_handler neg_op (NEGATE_EXPR, type);
+ if (!abs_op || !abs_op.fold_range (r, type, lh, frange (type)))
+ return false;
+ if (!neg_op || !neg_op.fold_range (neg, type, r, frange (type)))
+ return false;
+
+ bool signbit;
+ if (rh.signbit_p (signbit))
+ {
+ // If the sign is negative, flip the result from ABS,
+ // otherwise leave things positive.
+ if (signbit)
+ r = neg;
+ }
+ else
+ // If the sign is unknown, keep the positive and negative
+ // alternatives.
+ r.union_ (neg);
+ return true;
+ }
+} op_cfn_copysign;
+
// Implement range operator for CFN_BUILT_IN_TOUPPER and CFN_BUILT_IN_TOLOWER.
class cfn_toupper_tolower : public range_operator
{
@@ -756,12 +788,19 @@ gimple_range_op_handler::maybe_builtin_call ()
m_valid = false;
break;
- case CFN_BUILT_IN_SIGNBIT:
+ CASE_FLT_FN (CFN_BUILT_IN_SIGNBIT):
m_op1 = gimple_call_arg (call, 0);
m_float = &op_cfn_signbit;
m_valid = true;
break;
+ CASE_CFN_COPYSIGN_ALL:
+ m_op1 = gimple_call_arg (call, 0);
+ m_op2 = gimple_call_arg (call, 1);
+ m_float = &op_cfn_copysign;
+ m_valid = true;
+ break;
+
case CFN_BUILT_IN_TOUPPER:
case CFN_BUILT_IN_TOLOWER:
// Only proceed If the argument is compatible with the LHS.
diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc
index 04aa849..59a7053 100644
--- a/gcc/gimple-ssa-warn-access.cc
+++ b/gcc/gimple-ssa-warn-access.cc
@@ -4291,14 +4291,18 @@ pass_waccess::check_pointer_uses (gimple *stmt, tree ptr,
void
pass_waccess::check_call (gcall *stmt)
{
- if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
- check_builtin (stmt);
+ /* Skip special calls generated by the compiler. */
+ if (gimple_call_from_thunk_p (stmt))
+ return;
/* .ASAN_MARK doesn't access any vars, only modifies shadow memory. */
if (gimple_call_internal_p (stmt)
&& gimple_call_internal_fn (stmt) == IFN_ASAN_MARK)
return;
+ if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
+ check_builtin (stmt);
+
if (!m_early_checks_p)
if (tree callee = gimple_call_fndecl (stmt))
{
diff --git a/gcc/machmode.h b/gcc/machmode.h
index 45df720df..99b0e46 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -28,6 +28,7 @@ extern const unsigned char mode_inner[NUM_MACHINE_MODES];
extern CONST_MODE_NUNITS poly_uint16_pod mode_nunits[NUM_MACHINE_MODES];
extern CONST_MODE_UNIT_SIZE unsigned char mode_unit_size[NUM_MACHINE_MODES];
extern const unsigned short mode_unit_precision[NUM_MACHINE_MODES];
+extern const unsigned char mode_next[NUM_MACHINE_MODES];
extern const unsigned char mode_wider[NUM_MACHINE_MODES];
extern const unsigned char mode_2xwider[NUM_MACHINE_MODES];
@@ -760,7 +761,23 @@ GET_MODE_NUNITS (const T &mode)
}
#endif
-/* Get the next wider natural mode (eg, QI -> HI -> SI -> DI -> TI). */
+/* Get the next natural mode (not narrower, eg, QI -> HI -> SI -> DI -> TI
+ or HF -> BF -> SF -> DF -> XF -> TF). */
+
+template<typename T>
+ALWAYS_INLINE opt_mode<T>
+GET_MODE_NEXT_MODE (const T &m)
+{
+ return typename opt_mode<T>::from_int (mode_next[m]);
+}
+
+/* Get the next wider mode (eg, QI -> HI -> SI -> DI -> TI
+ or { HF, BF } -> SF -> DF -> XF -> TF).
+ This is similar to GET_MODE_NEXT_MODE, but while GET_MODE_NEXT_MODE
+ can include mode that have the same precision (e.g.
+ GET_MODE_NEXT_MODE (HFmode) can be BFmode even when both have the same
+ precision), this one will skip those. And always VOIDmode for
+ modes whose class is !CLASS_HAS_WIDER_MODES_P. */
template<typename T>
ALWAYS_INLINE opt_mode<T>
@@ -1098,7 +1115,33 @@ namespace mode_iterator
return *iter != E_VOIDmode;
}
- /* Set mode iterator *ITER to the next widest mode in the same class,
+ /* Set mode iterator *ITER to the next mode in the same class,
+ if any. */
+
+ template<typename T>
+ inline void
+ get_next (opt_mode<T> *iter)
+ {
+ *iter = GET_MODE_NEXT_MODE (iter->require ());
+ }
+
+ inline void
+ get_next (machine_mode *iter)
+ {
+ *iter = GET_MODE_NEXT_MODE (*iter).else_void ();
+ }
+
+ /* Set mode iterator *ITER to the next mode in the same class.
+ Such a mode is known to exist. */
+
+ template<typename T>
+ inline void
+ get_known_next (T *iter)
+ {
+ *iter = GET_MODE_NEXT_MODE (*iter).require ();
+ }
+
+ /* Set mode iterator *ITER to the next wider mode in the same class,
if any. */
template<typename T>
@@ -1114,7 +1157,7 @@ namespace mode_iterator
*iter = GET_MODE_WIDER_MODE (*iter).else_void ();
}
- /* Set mode iterator *ITER to the next widest mode in the same class.
+ /* Set mode iterator *ITER to the next wider mode in the same class.
Such a mode is known to exist. */
template<typename T>
@@ -1146,20 +1189,27 @@ namespace mode_iterator
#define FOR_EACH_MODE_IN_CLASS(ITERATOR, CLASS) \
for (mode_iterator::start (&(ITERATOR), CLASS); \
mode_iterator::iterate_p (&(ITERATOR)); \
- mode_iterator::get_wider (&(ITERATOR)))
+ mode_iterator::get_next (&(ITERATOR)))
/* Make ITERATOR iterate over all the modes in the range [START, END),
in order of increasing width. */
#define FOR_EACH_MODE(ITERATOR, START, END) \
for ((ITERATOR) = (START); \
(ITERATOR) != (END); \
- mode_iterator::get_known_wider (&(ITERATOR)))
+ mode_iterator::get_known_next (&(ITERATOR)))
-/* Make ITERATOR iterate over START and all wider modes in the same
+/* Make ITERATOR iterate over START and all non-narrower modes in the same
class, in order of increasing width. */
#define FOR_EACH_MODE_FROM(ITERATOR, START) \
for ((ITERATOR) = (START); \
mode_iterator::iterate_p (&(ITERATOR)); \
+ mode_iterator::get_next (&(ITERATOR)))
+
+/* Make ITERATOR iterate over START and all wider modes in the same
+ class, in order of strictly increasing width. */
+#define FOR_EACH_WIDER_MODE_FROM(ITERATOR, START) \
+ for ((ITERATOR) = (START); \
+ mode_iterator::iterate_p (&(ITERATOR)); \
mode_iterator::get_wider (&(ITERATOR)))
/* Make ITERATOR iterate over modes in the range [NARROWEST, END)
@@ -1169,6 +1219,14 @@ namespace mode_iterator
FOR_EACH_MODE (ITERATOR, get_narrowest_mode (END), END)
/* Make ITERATOR iterate over modes in the same class as MODE, in order
+ of non-decreasing width. Start at next such mode after START,
+ or don't iterate at all if there is no such mode. */
+#define FOR_EACH_NEXT_MODE(ITERATOR, START) \
+ for ((ITERATOR) = (START), mode_iterator::get_next (&(ITERATOR)); \
+ mode_iterator::iterate_p (&(ITERATOR)); \
+ mode_iterator::get_next (&(ITERATOR)))
+
+/* Make ITERATOR iterate over modes in the same class as MODE, in order
of increasing width. Start at the first mode wider than START,
or don't iterate at all if there is no wider mode. */
#define FOR_EACH_WIDER_MODE(ITERATOR, START) \
diff --git a/gcc/optabs.cc b/gcc/optabs.cc
index 165f8d1..c2a6f97 100644
--- a/gcc/optabs.cc
+++ b/gcc/optabs.cc
@@ -4384,7 +4384,6 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size,
machine_mode mode = *pmode;
rtx libfunc, test;
machine_mode cmp_mode;
- enum mode_class mclass;
/* The other methods are not needed. */
gcc_assert (methods == OPTAB_DIRECT || methods == OPTAB_WIDEN
@@ -4490,9 +4489,8 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size,
return;
}
- mclass = GET_MODE_CLASS (mode);
test = gen_rtx_fmt_ee (comparison, VOIDmode, x, y);
- FOR_EACH_MODE_FROM (cmp_mode, mode)
+ FOR_EACH_WIDER_MODE_FROM (cmp_mode, mode)
{
enum insn_code icode;
icode = optab_handler (cbranch_optab, cmp_mode);
@@ -4515,7 +4513,7 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size,
delete_insns_since (last);
}
- if (methods == OPTAB_DIRECT || !CLASS_HAS_WIDER_MODES_P (mclass))
+ if (methods == OPTAB_DIRECT)
break;
}
@@ -4711,7 +4709,7 @@ prepare_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison,
bool reversed_p = false;
scalar_int_mode cmp_mode = targetm.libgcc_cmp_return_mode ();
- FOR_EACH_MODE_FROM (mode, orig_mode)
+ FOR_EACH_WIDER_MODE_FROM (mode, orig_mode)
{
if (code_to_optab (comparison)
&& (libfunc = optab_libfunc (code_to_optab (comparison), mode)))
diff --git a/gcc/output.h b/gcc/output.h
index 6dea630..6936bde 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -199,10 +199,6 @@ extern void assemble_end_function (tree, const char *);
initial value (that will be done by the caller). */
extern void assemble_variable (tree, int, int, int);
-/* Put the vtable verification constructor initialization function
- into the preinit array. */
-extern void assemble_vtv_preinit_initializer (tree);
-
/* Assemble everything that is needed for a variable declaration that has
no definition in the current translation unit. */
extern void assemble_undefined_decl (tree);
diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc
index 229b9d2..23e0f5e 100644
--- a/gcc/range-op-float.cc
+++ b/gcc/range-op-float.cc
@@ -160,6 +160,12 @@ range_operator_float::op1_op2_relation (const irange &lhs ATTRIBUTE_UNUSED) cons
return VREL_VARYING;
}
+relation_kind
+range_operator_float::op1_op2_relation (const frange &lhs ATTRIBUTE_UNUSED) const
+{
+ return VREL_VARYING;
+}
+
// Return TRUE if OP1 is known to be free of NANs.
static inline bool
@@ -338,6 +344,7 @@ class foperator_equal : public range_operator_float
using range_operator_float::fold_range;
using range_operator_float::op1_range;
using range_operator_float::op2_range;
+ using range_operator_float::op1_op2_relation;
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
@@ -444,6 +451,7 @@ class foperator_not_equal : public range_operator_float
{
using range_operator_float::fold_range;
using range_operator_float::op1_range;
+ using range_operator_float::op1_op2_relation;
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
@@ -545,6 +553,7 @@ class foperator_lt : public range_operator_float
using range_operator_float::fold_range;
using range_operator_float::op1_range;
using range_operator_float::op2_range;
+ using range_operator_float::op1_op2_relation;
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
@@ -660,6 +669,7 @@ class foperator_le : public range_operator_float
using range_operator_float::fold_range;
using range_operator_float::op1_range;
using range_operator_float::op2_range;
+ using range_operator_float::op1_op2_relation;
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
@@ -767,6 +777,7 @@ class foperator_gt : public range_operator_float
using range_operator_float::fold_range;
using range_operator_float::op1_range;
using range_operator_float::op2_range;
+ using range_operator_float::op1_op2_relation;
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
@@ -882,6 +893,7 @@ class foperator_ge : public range_operator_float
using range_operator_float::fold_range;
using range_operator_float::op1_range;
using range_operator_float::op2_range;
+ using range_operator_float::op1_op2_relation;
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index 16fa1f4..cf7f0dc 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -2417,6 +2417,10 @@ public:
const irange &lhs,
const irange &op2,
relation_kind rel = VREL_VARYING) const;
+ virtual relation_kind lhs_op1_relation (const irange &lhs,
+ const irange &op1,
+ const irange &op2,
+ relation_kind) const;
private:
bool truncating_cast_p (const irange &inner, const irange &outer) const;
bool inside_domain_p (const wide_int &min, const wide_int &max,
@@ -2425,6 +2429,35 @@ private:
const irange &outer) const;
} op_convert;
+// Add a partial equivalence between the LHS and op1 for casts.
+
+relation_kind
+operator_cast::lhs_op1_relation (const irange &lhs,
+ const irange &op1,
+ const irange &op2 ATTRIBUTE_UNUSED,
+ relation_kind) const
+{
+ if (lhs.undefined_p () || op1.undefined_p ())
+ return VREL_VARYING;
+ unsigned lhs_prec = TYPE_PRECISION (lhs.type ());
+ unsigned op1_prec = TYPE_PRECISION (op1.type ());
+ // If the result gets sign extended into a larger type check first if this
+ // qualifies as a partial equivalence.
+ if (TYPE_SIGN (op1.type ()) == SIGNED && lhs_prec > op1_prec)
+ {
+ // If the result is sign extended, and the LHS is larger than op1,
+ // check if op1's range can be negative as the sign extention will
+ // cause the upper bits to be 1 instead of 0, invalidating the PE.
+ int_range<3> negs = range_negatives (op1.type ());
+ negs.intersect (op1);
+ if (!negs.undefined_p ())
+ return VREL_VARYING;
+ }
+
+ unsigned prec = MIN (lhs_prec, op1_prec);
+ return bits_to_pe (prec);
+}
+
// Return TRUE if casting from INNER to OUTER is a truncating cast.
inline bool
@@ -2739,6 +2772,10 @@ public:
const wide_int &lh_ub,
const wide_int &rh_lb,
const wide_int &rh_ub) const;
+ virtual relation_kind lhs_op1_relation (const irange &lhs,
+ const irange &op1,
+ const irange &op2,
+ relation_kind) const;
private:
void simple_op1_range_solver (irange &r, tree type,
const irange &lhs,
@@ -2784,6 +2821,34 @@ wi_optimize_signed_bitwise_op (irange &r, tree type,
return true;
}
+// An AND of 8,16, 32 or 64 bits can produce a partial equivalence between
+// the LHS and op1.
+
+relation_kind
+operator_bitwise_and::lhs_op1_relation (const irange &lhs,
+ const irange &op1,
+ const irange &op2,
+ relation_kind) const
+{
+ if (lhs.undefined_p () || op1.undefined_p () || op2.undefined_p ())
+ return VREL_VARYING;
+ if (!op2.singleton_p ())
+ return VREL_VARYING;
+ // if val == 0xff or 0xFFFF OR 0Xffffffff OR 0Xffffffffffffffff, return TRUE
+ int prec1 = TYPE_PRECISION (op1.type ());
+ int prec2 = TYPE_PRECISION (op2.type ());
+ int mask_prec = 0;
+ wide_int mask = op2.lower_bound ();
+ if (wi::eq_p (mask, wi::mask (8, false, prec2)))
+ mask_prec = 8;
+ else if (wi::eq_p (mask, wi::mask (16, false, prec2)))
+ mask_prec = 16;
+ else if (wi::eq_p (mask, wi::mask (32, false, prec2)))
+ mask_prec = 32;
+ else if (wi::eq_p (mask, wi::mask (64, false, prec2)))
+ mask_prec = 64;
+ return bits_to_pe (MIN (prec1, mask_prec));
+}
// Optimize BIT_AND_EXPR and BIT_IOR_EXPR in terms of a mask if
// possible. Basically, see if we can optimize:
@@ -4476,7 +4541,9 @@ range_op_handler::op1_op2_relation (const vrange &lhs) const
gcc_checking_assert (m_valid);
if (m_int)
return m_int->op1_op2_relation (as_a <irange> (lhs));
- return m_float->op1_op2_relation (as_a <irange> (lhs));
+ if (is_a <irange> (lhs))
+ return m_float->op1_op2_relation (as_a <irange> (lhs));
+ return m_float->op1_op2_relation (as_a <frange> (lhs));
}
// Cast the range in R to TYPE.
diff --git a/gcc/range-op.h b/gcc/range-op.h
index b2f063a..48adcec 100644
--- a/gcc/range-op.h
+++ b/gcc/range-op.h
@@ -160,6 +160,7 @@ public:
const frange &op2,
relation_kind = VREL_VARYING) const;
virtual relation_kind op1_op2_relation (const irange &lhs) const;
+ virtual relation_kind op1_op2_relation (const frange &lhs) const;
};
class range_op_handler
diff --git a/gcc/real.h b/gcc/real.h
index f9528d7..306e959 100644
--- a/gcc/real.h
+++ b/gcc/real.h
@@ -290,7 +290,7 @@ extern bool real_issignaling_nan (const REAL_VALUE_TYPE *);
inline bool
real_isdenormal (const REAL_VALUE_TYPE *r)
{
- return (r->sig[SIGSZ-1] & SIG_MSB) == 0;
+ return r->cl == rvc_normal && (r->sig[SIGSZ-1] & SIG_MSB) == 0;
}
/* Determine whether a floating-point value X is finite. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 737ee21..f717614 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,160 @@
+2022-10-14 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/cpp/c2x-ucnid-1-utf8.c, gcc.dg/cpp/c2x-ucnid-1.c: New
+ tests.
+
+2022-10-14 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/100971
+ * gfortran.dg/der_io_5.f90: New test.
+
+2022-10-14 Tobias Burnus <tobias@codesourcery.com>
+
+ * gfortran.dg/c-interop/deferred-character-2.f90: Use 'dg-do run'.
+
+2022-10-14 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/106304
+ * g++.dg/modules/pr106304_a.C: New test.
+ * g++.dg/modules/pr106304_b.C: New test.
+
+2022-10-14 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/107254
+ * gfortran.dg/vect/pr107254.f90: New testcase.
+
+2022-10-14 Jørgen Kvalsvik <jorgen.kvalsvik@woven-planet.global>
+
+ * gcc.misc-tests/gcov-4.c: New testcase.
+
+2022-10-14 Jørgen Kvalsvik <jorgen.kvalsvik@woven-planet.global>
+
+ * g++.dg/gcov/gcov-1.C: Add line count check.
+ * gcc.misc-tests/gcov-4.c: Likewise.
+
+2022-10-14 Jakub Jelinek <jakub@redhat.com>
+
+ * lib/target-supports.exp (check_effective_target_bfloat16,
+ check_effective_target_bfloat16_runtime, add_options_for_bfloat16):
+ New.
+ * gcc.dg/torture/bfloat16-basic.c: New test.
+ * gcc.dg/torture/bfloat16-builtin.c: New test.
+ * gcc.dg/torture/bfloat16-builtin-issignaling-1.c: New test.
+ * gcc.dg/torture/bfloat16-complex.c: New test.
+ * gcc.dg/torture/builtin-issignaling-1.c: Allow to be includable
+ from bfloat16-builtin-issignaling-1.c.
+ * gcc.dg/torture/floatn-basic.h: Allow to be includable from
+ bfloat16-basic.c.
+ * gcc.target/i386/vect-bfloat16-typecheck_2.c: Adjust expected
+ diagnostics.
+ * gcc.target/i386/sse2-bfloat16-scalar-typecheck.c: Likewise.
+ * gcc.target/i386/vect-bfloat16-typecheck_1.c: Likewise.
+ * g++.target/i386/bfloat_cpp_typecheck.C: Likewise.
+
+2022-10-14 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/82071
+ PR c/87390
+ PR c++/107097
+ * gcc.target/i386/excess-precision-8.c: For C++ wrap abort and
+ exit declarations into extern "C" block.
+ * gcc.target/i386/excess-precision-10.c: Likewise.
+ * g++.target/i386/excess-precision-7.C: Remove.
+ * g++.target/i386/excess-precision-8.C: New test.
+ * g++.target/i386/excess-precision-9.C: Remove.
+ * g++.target/i386/excess-precision-10.C: New test.
+ * g++.target/i386/excess-precision-12.C: New test.
+
+2022-10-14 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/323
+ PR c++/107097
+ * gcc.target/i386/excess-precision-1.c: For C++ wrap abort and
+ exit declarations into extern "C" block.
+ * gcc.target/i386/excess-precision-2.c: Likewise.
+ * gcc.target/i386/excess-precision-3.c: Likewise. Remove
+ check_float_nonproto and check_double_nonproto tests for C++.
+ * gcc.target/i386/excess-precision-7.c: For C++ wrap abort and
+ exit declarations into extern "C" block.
+ * gcc.target/i386/excess-precision-9.c: Likewise.
+ * g++.target/i386/excess-precision-1.C: New test.
+ * g++.target/i386/excess-precision-2.C: New test.
+ * g++.target/i386/excess-precision-3.C: New test.
+ * g++.target/i386/excess-precision-4.C: New test.
+ * g++.target/i386/excess-precision-5.C: New test.
+ * g++.target/i386/excess-precision-6.C: New test.
+ * g++.target/i386/excess-precision-7.C: New test.
+ * g++.target/i386/excess-precision-9.C: New test.
+ * g++.target/i386/excess-precision-11.C: New test.
+ * c-c++-common/dfp/convert-bfp-10.c: Add -fexcess-precision=fast
+ as dg-additional-options.
+ * c-c++-common/dfp/compare-eq-const.c: Likewise.
+ * g++.dg/cpp1z/constexpr-96862.C: Likewise.
+ * g++.dg/cpp1z/decomp12.C (main): Use 2.25 instead of 2.3 to
+ avoid excess precision differences.
+ * g++.dg/other/thunk1.C: Add -fexcess-precision=fast
+ as dg-additional-options.
+ * g++.dg/vect/pr64410.cc: Likewise.
+ * g++.dg/cpp1y/pr68180.C: Likewise.
+ * g++.dg/vect/pr89653.cc: Likewise.
+ * g++.dg/cpp0x/variadic-tuple.C: Likewise.
+ * g++.dg/cpp0x/nsdmi-union1.C: Use 4.25 instead of 4.2 to
+ avoid excess precision differences.
+ * g++.old-deja/g++.brendan/copy9.C: Add -fexcess-precision=fast
+ as dg-additional-options.
+ * g++.old-deja/g++.brendan/overload7.C: Likewise.
+
+2022-10-14 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/c11-complit-1.c, gcc.dg/c11-complit-2.c,
+ gcc.dg/c11-complit-3.c, gcc.dg/c2x-complit-2.c,
+ gcc.dg/c2x-complit-3.c, gcc.dg/c2x-complit-4.c,
+ gcc.dg/c2x-complit-5.c, gcc.dg/c2x-complit-6.c,
+ gcc.dg/c2x-complit-7.c, gcc.dg/c90-complit-2.c,
+ gcc.dg/gnu2x-complit-1.c, gcc.dg/gnu2x-complit-2.c: New tests.
+
+2022-10-13 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.dg/Wstringop-overflow-89.c: New test.
+
+2022-10-13 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/107210
+ * gfortran.dg/analyzer/pr107210.f90: New test.
+
+2022-10-13 Andrew MacLeod <amacleod@redhat.com>
+
+ * gcc.dg/pr102540.c: New.
+ * gcc.dg/pr102872.c: New.
+
+2022-10-13 Marek Polacek <polacek@redhat.com>
+
+ PR c++/106925
+ * g++.dg/cpp0x/initlist-defarg3.C: New test.
+
+2022-10-13 Wilco Dijkstra <wdijkstr@arm.com>
+
+ PR target/105773
+ * gcc.target/aarch64/ands_2.c: Test for ANDS.
+ * gcc.target/aarch64/bics_2.c: Test for BICS.
+ * gcc.target/aarch64/tst_2.c: Test for TST.
+ * gcc.target/aarch64/tst_imm_split_1.c: Fix test.
+
+2022-10-13 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/107160
+ * gcc.dg/vect/pr107160.c: New testcase.
+
+2022-10-13 Andre Vieira <andre.simoesdiasvieira@arm.com>
+
+ * gcc.dg/vect/pr107229-1.c: New test.
+ * gcc.dg/vect/pr107229-2.c: New test.
+ * gcc.dg/vect/pr107229-3.c: New test.
+
+2022-10-13 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/c2x-float-10.c: Do not expect value 2 for *_IS_IEC_60559.
+
2022-10-12 Lewis Hyatt <lhyatt@gmail.com>
PR preprocessor/60014
diff --git a/gcc/testsuite/c-c++-common/dfp/compare-eq-const.c b/gcc/testsuite/c-c++-common/dfp/compare-eq-const.c
index 0c9ff20..4bc2189 100644
--- a/gcc/testsuite/c-c++-common/dfp/compare-eq-const.c
+++ b/gcc/testsuite/c-c++-common/dfp/compare-eq-const.c
@@ -1,5 +1,6 @@
/* C99 6.5.9 Equality operators.
Compare decimal float constants against each other. */
+/* { dg-additional-options "-fexcess-precision=fast" } */
#include "dfp-dbg.h"
diff --git a/gcc/testsuite/c-c++-common/dfp/convert-bfp-10.c b/gcc/testsuite/c-c++-common/dfp/convert-bfp-10.c
index 3fef98a..2cce3e6 100644
--- a/gcc/testsuite/c-c++-common/dfp/convert-bfp-10.c
+++ b/gcc/testsuite/c-c++-common/dfp/convert-bfp-10.c
@@ -1,4 +1,5 @@
/* This test assumes IEEE float and double. */
+/* { dg-additional-options "-fexcess-precision=fast" } */
#include "convert.h"
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-defarg3.C b/gcc/testsuite/g++.dg/cpp0x/initlist-defarg3.C
new file mode 100644
index 0000000..5c3e886
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-defarg3.C
@@ -0,0 +1,13 @@
+// PR c++/106925
+// { dg-do compile { target c++11 } }
+
+struct Foo;
+template <int _Nm> struct __array_traits { typedef Foo _Type[_Nm]; };
+template <int _Nm> struct array {
+ typename __array_traits<_Nm>::_Type _M_elems;
+};
+template <int size> struct MyVector { array<size> data{}; };
+struct Foo {
+ float a{0};
+};
+void foo(MyVector<1> = MyVector<1>());
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-union1.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-union1.C
index 11bdd88..c5acc4a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nsdmi-union1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-union1.C
@@ -18,8 +18,8 @@ int main()
{
Test t;
B b;
- B b2(4.2);
+ B b2(4.25);
- if (t.a != 4 || b.i != 42 || b2.d != 4.2)
+ if (t.a != 4 || b.i != 42 || b2.d != 4.25)
__builtin_abort();
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-tuple.C b/gcc/testsuite/g++.dg/cpp0x/variadic-tuple.C
index e2699d9..5164598 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-tuple.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-tuple.C
@@ -1,4 +1,5 @@
// { dg-do run { target c++11 } }
+// { dg-additional-options "-fexcess-precision=fast" }
// An implementation of TR1's <tuple> using variadic teplates
// Contributed by Douglas Gregor <doug.gregor@gmail.com>
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr68180.C b/gcc/testsuite/g++.dg/cpp1y/pr68180.C
index 9e6e5e9..64d613e 100644
--- a/gcc/testsuite/g++.dg/cpp1y/pr68180.C
+++ b/gcc/testsuite/g++.dg/cpp1y/pr68180.C
@@ -1,6 +1,6 @@
// PR c++/68180
// { dg-do compile { target c++14 } }
-// { dg-additional-options "-Wno-psabi" }
+// { dg-additional-options "-Wno-psabi -fexcess-precision=fast" }
typedef float __attribute__( ( vector_size( 16 ) ) ) float32x4_t;
constexpr float32x4_t fill(float x) {
diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-96862.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-96862.C
index 0b5c2e81..daefca9 100644
--- a/gcc/testsuite/g++.dg/cpp1z/constexpr-96862.C
+++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-96862.C
@@ -1,6 +1,6 @@
// PR c++/96862
// { dg-do compile { target c++17 } }
-// { dg-additional-options "-frounding-math" }
+// { dg-additional-options "-frounding-math -fexcess-precision=fast" }
constexpr double a = 0x1.0p+100 + 0x1.0p-100;
const double b = 0x1.0p+100 + 0x1.0p-100;
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp12.C b/gcc/testsuite/g++.dg/cpp1z/decomp12.C
index 56fd498..a65aaf9 100644
--- a/gcc/testsuite/g++.dg/cpp1z/decomp12.C
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp12.C
@@ -7,13 +7,13 @@ template <typename, typename> struct same_type;
template <typename T> struct same_type<T, T> {};
int main() {
- std::tuple tuple = { 1, 'a', 2.3, true };
+ std::tuple tuple = { 1, 'a', 2.25, true };
auto[i, c, d, b] = tuple;
same_type<std::tuple_element<0, decltype(tuple)>::type, decltype(i)>{};
same_type<decltype(i), int>{};
same_type<decltype(c), char>{};
same_type<decltype(d), double>{};
same_type<decltype(b), bool>{};
- if (i != 1 || c != 'a' || d != 2.3 || b != true)
+ if (i != 1 || c != 'a' || d != 2.25 || b != true)
__builtin_abort ();
}
diff --git a/gcc/testsuite/g++.dg/gcov/gcov-1.C b/gcc/testsuite/g++.dg/gcov/gcov-1.C
index 9018b9a..ee383b4 100644
--- a/gcc/testsuite/g++.dg/gcov/gcov-1.C
+++ b/gcc/testsuite/g++.dg/gcov/gcov-1.C
@@ -257,20 +257,20 @@ test_switch (int i, int j)
switch (i) /* count(5) */
/* branch(end) */
{
- case 1:
+ case 1: /* count(1) */
result = do_something (2); /* count(1) */
- break;
+ break; /* count(1) */
case 2:
result = do_something (1024);
break;
- case 3:
+ case 3: /* count(3) */
case 4:
/* branch(67) */
if (j == 2) /* count(3) */
/* branch(end) */
return do_something (4); /* count(1) */
result = do_something (8); /* count(2) */
- break;
+ break; /* count(2) */
default:
result = do_something (32); /* count(1) */
switch_m++; /* count(1) */
diff --git a/gcc/testsuite/g++.dg/modules/pr106304_a.C b/gcc/testsuite/g++.dg/modules/pr106304_a.C
new file mode 100644
index 0000000..b999eec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr106304_a.C
@@ -0,0 +1,12 @@
+// PR c++/106304
+// { dg-additional-options -fmodules-ts }
+// { dg-module-cmi pr106304 }
+
+export module pr106304;
+
+struct A { virtual ~A() = default; };
+struct B : A { };
+
+inline const B* as_b(const A& a) {
+ return dynamic_cast<const B*>(&a);
+}
diff --git a/gcc/testsuite/g++.dg/modules/pr106304_b.C b/gcc/testsuite/g++.dg/modules/pr106304_b.C
new file mode 100644
index 0000000..e833390
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr106304_b.C
@@ -0,0 +1,8 @@
+// PR c++/106304
+// { dg-additional-options -fmodules-ts }
+
+module pr106304;
+
+void f(A& a) {
+ as_b(a);
+}
diff --git a/gcc/testsuite/g++.dg/other/thunk1.C b/gcc/testsuite/g++.dg/other/thunk1.C
index 9016562..7758111 100644
--- a/gcc/testsuite/g++.dg/other/thunk1.C
+++ b/gcc/testsuite/g++.dg/other/thunk1.C
@@ -1,5 +1,6 @@
// PR c++/12007 Multiple inheritance float pass by value fails
// { dg-do run }
+// { dg-additional-options "-fexcess-precision=fast" }
extern "C" void abort (void);
diff --git a/gcc/testsuite/g++.dg/vect/pr64410.cc b/gcc/testsuite/g++.dg/vect/pr64410.cc
index cbc2acc..ad4b085 100644
--- a/gcc/testsuite/g++.dg/vect/pr64410.cc
+++ b/gcc/testsuite/g++.dg/vect/pr64410.cc
@@ -1,5 +1,6 @@
// { dg-do compile }
// { dg-require-effective-target vect_double }
+// { dg-additional-options "-fexcess-precision=fast" }
#include <vector>
#include <complex>
diff --git a/gcc/testsuite/g++.dg/vect/pr89653.cc b/gcc/testsuite/g++.dg/vect/pr89653.cc
index d38b49a..f5a071f 100644
--- a/gcc/testsuite/g++.dg/vect/pr89653.cc
+++ b/gcc/testsuite/g++.dg/vect/pr89653.cc
@@ -1,5 +1,6 @@
// { dg-do compile }
// { dg-require-effective-target vect_double }
+// { dg-additional-options "-fexcess-precision=fast" }
#include <algorithm>
diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/copy9.C b/gcc/testsuite/g++.old-deja/g++.brendan/copy9.C
index f05b194..79339c1 100644
--- a/gcc/testsuite/g++.old-deja/g++.brendan/copy9.C
+++ b/gcc/testsuite/g++.old-deja/g++.brendan/copy9.C
@@ -1,4 +1,5 @@
// { dg-do run }
+// { dg-additional-options "-fexcess-precision=fast" }
// GROUPS passed copy-ctors
#include <iostream>
diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/overload7.C b/gcc/testsuite/g++.old-deja/g++.brendan/overload7.C
index 29a9060..08f220c 100644
--- a/gcc/testsuite/g++.old-deja/g++.brendan/overload7.C
+++ b/gcc/testsuite/g++.old-deja/g++.brendan/overload7.C
@@ -1,4 +1,5 @@
// { dg-do run }
+// { dg-additional-options "-fexcess-precision=fast" }
// GROUPS passed overloading
extern "C" int printf (const char *, ...);
diff --git a/gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C b/gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C
index b800a6d..2567129 100644
--- a/gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C
+++ b/gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C
@@ -5,6 +5,6 @@ void foo (void)
{
__bf16 (); /* { dg-bogus {invalid conversion to type '__bf16'} } */
__bf16 a = __bf16(); /* { dg-bogus {invalid conversion to type '__bf16'} } */
- __bf16 (0x1234); /* { dg-error {invalid conversion to type '__bf16'} } */
- __bf16 (0.1); /* { dg-error {invalid conversion to type '__bf16'} } */
+ __bf16 (0x1234); /* { dg-bogus {invalid conversion to type '__bf16'} } */
+ __bf16 (0.1); /* { dg-bogus {invalid conversion to type '__bf16'} } */
}
diff --git a/gcc/testsuite/g++.target/i386/excess-precision-1.C b/gcc/testsuite/g++.target/i386/excess-precision-1.C
new file mode 100644
index 0000000..0519d63
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/excess-precision-1.C
@@ -0,0 +1,6 @@
+// Excess precision tests. Test that excess precision is carried
+// through various operations.
+// { dg-do run }
+// { dg-options "-O2 -mfpmath=387 -fexcess-precision=standard" }
+
+#include "../../gcc.target/i386/excess-precision-1.c"
diff --git a/gcc/testsuite/g++.target/i386/excess-precision-10.C b/gcc/testsuite/g++.target/i386/excess-precision-10.C
new file mode 100644
index 0000000..9dbe25e
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/excess-precision-10.C
@@ -0,0 +1,6 @@
+// Excess precision tests. Test implicit conversions in comparisons:
+// excess precision in C++.
+// { dg-do run }
+// { dg-options "-mfpmath=387 -fexcess-precision=standard" }
+
+#include "../../gcc.target/i386/excess-precision-10.c"
diff --git a/gcc/testsuite/g++.target/i386/excess-precision-11.C b/gcc/testsuite/g++.target/i386/excess-precision-11.C
new file mode 100644
index 0000000..119b666
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/excess-precision-11.C
@@ -0,0 +1,105 @@
+// Excess precision tests. Test excess precision is removed when
+// necessary.
+// { dg-do run }
+// { dg-options "-O2 -mfpmath=387 -fexcess-precision=standard" }
+
+#include <float.h>
+#include <stdarg.h>
+
+extern "C" void abort ();
+
+volatile float f1 = 1.0f;
+volatile float f2 = 0x1.0p-30f;
+volatile float f3 = 0x1.0p-60f;
+volatile double d1 = 1.0;
+volatile double d2 = 0x1.0p-30;
+volatile double d3 = 0x1.0p-60;
+volatile double d3d = 0x1.0p-52;
+volatile float fadd1 = 1.0f + 0x1.0p-30f;
+volatile double dadd2 = 1.0 + 0x1.0p-30 + 0x1.0p-60;
+volatile double dh = 0x1.0p-24;
+volatile float fha = 1.0f + 0x1.0p-23f;
+
+static inline void
+check_float (float f)
+{
+ if (f != fadd1)
+ abort ();
+}
+
+static inline void
+check_float (double)
+{
+ abort ();
+}
+
+static inline void
+check_float (long double)
+{
+ abort ();
+}
+
+static inline void
+check_double (double d)
+{
+ if (d != dadd2)
+ abort ();
+}
+
+static inline void
+check_double (long double)
+{
+ abort ();
+}
+
+static inline void
+check_float2 (float f)
+{
+ if (f != fha)
+ abort ();
+}
+
+struct S {
+ S () {}
+ S (float f) { if (f != fadd1) abort (); }
+};
+
+struct T {
+ T () {}
+ T (double d) { if (d != dadd2) abort (); }
+};
+
+static inline void
+check_float3 (S)
+{
+}
+
+static inline void
+check_double2 (T)
+{
+}
+
+void
+test_call ()
+{
+ check_float (f1 + f2);
+ check_double (f1 + f2);
+ check_double (d1 + d2 + d3);
+ /* Verify rounding direct to float without double rounding. */
+ if (sizeof (long double) > sizeof (double))
+ check_float2 (d1 + dh + d3);
+ else
+ check_float2 (d1 + dh + d3d);
+ check_float3 (f1 + f2);
+ check_double2 (f1 + f2);
+ check_double2 (d1 + d2 + d3);
+ S s1 = static_cast<S> (f1 + f2);
+ T t2 = static_cast<T> (f1 + f2);
+ T t3 = static_cast<T> (d1 + d2 + d3);
+}
+
+int
+main ()
+{
+ test_call ();
+}
diff --git a/gcc/testsuite/g++.target/i386/excess-precision-12.C b/gcc/testsuite/g++.target/i386/excess-precision-12.C
new file mode 100644
index 0000000..dff48c0
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/excess-precision-12.C
@@ -0,0 +1,20 @@
+// Excess precision tests. Test implicit conversions in 3-way comparisons:
+// excess precision in C++.
+// { dg-do run { target c++20 } }
+// { dg-options "-mfpmath=387 -fexcess-precision=standard" }
+
+#include <compare>
+#include <cstdlib>
+
+int
+main (void)
+{
+ float f = 0x1p63f;
+ unsigned long long int u = (1ULL << 63) + 1;
+
+ if ((f <=> u) >= 0)
+ abort ();
+
+ if ((u <=> f) <= 0)
+ abort ();
+}
diff --git a/gcc/testsuite/g++.target/i386/excess-precision-2.C b/gcc/testsuite/g++.target/i386/excess-precision-2.C
new file mode 100644
index 0000000..afb2197
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/excess-precision-2.C
@@ -0,0 +1,5 @@
+// Excess precision tests. Test excess precision of constants.
+// { dg-do run }
+// { dg-options "-O2 -mfpmath=387 -fexcess-precision=standard" }
+
+#include "../../gcc.target/i386/excess-precision-2.c"
diff --git a/gcc/testsuite/g++.target/i386/excess-precision-3.C b/gcc/testsuite/g++.target/i386/excess-precision-3.C
new file mode 100644
index 0000000..be8cc42
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/excess-precision-3.C
@@ -0,0 +1,6 @@
+// Excess precision tests. Test excess precision is removed when
+// necessary.
+// { dg-do run }
+// { dg-options "-O2 -mfpmath=387 -fexcess-precision=standard" }
+
+#include "../../gcc.target/i386/excess-precision-3.c"
diff --git a/gcc/testsuite/g++.target/i386/excess-precision-4.C b/gcc/testsuite/g++.target/i386/excess-precision-4.C
new file mode 100644
index 0000000..30606b1
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/excess-precision-4.C
@@ -0,0 +1,7 @@
+// Excess precision tests. Test diagnostics for excess precision of
+// constants.
+// { dg-do compile }
+// { dg-options "-mfpmath=387 -fexcess-precision=standard" }
+
+float f = 0.0f * 1e50f; // { dg-warning "floating constant exceeds range of 'float'" }
+double d = 0.0 * 1e400; // { dg-warning "floating constant exceeds range of 'double'" }
diff --git a/gcc/testsuite/g++.target/i386/excess-precision-5.C b/gcc/testsuite/g++.target/i386/excess-precision-5.C
new file mode 100644
index 0000000..fa15753
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/excess-precision-5.C
@@ -0,0 +1,32 @@
+// Excess precision tests. Verify excess precision doesn't affect
+// actual types.
+// { dg-do compile { target c++11 } }
+// { dg-options "-mfpmath=387 -fexcess-precision=standard" }
+
+namespace std {
+ template<typename T, T v> struct integral_constant {
+ static constexpr T value = v;
+ };
+ typedef integral_constant<bool, false> false_type;
+ typedef integral_constant<bool, true> true_type;
+ template<class T, class U>
+ struct is_same : std::false_type {};
+ template <class T>
+ struct is_same<T, T> : std::true_type {};
+}
+
+float f;
+double d;
+
+void
+test_types (void)
+{
+#define CHECK_FLOAT(E) static_assert (std::is_same <float, decltype (E)>::value, "")
+#define CHECK_DOUBLE(E) static_assert (std::is_same <double, decltype (E)>::value, "")
+ CHECK_FLOAT (f + f);
+ CHECK_DOUBLE (d + d);
+ CHECK_FLOAT (f * f / f);
+ CHECK_DOUBLE (d * d / d);
+ CHECK_FLOAT (f ? f - f : f);
+ CHECK_DOUBLE (d ? d - d : d);
+}
diff --git a/gcc/testsuite/g++.target/i386/excess-precision-6.C b/gcc/testsuite/g++.target/i386/excess-precision-6.C
new file mode 100644
index 0000000..06e9a93
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/excess-precision-6.C
@@ -0,0 +1,19 @@
+// Excess precision tests. Make sure sqrt is not inlined for float or
+// double.
+// { dg-do compile }
+// { dg-options "-mfpmath=387 -O2 -fno-math-errno -fexcess-precision=standard" }
+
+float f;
+double d;
+
+float fr;
+double dr;
+
+void
+test_builtins (void)
+{
+ fr = __builtin_sqrtf (f);
+ dr = __builtin_sqrt (d);
+}
+
+// { dg-final { scan-assembler-not "fsqrt" } }
diff --git a/gcc/testsuite/g++.target/i386/excess-precision-8.C b/gcc/testsuite/g++.target/i386/excess-precision-8.C
new file mode 100644
index 0000000..c170c00
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/excess-precision-8.C
@@ -0,0 +1,7 @@
+// Excess precision tests. Test C++ semantics for conversions from
+// integers to floating point: no excess precision for either explicit
+// or implicit conversions.
+// { dg-do run }
+// { dg-options "-mfpmath=387 -fexcess-precision=standard" }
+
+#include "../../gcc.target/i386/excess-precision-8.c"
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-89.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-89.c
new file mode 100644
index 0000000..ba25a93
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-89.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-inline -Wall" } */
+
+extern void process (char);
+
+void process_array4 (char a[4], int n)
+{
+ for (int i = 0; i < n; i++)
+ process (a[i]);
+}
+
+void process_array3 (char a[3], int n)
+{
+ for (int i = 0; i < n; i++)
+ process (a[i]);
+}
diff --git a/gcc/testsuite/gcc.dg/c11-complit-1.c b/gcc/testsuite/gcc.dg/c11-complit-1.c
new file mode 100644
index 0000000..e191ceb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-complit-1.c
@@ -0,0 +1,7 @@
+/* Test C2x storage class specifiers in compound literals not permitted for
+ C11. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+int *ps = &(static int) { 1 }; /* { dg-error "forbids storage class specifiers in compound literals" } */
+int ss = sizeof (static int) { 1 }; /* { dg-error "forbids storage class specifiers in compound literals" } */
diff --git a/gcc/testsuite/gcc.dg/c11-complit-2.c b/gcc/testsuite/gcc.dg/c11-complit-2.c
new file mode 100644
index 0000000..d4d1f16
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-complit-2.c
@@ -0,0 +1,7 @@
+/* Test C2x storage class specifiers in compound literals not permitted for
+ C11. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic" } */
+
+int *ps = &(static int) { 1 }; /* { dg-warning "forbids storage class specifiers in compound literals" } */
+int ss = sizeof (static int) { 1 }; /* { dg-warning "forbids storage class specifiers in compound literals" } */
diff --git a/gcc/testsuite/gcc.dg/c11-complit-3.c b/gcc/testsuite/gcc.dg/c11-complit-3.c
new file mode 100644
index 0000000..a73a8ef
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-complit-3.c
@@ -0,0 +1,7 @@
+/* Test C2x storage class specifiers in compound literals not permitted for
+ C11, but -Wno-c11-c2x-compat disables the -pedantic diagnostic for that. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors -Wno-c11-c2x-compat" } */
+
+int *ps = &(static int) { 1 };
+int ss = sizeof (static int) { 1 };
diff --git a/gcc/testsuite/gcc.dg/c2x-complit-2.c b/gcc/testsuite/gcc.dg/c2x-complit-2.c
new file mode 100644
index 0000000..dcca5e8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-complit-2.c
@@ -0,0 +1,48 @@
+/* Test C2x storage class specifiers in compound literals. */
+/* { dg-do run } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+#include <stddef.h>
+
+extern void abort (void);
+extern void exit (int);
+
+/* static is OK (although redundant) at file scope. */
+int *ps = &(static int) { 1 };
+size_t ss = sizeof (static int) { 1 };
+int *psa = (static int [3]) { 1, 2, 3 };
+
+int
+main ()
+{
+ if (ps[0] != 1)
+ abort ();
+ if (ss != sizeof (int))
+ abort ();
+ if (psa[0] != 1 || psa[1] != 2 || psa[2] != 3)
+ abort ();
+ if ((register int) { 3 } != 3)
+ abort ();
+ /* A static compound literal, like a static variable, is initialized once,
+ but an automatic compound literal is initialized every time it is reached
+ in the order of execution. */
+ int i = 0;
+ lab:
+ int *p = &(static int) { 0 };
+ if (*p != i)
+ abort ();
+ i++;
+ *p = i;
+ if (i < 5)
+ goto lab;
+ i = 0;
+ lab2:
+ int *p2 = &(int) { 0 };
+ if (*p2 != 0)
+ abort ();
+ i++;
+ *p2 = i;
+ if (i < 5)
+ goto lab2;
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/c2x-complit-3.c b/gcc/testsuite/gcc.dg/c2x-complit-3.c
new file mode 100644
index 0000000..c672525
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-complit-3.c
@@ -0,0 +1,24 @@
+/* Test C2x storage class specifiers in compound literals. Thread-local
+ cases, compilation tests. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+/* { dg-require-effective-target tls } */
+
+#include <stddef.h>
+
+/* thread_local is OK at file scope, although of limited use since the
+ thread-local object and its address are not constant expressions. */
+size_t st = sizeof (thread_local int) { 1 };
+size_t sst = sizeof (static thread_local int) { 1 };
+
+int *
+f ()
+{
+ return &(static thread_local int) { 2 };
+}
+
+int *
+g ()
+{
+ return &(thread_local static int) { 3 };
+}
diff --git a/gcc/testsuite/gcc.dg/c2x-complit-4.c b/gcc/testsuite/gcc.dg/c2x-complit-4.c
new file mode 100644
index 0000000..31d7413
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-complit-4.c
@@ -0,0 +1,60 @@
+/* Test C2x storage class specifiers in compound literals. Thread-local
+ cases, execution tests. */
+/* { dg-do run } */
+/* { dg-options "-pthread -std=gnu2x -pedantic-errors" } */
+/* { dg-require-effective-target pthread_h } */
+/* { dg-require-effective-target pthread } */
+/* { dg-require-effective-target tls_runtime } */
+/* { dg-add-options tls } */
+
+#include <pthread.h>
+
+extern void abort (void);
+extern void exit (int);
+
+int *
+thread_addr ()
+{
+ return (static thread_local int []) { 1, 2 };
+}
+
+int *volatile p, *volatile q, r;
+
+void *
+thread_fn (void *)
+{
+ q = thread_addr ();
+ if (q[0] != 1 || q[1] != 2)
+ return NULL;
+ q[0] = 5;
+ q[1] = 6;
+ return &r;
+}
+
+int
+main ()
+{
+ int i;
+ pthread_t tid;
+ void *ret;
+ p = thread_addr ();
+ if (p[0] != 1 || p[1] != 2)
+ abort ();
+ p[0] = 3;
+ p[1] = 4;
+ if (p != thread_addr ())
+ abort ();
+ i = pthread_create (&tid, NULL, thread_fn, NULL);
+ if (p != thread_addr ())
+ abort ();
+ i = pthread_join (tid, &ret);
+ if (i != 0)
+ abort ();
+ if (ret != &r)
+ abort ();
+ if (p != thread_addr ())
+ abort ();
+ if (p[0] != 3 || p[1] != 4)
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/c2x-complit-5.c b/gcc/testsuite/gcc.dg/c2x-complit-5.c
new file mode 100644
index 0000000..1eb0f8d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-complit-5.c
@@ -0,0 +1,52 @@
+/* Test C2x storage class specifiers in compound literals: invalid code. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+int *p = &(register int) { 0 }; /* { dg-error "file-scope compound literal specifies" } */
+
+int v;
+
+void
+f ()
+{
+ int *q = &(thread_local int) { 0 }; /* { dg-error "compound literal implicitly auto and declared" } */
+ int *pc = &(static int) { v }; /* { dg-error "not constant" } */
+ int *pt = &(static thread_local int) { v }; /* { dg-error "not constant" } */
+ &(register int) { 0 }; /* { dg-error "address of register compound literal requested" } */
+ struct s { int a, b; };
+ &((register struct s) { 1, 2 }.b); /* { dg-error "address of register compound literal requested" } */
+}
+
+int *s = &(static static int) { 0 }; /* { dg-error "duplicate" } */
+
+void
+g ()
+{
+ (void) (register register int) { 0 }; /* { dg-error "duplicate" } */
+ (void) (static static int) { 0 }; /* { dg-error "duplicate" } */
+ (void) (static thread_local thread_local int) { 0 }; /* { dg-error "duplicate" } */
+ (void) (static register int) { 0 }; /* { dg-error "multiple storage classes in declaration specifiers" } */
+ (void) (register static int) { 0 }; /* { dg-error "multiple storage classes in declaration specifiers" } */
+ (void) (register thread_local int) { 0 }; /* { dg-error "used with" } */
+ (void) (thread_local register int) { 0 }; /* { dg-error "used with" } */
+}
+
+void
+h ()
+{
+ /* The following cases are not part of the C2x syntax, but are detected
+ specially by the parser. */
+ (static int) 0; /* { dg-error "storage class specifier in cast" } */
+ sizeof (static int); /* { dg-error "storage class specifier in" } */
+ alignof (static int); /* { dg-error "storage class specifier in" } */
+}
+
+void
+bad_scspec ()
+{
+ /* Storage class specifiers not permitted in compound literals result in a
+ syntax error. */
+ (typedef int) { 0 }; /* { dg-error "expected" } */
+ (auto int) { 0 }; /* { dg-error "expected" } */
+ (extern int) { 0 }; /* { dg-error "expected" } */
+}
diff --git a/gcc/testsuite/gcc.dg/c2x-complit-6.c b/gcc/testsuite/gcc.dg/c2x-complit-6.c
new file mode 100644
index 0000000..23a0bb6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-complit-6.c
@@ -0,0 +1,7 @@
+/* Test C2x storage class specifiers in compound literals diagnosed with
+ -Wc11-c2x-compat. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -Wc11-c2x-compat" } */
+
+int *ps = &(static int) { 1 }; /* { dg-warning "forbids storage class specifiers in compound literals" } */
+int ss = sizeof (static int) { 1 }; /* { dg-warning "forbids storage class specifiers in compound literals" } */
diff --git a/gcc/testsuite/gcc.dg/c2x-complit-7.c b/gcc/testsuite/gcc.dg/c2x-complit-7.c
new file mode 100644
index 0000000..0cd0b86
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-complit-7.c
@@ -0,0 +1,7 @@
+/* Test C2x storage class specifiers in compound literals diagnosed with
+ -Wc11-c2x-compat, but not errors with -pedantic-errors. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -Wc11-c2x-compat -pedantic-errors" } */
+
+int *ps = &(static int) { 1 }; /* { dg-warning "forbids storage class specifiers in compound literals" } */
+int ss = sizeof (static int) { 1 }; /* { dg-warning "forbids storage class specifiers in compound literals" } */
diff --git a/gcc/testsuite/gcc.dg/c90-complit-2.c b/gcc/testsuite/gcc.dg/c90-complit-2.c
new file mode 100644
index 0000000..6fcf2a5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c90-complit-2.c
@@ -0,0 +1,8 @@
+/* Test C2x storage class specifiers in compound literals not permitted for
+ C90, but without a duplicate diagnostic, just the diagnostic for compound
+ literals not being permitted in C90 at all. */
+/* { dg-do compile } */
+/* { dg-options "-std=c90 -pedantic-errors" } */
+
+int *ps = &(static int) { 1 }; /* { dg-error "ISO C90 forbids compound literals" } */
+int ss = sizeof (static int) { 1 }; /* { dg-error "ISO C90 forbids compound literals" } */
diff --git a/gcc/testsuite/gcc.dg/cpp/c2x-ucnid-1-utf8.c b/gcc/testsuite/gcc.dg/cpp/c2x-ucnid-1-utf8.c
new file mode 100644
index 0000000..55d2281
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/c2x-ucnid-1-utf8.c
@@ -0,0 +1,13 @@
+/* Test C2x (= Unicode) rules for characters in identifiers. */
+/* { dg-do preprocess } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+¨
+
+/* The requirement for NFC only applies in identifiers, not pp-numbers. */
+
+AÌ€ /* { dg-error "not in NFC" } */
+ÿÀ /* { dg-error "not in NFC" } */
+
+0AÌ€ /* { dg-warning "not in NFC" } */
+.1AÌ€ /* { dg-warning "not in NFC" } */
diff --git a/gcc/testsuite/gcc.dg/cpp/c2x-ucnid-1.c b/gcc/testsuite/gcc.dg/cpp/c2x-ucnid-1.c
new file mode 100644
index 0000000..f9fdbea
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/c2x-ucnid-1.c
@@ -0,0 +1,13 @@
+/* Test C2x (= Unicode) rules for characters in identifiers. */
+/* { dg-do preprocess } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+\u00A8 /* { dg-error "is not valid in an identifier" } */
+
+/* The requirement for NFC only applies in identifiers, not pp-numbers. */
+
+A\u0300 /* { dg-error "not in NFC" } */
+\u00ffA\u0300 /* { dg-error "not in NFC" } */
+
+0A\u0300 /* { dg-warning "not in NFC" } */
+.1A\u0300 /* { dg-warning "not in NFC" } */
diff --git a/gcc/testsuite/gcc.dg/gnu2x-complit-1.c b/gcc/testsuite/gcc.dg/gnu2x-complit-1.c
new file mode 100644
index 0000000..e9da5ad
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gnu2x-complit-1.c
@@ -0,0 +1,7 @@
+/* Test C2x storage class specifiers in compound literals: GNU use of alignof
+ on objects (tested separately since alignof parsing handles the type name of
+ compound literals). */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu2x" } */
+
+int a = alignof (static int) { 0 };
diff --git a/gcc/testsuite/gcc.dg/gnu2x-complit-2.c b/gcc/testsuite/gcc.dg/gnu2x-complit-2.c
new file mode 100644
index 0000000..20cb38f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gnu2x-complit-2.c
@@ -0,0 +1,18 @@
+/* Test C2x storage class specifiers in compound literals. Thread-local
+ cases, compilation tests, GNU __thread used. */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu2x" } */
+/* { dg-require-effective-target tls } */
+
+#include <stddef.h>
+
+/* __thread is OK at file scope, although of limited use since the
+ thread-local object and its address are not constant expressions. */
+size_t st = sizeof (__thread int) { 1 };
+size_t sst = sizeof (static __thread int) { 1 };
+
+int *
+f ()
+{
+ return &(static __thread int) { 2 };
+}
diff --git a/gcc/testsuite/gcc.dg/pr102540.c b/gcc/testsuite/gcc.dg/pr102540.c
new file mode 100644
index 0000000..c12f8fc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr102540.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-tree-evrp" } */
+
+
+void kill();
+
+static long a;
+static unsigned b;
+int test1 () {
+ long c, e;
+ c = b = a;
+ e = c ? 2 / (c + 1) : 0;
+ if (e && !b)
+ kill ();
+ a = 0;
+}
+
+/* { dg-final { scan-tree-dump-not "kill" "evrp" } } */
+
diff --git a/gcc/testsuite/gcc.dg/pr102872.c b/gcc/testsuite/gcc.dg/pr102872.c
new file mode 100644
index 0000000..971bb03
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr102872.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+void foo(void);
+
+static int a, b;
+int main() {
+ for (; a; ++a) {
+ unsigned short d = a;
+ if (!(b | d) && d)
+ foo();
+ }
+}
+
+/* { dg-final { scan-tree-dump-not "foo" "evrp" } } */
+
diff --git a/gcc/testsuite/gcc.dg/torture/bfloat16-basic.c b/gcc/testsuite/gcc.dg/torture/bfloat16-basic.c
new file mode 100644
index 0000000..09e54d4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/bfloat16-basic.c
@@ -0,0 +1,11 @@
+/* Test __bf16. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options bfloat16 } */
+/* { dg-require-effective-target bfloat16_runtime } */
+
+#define TYPE __bf16
+#define CST(C) CONCAT (C, bf16)
+#define CSTU(C) CONCAT (C, BF16)
+
+#include "floatn-basic.h"
diff --git a/gcc/testsuite/gcc.dg/torture/bfloat16-builtin-issignaling-1.c b/gcc/testsuite/gcc.dg/torture/bfloat16-builtin-issignaling-1.c
new file mode 100644
index 0000000..0e428db
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/bfloat16-builtin-issignaling-1.c
@@ -0,0 +1,21 @@
+/* Test __bf16 __builtin_issignaling. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options bfloat16 } */
+/* { dg-add-options ieee } */
+/* { dg-require-effective-target bfloat16_runtime } */
+/* { dg-additional-options "-fsignaling-nans" } */
+/* Workaround for PR57484 on ia32: */
+/* { dg-additional-options "-msse2 -mfpmath=sse" { target { ia32 && sse2_runtime } } } */
+
+#define CONCATX(X, Y) X ## Y
+#define CONCAT(X, Y) CONCATX (X, Y)
+
+#define TYPE __bf16
+#define CST(C) CONCAT (C, bf16)
+#define FN(F) CONCAT (F, f16b)
+#define NAN(x) ((__bf16) __builtin_nanf (x))
+#define INF ((__bf16) __builtin_inff ())
+#define EXT 0
+
+#include "builtin-issignaling-1.c"
diff --git a/gcc/testsuite/gcc.dg/torture/bfloat16-builtin.c b/gcc/testsuite/gcc.dg/torture/bfloat16-builtin.c
new file mode 100644
index 0000000..ce02f6f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/bfloat16-builtin.c
@@ -0,0 +1,47 @@
+/* Test __bf16 built-in functions. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options bfloat16 } */
+/* { dg-add-options ieee } */
+/* { dg-require-effective-target bfloat16_runtime } */
+
+extern void exit (int);
+extern void abort (void);
+
+extern __bf16 test_type;
+extern __typeof (__builtin_nansf16b ("")) test_type;
+
+volatile __bf16 inf_cst = (__bf16) __builtin_inff ();
+volatile __bf16 huge_val_cst = (__bf16) __builtin_huge_valf ();
+volatile __bf16 nan_cst = (__bf16) __builtin_nanf ("");
+volatile __bf16 nans_cst = __builtin_nansf16b ("");
+volatile __bf16 neg0 = -0.0bf16, neg1 = -1.0bf16, one = 1.0;
+
+int
+main (void)
+{
+ volatile __bf16 r;
+ if (!__builtin_isinf (inf_cst))
+ abort ();
+ if (!__builtin_isinf (huge_val_cst))
+ abort ();
+ if (inf_cst != huge_val_cst)
+ abort ();
+ if (!__builtin_isnan (nan_cst))
+ abort ();
+ if (!__builtin_isnan (nans_cst))
+ abort ();
+ r = __builtin_fabsf (neg1);
+ if (r != 1.0bf16)
+ abort ();
+ r = __builtin_copysignf (one, neg0);
+ if (r != neg1)
+ abort ();
+ r = __builtin_copysignf (inf_cst, neg1);
+ if (r != -huge_val_cst)
+ abort ();
+ r = __builtin_copysignf (-inf_cst, one);
+ if (r != huge_val_cst)
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/bfloat16-complex.c b/gcc/testsuite/gcc.dg/torture/bfloat16-complex.c
new file mode 100644
index 0000000..fa27a77
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/bfloat16-complex.c
@@ -0,0 +1,61 @@
+/* Test __bf16 complex arithmetic. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options bfloat16 } */
+/* { dg-require-effective-target bfloat16_runtime } */
+
+extern void exit (int);
+extern void abort (void);
+
+volatile __bf16 a = 1.0bf16;
+typedef _Complex float __cbf16 __attribute__((__mode__(__BC__)));
+volatile __cbf16 b = __builtin_complex (2.0bf16, 3.0bf16);
+volatile __cbf16 c = __builtin_complex (2.0bf16, 3.0bf16);
+volatile __cbf16 d = __builtin_complex (2.0bf16, 3.0bf16);
+
+__cbf16
+fn (__cbf16 arg)
+{
+ return arg / 4;
+}
+
+int
+main (void)
+{
+ volatile __cbf16 r;
+ if (b != c)
+ abort ();
+ if (b != d)
+ abort ();
+ r = a + b;
+ if (__real__ r != 3.0bf16 || __imag__ r != 3.0bf16)
+ abort ();
+ r += d;
+ if (__real__ r != 5.0bf16 || __imag__ r != 6.0bf16)
+ abort ();
+ r -= a;
+ if (__real__ r != 4.0bf16 || __imag__ r != 6.0bf16)
+ abort ();
+ r /= (a + a);
+ if (__real__ r != 2.0bf16 || __imag__ r != 3.0bf16)
+ abort ();
+ r *= (a + a);
+ if (__real__ r != 4.0bf16 || __imag__ r != 6.0bf16)
+ abort ();
+ r -= b;
+ if (__real__ r != 2.0bf16 || __imag__ r != 3.0bf16)
+ abort ();
+ r *= r;
+ if (__real__ r != -5.0bf16 || __imag__ r != 12.0bf16)
+ abort ();
+ /* Division may not be exact, so round result before comparing. */
+ r /= b;
+ r += __builtin_complex (100.0bf16, 100.0bf16);
+ r -= __builtin_complex (100.0bf16, 100.0bf16);
+ if (r != b)
+ abort ();
+ r = fn (r);
+ if (__real__ r != 0.5bf16 || __imag__ r != 0.75bf16)
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/builtin-issignaling-1.c b/gcc/testsuite/gcc.dg/torture/builtin-issignaling-1.c
index fddca6c..60125b2 100644
--- a/gcc/testsuite/gcc.dg/torture/builtin-issignaling-1.c
+++ b/gcc/testsuite/gcc.dg/torture/builtin-issignaling-1.c
@@ -4,7 +4,7 @@
/* Workaround for PR57484 on ia32: */
/* { dg-additional-options "-msse2 -mfpmath=sse" { target { ia32 && sse2_runtime } } } */
-#ifndef EXT
+#if !defined(EXT) && !defined(TYPE)
int
f1 (void)
{
@@ -41,31 +41,42 @@ f6 (long double x)
return __builtin_issignaling (x);
}
#else
-#define CONCATX(X, Y) X ## Y
-#define CONCAT(X, Y) CONCATX (X, Y)
-#define CONCAT3(X, Y, Z) CONCAT (CONCAT (X, Y), Z)
-#define CONCAT4(W, X, Y, Z) CONCAT (CONCAT (CONCAT (W, X), Y), Z)
+#ifndef TYPE
+# define CONCATX(X, Y) X ## Y
+# define CONCAT(X, Y) CONCATX (X, Y)
+# define CONCAT3(X, Y, Z) CONCAT (CONCAT (X, Y), Z)
+# define CONCAT4(W, X, Y, Z) CONCAT (CONCAT (CONCAT (W, X), Y), Z)
-#if EXT
-# define TYPE CONCAT3 (_Float, WIDTH, x)
-# define CST(C) CONCAT4 (C, f, WIDTH, x)
-# define FN(F) CONCAT4 (F, f, WIDTH, x)
-#else
-# define TYPE CONCAT (_Float, WIDTH)
-# define CST(C) CONCAT3 (C, f, WIDTH)
-# define FN(F) CONCAT3 (F, f, WIDTH)
+# if EXT
+# define TYPE CONCAT3 (_Float, WIDTH, x)
+# define CST(C) CONCAT4 (C, f, WIDTH, x)
+# define FN(F) CONCAT4 (F, f, WIDTH, x)
+# else
+# define TYPE CONCAT (_Float, WIDTH)
+# define CST(C) CONCAT3 (C, f, WIDTH)
+# define FN(F) CONCAT3 (F, f, WIDTH)
+# endif
+#endif
+#ifndef NANS
+# define NANS(x) FN (__builtin_nans) (x)
+#endif
+#ifndef NAN
+# define NAN(x) FN (__builtin_nan) (x)
+#endif
+#ifndef INF
+# define INF FN (__builtin_inf) ()
#endif
int
f1 (void)
{
- return __builtin_issignaling (FN (__builtin_nans) (""));
+ return __builtin_issignaling (NANS (""));
}
int
f2 (void)
{
- return __builtin_issignaling (FN (__builtin_nan) (""));
+ return __builtin_issignaling (NAN (""));
}
int
@@ -118,10 +129,10 @@ main ()
if (!f6 (z))
__builtin_abort ();
#else
- if (f4 (w) || !f4 (FN (__builtin_nans) ("0x123")) || f4 (CST (42.0)) || f4 (FN (__builtin_nan) ("0x234"))
- || f4 (FN (__builtin_inf) ()) || f4 (-FN (__builtin_inf) ()) || f4 (CST (-42.0)) || f4 (CST (-0.0)) || f4 (CST (0.0)))
+ if (f4 (w) || !f4 (NANS ("0x123")) || f4 (CST (42.0)) || f4 (NAN ("0x234"))
+ || f4 (INF) || f4 (-INF) || f4 (CST (-42.0)) || f4 (CST (-0.0)) || f4 (CST (0.0)))
__builtin_abort ();
- w = FN (__builtin_nans) ("");
+ w = NANS ("");
asm volatile ("" : : : "memory");
if (!f4 (w))
__builtin_abort ();
diff --git a/gcc/testsuite/gcc.dg/torture/floatn-basic.h b/gcc/testsuite/gcc.dg/torture/floatn-basic.h
index 9131f46..6540b53 100644
--- a/gcc/testsuite/gcc.dg/torture/floatn-basic.h
+++ b/gcc/testsuite/gcc.dg/torture/floatn-basic.h
@@ -9,14 +9,16 @@
#define CONCAT3(X, Y, Z) CONCAT (CONCAT (X, Y), Z)
#define CONCAT4(W, X, Y, Z) CONCAT (CONCAT (CONCAT (W, X), Y), Z)
-#if EXT
-# define TYPE CONCAT3 (_Float, WIDTH, x)
-# define CST(C) CONCAT4 (C, f, WIDTH, x)
-# define CSTU(C) CONCAT4 (C, F, WIDTH, x)
-#else
-# define TYPE CONCAT (_Float, WIDTH)
-# define CST(C) CONCAT3 (C, f, WIDTH)
-# define CSTU(C) CONCAT3 (C, F, WIDTH)
+#ifndef TYPE
+# if EXT
+# define TYPE CONCAT3 (_Float, WIDTH, x)
+# define CST(C) CONCAT4 (C, f, WIDTH, x)
+# define CSTU(C) CONCAT4 (C, F, WIDTH, x)
+# else
+# define TYPE CONCAT (_Float, WIDTH)
+# define CST(C) CONCAT3 (C, f, WIDTH)
+# define CSTU(C) CONCAT3 (C, F, WIDTH)
+# endif
#endif
extern void exit (int);
diff --git a/gcc/testsuite/gcc.dg/vect/pr107160.c b/gcc/testsuite/gcc.dg/vect/pr107160.c
new file mode 100644
index 0000000..4f9f853c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr107160.c
@@ -0,0 +1,41 @@
+/* { dg-do run } */
+
+#include <math.h>
+
+#define N 128
+float fl[N];
+
+__attribute__ ((noipa)) void
+init ()
+{
+ for (int i = 0; i < N; i++)
+ fl[i] = i;
+}
+
+__attribute__ ((noipa)) float
+foo (int n1)
+{
+ float sum0, sum1, sum2, sum3;
+ sum0 = sum1 = sum2 = sum3 = 0.0f;
+
+ int n = (n1 / 4) * 4;
+ for (int i = 0; i < n; i += 4)
+ {
+ sum0 += fabs (fl[i]);
+ sum1 += fabs (fl[i + 1]);
+ sum2 += fabs (fl[i + 2]);
+ sum3 += fabs (fl[i + 3]);
+ }
+
+ return sum0 + sum1 + sum2 + sum3;
+}
+
+int
+main ()
+{
+ init ();
+ float res = foo (80);
+ if (res != 3160)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.misc-tests/gcov-4.c b/gcc/testsuite/gcc.misc-tests/gcov-4.c
index 9d8ab1c..da7929e 100644
--- a/gcc/testsuite/gcc.misc-tests/gcov-4.c
+++ b/gcc/testsuite/gcc.misc-tests/gcov-4.c
@@ -110,6 +110,29 @@ lab2:
return 8; /* count(1) */
}
+int
+test_goto3 (int i, int j)
+{
+ if (j) goto else_; /* count(1) */
+
+top:
+ if (i) /* count(1) */
+ {
+ i = do_something (i);
+ }
+ else
+ {
+else_: /* count(1) */
+ j = do_something (j); /* count(2) */
+ if (j) /* count(2) */
+ {
+ j = 0; /* count(1) */
+ goto top; /* count(1) */
+ }
+ }
+ return 16;
+}
+
void
call_goto ()
{
@@ -117,6 +140,7 @@ call_goto ()
goto_val += test_goto1 (1);
goto_val += test_goto2 (3);
goto_val += test_goto2 (30);
+ goto_val += test_goto3 (0, 1);
}
/* Check nested if-then-else statements. */
@@ -221,7 +245,7 @@ test_switch (int i, int j)
{
case 1:
result = do_something (2); /* count(1) */
- break;
+ break; /* count(1) */
case 2:
result = do_something (1024);
break;
@@ -230,7 +254,7 @@ test_switch (int i, int j)
if (j == 2) /* count(3) */
return do_something (4); /* count(1) */
result = do_something (8); /* count(2) */
- break;
+ break; /* count(2) */
default:
result = do_something (32); /* count(1) */
switch_m++; /* count(1) */
@@ -260,7 +284,7 @@ main()
call_unref ();
if ((for_val1 != 12)
|| (for_val2 != 87)
- || (goto_val != 15)
+ || (goto_val != 31)
|| (ifelse_val1 != 31)
|| (ifelse_val2 != 23)
|| (ifelse_val3 != 246)
diff --git a/gcc/testsuite/gcc.target/aarch64/ands_2.c b/gcc/testsuite/gcc.target/aarch64/ands_2.c
index b061b1d..c8763f2 100644
--- a/gcc/testsuite/gcc.target/aarch64/ands_2.c
+++ b/gcc/testsuite/gcc.target/aarch64/ands_2.c
@@ -8,8 +8,7 @@ ands_si_test1 (int a, int b, int c)
{
int d = a & b;
- /* { dg-final { scan-assembler-not "ands\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+" } } */
- /* { dg-final { scan-assembler-times "and\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+" 2 } } */
+ /* { dg-final { scan-assembler "ands\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+" } } */
if (d <= 0)
return a + c;
else
@@ -21,12 +20,11 @@ ands_si_test2 (int a, int b, int c)
{
int d = a & 0x99999999;
- /* { dg-final { scan-assembler-not "ands\tw\[0-9\]+, w\[0-9\]+, -1717986919" } } */
- /* { dg-final { scan-assembler "and\tw\[0-9\]+, w\[0-9\]+, -1717986919" } } */
- if (d <= 0)
- return a + c;
- else
+ /* { dg-final { scan-assembler "ands\tw\[0-9\]+, w\[0-9\]+, -1717986919" } } */
+ if (d > 0)
return b + d + c;
+ else
+ return a + c;
}
int
@@ -34,8 +32,7 @@ ands_si_test3 (int a, int b, int c)
{
int d = a & (b << 3);
- /* { dg-final { scan-assembler-not "ands\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, lsl 3" } } */
- /* { dg-final { scan-assembler "and\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, lsl 3" } } */
+ /* { dg-final { scan-assembler "ands\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, lsl 3" } } */
if (d <= 0)
return a + c;
else
@@ -49,8 +46,7 @@ ands_di_test1 (s64 a, s64 b, s64 c)
{
s64 d = a & b;
- /* { dg-final { scan-assembler-not "ands\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+" } } */
- /* { dg-final { scan-assembler-times "and\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+" 2 } } */
+ /* { dg-final { scan-assembler "ands\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+" } } */
if (d <= 0)
return a + c;
else
@@ -62,12 +58,11 @@ ands_di_test2 (s64 a, s64 b, s64 c)
{
s64 d = a & 0xaaaaaaaaaaaaaaaall;
- /* { dg-final { scan-assembler-not "ands\tx\[0-9\]+, x\[0-9\]+, -6148914691236517206" } } */
- /* { dg-final { scan-assembler "and\tx\[0-9\]+, x\[0-9\]+, -6148914691236517206" } } */
- if (d <= 0)
- return a + c;
- else
+ /* { dg-final { scan-assembler "ands\tx\[0-9\]+, x\[0-9\]+, -6148914691236517206" } } */
+ if (d > 0)
return b + d + c;
+ else
+ return a + c;
}
s64
@@ -75,8 +70,7 @@ ands_di_test3 (s64 a, s64 b, s64 c)
{
s64 d = a & (b << 3);
- /* { dg-final { scan-assembler-not "ands\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, lsl 3" } } */
- /* { dg-final { scan-assembler "and\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, lsl 3" } } */
+ /* { dg-final { scan-assembler "ands\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, lsl 3" } } */
if (d <= 0)
return a + c;
else
diff --git a/gcc/testsuite/gcc.target/aarch64/bics_2.c b/gcc/testsuite/gcc.target/aarch64/bics_2.c
index 9ccae36..c1f7e87 100644
--- a/gcc/testsuite/gcc.target/aarch64/bics_2.c
+++ b/gcc/testsuite/gcc.target/aarch64/bics_2.c
@@ -8,8 +8,7 @@ bics_si_test1 (int a, int b, int c)
{
int d = a & ~b;
- /* { dg-final { scan-assembler-not "bics\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+" } } */
- /* { dg-final { scan-assembler-times "bic\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+" 2 } } */
+ /* { dg-final { scan-assembler "bics\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+" } } */
if (d <= 0)
return a + c;
else
@@ -21,12 +20,11 @@ bics_si_test2 (int a, int b, int c)
{
int d = a & ~(b << 3);
- /* { dg-final { scan-assembler-not "bics\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, lsl 3" } } */
- /* { dg-final { scan-assembler "bic\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, lsl 3" } } */
- if (d <= 0)
- return a + c;
- else
+ /* { dg-final { scan-assembler "bics\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, lsl 3" } } */
+ if (d > 0)
return b + d + c;
+ else
+ return a + c;
}
typedef long long s64;
@@ -36,8 +34,7 @@ bics_di_test1 (s64 a, s64 b, s64 c)
{
s64 d = a & ~b;
- /* { dg-final { scan-assembler-not "bics\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+" } } */
- /* { dg-final { scan-assembler-times "bic\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+" 2 } } */
+ /* { dg-final { scan-assembler "bics\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+" } } */
if (d <= 0)
return a + c;
else
@@ -49,12 +46,11 @@ bics_di_test2 (s64 a, s64 b, s64 c)
{
s64 d = a & ~(b << 3);
- /* { dg-final { scan-assembler-not "bics\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, lsl 3" } } */
- /* { dg-final { scan-assembler "bic\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, lsl 3" } } */
- if (d <= 0)
- return a + c;
- else
+ /* { dg-final { scan-assembler "bics\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, lsl 3" } } */
+ if (d > 0)
return b + d + c;
+ else
+ return a + c;
}
int
diff --git a/gcc/testsuite/gcc.target/aarch64/tst_2.c b/gcc/testsuite/gcc.target/aarch64/tst_2.c
index c8b28fc..3c9bdfd 100644
--- a/gcc/testsuite/gcc.target/aarch64/tst_2.c
+++ b/gcc/testsuite/gcc.target/aarch64/tst_2.c
@@ -8,8 +8,7 @@ tst_si_test1 (int a, int b, int c)
{
int d = a & b;
- /* { dg-final { scan-assembler-not "tst\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+" } } */
- /* { dg-final { scan-assembler-times "and\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+" 2 } } */
+ /* { dg-final { scan-assembler "tst\tw\[0-9\]+, w\[0-9\]+" } } */
if (d <= 0)
return 12;
else
@@ -21,12 +20,11 @@ tst_si_test2 (int a, int b, int c)
{
int d = a & 0x99999999;
- /* { dg-final { scan-assembler-not "tst\tw\[0-9\]+, w\[0-9\]+, -1717986919" } } */
- /* { dg-final { scan-assembler "and\tw\[0-9\]+, w\[0-9\]+, -1717986919" } } */
- if (d <= 0)
- return 12;
- else
+ /* { dg-final { scan-assembler "tst\tw\[0-9\]+, -1717986919" } } */
+ if (d > 0)
return 18;
+ else
+ return 12;
}
int
@@ -34,8 +32,7 @@ tst_si_test3 (int a, int b, int c)
{
int d = a & (b << 3);
- /* { dg-final { scan-assembler-not "tst\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, lsl 3" } } */
- /* { dg-final { scan-assembler "and\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, lsl 3" } } */
+ /* { dg-final { scan-assembler "tst\tw\[0-9\]+, w\[0-9\]+, lsl 3" } } */
if (d <= 0)
return 12;
else
@@ -49,8 +46,7 @@ tst_di_test1 (s64 a, s64 b, s64 c)
{
s64 d = a & b;
- /* { dg-final { scan-assembler-not "tst\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+" } } */
- /* { dg-final { scan-assembler-times "and\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+" 2 } } */
+ /* { dg-final { scan-assembler "tst\tx\[0-9\]+, x\[0-9\]+" } } */
if (d <= 0)
return 12;
else
@@ -62,8 +58,7 @@ tst_di_test2 (s64 a, s64 b, s64 c)
{
s64 d = a & 0xaaaaaaaaaaaaaaaall;
- /* { dg-final { scan-assembler-not "tst\tx\[0-9\]+, x\[0-9\]+, -6148914691236517206" } } */
- /* { dg-final { scan-assembler "and\tx\[0-9\]+, x\[0-9\]+, -6148914691236517206" } } */
+ /* { dg-final { scan-assembler "tst\tx\[0-9\]+, -6148914691236517206" } } */
if (d <= 0)
return 12;
else
@@ -75,12 +70,11 @@ tst_di_test3 (s64 a, s64 b, s64 c)
{
s64 d = a & (b << 3);
- /* { dg-final { scan-assembler-not "tst\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, lsl 3" } } */
- /* { dg-final { scan-assembler "and\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, lsl 3" } } */
- if (d <= 0)
- return 12;
- else
+ /* { dg-final { scan-assembler "tst\tx\[0-9\]+, x\[0-9\]+, lsl 3" } } */
+ if (d > 0)
return 18;
+ else
+ return 12;
}
int
diff --git a/gcc/testsuite/gcc.target/aarch64/tst_imm_split_1.c b/gcc/testsuite/gcc.target/aarch64/tst_imm_split_1.c
index 33a2c0f..e456e82 100644
--- a/gcc/testsuite/gcc.target/aarch64/tst_imm_split_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/tst_imm_split_1.c
@@ -14,5 +14,4 @@ g (unsigned char *p)
}
/* { dg-final { scan-assembler-not "and\\t\[xw\]\[0-9\]+, \[xw\]\[0-9\]+.*" } } */
-/* { dg-final { scan-assembler "tst\\t\[xw\]\[0-9\]+, \[xw\]\[0-9\]+" } } */
-/* { dg-final { scan-assembler "tst\\t\[xw\]\[0-9\]+, \[xw\]\[0-9\]+, lsr 4" } } */
+/* { dg-final { scan-assembler-times "tst\\t\[xw\]\[0-9\]+, \[xw\]\[0-9\]+" 2 } } */
diff --git a/gcc/testsuite/gcc.target/i386/excess-precision-1.c b/gcc/testsuite/gcc.target/i386/excess-precision-1.c
index 1bd3b88..388cee7 100644
--- a/gcc/testsuite/gcc.target/i386/excess-precision-1.c
+++ b/gcc/testsuite/gcc.target/i386/excess-precision-1.c
@@ -5,8 +5,14 @@
#include <float.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
extern void abort (void);
extern void exit (int);
+#ifdef __cplusplus
+}
+#endif
volatile float f1 = 1.0f;
volatile float f2 = 0x1.0p-30f;
diff --git a/gcc/testsuite/gcc.target/i386/excess-precision-10.c b/gcc/testsuite/gcc.target/i386/excess-precision-10.c
index f1b9b7e..1dd3e7a 100644
--- a/gcc/testsuite/gcc.target/i386/excess-precision-10.c
+++ b/gcc/testsuite/gcc.target/i386/excess-precision-10.c
@@ -3,8 +3,14 @@
/* { dg-do run } */
/* { dg-options "-std=c11 -mfpmath=387 -fexcess-precision=standard" } */
+#ifdef __cplusplus
+extern "C" {
+#endif
extern void abort (void);
extern void exit (int);
+#ifdef __cplusplus
+}
+#endif
int
main (void)
diff --git a/gcc/testsuite/gcc.target/i386/excess-precision-2.c b/gcc/testsuite/gcc.target/i386/excess-precision-2.c
index b5035e5..c14784e 100644
--- a/gcc/testsuite/gcc.target/i386/excess-precision-2.c
+++ b/gcc/testsuite/gcc.target/i386/excess-precision-2.c
@@ -4,8 +4,14 @@
#include <float.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
extern void abort (void);
extern void exit (int);
+#ifdef __cplusplus
+}
+#endif
volatile long double ldadd1 = 1.0l + 0x1.0p-30l;
volatile long double ld11f = 1.1f;
diff --git a/gcc/testsuite/gcc.target/i386/excess-precision-3.c b/gcc/testsuite/gcc.target/i386/excess-precision-3.c
index 1fd038a..e8e9abc 100644
--- a/gcc/testsuite/gcc.target/i386/excess-precision-3.c
+++ b/gcc/testsuite/gcc.target/i386/excess-precision-3.c
@@ -6,8 +6,14 @@
#include <float.h>
#include <stdarg.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
extern void abort (void);
extern void exit (int);
+#ifdef __cplusplus
+}
+#endif
volatile float f1 = 1.0f;
volatile float f2 = 0x1.0p-30f;
@@ -100,6 +106,7 @@ check_double (double d)
abort ();
}
+#ifndef __cplusplus
static inline void
check_float_nonproto (f)
float f;
@@ -115,6 +122,7 @@ check_double_nonproto (d)
if (d != dadd2)
abort ();
}
+#endif
static void
check_double_va (int i, ...)
@@ -132,9 +140,11 @@ test_call (void)
check_float (f1 + f2);
check_double (d1 + d2 + d3);
check_double (f1 + f2 + f3);
+#ifndef __cplusplus
check_float_nonproto (f1 + f2);
check_double_nonproto (d1 + d2 + d3);
check_double_nonproto (f1 + f2 + f3);
+#endif
check_double_va (0, d1 + d2 + d3);
check_double_va (0, f1 + f2 + f3);
}
diff --git a/gcc/testsuite/gcc.target/i386/excess-precision-7.c b/gcc/testsuite/gcc.target/i386/excess-precision-7.c
index 0cdd932..4c3b950 100644
--- a/gcc/testsuite/gcc.target/i386/excess-precision-7.c
+++ b/gcc/testsuite/gcc.target/i386/excess-precision-7.c
@@ -4,8 +4,14 @@
/* { dg-do run } */
/* { dg-options "-std=c99 -mfpmath=387 -fexcess-precision=standard" } */
+#ifdef __cplusplus
+extern "C" {
+#endif
extern void abort (void);
extern void exit (int);
+#ifdef __cplusplus
+}
+#endif
int
main (void)
diff --git a/gcc/testsuite/gcc.target/i386/excess-precision-8.c b/gcc/testsuite/gcc.target/i386/excess-precision-8.c
index c0a31ed..8dd0458 100644
--- a/gcc/testsuite/gcc.target/i386/excess-precision-8.c
+++ b/gcc/testsuite/gcc.target/i386/excess-precision-8.c
@@ -4,8 +4,14 @@
/* { dg-do run } */
/* { dg-options "-std=c11 -mfpmath=387 -fexcess-precision=standard" } */
+#ifdef __cplusplus
+extern "C" {
+#endif
extern void abort (void);
extern void exit (int);
+#ifdef __cplusplus
+}
+#endif
int
main (void)
diff --git a/gcc/testsuite/gcc.target/i386/excess-precision-9.c b/gcc/testsuite/gcc.target/i386/excess-precision-9.c
index 61e5fc1..5008164 100644
--- a/gcc/testsuite/gcc.target/i386/excess-precision-9.c
+++ b/gcc/testsuite/gcc.target/i386/excess-precision-9.c
@@ -3,8 +3,14 @@
/* { dg-do run } */
/* { dg-options "-std=c99 -mfpmath=387 -fexcess-precision=standard" } */
+#ifdef __cplusplus
+extern "C" {
+#endif
extern void abort (void);
extern void exit (int);
+#ifdef __cplusplus
+}
+#endif
int
main (void)
diff --git a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c
index 52b53b9..d1a76db 100644
--- a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c
+++ b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c
@@ -12,8 +12,8 @@ double is_a_double;
float *float_ptr;
-__bf16 foo1 (void) { return (__bf16) 0x1234; } /* { dg-error {invalid conversion to type '__bf16'} } */
-__bf16 foo2 (void) { return (__bf16) (short) 0x1234; } /* { dg-error {invalid conversion to type '__bf16'} } */
+__bf16 foo1 (void) { return (__bf16) 0x1234; }
+__bf16 foo2 (void) { return (__bf16) (short) 0x1234; }
__bf16 footest (__bf16 scalar0)
{
@@ -22,87 +22,87 @@ __bf16 footest (__bf16 scalar0)
__bf16 scalar1_1;
__bf16 scalar1_2 = glob_bfloat;
- __bf16 scalar1_3 = 0; /* { dg-error {invalid conversion to type '__bf16'} } */
- __bf16 scalar1_4 = 0.1; /* { dg-error {invalid conversion to type '__bf16'} } */
- __bf16 scalar1_5 = is_a_float; /* { dg-error {invalid conversion to type '__bf16'} } */
- __bf16 scalar1_6 = is_an_int; /* { dg-error {invalid conversion to type '__bf16'} } */
- __bf16 scalar1_7 = is_a_float16; /* { dg-error {invalid conversion to type '__bf16'} } */
- __bf16 scalar1_8 = is_a_double; /* { dg-error {invalid conversion to type '__bf16'} } */
- __bf16 scalar1_9 = is_a_short_int; /* { dg-error {invalid conversion to type '__bf16'} } */
-
- int initi_1_1 = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */
- float initi_1_2 = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */
- _Float16 initi_1_3 = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */
- short initi_1_4 = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */
- double initi_1_5 = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */
+ __bf16 scalar1_3 = 0;
+ __bf16 scalar1_4 = 0.1;
+ __bf16 scalar1_5 = is_a_float;
+ __bf16 scalar1_6 = is_an_int;
+ __bf16 scalar1_7 = is_a_float16;
+ __bf16 scalar1_8 = is_a_double;
+ __bf16 scalar1_9 = is_a_short_int;
+
+ int initi_1_1 = glob_bfloat;
+ float initi_1_2 = glob_bfloat;
+ _Float16 initi_1_3 = glob_bfloat;
+ short initi_1_4 = glob_bfloat;
+ double initi_1_5 = glob_bfloat;
__bf16 scalar2_1 = {};
__bf16 scalar2_2 = { glob_bfloat };
- __bf16 scalar2_3 = { 0 }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __bf16 scalar2_4 = { 0.1 }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __bf16 scalar2_5 = { is_a_float }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __bf16 scalar2_6 = { is_an_int }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __bf16 scalar2_7 = { is_a_float16 }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __bf16 scalar2_8 = { is_a_double }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __bf16 scalar2_9 = { is_a_short_int }; /* { dg-error {invalid conversion to type '__bf16'} } */
-
- int initi_2_1 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- float initi_2_2 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- _Float16 initi_2_3 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- short initi_2_4 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- double initi_2_5 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
+ __bf16 scalar2_3 = { 0 };
+ __bf16 scalar2_4 = { 0.1 };
+ __bf16 scalar2_5 = { is_a_float };
+ __bf16 scalar2_6 = { is_an_int };
+ __bf16 scalar2_7 = { is_a_float16 };
+ __bf16 scalar2_8 = { is_a_double };
+ __bf16 scalar2_9 = { is_a_short_int };
+
+ int initi_2_1 = { glob_bfloat };
+ float initi_2_2 = { glob_bfloat };
+ _Float16 initi_2_3 = { glob_bfloat };
+ short initi_2_4 = { glob_bfloat };
+ double initi_2_5 = { glob_bfloat };
/* Assignments. */
glob_bfloat = glob_bfloat;
- glob_bfloat = 0; /* { dg-error {invalid conversion to type '__bf16'} } */
- glob_bfloat = 0.1; /* { dg-error {invalid conversion to type '__bf16'} } */
- glob_bfloat = is_a_float; /* { dg-error {invalid conversion to type '__bf16'} } */
- glob_bfloat = is_an_int; /* { dg-error {invalid conversion to type '__bf16'} } */
- glob_bfloat = is_a_float16; /* { dg-error {invalid conversion to type '__bf16'} } */
- glob_bfloat = is_a_double; /* { dg-error {invalid conversion to type '__bf16'} } */
- glob_bfloat = is_a_short_int; /* { dg-error {invalid conversion to type '__bf16'} } */
-
- is_an_int = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */
- is_a_float = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */
- is_a_float16 = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */
- is_a_double = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */
- is_a_short_int = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */
+ glob_bfloat = 0;
+ glob_bfloat = 0.1;
+ glob_bfloat = is_a_float;
+ glob_bfloat = is_an_int;
+ glob_bfloat = is_a_float16;
+ glob_bfloat = is_a_double;
+ glob_bfloat = is_a_short_int;
+
+ is_an_int = glob_bfloat;
+ is_a_float = glob_bfloat;
+ is_a_float16 = glob_bfloat;
+ is_a_double = glob_bfloat;
+ is_a_short_int = glob_bfloat;
/* Casting. */
(void) glob_bfloat;
(__bf16) glob_bfloat;
- (int) glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */
- (float) glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */
- (_Float16) glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */
- (double) glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */
- (short) glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */
+ (int) glob_bfloat;
+ (float) glob_bfloat;
+ (_Float16) glob_bfloat;
+ (double) glob_bfloat;
+ (short) glob_bfloat;
- (__bf16) is_an_int; /* { dg-error {invalid conversion to type '__bf16'} } */
- (__bf16) is_a_float; /* { dg-error {invalid conversion to type '__bf16'} } */
- (__bf16) is_a_float16; /* { dg-error {invalid conversion to type '__bf16'} } */
- (__bf16) is_a_double; /* { dg-error {invalid conversion to type '__bf16'} } */
- (__bf16) is_a_short_int; /* { dg-error {invalid conversion to type '__bf16'} } */
+ (__bf16) is_an_int;
+ (__bf16) is_a_float;
+ (__bf16) is_a_float16;
+ (__bf16) is_a_double;
+ (__bf16) is_a_short_int;
/* Compound literals. */
(__bf16) {};
(__bf16) { glob_bfloat };
- (__bf16) { 0 }; /* { dg-error {invalid conversion to type '__bf16'} } */
- (__bf16) { 0.1 }; /* { dg-error {invalid conversion to type '__bf16'} } */
- (__bf16) { is_a_float }; /* { dg-error {invalid conversion to type '__bf16'} } */
- (__bf16) { is_an_int }; /* { dg-error {invalid conversion to type '__bf16'} } */
- (__bf16) { is_a_float16 }; /* { dg-error {invalid conversion to type '__bf16'} } */
- (__bf16) { is_a_double }; /* { dg-error {invalid conversion to type '__bf16'} } */
- (__bf16) { is_a_short_int }; /* { dg-error {invalid conversion to type '__bf16'} } */
-
- (int) { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- (float) { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- (_Float16) { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- (double) { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- (short) { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
+ (__bf16) { 0 };
+ (__bf16) { 0.1 };
+ (__bf16) { is_a_float };
+ (__bf16) { is_an_int };
+ (__bf16) { is_a_float16 };
+ (__bf16) { is_a_double };
+ (__bf16) { is_a_short_int };
+
+ (int) { glob_bfloat };
+ (float) { glob_bfloat };
+ (_Float16) { glob_bfloat };
+ (double) { glob_bfloat };
+ (short) { glob_bfloat };
/* Arrays and Structs. */
@@ -145,16 +145,16 @@ __bf16 footest (__bf16 scalar0)
bfloat_ptr = &bfloat_ptr3[1];
/* Simple comparison. */
- scalar0 > glob_bfloat; /* { dg-error {operation not permitted on type '__bf16'} } */
- glob_bfloat == scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */
- scalar0 > is_a_float; /* { dg-error {operation not permitted on type '__bf16'} } */
- is_a_float == scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */
- scalar0 > 0; /* { dg-error {operation not permitted on type '__bf16'} } */
- 0 == scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */
- scalar0 > 0.1; /* { dg-error {operation not permitted on type '__bf16'} } */
- 0.1 == scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */
- scalar0 > is_an_int; /* { dg-error {operation not permitted on type '__bf16'} } */
- is_an_int == scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */
+ scalar0 > glob_bfloat;
+ glob_bfloat == scalar0;
+ scalar0 > is_a_float;
+ is_a_float == scalar0;
+ scalar0 > 0;
+ 0 == scalar0;
+ scalar0 > 0.1;
+ 0.1 == scalar0;
+ scalar0 > is_an_int;
+ is_an_int == scalar0;
/* Pointer comparison. */
@@ -174,41 +174,41 @@ __bf16 footest (__bf16 scalar0)
/* Conditional expressions. */
0 ? scalar0 : scalar0;
- 0 ? scalar0 : is_a_float; /* { dg-error {invalid conversion from type '__bf16'} } */
- 0 ? is_a_float : scalar0; /* { dg-error {invalid conversion from type '__bf16'} } */
- 0 ? scalar0 : 0; /* { dg-error {invalid conversion to type '__bf16'} } */
- 0 ? 0 : scalar0; /* { dg-error {invalid conversion to type '__bf16'} } */
- 0 ? 0.1 : scalar0; /* { dg-error {invalid conversion from type '__bf16'} } */
- 0 ? scalar0 : 0.1; /* { dg-error {invalid conversion from type '__bf16'} } */
+ 0 ? scalar0 : is_a_float;
+ 0 ? is_a_float : scalar0;
+ 0 ? scalar0 : 0;
+ 0 ? 0 : scalar0;
+ 0 ? 0.1 : scalar0;
+ 0 ? scalar0 : 0.1;
0 ? bfloat_ptr : bfloat_ptr2;
0 ? bfloat_ptr : float_ptr; /* { dg-warning {pointer type mismatch in conditional expression} } */
0 ? float_ptr : bfloat_ptr; /* { dg-warning {pointer type mismatch in conditional expression} } */
- scalar0 ? scalar0 : scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */
- scalar0 ? is_a_float : scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */
- scalar0 ? scalar0 : is_a_float; /* { dg-error {operation not permitted on type '__bf16'} } */
- scalar0 ? is_a_float : is_a_float; /* { dg-error {operation not permitted on type '__bf16'} } */
+ scalar0 ? scalar0 : scalar0;
+ scalar0 ? is_a_float : scalar0;
+ scalar0 ? scalar0 : is_a_float;
+ scalar0 ? is_a_float : is_a_float;
/* Unary operators. */
- +scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */
- -scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */
- ~scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */
- !scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */
+ +scalar0;
+ -scalar0;
+ ~scalar0; /* { dg-error {wrong type argument to bit-complement} } */
+ !scalar0;
*scalar0; /* { dg-error {invalid type argument of unary '\*'} } */
- __real scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */
- __imag scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */
- ++scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */
- --scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */
- scalar0++; /* { dg-error {operation not permitted on type '__bf16'} } */
- scalar0--; /* { dg-error {operation not permitted on type '__bf16'} } */
+ __real scalar0;
+ __imag scalar0;
+ ++scalar0;
+ --scalar0;
+ scalar0++;
+ scalar0--;
/* Binary arithmetic operations. */
- scalar0 = glob_bfloat + *bfloat_ptr; /* { dg-error {operation not permitted on type '__bf16'} } */
- scalar0 = glob_bfloat + 0.1; /* { dg-error {operation not permitted on type '__bf16'} } */
- scalar0 = glob_bfloat + 0; /* { dg-error {operation not permitted on type '__bf16'} } */
- scalar0 = glob_bfloat + is_a_float; /* { dg-error {operation not permitted on type '__bf16'} } */
+ scalar0 = glob_bfloat + *bfloat_ptr;
+ scalar0 = glob_bfloat + 0.1;
+ scalar0 = glob_bfloat + 0;
+ scalar0 = glob_bfloat + is_a_float;
return scalar0;
}
diff --git a/gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_1.c b/gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_1.c
index 3804bac..8bc3f4a 100644
--- a/gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_1.c
+++ b/gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_1.c
@@ -48,20 +48,20 @@ __m128bf16 footest (__m128bf16 vector0)
__m128bf16 vector2_1 = {};
__m128bf16 vector2_2 = { glob_bfloat };
__m128bf16 vector2_3 = { glob_bfloat, glob_bfloat, glob_bfloat, glob_bfloat };
- __m128bf16 vector2_4 = { 0 }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __m128bf16 vector2_5 = { 0.1 }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __m128bf16 vector2_6 = { is_a_float16 }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __m128bf16 vector2_7 = { is_a_float }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __m128bf16 vector2_8 = { is_an_int }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __m128bf16 vector2_9 = { is_a_short_int }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __m128bf16 vector2_10 = { 0.0, 0, is_a_short_int, is_a_float }; /* { dg-error {invalid conversion to type '__bf16'} } */
-
- __v8si initi_2_1 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- __m256 initi_2_2 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- __m128h initi_2_3 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- __m128 initi_2_4 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- __v4si initi_2_5 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- __v4hi initi_2_6 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
+ __m128bf16 vector2_4 = { 0 };
+ __m128bf16 vector2_5 = { 0.1 };
+ __m128bf16 vector2_6 = { is_a_float16 };
+ __m128bf16 vector2_7 = { is_a_float };
+ __m128bf16 vector2_8 = { is_an_int };
+ __m128bf16 vector2_9 = { is_a_short_int };
+ __m128bf16 vector2_10 = { 0.0, 0, is_a_short_int, is_a_float };
+
+ __v8si initi_2_1 = { glob_bfloat };
+ __m256 initi_2_2 = { glob_bfloat };
+ __m128h initi_2_3 = { glob_bfloat };
+ __m128 initi_2_4 = { glob_bfloat };
+ __v4si initi_2_5 = { glob_bfloat };
+ __v4hi initi_2_6 = { glob_bfloat };
/* Assignments to/from vectors. */
@@ -85,25 +85,25 @@ __m128bf16 footest (__m128bf16 vector0)
/* Assignments to/from elements. */
vector2_3[0] = glob_bfloat;
- vector2_3[0] = is_an_int; /* { dg-error {invalid conversion to type '__bf16'} } */
- vector2_3[0] = is_a_short_int; /* { dg-error {invalid conversion to type '__bf16'} } */
- vector2_3[0] = is_a_float; /* { dg-error {invalid conversion to type '__bf16'} } */
- vector2_3[0] = is_a_float16; /* { dg-error {invalid conversion to type '__bf16'} } */
- vector2_3[0] = 0; /* { dg-error {invalid conversion to type '__bf16'} } */
- vector2_3[0] = 0.1; /* { dg-error {invalid conversion to type '__bf16'} } */
+ vector2_3[0] = is_an_int;
+ vector2_3[0] = is_a_short_int;
+ vector2_3[0] = is_a_float;
+ vector2_3[0] = is_a_float16;
+ vector2_3[0] = 0;
+ vector2_3[0] = 0.1;
glob_bfloat = vector2_3[0];
- is_an_int = vector2_3[0]; /* { dg-error {invalid conversion from type '__bf16'} } */
- is_a_short_int = vector2_3[0]; /* { dg-error {invalid conversion from type '__bf16'} } */
- is_a_float = vector2_3[0]; /* { dg-error {invalid conversion from type '__bf16'} } */
- is_a_float16 = vector2_3[0]; /* { dg-error {invalid conversion from type '__bf16'} } */
+ is_an_int = vector2_3[0];
+ is_a_short_int = vector2_3[0];
+ is_a_float = vector2_3[0];
+ is_a_float16 = vector2_3[0];
/* Compound literals. */
(__m128bf16) {};
- (__m128bf16) { 0 }; /* { dg-error {invalid conversion to type '__bf16'} } */
- (__m128bf16) { 0.1 }; /* { dg-error {invalid conversion to type '__bf16'} } */
+ (__m128bf16) { 0 };
+ (__m128bf16) { 0.1 };
(__m128bf16) { is_a_float_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type '__m256'} } */
(__m128bf16) { is_an_int_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type '__v8si'} } */
(__m128bf16) { is_a_float_pair }; /* { dg-error {incompatible types when initializing type '__bf16' using type '__m128'} } */
@@ -186,16 +186,16 @@ __m128bf16 footest (__m128bf16 vector0)
bfloat_ptr = &bfloat_ptr3[1];
/* Simple comparison. */
- vector0 > glob_bfloat_vec; /* { dg-error {operation not permitted on type '__bf16'} } */
- glob_bfloat_vec == vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0 > is_a_float_vec; /* { dg-error {operation not permitted on type '__bf16'} } */
- is_a_float_vec == vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0 > 0; /* { dg-error {operation not permitted on type '__bf16'} } */
- 0 == vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0 > 0.1; /* { dg-error {operation not permitted on type '__bf16'} } */
- 0.1 == vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0 > is_an_int_vec; /* { dg-error {operation not permitted on type '__bf16'} } */
- is_an_int_vec == vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
+ vector0 > glob_bfloat_vec;
+ glob_bfloat_vec == vector0;
+ vector0 > is_a_float_vec; /* { dg-error {comparing vectors with different element types} } */
+ is_a_float_vec == vector0; /* { dg-error {comparing vectors with different element types} } */
+ vector0 > 0;
+ 0 == vector0;
+ vector0 > 0.1; /* { dg-error {conversion of scalar 'double' to vector '__m128bf16'} } */
+ 0.1 == vector0; /* { dg-error {conversion of scalar 'double' to vector '__m128bf16'} } */
+ vector0 > is_an_int_vec; /* { dg-error {comparing vectors with different element types} } */
+ is_an_int_vec == vector0; /* { dg-error {comparing vectors with different element types} } */
/* Pointer comparison. */
@@ -234,24 +234,24 @@ __m128bf16 footest (__m128bf16 vector0)
/* Unary operators. */
- +vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- -vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- ~vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- !vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
+ +vector0;
+ -vector0;
+ ~vector0; /* { dg-error {wrong type argument to bit-complement} } */
+ !vector0; /* { dg-error {wrong type argument to unary exclamation mark} } */
*vector0; /* { dg-error {invalid type argument of unary '\*'} } */
- __real vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- __imag vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- ++vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- --vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0++; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0--; /* { dg-error {operation not permitted on type '__bf16'} } */
+ __real vector0; /* { dg-error {wrong type argument to __real} } */
+ __imag vector0; /* { dg-error {wrong type argument to __imag} } */
+ ++vector0;
+ --vector0;
+ vector0++;
+ vector0--;
/* Binary arithmetic operations. */
- vector0 = glob_bfloat_vec + *bfloat_ptr; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0 = glob_bfloat_vec + 0.1; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0 = glob_bfloat_vec + 0; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0 = glob_bfloat_vec + is_a_float_vec; /* { dg-error {operation not permitted on type '__bf16'} } */
+ vector0 = glob_bfloat_vec + *bfloat_ptr;
+ vector0 = glob_bfloat_vec + 0.1; /* { dg-error {conversion of scalar 'double' to vector '__m128bf16'} } */
+ vector0 = glob_bfloat_vec + 0;
+ vector0 = glob_bfloat_vec + is_a_float_vec; /* { dg-error {invalid operands to binary \+} } */
return vector0;
}
diff --git a/gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_2.c b/gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_2.c
index f63b41d8..2a8a535 100644
--- a/gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_2.c
+++ b/gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_2.c
@@ -45,19 +45,19 @@ __m256bf16 footest (__m256bf16 vector0)
__m256bf16 vector2_1 = {};
__m256bf16 vector2_2 = { glob_bfloat };
__m256bf16 vector2_3 = { glob_bfloat, glob_bfloat, glob_bfloat, glob_bfloat };
- __m256bf16 vector2_4 = { 0 }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __m256bf16 vector2_5 = { 0.1 }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __m256bf16 vector2_6 = { is_a_float16 }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __m256bf16 vector2_7 = { is_a_float }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __m256bf16 vector2_8 = { is_an_int }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __m256bf16 vector2_9 = { is_a_short_int }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __m256bf16 vector2_10 = { 0.0, 0, is_a_short_int, is_a_float }; /* { dg-error "invalid conversion to type '__bf16'" } */
-
- __v8si initi_2_1 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- __m256 initi_2_2 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- __m256h initi_2_3 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- __m256i initi_2_5 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- __v16hi initi_2_6 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
+ __m256bf16 vector2_4 = { 0 };
+ __m256bf16 vector2_5 = { 0.1 };
+ __m256bf16 vector2_6 = { is_a_float16 };
+ __m256bf16 vector2_7 = { is_a_float };
+ __m256bf16 vector2_8 = { is_an_int };
+ __m256bf16 vector2_9 = { is_a_short_int };
+ __m256bf16 vector2_10 = { 0.0, 0, is_a_short_int, is_a_float };
+
+ __v8si initi_2_1 = { glob_bfloat };
+ __m256 initi_2_2 = { glob_bfloat };
+ __m256h initi_2_3 = { glob_bfloat };
+ __m256i initi_2_5 = { glob_bfloat };
+ __v16hi initi_2_6 = { glob_bfloat };
/* Assignments to/from vectors. */
@@ -79,25 +79,25 @@ __m256bf16 footest (__m256bf16 vector0)
/* Assignments to/from elements. */
vector2_3[0] = glob_bfloat;
- vector2_3[0] = is_an_int; /* { dg-error {invalid conversion to type '__bf16'} } */
- vector2_3[0] = is_a_short_int; /* { dg-error {invalid conversion to type '__bf16'} } */
- vector2_3[0] = is_a_float; /* { dg-error {invalid conversion to type '__bf16'} } */
- vector2_3[0] = is_a_float16; /* { dg-error {invalid conversion to type '__bf16'} } */
- vector2_3[0] = 0; /* { dg-error {invalid conversion to type '__bf16'} } */
- vector2_3[0] = 0.1; /* { dg-error {invalid conversion to type '__bf16'} } */
+ vector2_3[0] = is_an_int;
+ vector2_3[0] = is_a_short_int;
+ vector2_3[0] = is_a_float;
+ vector2_3[0] = is_a_float16;
+ vector2_3[0] = 0;
+ vector2_3[0] = 0.1;
glob_bfloat = vector2_3[0];
- is_an_int = vector2_3[0]; /* { dg-error {invalid conversion from type '__bf16'} } */
- is_a_short_int = vector2_3[0]; /* { dg-error {invalid conversion from type '__bf16'} } */
- is_a_float = vector2_3[0]; /* { dg-error {invalid conversion from type '__bf16'} } */
- is_a_float16 = vector2_3[0]; /* { dg-error {invalid conversion from type '__bf16'} } */
+ is_an_int = vector2_3[0];
+ is_a_short_int = vector2_3[0];
+ is_a_float = vector2_3[0];
+ is_a_float16 = vector2_3[0];
/* Compound literals. */
(__m256bf16) {};
- (__m256bf16) { 0 }; /* { dg-error {invalid conversion to type '__bf16'} } */
- (__m256bf16) { 0.1 }; /* { dg-error {invalid conversion to type '__bf16'} } */
+ (__m256bf16) { 0 };
+ (__m256bf16) { 0.1 };
(__m256bf16) { is_a_float_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type '__m256'} } */
(__m256bf16) { is_an_int_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type '__v8si'} } */
(__m256bf16) { is_a_long_int_pair }; /* { dg-error {incompatible types when initializing type '__bf16' using type '__m256i'} } */
@@ -176,16 +176,16 @@ __m256bf16 footest (__m256bf16 vector0)
bfloat_ptr = &bfloat_ptr3[1];
/* Simple comparison. */
- vector0 > glob_bfloat_vec; /* { dg-error {operation not permitted on type '__bf16'} } */
- glob_bfloat_vec == vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0 > is_a_float_vec; /* { dg-error {operation not permitted on type '__bf16'} } */
- is_a_float_vec == vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0 > 0; /* { dg-error {operation not permitted on type '__bf16'} } */
- 0 == vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0 > 0.1; /* { dg-error {operation not permitted on type '__bf16'} } */
- 0.1 == vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0 > is_an_int_vec; /* { dg-error {operation not permitted on type '__bf16'} } */
- is_an_int_vec == vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
+ vector0 > glob_bfloat_vec;
+ glob_bfloat_vec == vector0;
+ vector0 > is_a_float_vec; /* { dg-error {comparing vectors with different element types} } */
+ is_a_float_vec == vector0; /* { dg-error {comparing vectors with different element types} } */
+ vector0 > 0;
+ 0 == vector0;
+ vector0 > 0.1; /* { dg-error {conversion of scalar 'double' to vector '__m256bf16'} } */
+ 0.1 == vector0; /* { dg-error {conversion of scalar 'double' to vector '__m256bf16'} } */
+ vector0 > is_an_int_vec; /* { dg-error {comparing vectors with different element types} } */
+ is_an_int_vec == vector0; /* { dg-error {comparing vectors with different element types} } */
/* Pointer comparison. */
@@ -224,24 +224,24 @@ __m256bf16 footest (__m256bf16 vector0)
/* Unary operators. */
- +vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- -vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- ~vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- !vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
+ +vector0;
+ -vector0;
+ ~vector0; /* { dg-error {wrong type argument to bit-complement} } */
+ !vector0; /* { dg-error {wrong type argument to unary exclamation mark} } */
*vector0; /* { dg-error {invalid type argument of unary '\*'} } */
- __real vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- __imag vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- ++vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- --vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0++; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0--; /* { dg-error {operation not permitted on type '__bf16'} } */
+ __real vector0; /* { dg-error {wrong type argument to __real} } */
+ __imag vector0; /* { dg-error {wrong type argument to __imag} } */
+ ++vector0;
+ --vector0;
+ vector0++;
+ vector0--;
/* Binary arithmetic operations. */
- vector0 = glob_bfloat_vec + *bfloat_ptr; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0 = glob_bfloat_vec + 0.1; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0 = glob_bfloat_vec + 0; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0 = glob_bfloat_vec + is_a_float_vec; /* { dg-error {operation not permitted on type '__bf16'} } */
+ vector0 = glob_bfloat_vec + *bfloat_ptr;
+ vector0 = glob_bfloat_vec + 0.1; /* { dg-error {conversion of scalar 'double' to vector '__m256bf16'} } */
+ vector0 = glob_bfloat_vec + 0;
+ vector0 = glob_bfloat_vec + is_a_float_vec; /* { dg-error {invalid operands to binary \+} } */
return vector0;
}
diff --git a/gcc/testsuite/gfortran.dg/analyzer/pr107210.f90 b/gcc/testsuite/gfortran.dg/analyzer/pr107210.f90
new file mode 100644
index 0000000..6132db4
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/analyzer/pr107210.f90
@@ -0,0 +1,16 @@
+! { dg-additional-options "-O1" }
+
+subroutine check_int (j)
+ INTEGER(4) :: i, ia(5), ib(5,4), ip, ipa(:)
+ target :: ib
+ POINTER :: ip, ipa
+ logical :: l(5)
+
+ ipa=>ib(2:3,1)
+
+ l = (/ sizeof(i) == 4, sizeof(ia) == 20, sizeof(ib) == 80, &
+ sizeof(ip) == 4, sizeof(ipa) == 8 /)
+
+ if (any(.not.l)) STOP 4
+
+end subroutine check_int
diff --git a/gcc/testsuite/gfortran.dg/c-interop/deferred-character-2.f90 b/gcc/testsuite/gfortran.dg/c-interop/deferred-character-2.f90
index 356097a..4dab326 100644
--- a/gcc/testsuite/gfortran.dg/c-interop/deferred-character-2.f90
+++ b/gcc/testsuite/gfortran.dg/c-interop/deferred-character-2.f90
@@ -1,5 +1,5 @@
! PR 92482
-! { dg-do execute}
+! { dg-do run }
!
! TS 29113
! 8.7 Interoperability of procedures and procedure interfaces
diff --git a/gcc/testsuite/gfortran.dg/der_io_5.f90 b/gcc/testsuite/gfortran.dg/der_io_5.f90
new file mode 100644
index 0000000..193916c
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/der_io_5.f90
@@ -0,0 +1,17 @@
+! { dg-do compile }
+! PR fortran/100971 - ICE: Bad IO basetype (7)
+! Contributed by G.Steinmetz
+
+program p
+ implicit none
+ type t
+ end type
+ class(t), allocatable :: a, b(:)
+ type(t) :: x, y(1)
+ integer :: i
+ allocate (a,b(1))
+ print *, [a] ! { dg-error "Data transfer element at .1. cannot be polymorphic" }
+ print *, [(b(i),i=1,1)] ! { dg-error "Data transfer element at .1. cannot be polymorphic" }
+ print *, [x]
+ print *, [(y(i),i=1,1)]
+end
diff --git a/gcc/testsuite/gfortran.dg/vect/pr107254.f90 b/gcc/testsuite/gfortran.dg/vect/pr107254.f90
new file mode 100644
index 0000000..85bcb5f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/vect/pr107254.f90
@@ -0,0 +1,49 @@
+! { dg-do run }
+
+subroutine dlartg( f, g, s, r )
+ implicit none
+ double precision :: f, g, r, s
+ double precision :: d, p
+
+ d = sqrt( f*f + g*g )
+ p = 1.d0 / d
+ if( abs( f ) > 1 ) then
+ s = g*sign( p, f )
+ r = sign( d, f )
+ else
+ s = g*sign( p, f )
+ r = sign( d, f )
+ end if
+end subroutine
+
+subroutine dhgeqz( n, h, t )
+ implicit none
+ integer n
+ double precision h( n, * ), t( n, * )
+ integer jc
+ double precision c, s, temp, temp2, tempr
+ temp2 = 10d0
+ call dlartg( 10d0, temp2, s, tempr )
+ c = 0.9d0
+ s = 1.d0
+ do jc = 1, n
+ temp = c*h( 1, jc ) + s*h( 2, jc )
+ h( 2, jc ) = -s*h( 1, jc ) + c*h( 2, jc )
+ h( 1, jc ) = temp
+ temp2 = c*t( 1, jc ) + s*t( 2, jc )
+ t( 2, jc ) = -s*t( 1, jc ) + c*t( 2, jc )
+ t( 1, jc ) = temp2
+ enddo
+end subroutine dhgeqz
+
+program test
+ implicit none
+ double precision h(2,2), t(2,2)
+ h = 0
+ t(1,1) = 1
+ t(2,1) = 0
+ t(1,2) = 0
+ t(2,2) = 0
+ call dhgeqz( 2, h, t )
+ if (t(2,2).ne.0) STOP 1
+end program test
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index fdd88e6..8d45bc2 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -3416,6 +3416,22 @@ proc check_effective_target_base_quadfloat_support { } {
return 1
}
+# Return 1 if the target supports the __bf16 type, 0 otherwise.
+
+proc check_effective_target_bfloat16 {} {
+ return [check_no_compiler_messages_nocache bfloat16 object {
+ __bf16 foo (__bf16 x) { return x + x; }
+ } [add_options_for_bfloat16 ""]]
+}
+
+proc check_effective_target_bfloat16_runtime {} {
+ return [check_effective_target_bfloat16]
+}
+
+proc add_options_for_bfloat16 { flags } {
+ return "$flags"
+}
+
# Return 1 if the target supports all four forms of fused multiply-add
# (fma, fms, fnma, and fnms) for both float and double.
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index c4f2cea..80b886c 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -665,6 +665,9 @@ enum tree_index {
TI_DOUBLE_TYPE,
TI_LONG_DOUBLE_TYPE,
+ /* __bf16 type if supported (used in C++ as std::bfloat16_t). */
+ TI_BFLOAT16_TYPE,
+
/* The _FloatN and _FloatNx types must be consecutive, and in the
same sequence as the corresponding complex types, which must also
be consecutive; _FloatN must come before _FloatNx; the order must
diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc
index 1996ecf..98a943d 100644
--- a/gcc/tree-vect-loop.cc
+++ b/gcc/tree-vect-loop.cc
@@ -5642,9 +5642,21 @@ vect_create_epilog_for_reduction (loop_vec_info loop_vinfo,
we may end up with more than one vector result. Here we reduce them
to one vector.
+ The same is true for a SLP reduction, e.g.,
+ # a1 = phi <a2, a0>
+ # b1 = phi <b2, b0>
+ a2 = operation (a1)
+ b2 = operation (a2),
+
+ where we can end up with more than one vector as well. We can
+ easily accumulate vectors when the number of vector elements is
+ a multiple of the SLP group size.
+
The same is true if we couldn't use a single defuse cycle. */
if (REDUC_GROUP_FIRST_ELEMENT (stmt_info)
|| direct_slp_reduc
+ || (slp_reduc
+ && constant_multiple_p (TYPE_VECTOR_SUBPARTS (vectype), group_size))
|| ncopies > 1)
{
gimple_seq stmts = NULL;
@@ -6232,7 +6244,8 @@ vect_create_epilog_for_reduction (loop_vec_info loop_vinfo,
}
/* Record this operation if it could be reused by the epilogue loop. */
- if (STMT_VINFO_REDUC_TYPE (reduc_info) == TREE_CODE_REDUCTION)
+ if (STMT_VINFO_REDUC_TYPE (reduc_info) == TREE_CODE_REDUCTION
+ && reduc_inputs.length () == 1)
loop_vinfo->reusable_accumulators.put (scalar_results[0],
{ orig_reduc_input, reduc_info });
diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc
index 229f266..af27fd5 100644
--- a/gcc/tree-vect-slp.cc
+++ b/gcc/tree-vect-slp.cc
@@ -5930,7 +5930,23 @@ vect_slp_analyze_node_operations_1 (vec_info *vinfo, slp_tree node,
/* Handle purely internal nodes. */
if (SLP_TREE_CODE (node) == VEC_PERM_EXPR)
- return vectorizable_slp_permutation (vinfo, NULL, node, cost_vec);
+ {
+ if (!vectorizable_slp_permutation (vinfo, NULL, node, cost_vec))
+ return false;
+
+ stmt_vec_info slp_stmt_info;
+ unsigned int i;
+ FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, slp_stmt_info)
+ {
+ if (STMT_VINFO_LIVE_P (slp_stmt_info)
+ && !vectorizable_live_operation (vinfo,
+ slp_stmt_info, NULL, node,
+ node_instance, i,
+ false, cost_vec))
+ return false;
+ }
+ return true;
+ }
gcc_assert (STMT_SLP_TYPE (stmt_info) != loop_vect);
@@ -8897,8 +8913,6 @@ vect_schedule_slp_node (vec_info *vinfo,
}
}
- bool done_p = false;
-
/* Handle purely internal nodes. */
if (SLP_TREE_CODE (node) == VEC_PERM_EXPR)
{
@@ -8909,9 +8923,18 @@ vect_schedule_slp_node (vec_info *vinfo,
but open-code it here (partly). */
bool done = vectorizable_slp_permutation (vinfo, &si, node, NULL);
gcc_assert (done);
- done_p = true;
+ stmt_vec_info slp_stmt_info;
+ unsigned int i;
+ FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, slp_stmt_info)
+ if (STMT_VINFO_LIVE_P (slp_stmt_info))
+ {
+ done = vectorizable_live_operation (vinfo,
+ slp_stmt_info, &si, node,
+ instance, i, true, NULL);
+ gcc_assert (done);
+ }
}
- if (!done_p)
+ else
vect_transform_stmt (vinfo, stmt_info, &si, node, instance);
}
diff --git a/gcc/tree.cc b/gcc/tree.cc
index c4ead94..81a6cea 100644
--- a/gcc/tree.cc
+++ b/gcc/tree.cc
@@ -7711,7 +7711,7 @@ excess_precision_type (tree type)
= (flag_excess_precision == EXCESS_PRECISION_FAST
? EXCESS_PRECISION_TYPE_FAST
: (flag_excess_precision == EXCESS_PRECISION_FLOAT16
- ? EXCESS_PRECISION_TYPE_FLOAT16 :EXCESS_PRECISION_TYPE_STANDARD));
+ ? EXCESS_PRECISION_TYPE_FLOAT16 : EXCESS_PRECISION_TYPE_STANDARD));
enum flt_eval_method target_flt_eval_method
= targetm.c.excess_precision (requested_type);
@@ -7736,6 +7736,9 @@ excess_precision_type (tree type)
machine_mode float16_type_mode = (float16_type_node
? TYPE_MODE (float16_type_node)
: VOIDmode);
+ machine_mode bfloat16_type_mode = (bfloat16_type_node
+ ? TYPE_MODE (bfloat16_type_node)
+ : VOIDmode);
machine_mode float_type_mode = TYPE_MODE (float_type_node);
machine_mode double_type_mode = TYPE_MODE (double_type_node);
@@ -7747,16 +7750,19 @@ excess_precision_type (tree type)
switch (target_flt_eval_method)
{
case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT:
- if (type_mode == float16_type_mode)
+ if (type_mode == float16_type_mode
+ || type_mode == bfloat16_type_mode)
return float_type_node;
break;
case FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE:
if (type_mode == float16_type_mode
+ || type_mode == bfloat16_type_mode
|| type_mode == float_type_mode)
return double_type_node;
break;
case FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE:
if (type_mode == float16_type_mode
+ || type_mode == bfloat16_type_mode
|| type_mode == float_type_mode
|| type_mode == double_type_mode)
return long_double_type_node;
@@ -7774,16 +7780,19 @@ excess_precision_type (tree type)
switch (target_flt_eval_method)
{
case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT:
- if (type_mode == float16_type_mode)
+ if (type_mode == float16_type_mode
+ || type_mode == bfloat16_type_mode)
return complex_float_type_node;
break;
case FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE:
if (type_mode == float16_type_mode
+ || type_mode == bfloat16_type_mode
|| type_mode == float_type_mode)
return complex_double_type_node;
break;
case FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE:
if (type_mode == float16_type_mode
+ || type_mode == bfloat16_type_mode
|| type_mode == float_type_mode
|| type_mode == double_type_mode)
return complex_long_double_type_node;
@@ -9462,6 +9471,17 @@ build_common_tree_nodes (bool signed_char)
SET_TYPE_MODE (FLOATN_NX_TYPE_NODE (i), mode);
}
float128t_type_node = float128_type_node;
+#ifdef HAVE_BFmode
+ if (REAL_MODE_FORMAT (BFmode) == &arm_bfloat_half_format
+ && targetm.scalar_mode_supported_p (BFmode)
+ && targetm.libgcc_floating_mode_supported_p (BFmode))
+ {
+ bfloat16_type_node = make_node (REAL_TYPE);
+ TYPE_PRECISION (bfloat16_type_node) = GET_MODE_PRECISION (BFmode);
+ layout_type (bfloat16_type_node);
+ SET_TYPE_MODE (bfloat16_type_node, BFmode);
+ }
+#endif
float_ptr_type_node = build_pointer_type (float_type_node);
double_ptr_type_node = build_pointer_type (double_type_node);
diff --git a/gcc/tree.h b/gcc/tree.h
index 142e9c9..9af971c 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -4291,6 +4291,7 @@ tree_strip_any_location_wrapper (tree exp)
#define float_type_node global_trees[TI_FLOAT_TYPE]
#define double_type_node global_trees[TI_DOUBLE_TYPE]
#define long_double_type_node global_trees[TI_LONG_DOUBLE_TYPE]
+#define bfloat16_type_node global_trees[TI_BFLOAT16_TYPE]
/* Nodes for particular _FloatN and _FloatNx types in sequence. */
#define FLOATN_TYPE_NODE(IDX) global_trees[TI_FLOATN_TYPE_FIRST + (IDX)]
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 26a2b78..4794d23 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -324,6 +324,21 @@ frange::set (tree type,
m_neg_nan = false;
}
+ if (!MODE_HAS_SIGNED_ZEROS (TYPE_MODE (m_type)))
+ {
+ if (real_iszero (&m_min, 1))
+ m_min.sign = 0;
+ if (real_iszero (&m_max, 1))
+ m_max.sign = 0;
+ }
+ else if (!HONOR_SIGNED_ZEROS (m_type))
+ {
+ if (real_iszero (&m_max, 1))
+ m_max.sign = 0;
+ if (real_iszero (&m_min, 0))
+ m_min.sign = 1;
+ }
+
// For -ffinite-math-only we can drop ranges outside the
// representable numbers to min/max for the type.
if (flag_finite_math_only)
@@ -332,8 +347,12 @@ frange::set (tree type,
REAL_VALUE_TYPE max_repr = frange_val_max (m_type);
if (real_less (&m_min, &min_repr))
m_min = min_repr;
+ else if (real_less (&max_repr, &m_min))
+ m_min = max_repr;
if (real_less (&max_repr, &m_max))
m_max = max_repr;
+ else if (real_less (&m_max, &min_repr))
+ m_max = min_repr;
}
// Check for swapped ranges.
@@ -4002,6 +4021,11 @@ range_tests_floats ()
r1.clear_nan ();
r0.intersect (r1);
ASSERT_TRUE (r0.undefined_p ());
+
+ // Make sure [-Inf, -Inf] doesn't get normalized.
+ r0 = frange_float ("-Inf", "-Inf");
+ ASSERT_TRUE (real_isinf (&r0.lower_bound (), true));
+ ASSERT_TRUE (real_isinf (&r0.upper_bound (), true));
}
void
diff --git a/gcc/value-relation.cc b/gcc/value-relation.cc
index 1ee6da1..50fc190 100644
--- a/gcc/value-relation.cc
+++ b/gcc/value-relation.cc
@@ -32,10 +32,11 @@ along with GCC; see the file COPYING3. If not see
#include "alloc-pool.h"
#include "dominance.h"
-#define VREL_LAST VREL_NE
+#define VREL_LAST VREL_PE64
static const char *kind_string[VREL_LAST + 1] =
-{ "varying", "undefined", "<", "<=", ">", ">=", "==", "!=" };
+{ "varying", "undefined", "<", "<=", ">", ">=", "==", "!=", "pe8", "pe16",
+ "pe32", "pe64" };
// Print a relation_kind REL to file F.
@@ -302,7 +303,7 @@ equiv_chain::dump (FILE *f) const
bitmap_iterator bi;
unsigned i;
- if (!m_names)
+ if (!m_names || bitmap_empty_p (m_names))
return;
fprintf (f, "Equivalence set : [");
unsigned c = 0;
@@ -329,18 +330,124 @@ equiv_oracle::equiv_oracle ()
obstack_init (&m_chain_obstack);
m_self_equiv.create (0);
m_self_equiv.safe_grow_cleared (num_ssa_names + 1);
+ m_partial.create (0);
+ m_partial.safe_grow_cleared (num_ssa_names + 1);
}
// Destruct an equivalency oracle.
equiv_oracle::~equiv_oracle ()
{
+ m_partial.release ();
m_self_equiv.release ();
obstack_free (&m_chain_obstack, NULL);
m_equiv.release ();
bitmap_obstack_release (&m_bitmaps);
}
+// Add a partial equivalence R between OP1 and OP2.
+
+void
+equiv_oracle::add_partial_equiv (relation_kind r, tree op1, tree op2)
+{
+ int v1 = SSA_NAME_VERSION (op1);
+ int v2 = SSA_NAME_VERSION (op2);
+ int prec2 = TYPE_PRECISION (TREE_TYPE (op2));
+ int bits = pe_to_bits (r);
+ gcc_checking_assert (bits && prec2 >= bits);
+
+ if (v1 >= (int)m_partial.length () || v2 >= (int)m_partial.length ())
+ m_partial.safe_grow_cleared (num_ssa_names + 1);
+ gcc_checking_assert (v1 < (int)m_partial.length ()
+ && v2 < (int)m_partial.length ());
+
+ pe_slice &pe1 = m_partial[v1];
+ pe_slice &pe2 = m_partial[v2];
+
+ if (pe1.members)
+ {
+ // If the definition pe1 already has an entry, either the stmt is
+ // being re-evaluated, or the def was used before being registered.
+ // In either case, if PE2 has an entry, we simply do nothing.
+ if (pe2.members)
+ return;
+ // PE1 is the LHS and already has members, so everything in the set
+ // should be a slice of PE2 rather than PE1.
+ pe2.code = pe_min (r, pe1.code);
+ pe2.ssa_base = op2;
+ pe2.members = pe1.members;
+ bitmap_iterator bi;
+ unsigned x;
+ EXECUTE_IF_SET_IN_BITMAP (pe1.members, 0, x, bi)
+ {
+ m_partial[x].ssa_base = op2;
+ m_partial[x].code = pe2.code;
+ }
+ bitmap_set_bit (pe1.members, v2);
+ return;
+ }
+ if (pe2.members)
+ {
+ pe1.ssa_base = pe2.ssa_base;
+ // If pe2 is a 16 bit value, but only an 8 bit copy, we can't be any
+ // more than an 8 bit equivalence here, so choose MIN value.
+ pe1.code = pe_min (r, pe2.code);
+ pe1.members = pe2.members;
+ bitmap_set_bit (pe1.members, v1);
+ }
+ else
+ {
+ // Neither name has an entry, simply create op1 as slice of op2.
+ pe2.code = bits_to_pe (TYPE_PRECISION (TREE_TYPE (op2)));
+ if (pe2.code == VREL_VARYING)
+ return;
+ pe2.ssa_base = op2;
+ pe2.members = BITMAP_ALLOC (&m_bitmaps);
+ bitmap_set_bit (pe2.members, v2);
+ pe1.ssa_base = op2;
+ pe1.code = r;
+ pe1.members = pe2.members;
+ bitmap_set_bit (pe1.members, v1);
+ }
+}
+
+// Return the set of partial equivalences associated with NAME. The bitmap
+// will be NULL if there are none.
+
+const pe_slice *
+equiv_oracle::partial_equiv_set (tree name)
+{
+ int v = SSA_NAME_VERSION (name);
+ if (v >= (int)m_partial.length ())
+ return NULL;
+ return &m_partial[v];
+}
+
+// Query if there is a partial equivalence between SSA1 and SSA2. Return
+// VREL_VARYING if there is not one. If BASE is non-null, return the base
+// ssa-name this is a slice of.
+
+relation_kind
+equiv_oracle::partial_equiv (tree ssa1, tree ssa2, tree *base) const
+{
+ int v1 = SSA_NAME_VERSION (ssa1);
+ int v2 = SSA_NAME_VERSION (ssa2);
+
+ if (v1 >= (int)m_partial.length () || v2 >= (int)m_partial.length ())
+ return VREL_VARYING;
+
+ const pe_slice &pe1 = m_partial[v1];
+ const pe_slice &pe2 = m_partial[v2];
+ if (pe1.members && pe2.members == pe1.members)
+ {
+ if (base)
+ *base = pe1.ssa_base;
+ return pe_min (pe1.code, pe2.code);
+ }
+ return VREL_VARYING;
+}
+
+
// Find and return the equivalency set for SSA along the dominators of BB.
// This is the external API.
@@ -365,7 +472,7 @@ equiv_oracle::equiv_set (tree ssa, basic_block bb)
return m_self_equiv[v];
}
-// Query if thre is a relation (equivalence) between 2 SSA_NAMEs.
+// Query if there is a relation (equivalence) between 2 SSA_NAMEs.
relation_kind
equiv_oracle::query_relation (basic_block bb, tree ssa1, tree ssa2)
@@ -373,7 +480,9 @@ equiv_oracle::query_relation (basic_block bb, tree ssa1, tree ssa2)
// If the 2 ssa names share the same equiv set, they are equal.
if (equiv_set (ssa1, bb) == equiv_set (ssa2, bb))
return VREL_EQ;
- return VREL_VARYING;
+
+ // Check if there is a partial equivalence.
+ return partial_equiv (ssa1, ssa2);
}
// Query if thre is a relation (equivalence) between 2 SSA_NAMEs.
@@ -515,6 +624,12 @@ void
equiv_oracle::register_relation (basic_block bb, relation_kind k, tree ssa1,
tree ssa2)
{
+ // Process partial equivalencies.
+ if (relation_partial_equiv_p (k))
+ {
+ add_partial_equiv (k, ssa1, ssa2);
+ return;
+ }
// Only handle equality relations.
if (k != VREL_EQ)
return;
@@ -611,12 +726,34 @@ equiv_oracle::dump (FILE *f, basic_block bb) const
{
if (bb->index >= (int)m_equiv.length ())
return;
- if (!m_equiv[bb->index])
- return;
-
- equiv_chain *ptr = m_equiv[bb->index]->m_next;
- for (; ptr; ptr = ptr->m_next)
- ptr->dump (f);
+ // Process equivalences.
+ if (m_equiv[bb->index])
+ {
+ equiv_chain *ptr = m_equiv[bb->index]->m_next;
+ for (; ptr; ptr = ptr->m_next)
+ ptr->dump (f);
+ }
+ // Look for partial equivalences defined in this block..
+ for (unsigned i = 0; i < num_ssa_names; i++)
+ {
+ tree name = ssa_name (i);
+ if (!gimple_range_ssa_p (name) || !SSA_NAME_DEF_STMT (name))
+ continue;
+ if (i >= m_partial.length ())
+ break;
+ tree base = m_partial[i].ssa_base;
+ if (base && name != base && gimple_bb (SSA_NAME_DEF_STMT (name)) == bb)
+ {
+ relation_kind k = partial_equiv (name, base);
+ if (k != VREL_VARYING)
+ {
+ value_relation vr (k, name, base);
+ fprintf (f, "Partial equiv ");
+ vr.dump (f);
+ fputc ('\n',f);
+ }
+ }
+ }
}
// Dump all equivalence sets known to the oracle.
@@ -906,7 +1043,7 @@ dom_oracle::register_relation (basic_block bb, relation_kind k, tree op1,
return;
// Equivalencies are handled by the equivalence oracle.
- if (k == VREL_EQ)
+ if (relation_equiv_p (k))
equiv_oracle::register_relation (bb, k, op1, op2);
else
{
@@ -1210,6 +1347,10 @@ dom_oracle::query_relation (basic_block bb, tree ssa1, tree ssa2)
if (bitmap_bit_p (equiv1, v2) && bitmap_bit_p (equiv2, v1))
return VREL_EQ;
+ kind = partial_equiv (ssa1, ssa2);
+ if (kind != VREL_VARYING)
+ return kind;
+
// Initially look for a direct relationship and just return that.
kind = find_relation_dom (bb, v1, v2);
if (kind != VREL_VARYING)
@@ -1500,3 +1641,81 @@ path_oracle::dump (FILE *f) const
fprintf (f, "\n");
}
}
+
+// ------------------------------------------------------------------------
+// EQUIV iterator. Although we have bitmap iterators, don't expose that it
+// is currently a bitmap. Use an export iterator to hide future changes.
+
+// Construct a basic iterator over an equivalence bitmap.
+
+equiv_relation_iterator::equiv_relation_iterator (relation_oracle *oracle,
+ basic_block bb, tree name,
+ bool full, bool partial)
+{
+ m_name = name;
+ m_oracle = oracle;
+ m_pe = partial ? oracle->partial_equiv_set (name) : NULL;
+ m_bm = NULL;
+ if (full)
+ m_bm = oracle->equiv_set (name, bb);
+ if (!m_bm && m_pe)
+ m_bm = m_pe->members;
+ if (m_bm)
+ bmp_iter_set_init (&m_bi, m_bm, 1, &m_y);
+}
+
+// Move to the next export bitmap spot.
+
+void
+equiv_relation_iterator::next ()
+{
+ bmp_iter_next (&m_bi, &m_y);
+}
+
+// Fetch the name of the next export in the export list. Return NULL if
+// iteration is done.
+
+tree
+equiv_relation_iterator::get_name (relation_kind *rel)
+{
+ if (!m_bm)
+ return NULL_TREE;
+
+ while (bmp_iter_set (&m_bi, &m_y))
+ {
+ // Do not return self.
+ tree t = ssa_name (m_y);
+ if (t && t != m_name)
+ {
+ relation_kind k = VREL_EQ;
+ if (m_pe && m_bm == m_pe->members)
+ {
+ const pe_slice *equiv_pe = m_oracle->partial_equiv_set (t);
+ if (equiv_pe && equiv_pe->members == m_pe->members)
+ k = pe_min (m_pe->code, equiv_pe->code);
+ else
+ k = VREL_VARYING;
+ }
+ if (relation_equiv_p (k))
+ {
+ if (rel)
+ *rel = k;
+ return t;
+ }
+ }
+ next ();
+ }
+
+ // Process partial equivs after full equivs if both were requested.
+ if (m_pe && m_bm != m_pe->members)
+ {
+ m_bm = m_pe->members;
+ if (m_bm)
+ {
+ // Recursively call back to process First PE.
+ bmp_iter_set_init (&m_bi, m_bm, 1, &m_y);
+ return get_name (rel);
+ }
+ }
+ return NULL_TREE;
+}
diff --git a/gcc/value-relation.h b/gcc/value-relation.h
index e1347ea..a3bbe1e 100644
--- a/gcc/value-relation.h
+++ b/gcc/value-relation.h
@@ -70,7 +70,11 @@ typedef enum relation_kind_t
VREL_GT, // r1 > r2
VREL_GE, // r1 >= r2
VREL_EQ, // r1 == r2
- VREL_NE // r1 != r2
+ VREL_NE, // r1 != r2
+ VREL_PE8, // 8 bit partial equivalency
+ VREL_PE16, // 16 bit partial equivalency
+ VREL_PE32, // 32 bit partial equivalency
+ VREL_PE64 // 64 bit partial equivalency
} relation_kind;
// General relation kind transformations.
@@ -79,7 +83,12 @@ relation_kind relation_intersect (relation_kind r1, relation_kind r2);
relation_kind relation_negate (relation_kind r);
relation_kind relation_swap (relation_kind r);
inline bool relation_lt_le_gt_ge_p (relation_kind r)
- { return (r >= VREL_LT && r <= VREL_GE); }
+ { return (r >= VREL_LT && r <= VREL_GE); }
+inline bool relation_partial_equiv_p (relation_kind r)
+ { return (r >= VREL_PE8 && r <= VREL_PE64); }
+inline bool relation_equiv_p (relation_kind r)
+ { return r == VREL_EQ || relation_partial_equiv_p (r); }
+
void print_relation (FILE *f, relation_kind rel);
class relation_oracle
@@ -91,8 +100,6 @@ public:
// register a relation between 2 ssa names on an edge.
void register_edge (edge, relation_kind, tree, tree);
- // Return equivalency set for an SSA name in a basic block.
- virtual const_bitmap equiv_set (tree, basic_block) = 0;
// register a relation between 2 ssa names in a basic block.
virtual void register_relation (basic_block, relation_kind, tree, tree) = 0;
// Query for a relation between two ssa names in a basic block.
@@ -105,6 +112,11 @@ public:
virtual void dump (FILE *) const = 0;
void debug () const;
protected:
+ friend class equiv_relation_iterator;
+ // Return equivalency set for an SSA name in a basic block.
+ virtual const_bitmap equiv_set (tree, basic_block) = 0;
+ // Return partial equivalency record for an SSA name.
+ virtual const class pe_slice *partial_equiv_set (tree) { return NULL; }
void valid_equivs (bitmap b, const_bitmap equivs, basic_block bb);
// Query for a relation between two equivalency sets in a basic block.
virtual relation_kind query_relation (basic_block, const_bitmap,
@@ -125,6 +137,14 @@ public:
equiv_chain *find (unsigned ssa);
};
+class pe_slice
+{
+public:
+ tree ssa_base; // Slice of this name.
+ relation_kind code; // bits that are equivalent.
+ bitmap members; // Other members in the partial equivalency.
+};
+
// The equivalency oracle maintains equivalencies using the dominator tree.
// Equivalencies apply to an entire basic block. Equivalencies on edges
// can be represented only on edges whose destination is a single-pred block,
@@ -137,9 +157,12 @@ public:
~equiv_oracle ();
const_bitmap equiv_set (tree ssa, basic_block bb) final override;
+ const pe_slice *partial_equiv_set (tree name) final override;
void register_relation (basic_block bb, relation_kind k, tree ssa1,
tree ssa2) override;
+ void add_partial_equiv (relation_kind, tree, tree);
+ relation_kind partial_equiv (tree ssa1, tree ssa2, tree *base = NULL) const;
relation_kind query_relation (basic_block, tree, tree) override;
relation_kind query_relation (basic_block, const_bitmap, const_bitmap)
override;
@@ -153,6 +176,7 @@ private:
bitmap m_equiv_set; // Index by ssa-name. true if an equivalence exists.
vec <equiv_chain *> m_equiv; // Index by BB. list of equivalences.
vec <bitmap> m_self_equiv; // Index by ssa-name, self equivalency set.
+ vec <pe_slice> m_partial; // Partial equivalencies.
void limit_check (basic_block bb = NULL);
equiv_chain *find_equiv_block (unsigned ssa, int bb) const;
@@ -259,6 +283,39 @@ private:
struct obstack m_chain_obstack;
};
+// Used to assist with iterating over the equivalence list.
+class equiv_relation_iterator {
+public:
+ equiv_relation_iterator (relation_oracle *oracle, basic_block bb, tree name,
+ bool full = true, bool partial = false);
+ void next ();
+ tree get_name (relation_kind *rel = NULL);
+protected:
+ relation_oracle *m_oracle;
+ const_bitmap m_bm;
+ const pe_slice *m_pe;
+ bitmap_iterator m_bi;
+ unsigned m_y;
+ tree m_name;
+};
+
+#define FOR_EACH_EQUIVALENCE(oracle, bb, name, equiv_name) \
+ for (equiv_relation_iterator iter (oracle, bb, name, true, false); \
+ ((equiv_name) = iter.get_name ()); \
+ iter.next ())
+
+#define FOR_EACH_PARTIAL_EQUIV(oracle, bb, name, equiv_name, equiv_rel) \
+ for (equiv_relation_iterator iter (oracle, bb, name, false, true); \
+ ((equiv_name) = iter.get_name (&equiv_rel)); \
+ iter.next ())
+
+#define FOR_EACH_PARTIAL_AND_FULL_EQUIV(oracle, bb, name, equiv_name, \
+ equiv_rel) \
+ for (equiv_relation_iterator iter (oracle, bb, name, true, true); \
+ ((equiv_name) = iter.get_name (&equiv_rel)); \
+ iter.next ())
+
+
// The value-relation class is used to encapsulate the represention of an
// individual relation between 2 ssa-names, and to facilitate operating on
// the relation.
@@ -315,4 +372,56 @@ value_relation::value_relation (relation_kind kind, tree n1, tree n2)
set_relation (kind, n1, n2);
}
+// Return the number of bits associated with partial equivalency T.
+// Return 0 if this is not a supported partial equivalency relation.
+
+inline int
+pe_to_bits (relation_kind t)
+{
+ switch (t)
+ {
+ case VREL_PE8:
+ return 8;
+ case VREL_PE16:
+ return 16;
+ case VREL_PE32:
+ return 32;
+ case VREL_PE64:
+ return 64;
+ default:
+ return 0;
+ }
+}
+
+// Return the partial equivalency code associated with the number of BITS.
+// return VREL_VARYING if there is no exact match.
+
+inline relation_kind
+bits_to_pe (int bits)
+{
+ switch (bits)
+ {
+ case 8:
+ return VREL_PE8;
+ case 16:
+ return VREL_PE16;
+ case 32:
+ return VREL_PE32;
+ case 64:
+ return VREL_PE64;
+ default:
+ return VREL_VARYING;
+ }
+}
+
+// Given partial equivalencies T1 and T2, return the snmallest kind.
+
+inline relation_kind
+pe_min (relation_kind t1, relation_kind t2)
+{
+ gcc_checking_assert (relation_partial_equiv_p (t1));
+ gcc_checking_assert (relation_partial_equiv_p (t2));
+ // VREL_PE are declared small to large, so simple min will suffice.
+ return MIN (t1, t2);
+}
#endif /* GCC_VALUE_RELATION_H */
diff --git a/gcc/varasm.cc b/gcc/varasm.cc
index 423f3f9..a111845 100644
--- a/gcc/varasm.cc
+++ b/gcc/varasm.cc
@@ -2419,23 +2419,6 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED,
}
}
-
-/* Given a function declaration (FN_DECL), this function assembles the
- function into the .preinit_array section. */
-
-void
-assemble_vtv_preinit_initializer (tree fn_decl)
-{
- section *sect;
- unsigned flags = SECTION_WRITE;
- rtx symbol = XEXP (DECL_RTL (fn_decl), 0);
-
- flags |= SECTION_NOTYPE;
- sect = get_section (".preinit_array", flags, fn_decl);
- switch_to_section (sect);
- assemble_addr_to_section (symbol, sect);
-}
-
/* Return 1 if type TYPE contains any pointers. */
static int